Skip to content

Commit 7159723

Browse files
author
maksimovdmitrii
committed
Implementation of Centroid degree of freedom. Centeroid of the molecule is determined by some point in space.
Issues: creation of the molecule is sensitive to the order of applying of degrees of freedom. Need to add more comments for creation of new DOF object for future generetions.
1 parent 76c485e commit 7159723

7 files changed

Lines changed: 156 additions & 118 deletions

File tree

examples/ga.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
from fafoom import MoleculeDescription, Structure, selection, print_output,\
66
remover_dir, set_default, file2dict
77
import fafoom.run_utilities as run_util
8-
from utilities import atoms_positions, centreofthebox
98
from visual import draw_picture
109

1110

1211
from rdkit import Chem
1312
from rdkit.Chem import AllChem
1413

14+
from measure import centroid_measure
15+
from utilities import sdf2xyz
16+
1517
# Decide for restart or a simple run.
1618
opt = run_util.simple_or_restart()
1719
p_file = sys.argv[1]
@@ -31,7 +33,6 @@
3133
min_energy = []
3234

3335

34-
3536
#***********************************************************************
3637
"""
3738
Creation of the folders for valid and invalid structures.
@@ -72,6 +73,7 @@
7273
print_output("New trial")
7374
str3d = Structure(mol)
7475
str3d.generate_structure()
76+
print '\n{}'.format(sdf2xyz(str3d.sdf_string))
7577
aims_object = AimsObject(os.path.join(os.getcwd(),'adds')) #Need for creation of the input file. Does not affect the algoritm.
7678
if not str3d.is_geometry_valid():
7779
print_output("The geometry of "+str(str3d)+" is invalid. Copied to /invalid")
@@ -85,16 +87,6 @@
8587
os.mkdir(os.path.join(os.getcwd(),'valid',str(cnt)+'_geometry')) # creates the folder for particular structure inside th "valid" folder
8688
shutil.copy('geometry.in',os.path.join(os.getcwd(), 'valid', str(cnt)+'_geometry','geometry.in')) # copy input to self-titled folder
8789
############ draw_picture(os.path.join(os.getcwd(), 'valid', str(cnt)+'_geometry','geometry.in'), image_write = 'yes') # Part of post-processing module. Under construction. Produce nice image with PyMol
88-
89-
print str3d.sdf_string
90-
#~ print str3d
91-
# print atoms_positions(str3d.sdf_string)
92-
# print centreofthebox(atoms_positions(str3d.sdf_string))
93-
# print atoms_shift(atoms_positions(str3d.sdf_string), centreofthebox(atoms_positions(str3d.sdf_string)))
94-
# print centreofthebox(atoms_shift(atoms_positions(str3d.sdf_string), centreofthebox(atoms_positions(str3d.sdf_string))))
95-
new = apply_coord_translation(str3d.sdf_string, atoms_shift(atoms_positions(str3d.sdf_string), centreofthebox(atoms_positions(str3d.sdf_string))))
96-
str3d.sdf_string = new
97-
print str3d.sdf_string
9890
name = "initial_%d" % (len(population))
9991
# Perform the local optimization
10092
run_util.optimize(str3d, energy_function, params, name)

examples/parameters_aims.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
[Molecule]
22

33
smiles="CC(=O)N[C@H](C(=O)NC)C"
4-
optimize_torsion=True
54
optimize_cistrans=True
5+
optimize_torsion=True
66
smarts_torsion= "[*]~[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]~[*]"
77
smarts_cistrans= "C~[$(C=O)]-[$(NC)]~[C]"
88
filter_smarts_torsion= "C~[$(C=O)]-[$(NC)]~[C]"
99
rmsd_type="cartesian"
1010
rmsd_cutoff_uniq=0.25
1111
chiral=True
12-
12+
optimize_centroid=True
1313
[GA settings]
1414

1515
energy_var=0.001

fafoom/deg_of_freedom.py

Lines changed: 114 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,19 @@
2626
dihedral_measure,
2727
dihedral_set,
2828
pyranosering_measure,
29-
pyranosering_set
29+
pyranosering_set,
30+
centroid_measure,
31+
centroid_set
3032
)
3133

3234
from genetic_operations import mutation
3335

36+
from rdkit import Chem
37+
from rdkit.Chem import AllChem
38+
39+
from operator import itemgetter
40+
from rdkit.Chem import rdMolTransforms
41+
from utilities import *
3442

3543
class DOF:
3644

@@ -40,6 +48,77 @@ def __init__(self, name):
4048
def common_function():
4149
pass
4250

51+
class Centroid(DOF):
52+
'''Find and handle centre of the molecule. '''
53+
values_options = range(-10, 10, 1)
54+
@staticmethod
55+
def find(smiles, positions=None):
56+
if positions is None:
57+
mol = Chem.MolFromSmiles(smiles)
58+
if mol is None:
59+
raise ValueError("The smiles is invalid")
60+
pattern_cent = Chem.MolFromSmarts(smiles)
61+
cent = list(mol.GetSubstructMatches(pattern_cent))
62+
positions = cleaner(cent)
63+
return positions
64+
65+
def __init__(self, positions):
66+
"""Initialaize the Centroid object from the positions."""
67+
self.name = 'Centroid'
68+
self.type = "centroid"
69+
self.positions = positions
70+
71+
def apply_on_string(self, string, values_to_set=None):
72+
if values_to_set is not None:
73+
self.values = values_to_set
74+
string = centroid_set(string, self.values)
75+
return string
76+
77+
def get_random_values(self):
78+
"""Generate a random value for position of the Centroid object"""
79+
self.values = [choice(Centroid.values_options) for i in range(3)]
80+
81+
def get_weighted_values(self, weights):
82+
if len(weights) == len(Centroid.values_options):
83+
self.values = [Centroid.values_options[find_one_in_list(sum(
84+
weights), weights)]
85+
for i in range(len(self.positions))]
86+
else:
87+
self.values = [choice(Centroid.values_options)
88+
for i in range(len(self.positions))]
89+
90+
def mutate_values(self, max_mutations=None, weights=None):
91+
92+
if max_mutations is None:
93+
max_mutations = max(1, int(math.ceil(len(self.values)/2.0)))
94+
95+
self.values = mutation(self.values, max_mutations,
96+
Centroid.values_options, weights, periodic=False)
97+
98+
def update_values(self, string):
99+
self.values = centroid_measure(string)
100+
101+
def is_equal(self, other, threshold, chiral=False):
102+
values = []
103+
tmp = []
104+
for i in get_vec(self.values, other.values):
105+
if i == 0:
106+
tmp.append(0)
107+
else:
108+
tmp.append(1)
109+
values.append(sum(tmp)/len(tmp))
110+
if hasattr(other, "initial_values"):
111+
tmp = []
112+
for i in get_vec(self.values, other.initial_values):
113+
if i == 0:
114+
tmp.append(0)
115+
else:
116+
tmp.append(1)
117+
values.append(sum(tmp)/len(tmp))
118+
if min(values) > threshold:
119+
return False
120+
else:
121+
return True
43122

44123
class Torsion(DOF):
45124
""" Find, create and handle rotatable bonds"""
@@ -93,6 +172,7 @@ def find(smiles, smarts_torsion="[*]~[!$(*#*)&!D1]-&!@[!$(*#*)&!D1]~[*]",
93172

94173
def __init__(self, positions):
95174
"""Initialaize the Torsion object from the positions."""
175+
self.name = 'Torsion'
96176
self.type = "torsion"
97177
self.positions = positions
98178

@@ -283,6 +363,7 @@ def find(smiles, pyranosering_pattern="C1(CCCCO1)O", positions=None):
283363
return positions
284364

285365
def __init__(self, positions):
366+
self.name = 'PyranoseRing'
286367
self.type = "pyranosering"
287368
self.positions = positions
288369

@@ -361,9 +442,10 @@ def find(smiles, smarts_cistrans=None, positions=None):
361442
pattern_cistrans = Chem.MolFromSmarts(smarts_cistrans)
362443
cistrans = list(mol.GetSubstructMatches(pattern_cistrans))
363444
positions = cleaner(cistrans)
364-
return positions
445+
return positions
365446

366447
def __init__(self, positions):
448+
self.name = 'CisTrans'
367449
self.type = "cistrans"
368450
self.positions = positions
369451

@@ -421,3 +503,33 @@ def is_equal(self, other, threshold, chiral=True):
421503
return False
422504
else:
423505
return True
506+
#=======================================================================
507+
#~ '''
508+
#~ For test of the module only
509+
#~ '''
510+
511+
#~ smiles = 'CC(=O)N[C@H](C(=O)NC)C'
512+
#~ obj = Centroid(smiles)
513+
#~ mol = Chem.MolFromSmiles(obj.positions)
514+
#~ AllChem.EmbedMolecule(mol)
515+
#~ string = Chem.MolToMolBlock(mol)
516+
517+
#~ print 'Initial coordinates:'
518+
#~ print sdf2xyz(string)
519+
#~ print 'Initial centroid:'
520+
#~ print centroid_measure(string)
521+
#~ obj.get_random_values()
522+
#~ print 'Centroid will be set to:'
523+
#~ print obj.values
524+
#~ string = obj.apply_on_string(string, obj.values)
525+
#~ print 'Final coordinates:'
526+
#~ print sdf2xyz(string)
527+
#~ print 'Final centroid:'
528+
#~ print centroid_measure(string)
529+
#***********************************************************************
530+
531+
532+
533+
534+
535+

fafoom/get_parameters.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
from __future__ import division
1919
from rdkit import Chem
2020
from rdkit.Chem import AllChem
21-
from deg_of_freedom import Torsion, CisTrans, PyranoseRing
21+
from deg_of_freedom import Torsion, CisTrans, PyranoseRing, Centroid
2222
from utilities import check_geo_sdf
2323

2424

@@ -84,6 +84,13 @@ def get_positions(type_of_deg, smiles, **kwargs):
8484
else:
8585
return PyranoseRing.find(smiles)
8686

87+
if type_of_deg == "centroid":
88+
if 'list_of_centroid' in kwargs:
89+
return Centroid.find(smiles,
90+
positions=kwargs['list_of_centroid'])
91+
else:
92+
return Centroid.find(smiles)
93+
8794

8895
def create_dof_object(type_of_deg, positions):
8996
"""Initialize the degree of freedom from the positions
@@ -100,6 +107,8 @@ def create_dof_object(type_of_deg, positions):
100107
return CisTrans(positions)
101108
if type_of_deg == "pyranosering":
102109
return PyranoseRing(positions)
110+
if type_of_deg == "centroid":
111+
return Centroid(positions)
103112

