1 2
import os as os
2

3 2
import parmed as pmd
4 2
from paprika import utils
5 2
from parmed.structure import Structure as ParmedStructureClass
6

7

8 2
def add_dummy(
9
    structure,
10
    atom_name="DUM",
11
    residue_name="DUM",
12
    mass=208.00,
13
    atomic_number=82,
14
    x=0.000,
15
    y=0.000,
16
    z=0.000,
17
):
18
    """Add a dummy atom at the specified coordinates to the end of a structure.
19

20
    Parameters:
21
    ----------
22
    structure : str or pmd.Structure
23
        The structure to be modified
24
    atom_name : {str}, optional
25
        The name of the dummy atom (the default is 'DUM')
26
    residue_name : {str}, optional
27
        The residue name of the dummy atom (the default is 'DUM')
28
    mass : {float}, optional
29
        The mass of the dummy atom (the default is 208.00)
30
    atomic_number : {int}, optional
31
        The element of the dummy atom (the default is 82)
32
    x : {float}, optional
33
        The x coordinate of the dummy atom (the default is 0.000)
34
    y : {float}, optional
35
        The y coordinate of the dummy atom (the default is 0.000)
36
    z : {float}, optional
37
        The z coordinate of the dummy atom (the default is 0.000)
38
    mol2 : bool
39
        Whether to write a `mol2` file for the dummy atom
40
    frcmod : bool
41
        Whether to write a `frcmod` file for the dummy atom
42

43
    Returns:
44
    -------
45
    structure : pmd.Structure
46
        The modified structure
47
    """
48

49 2
    if isinstance(structure, str):
50 0
        structure = utils.return_parmed_structure(structure)
51 2
    elif isinstance(structure, ParmedStructureClass):
52 2
        pass
53
    else:
54 0
        raise Exception(
55
            "add_dummy does not support the type associated with structure: "
56
            + type(structure)
57
        )
58

59
    # Create an atom object
60 2
    dum = pmd.topologyobjects.Atom()
61 2
    dum.name = atom_name
62 2
    dum.mass = mass
63 2
    dum.atomic_number = atomic_number
64
    # This may be a problem if these coordinates are outside the periodic box
65
    # dimensions and ParmEd does not recalculate the box vectors before saving
66
    # `inpcrd`...
67 2
    dum.xx = x
68 2
    dum.xy = y
69 2
    dum.xz = z
70

71
    # Assume that the last atom in the structure has the highest atom index,
72
    # so the new atom will be at the end.
73 2
    dum.number = structure.atoms[-1].number + 1
74
    # Assume that the last residue in the structure has the highest residue
75
    # number, so the new atom will be at the end.
76 2
    residue_num = structure.residues[-1].number + 1
77

78 2
    structure.add_atom(dum, residue_name, residue_num)
79

80
    # Make sure that atom.number get set properly.  When reading in prmtop/inpcrd
81
    # parmed doesn't seem to set atom.number for some reason.
82 2
    for i, atom in enumerate(structure.atoms):
83 2
        atom.number = structure.atoms[i].idx + 1
84

85
    # tleap will probably want TER cards in any PDBs we make, so enforce
86
    # that for both the dummy residue and the residue before it
87 2
    structure.residues[-2].ter = True
88 2
    structure.residues[-1].ter = True
89

90 2
    return structure
91

92

93 2
def write_dummy_frcmod(
94
    atom_type="Du", mass="208.00", path="./", filename="dummy.frcmod", filepath=None
95
):
96
    """Write a `frcmod` file for dummy atoms.
97

98
    Parameters:
99
    ----------
100
    atom_type : {str}, optional
101
        The atom type of the dummy atom (the default is 'Du')
102
    mass : {str}, optional
103
        The mass of the dummy atom (the default is '208.00')
104
    path : {str}, optional
105
        The directory of the output file, if `filepath` is not specified (the default is './')
106
    filename : {str}, optional
107
        The name of the output file, if `filepath` is not specified (the default is 'dummy.frcmod')
108
    filepath : {str}, optional
109
        The full path (directory and file) of the output (the default is None, which means `path` and
110
        `filename` will be used)
111

112
    """
