Skip to content

Reference

Build

Make

mdna.nucleic.make(sequence=None, control_points=None, circular=False, closed=False, n_bp=None, dLk=None)

Generate a DNA structure from a given DNA sequence and control points.

Parameters:

Name Type Description Default
sequence str

DNA sequence code. If not provided, the default sequence 'CGCGAATTCGCG' will be used. (default: None)

None
control_points ndarray

Control points of the DNA structure. Should be a numpy array of shape (n, 3) where n is the number of control points. If not provided, a straight line will be used as the default control points. (default: None)

None
circular bool

Flag indicating if the DNA structure is circular/closed. If True, the DNA structure will be closed. If False, the DNA structure will be open. (default: False)

False
closed bool

Flag indicating if the DNA structure is closed. If True, the DNA structure will be closed. If False, the DNA structure will be open. This argument is deprecated and will be removed in a future version. Please use the 'circular' argument instead. (default: False)

False
n_bp int

Number of base pairs to scale the shape with. If not provided, the number of base pairs will be determined based on the length of the control points or the sequence. (default: None)

None
dLk int

Change in twist in terms of Linking number of the DNA structure. If not provided, a neutral twist based on bp_per_turn = 10.5 will be used. (default: None)

None

Returns:

Name Type Description
Nucleic object

DNA structure object.

Example

Generate a DNA structure from a sequence

dna = make(sequence='CGCGAATTCGCG', control_points=None, circular=False, closed=False, n_bp=None, dLk=None)

Source code in mdna/nucleic.py
def make(sequence: str = None, control_points: np.ndarray = None, circular : bool = False, closed: bool = False, n_bp : int = None, dLk : int = None):
    """Generate a DNA structure from a given DNA sequence and control points.

    Args:
        sequence (str, optional): DNA sequence code. If not provided, the default sequence 'CGCGAATTCGCG' will be used. (default: None)
        control_points (ndarray, optional): Control points of the DNA structure. Should be a numpy array of shape (n, 3) where n is the number of control points. If not provided, a straight line will be used as the default control points. (default: None)
        circular (bool, optional): Flag indicating if the DNA structure is circular/closed. If True, the DNA structure will be closed. If False, the DNA structure will be open. (default: False)
        closed (bool, optional): Flag indicating if the DNA structure is closed. If True, the DNA structure will be closed. If False, the DNA structure will be open. This argument is deprecated and will be removed in a future version. Please use the 'circular' argument instead. (default: False)
        n_bp (int, optional): Number of base pairs to scale the shape with. If not provided, the number of base pairs will be determined based on the length of the control points or the sequence. (default: None)
        dLk (int, optional): Change in twist in terms of Linking number of the DNA structure. If not provided, a neutral twist based on bp_per_turn = 10.5 will be used. (default: None)

    Returns:
        Nucleic (object): DNA structure object.

    Example:
        Generate a DNA structure from a sequence
        ```python
        dna = make(sequence='CGCGAATTCGCG', control_points=None, circular=False, closed=False, n_bp=None, dLk=None)
        ```
    """

    # Check if control points are provided, otherwise generate a straight line
    skip = False
    if control_points is not None:
        if len(control_points) < 4:
            raise ValueError('Control points should contain at least 4 points [x, y, z]')
        elif len(control_points) > 4 and n_bp is None and sequence is None:
            skip = True
    elif control_points is None and circular:
        control_points = Shapes.circle(radius=1)
        closed = True
    else:
        # Linear strand of control points
        control_points = Shapes.line(length=1)

    if not skip:
        sequence, n_bp = _check_input(sequence=sequence, n_bp=n_bp)
        spline = SplineFrames(control_points=control_points, n_bp=n_bp, closed=circular, dLk=dLk)
    else:
        spline = SplineFrames(control_points=control_points, n_bp=n_bp, closed=circular, dLk=dLk)
        sequence, n_bp = _check_input(sequence=sequence, n_bp=spline.n_bp)




    return Nucleic(sequence=sequence, n_bp=n_bp, frames=spline.frames, chainids=[0, 1], circular=circular)

Extend

mdna.nucleic.Nucleic.extend(n_bp=None, sequence=None, fixed_endpoints=False, forward=True, frame=-1, shape=None, margin=1, minimize=True, plot=False, exvol_rad=2.0, temperature=300)

Extend the DNA structure in the specified direction. The method updates the attributes of the DNA object.

Parameters:

Name Type Description Default
n_bp int

Number of base pairs to extend the DNA structure. Defaults to None.

None
sequence str or List

DNA sequence to extend the DNA structure. If not provided, the sequence will be generated randomly. Defaults to None.

