dockonsurf / modules / isolated.py @ cf980c86
Historique | Voir | Annoter | Télécharger (7,96 ko)
1 | 4614bb6a | Carles | """Functions to generate the conformers to be adsorbed and the most stable one.
|
---|---|---|---|
2 | 4614bb6a | Carles |
|
3 | 5c70d6c6 | Carles | functions:
|
4 | 5c70d6c6 | Carles | remove_C_linked_Hs: Removes hydrogens bonded to a carbon atom from a molecule.
|
5 | 92924d24 | Carles | gen_confs: Generate a number of conformers in random orientations.
|
6 | 92924d24 | Carles | get_moments_of_inertia: Computes moments of inertia of the given conformers.
|
7 | 4e82c425 | Carles Martí | get_moments_of_inertia: Computes the moments of inertia of the given conformers.
|
8 | 4e82c425 | Carles Martí | pre_opt_confs: Optimizes the geometry of the given conformers and returns the
|
9 | 92924d24 | Carles | new mol object and the energies of its conformers.
|
10 | 4614bb6a | Carles | run_isolated: directs the execution of functions to achieve the goal
|
11 | 4614bb6a | Carles | """
|
12 | 4614bb6a | Carles | import logging |
13 | 4614bb6a | Carles | |
14 | 92924d24 | Carles | import numpy as np |
15 | fff3aab1 | Carles | import rdkit.Chem.AllChem as Chem |
16 | 92924d24 | Carles | |
17 | 4614bb6a | Carles | logger = logging.getLogger('DockOnSurf')
|
18 | 4614bb6a | Carles | |
19 | 4614bb6a | Carles | |
20 | 92924d24 | Carles | def remove_C_linked_Hs(mol: Chem.rdchem.Mol): |
21 | b1f6e69d | Carles | """Removes hydrogen atoms bonded to a carbon atom from a rdkit mol object.
|
22 | 5c70d6c6 | Carles |
|
23 | 92924d24 | Carles | @param mol: rdkit mol object of the molecule with hydrogen atoms.
|
24 | 92924d24 | Carles | @return: rdkit mol object of the molecule without hydrogen atoms linked to
|
25 | 92924d24 | Carles | a carbon atom.
|
26 | 92924d24 | Carles |
|
27 | 92924d24 | Carles | The functions removes the hydrogen atoms bonded to carbon atoms while
|
28 | 92924d24 | Carles | keeping the ones bonded to other atoms or non-bonded at all.
|
29 | 5c70d6c6 | Carles | """
|
30 | 5c70d6c6 | Carles | |
31 | 5c70d6c6 | Carles | mol = Chem.RWMol(mol) |
32 | 5c70d6c6 | Carles | rev_atm_idxs = [atom.GetIdx() for atom in reversed(mol.GetAtoms())] |
33 | 5c70d6c6 | Carles | |
34 | 5c70d6c6 | Carles | for atm_idx in rev_atm_idxs: |
35 | 5c70d6c6 | Carles | atom = mol.GetAtomWithIdx(atm_idx) |
36 | 5c70d6c6 | Carles | if atom.GetAtomicNum() != 1: |
37 | 5c70d6c6 | Carles | continue
|
38 | 5c70d6c6 | Carles | for neigh in atom.GetNeighbors(): |
39 | 5c70d6c6 | Carles | if neigh.GetAtomicNum() == 6: |
40 | 5c70d6c6 | Carles | mol.RemoveAtom(atom.GetIdx()) |
41 | 5c70d6c6 | Carles | return mol
|
42 | 5c70d6c6 | Carles | |
43 | 5c70d6c6 | Carles | |
44 | 3a46e515 | Carles Marti | def gen_confs(mol: Chem.rdchem.Mol, num_confs: int): |
45 | 92924d24 | Carles | """Generate conformers in random orientations.
|
46 | 4614bb6a | Carles |
|
47 | 4614bb6a | Carles | @param mol: rdkit mol object of the molecule to be adsorbed.
|
48 | 92924d24 | Carles | @param num_confs: number of conformers to randomly generate.
|
49 | 4614bb6a | Carles | @return: mol: rdkit mol object containing the different conformers.
|
50 | bd573212 | Carles | rmsd_mtx: Matrix with the rmsd values of conformers.
|
51 | b1f6e69d | Carles |
|
52 | 92924d24 | Carles | Using the rdkit library, conformers are randomly generated. If structures
|
53 | 92924d24 | Carles | are required to be local minima, ie. setting the 'local_min' value to
|
54 | 92924d24 | Carles | True, a geometry optimisation using UFF is performed.
|
55 | 4614bb6a | Carles | """
|
56 | 695dcff8 | Carles Marti | logger.debug('Generating Conformers.')
|
57 | 9e83b5a1 | Carles | |
58 | 9324a38a | Carles | mol = Chem.AddHs(mol) |
59 | 9062afa6 | Carles Marti | Chem.EmbedMultipleConfs(mol, numConfs=num_confs, numThreads=0,
|
60 | 9062afa6 | Carles Marti | randomSeed=5817216)
|
61 | 5c70d6c6 | Carles | Chem.AlignMolConformers(mol) |
62 | 695dcff8 | Carles Marti | logger.info(f'Generated {len(mol.GetConformers())} conformers.')
|
63 | 92924d24 | Carles | return mol
|
64 | 92924d24 | Carles | |
65 | 62576f52 | Carles | |
66 | 58ede1f9 | Carles Martí | def get_moments_of_inertia(mol: Chem.rdchem.Mol): |
67 | 4e82c425 | Carles Martí | """Computes the moments of inertia of the given conformers.
|
68 | 92924d24 | Carles |
|
69 | 92924d24 | Carles | @param mol: rdkit mol object of the relevant molecule.
|
70 | 92924d24 | Carles | @return numpy array 2D: The inner array contains the moments of inertia for
|
71 | 92924d24 | Carles | the three principal axis of a given conformer. They are ordered by its value
|
72 | 92924d24 | Carles | in ascending order. The outer tuple loops over the conformers.
|
73 | 92924d24 | Carles | """
|
74 | 92924d24 | Carles | from rdkit.Chem.Descriptors3D import PMI1, PMI2, PMI3 |
75 | 92924d24 | Carles | |
76 | 92924d24 | Carles | return np.array([[PMI(mol, confId=conf) for PMI in (PMI1, PMI2, PMI3)] |
77 | 92924d24 | Carles | for conf in range(mol.GetNumConformers())]) |
78 | 92924d24 | Carles | |
79 | 92924d24 | Carles | |
80 | 365d5b9a | Carles Marti | def pre_opt_confs(mol: Chem.rdchem.Mol, force_field='mmff', max_iters=2000): |
81 | 92924d24 | Carles | """Optimizes the geometry of the given conformers and returns the new mol
|
82 | 92924d24 | Carles | object and the energies of its conformers.
|
83 | 92924d24 | Carles |
|
84 | 92924d24 | Carles | @param mol: rdkit mol object of the relevant molecule.
|
85 | ad57fd42 | Carles Marti | @param force_field: Force Field to use for the pre-optimization.
|
86 | 62576f52 | Carles | @param max_iters: Maximum number of geometry optimization iterations. With 0
|
87 | 62576f52 | Carles | a single point energy calculation is performed and only the conformer
|
88 | 62576f52 | Carles | energies are returned.
|
89 | 92924d24 | Carles | @return mol: rdkit mol object of the optimized molecule.
|
90 | 92924d24 | Carles | @return numpy.ndarray: Array with the energies of the optimized conformers.
|
91 | 92924d24 | Carles |
|
92 | ad57fd42 | Carles Marti | The MMFF and UFF force fields can be used for the geometry optimization in
|
93 | 4670488d | Carles Marti | their rdkit implementation. With max_iters value set to 0, a single point
|
94 | 4670488d | Carles Marti | energy calculation is performed and only the energies are returned. For
|
95 | 4670488d | Carles Marti | values larger than 0, if the geometry does not converge for a certain
|
96 | 4670488d | Carles Marti | conformer, the latter is removed from the list of conformers and its energy
|
97 | 4670488d | Carles Marti | is not included in the returned list.
|
98 | 92924d24 | Carles | """
|
99 | 4670488d | Carles Marti | from rdkit.Chem.rdForceFieldHelpers import MMFFOptimizeMoleculeConfs, \ |
100 | 4670488d | Carles Marti | UFFOptimizeMoleculeConfs
|
101 | 92924d24 | Carles | |
102 | 92924d24 | Carles | init_num_confs = mol.GetNumConformers() |
103 | ad57fd42 | Carles Marti | if force_field == 'mmff': |
104 | 4670488d | Carles Marti | results = np.array(MMFFOptimizeMoleculeConfs(mol, numThreads=0,
|
105 | 4670488d | Carles Marti | maxIters=max_iters, |
106 | 4670488d | Carles Marti | nonBondedThresh=10))
|
107 | ad57fd42 | Carles Marti | elif force_field == 'uff': |
108 | 4670488d | Carles Marti | results = np.array(UFFOptimizeMoleculeConfs(mol, numThreads=0,
|
109 | 4670488d | Carles Marti | maxIters=max_iters, |
110 | 4670488d | Carles Marti | vdwThresh=10))
|
111 | 4670488d | Carles Marti | else:
|
112 | 4670488d | Carles Marti | logger.error("force_field parameter must be 'MMFF' or 'UFF'")
|
113 | 4670488d | Carles Marti | raise ValueError("force_field parameter must be 'MMFF' or 'UFF'") |
114 | 62576f52 | Carles | |
115 | 62576f52 | Carles | # Remove non-converged conformers if optimization is on, ie. maxIters > 0
|
116 | 62576f52 | Carles | # return all conformers if optimization is switched off, ie. maxIters = 0
|
117 | 62576f52 | Carles | if max_iters > 0: |
118 | 62576f52 | Carles | for i, conv in enumerate(results[:, 0]): |
119 | 62576f52 | Carles | if conv != 0: |
120 | 62576f52 | Carles | mol.RemoveConformer(i) |
121 | 62576f52 | Carles | for i, conf in enumerate(mol.GetConformers()): |
122 | 62576f52 | Carles | conf.SetId(i) |
123 | 62576f52 | Carles | if mol.GetNumConformers() < init_num_confs:
|
124 | ad57fd42 | Carles Marti | logger.warning(f'Geometry optimization did not comverge for at'
|
125 | 62576f52 | Carles | f'least one conformer. Continuing with '
|
126 | 695dcff8 | Carles Marti | f'{mol.GetNumConformers()} converged conformers.')
|
127 | ad57fd42 | Carles Marti | logger.info(f'Pre-optimized conformers with {force_field}.')
|
128 | 62576f52 | Carles | return mol, np.array([res[1] for res in results if res[0] == 0]) |
129 | 62576f52 | Carles | else:
|
130 | ad57fd42 | Carles Marti | logger.info(f'Computed conformers energy with {force_field}.')
|
131 | 62576f52 | Carles | return np.array([res[1] for res in results]) |
132 | 4614bb6a | Carles | |
133 | 4614bb6a | Carles | |
134 | 4614bb6a | Carles | def run_isolated(inp_vars): |
135 | 4614bb6a | Carles | """Directs the execution of functions to obtain the conformers to adsorb
|
136 | 4614bb6a | Carles |
|
137 | a9b058a5 | Carles | @param inp_vars: Calculation parameters from input file.
|
138 | 4614bb6a | Carles | @return:
|
139 | 4614bb6a | Carles | """
|
140 | f3004731 | Carles | from modules.formats import adapt_format, confs_to_mol_list, \ |
141 | 1d8c374e | Carles Martí | rdkit_mol_to_ase_atoms, collect_confs |
142 | fff3aab1 | Carles | from modules.clustering import clustering, get_rmsd |
143 | 1f778710 | Carles Martí | from modules.calculation import run_calc, check_finished_calcs |
144 | 1f778710 | Carles Martí | from modules.refinement import select_stable_confs |
145 | 54be2a9e | Carles | |
146 | 695dcff8 | Carles Marti | logger.info('Carrying out procedures for the isolated molecule.')
|
147 | 4e82c425 | Carles Martí | # Read the molecule
|
148 | 90819cc3 | Carles Marti | rd_mol = adapt_format('rdkit', inp_vars['molec_file'], |
149 | 90819cc3 | Carles Marti | inp_vars['special_atoms'])
|
150 | 4e82c425 | Carles Martí | # Generate conformers
|
151 | 92924d24 | Carles | confs = gen_confs(rd_mol, inp_vars['num_conformers'])
|
152 | 4e82c425 | Carles Martí | # Pre-optimizes conformers
|
153 | 4670488d | Carles Marti | if inp_vars['pre_opt']: |
154 | 4670488d | Carles Marti | confs, confs_ener = pre_opt_confs(confs, inp_vars['pre_opt'])
|
155 | fab7b517 | Carles | else:
|
156 | 4670488d | Carles Marti | confs_ener = pre_opt_confs(confs, max_iters=0)
|
157 | fff3aab1 | Carles | conf_list = confs_to_mol_list(confs) |
158 | 4e82c425 | Carles Martí | # Calculates RMSD matrix of the conformers
|
159 | fff3aab1 | Carles | rmsd_mtx = get_rmsd(conf_list) |
160 | fab7b517 | Carles | confs_moi = get_moments_of_inertia(confs) |
161 | 4e82c425 | Carles Martí | # Clusters the conformers and selects a representative
|
162 | fd33bfdb | Carles | exemplars = clustering(rmsd_mtx) |
163 | f3004731 | Carles | mol_list = confs_to_mol_list(confs, exemplars) |
164 | f3004731 | Carles | ase_atms_list = [rdkit_mol_to_ase_atoms(mol) for mol in mol_list] |
165 | a44ad3c2 | Carles Martí | if len(ase_atms_list) == 0: |
166 | a44ad3c2 | Carles Martí | err_msg = "No configurations were generated: Check the parameters in" \
|
167 | a44ad3c2 | Carles Martí | "dockonsurf.inp"
|
168 | a44ad3c2 | Carles Martí | logger.error(err_msg) |
169 | a44ad3c2 | Carles Martí | raise ValueError(err_msg) |
170 | 4e82c425 | Carles Martí | # Runs the jobs.
|
171 | f3004731 | Carles | run_calc('isolated', inp_vars, ase_atms_list)
|
172 | 96d422c7 | Carles Martí | logger.info("Finished the procedures for the isolated molecule section. ")
|
173 | 96d422c7 | Carles Martí | if inp_vars["batch_q_sys"]: |
174 | 96d422c7 | Carles Martí | finished_calcs, failed_calcs = check_finished_calcs('isolated',
|
175 | 082685ad | Carles Martí | inp_vars['code'])
|
176 | 96d422c7 | Carles Martí | conf_list = collect_confs(finished_calcs, inp_vars['code'], 'isolated', |
177 | 1d8c374e | Carles Martí | inp_vars['special_atoms'])
|
178 | 96d422c7 | Carles Martí | most_stable_conf = select_stable_confs(conf_list, 0)[0] |
179 | 96d422c7 | Carles Martí | |
180 | 96d422c7 | Carles Martí | logger.info(f"Most stable conformers is {most_stable_conf.info['iso']},"
|
181 | 96d422c7 | Carles Martí | f" with a total energy of {most_stable_conf.info['energy']}"
|
182 | 96d422c7 | Carles Martí | f" eV.") |