113

114 2
    if filepath is None:
115 2
        filepath = os.path.join(path, filename)
116

117 2
    with open(filepath, "w") as f:
118 2
        f.write(
119
            """\
120
Parameters for dummy atom with type {0}
121
MASS
122
{0}     {1}
123

124
BOND
125

126
ANGLE
127

128
DIHE
129

130
IMPROPER
131

132
NONBON
133
  {0}       0.000     0.0000000
134
""".format(
135
                atom_type, mass
136
            )
137
        )
138

139

140 2
def write_dummy_mol2(
141
    atom_name="DUM",
142
    atom_type="Du",
143
    residue_name="DUM",
144
    path="./",
145
    filename="dummy.mol2",
146
    filepath=None,
147
):
148
    """Write a `mol2` file for dummy atoms.
149

150
    Parameters:
151
    ----------
152
    atom_name : {str}, optional
153
        The atom name of the dummy atoms (the default is 'DUM')
154
    atom_type : {str}, optional
155
        The atom type of the dummy atoms (the default is 'Du')
156
    residue_name : {str}, optional
157
        The residue name of the dummy atoms (the default is 'DUM')
158
    path : {str}, optional
159
        The directory of the output file, if `filepath` is not specified (the default is './')
160
    filename : {str}, optional
161
        The name of the output file, if `filepath` is not specified (the default is 'dummy.mol2')
162
    filepath : {str}, optional
163
        The full path (directory and file) of the output (the default is None, which means
164
        `path` and `filename` will be used)
165

166
    """
167

168 2
    if filepath is None:
169 2
        filepath = os.path.join(path, filename)
170

171 2
    with open(filepath, "w") as f:
172 2
        f.write(
173
            """\
174
@<TRIPOS>MOLECULE
175
{0}
176
    1     0     1     0     1
177
SMALL
178
USER_CHARGES
179

180
@<TRIPOS>ATOM
181
  1 {1:4s}    0.000000    0.000000    0.000000 {2}    1 {0}     0.0000 ****
182
@<TRIPOS>BOND
183
@<TRIPOS>SUBSTRUCTURE
184
      1  {0}              1 ****               0 ****  ****    0 ROOT
185
""".format(
186
                residue_name[0:3], atom_name, atom_type[0:2]
187
            )
188
        )
189

190

191 2
def extract_dummy_atoms(structure, resname=None, serial=True):
192
    """
193
    Extract information about dummy atoms from a parmed structure and
194
    returns the information as a dictionary.
195

196
    Parameters
197
    ----------
198
    structure : :class:`parmed.structure.Structure`
199
        The parmed structure object we want to extract from
200
    resname : list
201
        List of residue name for the dummy atoms (default: ["DM1", "DM2", "DM3"])
202
    serial : bool
203
        get indices in serial (starts from 1) or index (starts from 0)
204

205
    Returns
206
    -------
207
    dummy_atoms : dict
208

209
    Output example
210
    --------------
211

212
        main keys: {'DM1', 'DM2', 'DM3'}
213
        sub keys: 'pos'      - cartesian coordinates (x,y,z)
214
                  'idx'      - atom indices
215
                  'idx_type' - type of atom index (serial or index)
216
                  'mass'     - mass of dummy atom
217
    """
218

219 2
    if resname is None:
220 2
        resname = ["DM1", "DM2", "DM3"]
221

222 2
    dummy_atoms = {name: {} for name in resname}
223

224 2
    for dummy_atom in resname:
225 2
        residue = f":{dummy_atom}"
226 2
        dummy_atoms[dummy_atom]["pos"] = structure[residue].coordinates[0]
227 2
        dummy_atoms[dummy_atom]["mass"] = [atom.mass for atom in structure[residue].atoms][0]
228 2
        dummy_atoms[dummy_atom]["idx"] = utils.index_from_mask(structure, residue, amber_index=serial)[0]
229 2
        dummy_atoms[dummy_atom]["idx_type"] = "serial" if serial else "index"
230

231 2
    return dummy_atoms

Read our documentation on viewing source code .

Loading