104113
#~ , distance_cutoff_1, distance_cutoff_2
105114
def template_sdf(smiles):

fafoom/measure.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,33 @@
2222
from rdkit import Chem
2323
from rdkit.Chem import rdMolTransforms
2424

25-
from utilities import get_vec, tor_rmsd, xyz2sdf
25+
from utilities import get_vec, tor_rmsd, xyz2sdf, sdf2xyz
2626

2727

2828
def ig(x):
2929
return itemgetter(x)
3030

31+
def centroid_measure(sdf_string):
32+
mol = Chem.MolFromMolBlock(sdf_string, removeHs=False)
33+
pos = mol.GetConformer()
34+
centroid = rdMolTransforms.ComputeCentroid(pos, ignoreHs=True)
35+
return [centroid.x, centroid.y, centroid.z]
3136

37+
def centroid_set(sdf_string, values_to_set):
38+
atoms_list = []
39+
mol = Chem.MolFromMolBlock(sdf_string, removeHs=False)
40+
for i in range(0, mol.GetNumAtoms()):
41+
pos = mol.GetConformer().GetAtomPosition(i)
42+
atoms_list.append([pos.x, pos.y, pos.z])
43+
new_coordinates = []
44+
shift = [values_to_set[0] - centroid_measure(sdf_string)[0], values_to_set[1] - centroid_measure(sdf_string)[1], values_to_set[2] - centroid_measure(sdf_string)[2]]
45+
for i in range(len(atoms_list)):
46+
new_coordinates.append([atoms_list[i][0] + shift[0], atoms_list[i][1] + shift[1], atoms_list[i][2] + shift[2]])
47+
for i in range(0, mol.GetNumAtoms()):
48+
mol.GetConformer().SetAtomPosition(i, new_coordinates[i])
49+
sdf_string = Chem.MolToMolBlock(mol)
50+
return sdf_string
51+
3252
def dihedral_measure(sdf_string, position):
3353
""" Measure the dihedral angle.
3454

fafoom/structure.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ def __init__(self, parameter_file=None, **kwargs):
5858
new_names_dict = {'smile': 'smiles',
5959
'smart_torsion': 'smarts_torsion',
6060
'filter_smart_torsion': 'filter_smarts_torsion',
61-
'smart_cistrans': 'smarts_cistrans'}
61+
'smart_cistrans': 'smarts_cistrans',
62+
'centroid': 'centroids'}
6263
for key in new_names_dict:
6364
try:
6465
params[new_names_dict[key]] = params.pop(key)
@@ -269,11 +270,12 @@ def generate_structure(self, values={}):
269270
dof.get_weighted_values(weights)
270271
else:
271272
dof.get_random_values()
273+
print 'Initial values for {} are {}'.format(dof.name ,dof.values)
272274
new_string = dof.apply_on_string(new_string)
273275
self.sdf_string = new_string
274276
for dof in self.dof:
275277
dof.update_values(self.sdf_string)
276-
278+
print 'Updated values for {} are {}'.format(dof.name, dof.values)
277279
def is_geometry_valid(self):
278280
"""Return True if the geometry is valid."""
279281
#~ , self.mol_info.distance_cutoff_1, self.mol_info.distance_cutoff_2

0 commit comments

Comments
 (0)