$darkmode
DENOPTIM
RotationalSpaceUtils.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2019 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.utils;
20
21import java.io.BufferedReader;
22import java.io.File;
23import java.io.FileReader;
24import java.io.IOException;
25import java.util.ArrayList;
26import java.util.HashMap;
27import java.util.Map;
28import java.util.logging.Level;
29import java.util.logging.Logger;
30
31import org.openscience.cdk.graph.SpanningTree;
32import org.openscience.cdk.interfaces.IAtom;
33import org.openscience.cdk.interfaces.IAtomContainer;
34import org.openscience.cdk.interfaces.IBond;
35import org.openscience.cdk.interfaces.IChemObjectBuilder;
36import org.openscience.cdk.interfaces.IRingSet;
37import org.openscience.cdk.isomorphism.Mappings;
38import org.openscience.cdk.silent.RingSet;
39import org.openscience.cdk.silent.SilentChemObjectBuilder;
40
41import denoptim.constants.DENOPTIMConstants;
42import denoptim.exception.DENOPTIMException;
43
44
53{
54 private static final IChemObjectBuilder builder =
55 SilentChemObjectBuilder.getInstance();
56
57//------------------------------------------------------------------------------
58
78 public static ArrayList<ObjectPair> defineRotatableBonds(IAtomContainer mol,
79 String defRotBndsFile, boolean addIterfragBonds, boolean excludeRings,
80 Logger logger) throws DENOPTIMException
81 {
82 ArrayList<ObjectPair> rotatableBonds = new ArrayList<ObjectPair>();
83
84 // Set all bond flags
85 for (IBond b : mol.bonds())
86 {
87 b.setProperty(DENOPTIMConstants.BONDPROPROTATABLE,"false");
88 }
89
90 // Deal with inter-fragment bonds
91 if (addIterfragBonds)
92 {
93 rotatableBonds.addAll(getInterVertexBonds(mol));
94 }
95
96 // We'll use SMARTS so get rid of pseudoatoms that can create problems
97 // We'll use this modified IAtomContainer only when dealing with SMARTS
98 IAtomContainer locMol = builder.newAtomContainer();
99 try {
100 locMol = mol.clone();
101 } catch (Throwable t) {
102 throw new DENOPTIMException(t);
103 }
104 MoleculeUtils.removeRCA(locMol);
105
106
107 if (!defRotBndsFile.equals(""))
108 {
109 // Get definition of rotational space as list of SMARTS queries
110 Map<String,String> listQueries = getRotationalSpaceDefinition(
111 defRotBndsFile);
112
113 // Get bonds matching one of the definitions of rotatable bonds
114 ManySMARTSQuery msq = new ManySMARTSQuery(locMol,listQueries);
115 if (msq.hasProblems())
116 {
117 String msg = "WARNING! Attempt to match rotatable bonds returned "
118 + "an error! Selecting only fragment-fragment "
119 + "bonds. Details: " + msq.getMessage();
120 logger.log(Level.WARNING, msg);
121 } else {
122 //Transform list of indeces
123 for (String name : listQueries.keySet())
124 {
125 //Skip if no match
126 if (msq.getNumMatchesOfQuery(name) == 0)
127 {
128 continue;
129 }
130
131 //Put all matches in one list
132 Mappings matches = msq.getMatchesOfSMARTS(name);
133 for (int[] singleMatch : matches)
134 {
135 //Check assumption on number of atoms involved in each bond
136 if (singleMatch.length != 2)
137 {
138 throw new Error("DENOPTIM can only deal with bonds "
139 + "involving 2 atoms. Check bond "
140 + singleMatch);
141 }
142
143 //NOTE the index refers to the IAtomContainer locMol that is a
144 //clone of mol and has the same atom order. Thus we use the
145 //atom idenx to identify atoms in mol rather than locMol.
146
147 int idAtmA = singleMatch[0];
148 int idAtmB = singleMatch[1];
149
150 // Compare with bonds already in the list
151 boolean alreadyThere = false;
152 for (ObjectPair op : rotatableBonds)
153 {
154 int a1 = ((Integer)op.getFirst()).intValue();
155 int a2 = ((Integer)op.getSecond()).intValue();
156 if (((a1 == idAtmA) && (a2 == idAtmB)) ||
157 ((a2 == idAtmA) && (a1 == idAtmB)))
158 {
159 alreadyThere = true;
160 break;
161 }
162 }
163 if (!alreadyThere)
164 {
165 ObjectPair newRotBnd = new ObjectPair(
166 Integer.valueOf(idAtmA),
167 Integer.valueOf(idAtmB));
168 rotatableBonds.add(newRotBnd);
169 }
170 }
171 }
172 }
173 }
174
175 // Find all rings to identify cyclic bonds
176 SpanningTree st = new SpanningTree(mol);
177 IRingSet allRings = new RingSet();
178 if (excludeRings)
179 {
180 try {
181 allRings = st.getAllRings();
182 } catch (Exception ex) {
183 throw new DENOPTIMException(ex);
184 }
185 }
186
187 // Purge list and store information as bond property
188 ArrayList<ObjectPair> toRemove = new ArrayList<ObjectPair>();
189 for (ObjectPair op : rotatableBonds)
190 {
191 int a1 = ((Integer)op.getFirst()).intValue();
192 int a2 = ((Integer)op.getSecond()).intValue();
193
194 IBond bnd = mol.getBond(mol.getAtom(a1),mol.getAtom(a2));
195
196 if (excludeRings)
197 {
198 IRingSet rs = allRings.getRings(bnd);
199 if (!rs.isEmpty())
200 {
201 logger.log(Level.FINE, "Ignoring cyclic bond: "+bnd);
202 toRemove.add(op);
203 continue;
204 }
205 }
206 bnd.setProperty(DENOPTIMConstants.BONDPROPROTATABLE, "true");
207 }
208
209 if (excludeRings)
210 {
211 for (ObjectPair op : toRemove)
212 {
213 rotatableBonds.remove(op);
214 }
215 }
216
217 return rotatableBonds;
218 }
219
220//------------------------------------------------------------------------------
221
230 public static ArrayList<ObjectPair> getInterVertexBonds(IAtomContainer mol)
231 throws DENOPTIMException
232 {
233 ArrayList<ObjectPair> interfragBonds = new ArrayList<ObjectPair>();
234
236 for (IBond bnd : mol.bonds())
237 {
238 if (bnd.getAtomCount() == 2)
239 {
240 IAtom atmA = bnd.getAtom(0);
241 IAtom atmB = bnd.getAtom(1);
242 String fragIdA = atmA.getProperty(p).toString();
243 String fragIdB = atmB.getProperty(p).toString();
244
245 if (!fragIdA.equals(fragIdB) &&
246 (mol.getConnectedBondsCount(atmA) != 1) &&
247 (mol.getConnectedBondsCount(atmB) != 1))
248 {
249 ObjectPair newRotBnd = new ObjectPair();
250 int idAtmA = mol.indexOf(atmA);
251 int idAtmB = mol.indexOf(atmB);
252 if (idAtmA < idAtmB)
253 {
254 newRotBnd = new ObjectPair(Integer.valueOf(idAtmA),
255 Integer.valueOf(idAtmB));
256 } else {
257 newRotBnd = new ObjectPair(Integer.valueOf(idAtmB),
258 Integer.valueOf(idAtmA));
259 }
260 interfragBonds.add(newRotBnd);
261 }
262 }
263 else
264 {
265 String str = "ERROR! Unable to handle bonds involving other "
266 + "than two atoms.";
267 throw new DENOPTIMException(str);
268 }
269 }
270 return interfragBonds;
271 }
272
273//------------------------------------------------------------------------------
282 public static Map<String,String> getRotationalSpaceDefinition(
283 String filename) throws DENOPTIMException
284 {
285 Map<String,String> mapOfSMARTS = new HashMap<String,String>();
286
287 //Read the file
288 if (filename.equals(null))
289 {
290 DENOPTIMException ex = new DENOPTIMException("Pointer to file is "
291 + " null! annot read definition of rotational space.");
292 throw ex;
293 }
294 File f = new File(filename);
295 if (!f.exists())
296 {
297 DENOPTIMException ex = new DENOPTIMException("File '" + filename
298 + "' does not exist! Cannot find definition of rotational "
299 + "space.");
300 throw ex;
301 }
302 BufferedReader br = null;
303 String line;
304 try
305 {
306 br = new BufferedReader(new FileReader(filename));
307 while ((line = br.readLine()) != null)
308 {
309 if (line.trim().length() == 0)
310 continue;
311
312 if (line.trim().startsWith("#"))
313 continue;
314
315 String[] parts = line.split("\\s+");
316 if (parts.length != 2)
317 {
318 throw new DENOPTIMException("Unable to understand "
319 + "rotational Space definition. "
320 + "Check line '"+ line +"' in file "
321 + filename);
322 } else {
323 String key = parts[0];
324 String smarts = parts[1];
325 if (mapOfSMARTS.keySet().contains(key))
326 {
327 throw new DENOPTIMException("Duplicate definition of "
328 + "rotatabe bond named '" + key + "'. "
329 + "Check line '"+ line +"' in file "
330 + filename);
331 }
332
333 //Everything is OK, thus store this definition
334 mapOfSMARTS.put(key,smarts);
335 }
336 }
337 }
338 catch (IOException nfe)
339 {
340 throw new DENOPTIMException(nfe);
341 }
342 finally
343 {
344 try
345 {
346 if (br != null)
347 {
348 br.close();
349 }
350 }
351 catch (IOException ioe)
352 {
353 throw new DENOPTIMException(ioe);
354 }
355 }
356
357 return mapOfSMARTS;
358 }
359
360//------------------------------------------------------------------------------
361}
General set of constants used in DENOPTIM.
static final String ATMPROPVERTEXPATH
Name of Atom property used to store the unique ID of the Vertex that owns the atom and the IDs of any...
static final String BONDPROPROTATABLE
String tag of Bond's property used to store the property of being rotatable.
Container of lists of atoms matching a list of SMARTS.
Mappings getMatchesOfSMARTS(String ref)
int getNumMatchesOfQuery(String query)
Utilities for molecule conversion.
static void removeRCA(IAtomContainer mol)
Replace any PseudoAtoms representing ring closing attractors with H.
This class is the equivalent of the Pair data structure used in C++ Although AbstractMap....
Definition: ObjectPair.java:30
Tool box for definition and management of the rotational space, which is given by the list of rotatab...
static final IChemObjectBuilder builder
static ArrayList< ObjectPair > getInterVertexBonds(IAtomContainer mol)
Search for all bonds connecting atoms corresponding to two different vertices in the DENOPTIMGraph.
static Map< String, String > getRotationalSpaceDefinition(String filename)
Read a formatted file and return a map with all the SMARTS queries identifying rotatable bonds.
static ArrayList< ObjectPair > defineRotatableBonds(IAtomContainer mol, String defRotBndsFile, boolean addIterfragBonds, boolean excludeRings, Logger logger)
Define the rotational space (also torsional space) for a given molecule.