None
fixed_endpoints bool

Whether to fix the endpoints of the DNA structure during extension. Defaults to False.

False
forward bool

Whether to extend the DNA structure in the forward direction. If False, the DNA structure will be extended in the backward direction. Defaults to True.

True
frame int

The time frame to extend. Defaults to -1.

-1
shape ndarray

Control points of the shape to be used for extension. The shape should be a numpy array of shape (n, 3), where n is greater than 3. Defaults to None.

None
margin int

Number of base pairs to fix at the end/start of the DNA structure during extension. Defaults to 1.

1
minimize bool

Whether to minimize the new DNA structure after extension. Defaults to True.

True
plot bool

Whether to plot the Energy during minmization. Defaults to False.

False
exvol_rad float

Excluded volume radius. Defaults to 2.0.

2.0
temperature int

Temperature for equilibration. Defaults

300

Raises:

Type Description
ValueError

If the DNA structure is circular and cannot be extended.

ValueError

If neither a fixed endpoint nor a length is specified for extension.

ValueError

If the input sequence is invalid or the number of base pairs is invalid.

Notes
  • If the DNA structure is circular, it cannot be extended.
Example

Extend DNA structure

nuc = mdna.make(n_bp=100)
nuc.extend(n_bp=10, forward=True, margin=2, minimize=True)

Source code in mdna/nucleic.py
def extend(self, n_bp: int = None, sequence: Union[str|List] = None, fixed_endpoints: bool = False, forward: bool = True, frame: int = -1, shape: np.ndarray = None, margin: int = 1, minimize: bool = True, plot : bool = False, exvol_rad : float = 2.0, temperature : int = 300):  
    """Extend the DNA structure in the specified direction.
        The method updates the attributes of the DNA object.


    Args:
        n_bp (int): Number of base pairs to extend the DNA structure. Defaults to None.
        sequence (str or List, optional): DNA sequence to extend the DNA structure. If not provided, the sequence will be generated randomly. Defaults to None.
        fixed_endpoints (bool, optional): Whether to fix the endpoints of the DNA structure during extension. Defaults to False.
        forward (bool, optional): Whether to extend the DNA structure in the forward direction. If False, the DNA structure will be extended in the backward direction. Defaults to True.
        frame (int, optional): The time frame to extend. Defaults to -1.
        shape (np.ndarray, optional): Control points of the shape to be used for extension. The shape should be a numpy array of shape (n, 3), where n is greater than 3. Defaults to None.
        margin (int, optional): Number of base pairs to fix at the end/start of the DNA structure during extension. Defaults to 1.
        minimize (bool, optional): Whether to minimize the new DNA structure after extension. Defaults to True.
        plot (bool, optional): Whether to plot the Energy during minmization. Defaults to False.
        exvol_rad (float, optional): Excluded volume radius. Defaults to 2.0.
        temperature (int, optional): Temperature for equilibration. Defaults

    Raises:
        ValueError: If the DNA structure is circular and cannot be extended.
        ValueError: If neither a fixed endpoint nor a length is specified for extension.
        ValueError: If the input sequence is invalid or the number of base pairs is invalid.

    Notes:
        - If the DNA structure is circular, it cannot be extended.

    Example:
        Extend DNA structure
        ```python
        nuc = mdna.make(n_bp=100)
        nuc.extend(n_bp=10, forward=True, margin=2, minimize=True)
        ```
    """
    if self.circular:
        raise ValueError('Cannot extend circular DNA structure')  
    if self.traj is None:
        self._frames_to_traj()
    if shape is None:
        shape = Shapes.line(length=1)
    if self.frames is None:
        self._traj_to_frames()

    # Check the input sequence and number of base pairs
    sequence, n_bp = _check_input(sequence=sequence, n_bp=n_bp)

    extender = Extender(self, n_bp=n_bp, sequence=sequence, fixed_endpoints=fixed_endpoints, frame=frame, forward=forward, shape=shape, margin=margin)
    # Also update, n_bp, sequence, frames etc
    self.nuc = extender.nuc

    if minimize:
        self.nuc.minimize(fixed=extender.fixed, endpoints_fixed=fixed_endpoints, plot=plot, exvol_rad=exvol_rad, temperature=temperature)

    # Update attributes
    self.sequence = self.nuc.sequence
    self.traj = self.nuc.get_traj()
    self.frames = self.nuc.get_frames()
    self.n_bp = self.nuc.n_bp

Connect

mdna.nucleic.connect(Nucleic0, Nucleic1, sequence=None, n_bp=None, leader=0, frame=-1, margin=1, minimize=True, exvol_rad=0.0, temperature=300, control_points=None, index=0)

