CI update -> use miniconda v2
1 | 38 |
import os as os |
2 |
|
|
3 | 38 |
import parmed as pmd |
4 | 38 |
from parmed.structure import Structure as ParmedStructureClass |
5 |
|
|
6 | 38 |
from paprika import utils |
7 |
|
|
8 |
|
|
9 | 38 |
def add_dummy( |
10 |
structure, |
|
11 |
atom_name="DUM", |
|
12 |
residue_name="DUM", |
|
13 |
mass=208.00, |
|
14 |
atomic_number=82, |
|
15 |
x=0.000, |
|
16 |
y=0.000, |
|
17 |
z=0.000, |
|
18 |
):
|
|
19 |
"""Add a dummy atom at the specified coordinates to the end of a structure.
|
|
20 |
|
|
21 |
Parameters
|
|
22 |
----------
|
|
23 |
structure : str or :class:`parmed.Structure`
|
|
24 |
The structure to be modified
|
|
25 |
atom_name : str, optional, default='DUM'
|
|
26 |
The name of the dummy atom.
|
|
27 |
residue_name : str, optional, default='DUM'
|
|
28 |
The residue name of the dummy atom.
|
|
29 |
mass : float, optional, default=208.0
|
|
30 |
The mass of the dummy atom.
|
|
31 |
atomic_number : int, optional, default=82
|
|
32 |
The element of the dummy atom.
|
|
33 |
x : float, optional, default=0.0
|
|
34 |
The x coordinate of the dummy atom.
|
|
35 |
y : float, optional, default=0.0
|
|
36 |
The y coordinate of the dummy atom.
|
|
37 |
z : float, optional, default=0.0
|
|
38 |
The z coordinate of the dummy atom.
|
|
39 |
|
|
40 |
Returns
|
|
41 |
-------
|
|
42 |
structure : :class:`parmed.Structure`
|
|
43 |
The modified structure with dummy atoms added.
|
|
44 |
|
|
45 |
"""
|
|
46 |
|
|
47 | 38 |
if isinstance(structure, str): |
48 |
structure = utils.return_parmed_structure(structure) |
|
49 | 38 |
elif isinstance(structure, ParmedStructureClass): |
50 | 38 |
pass
|
51 |
else: |
|
52 |
raise Exception( |
|
53 |
"add_dummy does not support the type associated with structure: "
|
|
54 |
+ type(structure) |
|
55 |
)
|
|
56 |
|
|
57 |
# Create an atom object
|
|
58 | 38 |
dum = pmd.topologyobjects.Atom() |
59 | 38 |
dum.name = atom_name |
60 | 38 |
dum.mass = mass |
61 | 38 |
dum.atomic_number = atomic_number |
62 |
# This may be a problem if these coordinates are outside the periodic box
|
|
63 |
# dimensions and ParmEd does not recalculate the box vectors before saving
|
|
64 |
# `inpcrd`...
|
|
65 | 38 |
dum.xx = x |
66 | 38 |
dum.xy = y |
67 | 38 |
dum.xz = z |
68 |
|
|
69 |
# Assume that the last atom in the structure has the highest atom index,
|
|
70 |
# so the new atom will be at the end.
|
|
71 | 38 |
dum.number = structure.atoms[-1].number + 1 |
72 |
# Assume that the last residue in the structure has the highest residue
|
|
73 |
# number, so the new atom will be at the end.
|
|
74 | 38 |
residue_num = structure.residues[-1].number + 1 |
75 |
|
|
76 | 38 |
structure.add_atom(dum, residue_name, residue_num) |
77 |
|
|
78 |
# Make sure that atom.number get set properly. When reading in prmtop/inpcrd
|
|
79 |
# parmed doesn't seem to set atom.number for some reason.
|
|
80 | 38 |
for i, atom in enumerate(structure.atoms): |
81 | 38 |
atom.number = structure.atoms[i].idx + 1 |
82 |
|
|
83 |
# tleap will probably want TER cards in any PDBs we make, so enforce
|
|
84 |
# that for both the dummy residue and the residue before it
|
|
85 | 38 |
structure.residues[-2].ter = True |
86 | 38 |
structure.residues[-1].ter = True |
87 |
|
|
88 | 38 |
return structure |
89 |
|
|
90 |
|
|
91 | 38 |
def write_dummy_frcmod( |
92 |
atom_type="Du", mass="208.00", path="./", filename="dummy.frcmod", filepath=None |
|
93 |
):
|
|
94 |
"""Write a ``frcmod`` file for dummy atoms.
|
|
95 |
|
|
96 |
Parameters
|
|
97 |
----------
|
|
98 |
atom_type : str, optional, default='Du'
|
|
99 |
The atom type of the dummy atom.
|
|
100 |
mass : str, optional, default=208.00
|
|
101 |
The mass of the dummy atom.
|
|
102 |
path : str, optional, default='./
|
|
103 |
The directory of the output file, if `filepath` is not specified.
|
|
104 |
filename : str, optional, default='dummy.frcmod`
|
|
105 |
The name of the output file, if `filepath` is not specified.
|
|
106 |
filepath : str, optional, default=None
|
|
107 |
The full path (directory and file) of the output.
|
|
108 |
|
|
109 |
"""
|
|
110 |
|
|
111 | 38 |
if filepath is None: |
112 | 38 |
filepath = os.path.join(path, filename) |
113 |
|
|
114 | 38 |
with open(filepath, "w") as f: |
115 | 38 |
f.write( |
116 |
"""\
|
|
117 |
Parameters for dummy atom with type {0}
|
|
118 |
MASS
|
|
119 |
{0} {1}
|
|
120 |
|
|
121 |
BOND
|
|
122 |
|
|
123 |
ANGLE
|
|
124 |
|
|
125 |
DIHE
|
|
126 |
|
|
127 |
IMPROPER
|
|
128 |
|
|
129 |
NONBON
|
|
130 |
{0} 0.000 0.0000000
|
|
131 |
""".format( |
|
132 |
atom_type, mass |
|
133 |
)
|
|
134 |
)
|
|
135 |
|
|
136 |
|
|
137 | 38 |
def write_dummy_mol2( |
138 |
atom_name="DUM", |
|
139 |
atom_type="Du", |
|
140 |
residue_name="DUM", |
|
141 |
path="./", |
|
142 |
filename="dummy.mol2", |
|
143 |
filepath=None, |
|
144 |
):
|
|
145 |
"""Write a ``mol2`` file for dummy atoms.
|
|
146 |
|
|
147 |
Parameters
|
|
148 |
----------
|
|
149 |
atom_name : str, optional, default='DUM'
|
|
150 |
The atom name of the dummy atoms.
|
|
151 |
atom_type : str, optional, default='Du'
|
|
152 |
The atom type of the dummy atoms.
|
|
153 |
residue_name : str, optional, default='DUM'
|
|
154 |
The residue name of the dummy atoms.
|
|
155 |
path : str, optional, default='./'
|
|
156 |
The directory of the output file, if `filepath` is not specified.
|
|
157 |
filename : str, optional, default='dummy.mol2'
|
|
158 |
The name of the output file, if `filepath` is not specified.
|
|
159 |
filepath : str, optional, default=None
|
|
160 |
The full path (directory and file) of the output.
|
|
161 |
|
|
162 |
"""
|
|
163 |
|
|
164 | 38 |
if filepath is None: |
165 | 38 |
filepath = os.path.join(path, filename) |
166 |
|
|
167 | 38 |
with open(filepath, "w") as f: |
168 | 38 |
f.write( |
169 |
"""\
|
|
170 |
@<TRIPOS>MOLECULE
|
|
171 |
{0}
|
|
172 |
1 0 1 0 1
|
|
173 |
SMALL
|
|
174 |
USER_CHARGES
|
|
175 |
|
|
176 |
@<TRIPOS>ATOM
|
|
177 |
1 {1:4s} 0.000000 0.000000 0.000000 {2} 1 {0} 0.0000 ****
|
|
178 |
@<TRIPOS>BOND
|
|
179 |
@<TRIPOS>SUBSTRUCTURE
|
|
180 |
1 {0} 1 **** 0 **** **** 0 ROOT
|
|
181 |
""".format( |
|
182 |
residue_name[0:3], atom_name, atom_type[0:2] |
|
183 |
)
|
|
184 |
)
|
|
185 |
|
|
186 |
|
|
187 | 38 |
def extract_dummy_atoms(structure, resname=None, serial=True): |
188 |
"""
|
|
189 |
Extract information about dummy atoms from a parmed structure and
|
|
190 |
returns the information as a dictionary.
|
|
191 |
|
|
192 |
Parameters
|
|
193 |
----------
|
|
194 |
structure : :class:`parmed.Structure`
|
|
195 |
The parmed structure object we want to extract from
|
|
196 |
resname : list
|
|
197 |
List of residue name for the dummy atoms (default: ["DM1", "DM2", "DM3"])
|
|
198 |
serial : bool
|
|
199 |
get indices in serial (starts from 1) or index (starts from 0)
|
|
200 |
|
|
201 |
Returns
|
|
202 |
-------
|
|
203 |
dummy_atoms : dict
|
|
204 |
A dictionary containing positions (``pos``), index (``idx``) and mass (``mass``) of dummy atoms.
|
|
205 |
"""
|
|
206 |
|
|
207 | 38 |
if resname is None: |
208 | 38 |
resname = ["DM1", "DM2", "DM3"] |
209 |
|
|
210 | 38 |
dummy_atoms = {name: {} for name in resname} |
211 |
|
|
212 | 38 |
for dummy_atom in resname: |
213 | 38 |
residue = f":{dummy_atom}" |
214 | 38 |
dummy_atoms[dummy_atom]["pos"] = structure[residue].coordinates[0] |
215 | 38 |
dummy_atoms[dummy_atom]["mass"] = [ |
216 |
atom.mass for atom in structure[residue].atoms |
|
217 |
][0] |
|
218 | 38 |
dummy_atoms[dummy_atom]["idx"] = utils.index_from_mask( |
219 |
structure, residue, amber_index=serial |
|
220 |
)[0] |
|
221 | 38 |
dummy_atoms[dummy_atom]["idx_type"] = "serial" if serial else "index" |
222 |
|
|
223 | 38 |
return dummy_atoms |
Read our documentation on viewing source code .