Connect two DNA structures by creating a new DNA structure with a connecting DNA strand.

The 3' end of the first DNA structure is connected to the 5' end of the second DNA structure. To connect the two strands, a straight line is interpolated between the two ends, and the optimal number of base pairs is distributed to achieve a neutral twist.

Parameters:

Name Type Description Default
Nucleic0 Nucleic

First DNA structure to connect.

required
Nucleic1 Nucleic

Second DNA structure to connect.

required
sequence str or List

DNA sequence of the connecting DNA strand. Default is None.

None
n_bp int

Number of base pairs of the connecting DNA strand. Default is None.

None
leader int

The leader of the DNA structure to connect. Default is 0.

0
frame int

The time frame to connect. Default is -1.

-1
margin int

Number of base pairs to fix at the end. Default is 1.

1
minimize bool

Whether to minimize the new DNA structure. Default is True.

True
exvol_rad float

Radius for excluded volume interactions during minimization. Default is 0.0.

0.0
temperature int

Temperature for minimization. Default is 300.

300

Returns:

Name Type Description
Nucleic object

DNA structure with the two DNA structures connected.

Raises:

Type Description
ValueError

If either of the DNA structures is circular.

Notes
  • The minimization does not use excluded volume interactions by default.This is because the excluded volume interactions require the EV beads to have no overlap. However, in the initial configuration, the EV beads are likely to have overlap. If desired, the resulting Nucleic object can be further minimized with the excluded volume interactions.
Example

Connect two DNA structures

dna = connect(Nucleic0, Nucleic1, margin=5)

Source code in mdna/nucleic.py
def connect(Nucleic0, Nucleic1, sequence: Union[str|List] = None, n_bp: int = None, leader: int = 0, frame: int = -1, margin: int = 1, minimize: bool = True, exvol_rad: float = 0.0, temperature: int = 300, control_points : np.ndarray = None, index : int = 0):  
    """Connect two DNA structures by creating a new DNA structure with a connecting DNA strand.

    The 3' end of the first DNA structure is connected to the 5' end of the second DNA structure.
    To connect the two strands, a straight line is interpolated between the two ends,
    and the optimal number of base pairs is distributed to achieve a neutral twist.

    Args:
        Nucleic0 (Nucleic): First DNA structure to connect.
        Nucleic1 (Nucleic): Second DNA structure to connect.
        sequence (str or List, optional): DNA sequence of the connecting DNA strand. Default is None.
        n_bp (int, optional): Number of base pairs of the connecting DNA strand. Default is None.
        leader (int, optional): The leader of the DNA structure to connect. Default is 0.
        frame (int, optional): The time frame to connect. Default is -1.
        margin (int, optional): Number of base pairs to fix at the end. Default is 1.
        minimize (bool, optional): Whether to minimize the new DNA structure. Default is True.
        exvol_rad (float, optional): Radius for excluded volume interactions during minimization. Default is 0.0.
        temperature (int, optional): Temperature for minimization. Default is 300.

    Returns:
        Nucleic (object): DNA structure with the two DNA structures connected.

    Raises:
        ValueError: If either of the DNA structures is circular.

    Notes:
        - The minimization does not use excluded volume interactions by default.This is because the excluded volume interactions require the EV beads to have no overlap. However, in the initial configuration, the EV beads are likely to have overlap. If desired, the resulting Nucleic object can be further minimized with the excluded volume interactions.

    Example:
        Connect two DNA structures
        ```python
        dna = connect(Nucleic0, Nucleic1, margin=5)
        ```
    """
    if Nucleic0.circular or Nucleic1.circular:
        raise ValueError('Cannot connect circular DNA structures')

    if (sequence is not None and n_bp is None) or (sequence is None and n_bp is not None) or (sequence is not None and n_bp is not None):
        sequence, n_bp = _check_input(sequence=sequence, n_bp=n_bp)

    # Connect the two DNA structures
    connector = Connector(Nucleic0, Nucleic1, sequence=sequence, n_bp=n_bp, leader=leader, frame=frame, margin=margin, control_points=control_points, index=index)
    if minimize:
        connector.connected_nuc.minimize(exvol_rad=exvol_rad, temperature=temperature, fixed=connector.fixed)
    return connector.connected_nuc

Modify

mdna.nucleic.Nucleic.mutate(mutations=None, complementary=True, frame=-1, verbose=False)

Mutate the DNA trajectory, updating the topology and coordinates of the DNA structure. The method updates the traj attribute and the sequence attribute of the DNA object.

Parameters:

Name Type Description Default
mutations dict

A dictionary containing the mutation information. The keys represent the indices of the base pairs to be mutated, and the values represent the new nucleobases. For example, mutations = {0: 'A', 1: 'T', 2: 'G'} will mutate the first three base pairs to A, T, and G, respectively. Defaults to None.

None
complementary bool

Whether to mutate the complementary strand. Defaults to True.

True
frame int

The frame to mutate. Defaults to -1.

-1
verbose bool

Whether to print the mutated sequence. Defaults to False.

False

Raises:

Type Description
ValueError

If no mutation dictionary is provided.

Notes
  • Valid nucleobases for mutations include:
    • Canonical bases: A, T, G, C, U
    • Hachimoji: B [A_ana], S [T_ana], P [C_ana], Z [G_ana] (DOI: 10.1126/science.aat0971)
    • Fluorescent: 2-aminopurine 2AP (E), triC (D) (DOI: 10.1002/anie.201001312), tricyclic cytosine base analogue (1tuq)
    • Hydrophobic pairs: d5SICS (L), dNaM (M)
Example

Create a DNA object

dna = DNA()
mutations = {0: 'A', 1: 'T', 2: 'G'}
dna.mutate(mutations=mutations, complementary=True, frame=-1)

Source code in mdna/nucleic.py
def mutate(self, mutations: dict = None, complementary: bool = True, frame: int = -1, verbose: bool = False):
    """Mutate the DNA trajectory, updating the topology and coordinates of the DNA structure.
    The method updates the `traj` attribute and the `sequence` attribute of the DNA object.


    Args:
        mutations (dict, optional): A dictionary containing the mutation information. The keys represent the indices of the base pairs to be mutated, and the values represent the new nucleobases. For example, `mutations = {0: 'A', 1: 'T', 2: 'G'}` will mutate the first three base pairs to A, T, and G, respectively. Defaults to None.
        complementary (bool, optional): Whether to mutate the complementary strand. Defaults to True.
        frame (int, optional): The frame to mutate. Defaults to -1.
        verbose (bool, optional): Whether to print the mutated sequence. Defaults to False.

    Raises:
        ValueError: If no mutation dictionary is provided.

    Notes:
        - Valid nucleobases for mutations include:
            - Canonical bases: A, T, G, C, U
            - Hachimoji: B [A_ana], S [T_ana], P [C_ana], Z [G_ana] (DOI: 10.1126/science.aat0971)
            - Fluorescent: 2-aminopurine 2AP (E), triC (D) (DOI: 10.1002/anie.201001312), tricyclic cytosine base analogue (1tuq)
            - Hydrophobic pairs: d5SICS (L), dNaM (M)

    Example:
        Create a DNA object 
        ```python
        dna = DNA()
        mutations = {0: 'A', 1: 'T', 2: 'G'}
        dna.mutate(mutations=mutations, complementary=True, frame=-1)
        ```
    """
    if self.traj is None:
        self._frames_to_traj()
    if mutations is None:
        raise ValueError('Provide a mutation dictionary')

    # TODO: Check if valid letters in mutations dictionary

    mutant = Mutate(self.traj[frame], mutations, complementary=complementary, verbose=verbose)
    self.traj = mutant.get_traj()
    # Update sequence
    self.sequence = ''.join(get_sequence_letters(self.traj, leading_chain=self.chainids[0]))

mdna.nucleic.Nucleic.methylate(methylations=[], CpG=False, leading_strand=0, frame=-1)

Methylate the nucleobases of the DNA structure. The method updates the traj attribute of the DNA object.

Parameters:

Name Type Description Default
methylations list

List of base pairs to methylate. Defaults to [].

[]
CpG bool

Whether to methylate CpG sites. Defaults to False.

False
leading_strand int

The leading strand to methylate. Defaults to 0.

0
frame int

The frame to methylate. Defaults to -1.

-1

Raises:

Type Description
ValueError

If the DNA structure is not loaded.

ValueError

If the methylations list is empty.

Notes

Using the CpG flag will methylate the CpG sites in the DNA structure. This flag supercedes the methylations list.

Example

Methylate DNA

dna = mdna.make('GCGCGCGAGCGA)
dna.metyhlate(fliplist=[3,4])

Source code in mdna/nucleic.py
def methylate(self, methylations: list = [], CpG: bool = False, leading_strand: int = 0, frame: int = -1):
        """Methylate the nucleobases of the DNA structure.
        The method updates the `traj` attribute of the DNA object.


        Args:
            methylations (list): List of base pairs to methylate. Defaults to [].
            CpG (bool): Whether to methylate CpG sites. Defaults to False.
            leading_strand (int): The leading strand to methylate. Defaults to 0.
            frame (int): The frame to methylate. Defaults to -1.

        Raises:
            ValueError: If the DNA structure is not loaded.
            ValueError: If the methylations list is empty.

        Notes:
            Using the `CpG` flag will methylate the CpG sites in the DNA structure. This flag supercedes the methylations list.

        Example:
            Methylate DNA
            ```python
            dna = mdna.make('GCGCGCGAGCGA)
            dna.metyhlate(fliplist=[3,4])
            ```
        """
        if self.traj is None:
            self._frames_to_traj()
        if len(methylations) == 0 and not CpG:
            raise ValueError('Provide a non-empty methylations list')

        methylator = Methylate(self.traj, methylations=methylations, CpG=CpG, leading_strand=leading_strand)
        self.traj = methylator.get_traj()

mdna.nucleic.Nucleic.flip(fliplist=[], deg=180, frame=-1)

Flips the nucleobases of the DNA structure. The method updates the traj attribute of the DNA object.

Parameters:

Name Type Description Default
fliplist list

A list of base pairs to flip. Defaults to an empty list.

[]
deg int

The degrees to flip. Defaults to 180.

180
frame int

The frame to flip. Defaults to -1.

-1

Raises:

Type Description
ValueError

If no fliplist is provided.

Notes
  • Rotating the nucleobase by 180 degrees corresponds to the Hoogsteen base pair configuration.
Example

Flip DNA

dna = mdna.make('GCAAAGC)
dna.flip(fliplist=[3,4], deg=180)

Source code in mdna/nucleic.py
def flip(self, fliplist: list = [], deg: int = 180, frame: int = -1):
        """Flips the nucleobases of the DNA structure.
        The method updates the `traj` attribute of the DNA object.


        Args:
            fliplist (list): A list of base pairs to flip. Defaults to an empty list.
            deg (int): The degrees to flip. Defaults to 180.
            frame (int): The frame to flip. Defaults to -1.

        Raises:
            ValueError: If no fliplist is provided.

        Notes:
            - Rotating the nucleobase by 180 degrees corresponds to the Hoogsteen base pair configuration.

        Example:
            Flip DNA
            ```python
            dna = mdna.make('GCAAAGC)
            dna.flip(fliplist=[3,4], deg=180)
            ```

        """

        if self.traj is None:
            self._frames_to_traj()
        if len(fliplist) == 0:
            raise ValueError('Provide a fliplist')

        flipper = Hoogsteen(self.traj, fliplist=fliplist, deg=deg, verbose=True)
        self.traj = flipper.get_traj()

Analyse Modules

Rigid Base Parameters

mdna.nucleic.compute_rigid_parameters(traj, chainids=[0, 1])

Compute the rigid base parameters of the DNA structure.

Parameters:

Name Type Description Default
traj object

MDtraj trajectory containing the DNA structure.

required
chainids list

List of chain IDs of the DNA structure. Default is [0, 1].

[0, 1]

Returns:

Name Type Description
NucleicFrames object

Object representing the rigid base parameters of the DNA structure.

Raises:

Type Description
ValueError

If the traj argument is not provided.

Notes
  • The returned NucleicFrames object contains information about the rigid base parameters of the DNA structure, such as the positions and orientations of the base steps.
Example

Compute the rigid base parameters of a DNA structure ```python traj = md.load('dna.pdb') rigid_params = mdna.compute_rigid_parameters(traj, chainids=[0, 1]) ````

Source code in mdna/nucleic.py
def compute_rigid_parameters(traj, chainids=[0,1]):
    """Compute the rigid base parameters of the DNA structure.

    Args:
        traj (object): MDtraj trajectory containing the DNA structure.
        chainids (list, optional): List of chain IDs of the DNA structure. Default is [0, 1].

    Returns:
        NucleicFrames (object): Object representing the rigid base parameters of the DNA structure.

    Raises:
        ValueError: If the traj argument is not provided.

    Notes:
        - The returned NucleicFrames object contains information about the rigid base parameters of the DNA structure, such as the positions and orientations of the base steps.

    Example:
        Compute the rigid base parameters of a DNA structure
        ```python
        traj = md.load('dna.pdb')
        rigid_params = mdna.compute_rigid_parameters(traj, chainids=[0, 1])
        ````
    """
    if traj is None:
        raise ValueError("The traj argument must be provided.")
    return NucleicFrames(traj, chainids)

Linking Number

mdna.nucleic.compute_linking_number(traj, chainids=[0, 1])

Compute the linking number of the DNA structure

Source code in mdna/nucleic.py
def compute_linking_number(traj, chainids=[0,1]):
    """Compute the linking number of the DNA structure"""
    raise NotImplementedError