$darkmode
DENOPTIM
RingClosureTool.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.molecularmodeling;
20
21import java.util.ArrayList;
22import java.util.Collections;
23import java.util.Comparator;
24import java.util.List;
25import java.util.Set;
26import java.util.logging.Level;
27import java.util.logging.Logger;
28
29import javax.vecmath.Point3d;
30
31import org.openscience.cdk.PseudoAtom;
32import org.openscience.cdk.interfaces.IAtom;
33import org.openscience.cdk.interfaces.IAtomContainer;
34import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
35
36import denoptim.constants.DENOPTIMConstants;
37import denoptim.exception.DENOPTIMException;
38import denoptim.files.FileUtils;
39import denoptim.graph.Edge.BondType;
40import denoptim.graph.rings.RingClosingAttractor;
41import denoptim.graph.rings.RingClosure;
42import denoptim.graph.rings.RingClosureParameters;
43import denoptim.integration.rcoserver.RCOSocketServerClient;
44import denoptim.integration.tinker.ConformationalSearchPSSROT;
45import denoptim.integration.tinker.TinkerException;
46import denoptim.molecularmodeling.zmatrix.ZMatrix;
47import denoptim.molecularmodeling.zmatrix.ZMatrixAtom;
48import denoptim.programs.RunTimeParameters.ParametersType;
49import denoptim.programs.moldecularmodelbuilder.MMBuilderParameters;
50import denoptim.utils.ObjectPair;
51
62public class RingClosureTool
63{
67 private int itn = 0;
68
72 final String fsep = System.getProperty("file.separator");
73
78
82 private Logger logger;
83
84//------------------------------------------------------------------------------
85
90 {
91 this.settings = settings;
92 this.logger = settings.getLogger();
93 }
94
95//------------------------------------------------------------------------------
96
108 public ArrayList<ChemicalObjectModel> attemptAllRingClosures(
110 {
111 ArrayList<ChemicalObjectModel> rcMols = new ArrayList<ChemicalObjectModel>();
112 for (int i=0; i<mol.getRCACombinations().size(); i++)
113 {
114 Set<ObjectPair> rcaComb = mol.getRCACombinations().get(i);
115 if (rcaComb.isEmpty())
116 {
117 logger.log(Level.WARNING,"Attempt to close rings with "
118 + "no compatible RCA combination. "
119 + "This is most likely a mistake. Please, "
120 + "make sure that ring-closing vertexes are"
121 + "properly detected.");
122 }
123 if (logger.isLoggable(Level.FINE))
124 {
125 String s = "";
126 for (ObjectPair p : rcaComb)
127 {
128 s = s + p.getFirst() + ":" + p.getSecond() + " ";
129 }
130 logger.log(Level.FINE,"Attempting Ring Closure with RCA "
131 + "Combination (" + i + "): " + s);
132 }
133
134 // Try to create new molecule
135 ChemicalObjectModel molTo3d = mol.deepcopy();
136 if (settings.getPSSROTTool() != null)
137 {
138 try
139 {
141 molTo3d.getRCACombinations().get(i));
142 } catch (TinkerException te)
143 {
144 String msg = "ERROR! Tinker failed on task '"
145 + te.taskName + "'!";
146 if (te.solution != "")
147 {
148 msg = msg + settings.NL + te.solution;
149 }
150 logger.log(Level.SEVERE, msg);
151 throw new DENOPTIMException(msg, te);
152 }
153 } else {
155 molTo3d.getRCACombinations().get(i));
156 }
157
158 // If some ring remains open, report in the MOL_ERROR field
159 int newRingClosed = molTo3d.getNewRingClosures().size();
160 if (newRingClosed < rcaComb.size())
161 {
162 String err = "#RingClosureTool: uncomplete closure (closed "
163 + newRingClosed + "/" + rcaComb.size() + ")";
164 molTo3d.getIAtomContainer().setProperty(
166 }
167 rcMols.add(molTo3d);
168 }
169
170 // Sort
171 Collections.sort(rcMols, new RingClosedMolComparator());
172
173 return rcMols;
174 }
175
176//------------------------------------------------------------------------------
177
186 private class RingClosedMolComparator implements Comparator<ChemicalObjectModel>
187 {
189 {
190 final int FIRST = 1;
191 final int EQUAL = 0;
192 final int LAST = -1;
193
194 // First criterion is the number of RingClosures
195 int nRcA = mA.getNewRingClosures().size();
196 int nRcB = mB.getNewRingClosures().size();
197 if (nRcA < nRcB) // The HIGHER the number, the BETTER
198 {
199 return FIRST;
200 }
201 else if (nRcA > nRcB)
202 {
203 return LAST;
204 }
205
206 // Second, the quality (closeness to perfection) of RingClosures
207 double scoreA = mA.getNewRingClosuresQuality();
208 double scoreB = mB.getNewRingClosuresQuality();
209 double dist = scoreA - scoreB;
210 double trsh = Math.min(scoreA,scoreB) * 0.05;
211 if (dist > 0.0 && dist > trsh) // The LOWER the score, the BETTER
212 {
213 return FIRST;
214 }
215 if (dist < 0.0 && Math.abs(dist) > trsh)
216 {
217 return LAST;
218 }
219
220 // Third, atom proximity
221 double proxScoreA = mA.getAtomOverlapScore();
222 double proxScoreB = mB.getAtomOverlapScore();
223 if (proxScoreA < proxScoreB) // The HIGHER the proxScore, the BETTER
224 {
225 return FIRST;
226 }
227 else if (proxScoreA > proxScoreB)
228 {
229 return LAST;
230 }
231
232 return EQUAL;
233 }
234 }
235
236//------------------------------------------------------------------------------
237
254 ChemicalObjectModel chemObj,
255 Set<ObjectPair> rcaCombination) throws DENOPTIMException
256 {
257 String molName = chemObj.getName();
258
259 // Increment iteration number (to make unique file names)
260 itn++;
261
262 logger.log(Level.INFO, "Attempting Ring Closure via conformational"
263 + " adaptation for " + molName
264 + " (Iteration: " + itn + ")");
265
269
270 long startTime = System.nanoTime();
271 try {
272 rcoServer.runConformationalOptimization(chemObj, rcaCombination, logger);
273 } catch (Exception e) {
274 logger.log(Level.SEVERE, "Error optimizing ring closing conformation: " + e.getMessage());
275 throw new DENOPTIMException("Error optimizing ring closing conformation: " + e.getMessage(), e);
276 }
277 long endTime = System.nanoTime();
278 long time = (endTime - startTime);
279 logger.log(Level.FINE, "TIME (RC conf. search): "+time/1000000+" ms"
280 + " #frags: " + chemObj.getGraph().getVertexList().size()
281 + " #atoms: " + chemObj.getIAtomContainer().getAtomCount()
282 + " #rotBnds: " + chemObj.getRotatableBonds().size());
283
284 logger.log(Level.INFO, "Ring-closing conformational optimization done. "
285 + "Now, post-processing.");
286
287 // Evaluate proximity of RingClosingAttractor and close rings
288 closeRings(chemObj, rcaCombination);
289
290 // Update list rotatable bonds
291 chemObj.purgeListRotatableBonds();
292
293 // Finalize the molecule: saturate free RCA
295
296 return chemObj;
297 }
298
299//------------------------------------------------------------------------------
300
320 ChemicalObjectModel chemObj, Set<ObjectPair> rcaCombination)
322 {
323 IAtomContainer fmol = chemObj.getIAtomContainer();
324 String workDir = settings.getWorkingDirectory();
325 String molName = chemObj.getName();
326
327 // Increment iteration number (to make unique file names)
328 itn++;
329
330 logger.log(Level.INFO, "Attempting Ring Closure via conformational"
331 + " adaptation for " + molName
332 + " (PSSROT - Iteration: " + itn + ")");
333
334 List<String> molSpecificKeyFileLines = new ArrayList<String>();
335 molSpecificKeyFileLines.addAll(settings.getRSKeyFileParams());
336 for (ObjectPair op : rcaCombination)
337 {
338 int iZMatRcaA = chemObj.getZMatIdxOfRCA(
339 (RingClosingAttractor) op.getFirst());
340 int iZMatRcaB = chemObj.getZMatIdxOfRCA(
341 (RingClosingAttractor) op.getSecond());
342 molSpecificKeyFileLines.add("RC-PAIR " + iZMatRcaA + " "
343 + iZMatRcaB);
344 }
345
346 // Definition of RingClosingPotential
347 molSpecificKeyFileLines.add("RC11BNDTERM");
348 molSpecificKeyFileLines.add("RC12BNDTERM NONE");
349 for (ObjectPair op : rcaCombination)
350 {
351 RingClosingAttractor rca0 = (RingClosingAttractor) op.getFirst();
352 RingClosingAttractor rca1 = (RingClosingAttractor) op.getSecond();
353 int s0t = fmol.indexOf(rca0.getSrcAtom()) + 1;
354 int s1t = fmol.indexOf(rca1.getSrcAtom()) + 1;
355 int i0t = chemObj.getZMatIdxOfRCA(rca0);
356 int i1t = chemObj.getZMatIdxOfRCA(rca1);
357
358 double parA = 0.0;
359 double parB = 0.0;
360 parA = (rca0.getParamA11() + rca1.getParamA11()) / 2.0;
361 parB = (rca0.getParamB11() + rca1.getParamB11()) / 2.0;
362
363 molSpecificKeyFileLines.add("RC-11-PAIRS " + i0t + " " +s1t + " "
364 + parA + " " + parB);
365 molSpecificKeyFileLines.add("RC-11-PAIRS " + s0t + " " + i1t + " "
366 + parA + " " + parB);
367 }
368
369 long startTime = System.nanoTime();
372 itn, "rs",
374 molSpecificKeyFileLines,
379 workDir,
381 long endTime = System.nanoTime();
382 long time = (endTime - startTime);
383 logger.log(Level.FINE, "TIME (RC conf. search): "+time/1000000+" ms"
384 + " #frags: " + chemObj.getGraph().getVertexList().size()
385 + " #atoms: " + chemObj.getIAtomContainer().getAtomCount()
386 + " #rotBnds: " + chemObj.getRotatableBonds().size());
387
388 logger.log(Level.INFO, "RC-PSSROT done. Now, post-processing.");
389
390 // Evaluate proximity of RingClosingAttractor and close rings
391 closeRings(chemObj, rcaCombination);
392
393 // Update list rotatable bonds
394 chemObj.purgeListRotatableBonds();
395
396 // Finalize the molecule: saturate free RCA
398
399 // Cleanup
400 FileUtils.deleteFilesContaining(workDir,molName + "_rs" + itn);
401
402 return chemObj;
403 }
404
405//------------------------------------------------------------------------------
406
417 public void closeRings(ChemicalObjectModel mol, Set<ObjectPair> rcaCombination)
418 {
419 // get settings //TODO: this should happen inside RunTimeParameters
422 {
425 }
426
427 // Collect candidate RingClosures
428 List<RingClosure> candidatesClosures = new ArrayList<RingClosure>();
429 for (ObjectPair op : rcaCombination)
430 {
431 logger.log(Level.FINEST, "closeRings: evaluating closure of " + op);
432 RingClosingAttractor rcaA = (RingClosingAttractor) op.getFirst();
433 RingClosingAttractor rcaB = (RingClosingAttractor) op.getSecond();
434 Point3d srcA = rcaA.getSrcAtom().getPoint3d();
435 Point3d atmA = rcaA.getIAtom().getPoint3d();
436 Point3d srcB = rcaB.getSrcAtom().getPoint3d();
437 Point3d atmB = rcaB.getIAtom().getPoint3d();
438 RingClosure rc = new RingClosure(srcA, atmA, srcB, atmB);
439 candidatesClosures.add(rc);
440
441 //Define closability conditions
442 double lenH = srcA.distance(atmA);
443 double lenT = srcB.distance(atmB);
444 double distTolerance = (lenH + lenT) / 2.0;
445 distTolerance = distTolerance * rcParams.getRCDistTolerance();
446 double minDistH1T2 = -1.0;
447 double minDistH2T1 = -1.0;
448 double minDistH2T2 = -1.0;
449 double maxDistH1T2 = 0.0;
450 double maxDistH2T1 = 0.0;
451 double maxDistH2T2 = 0.0;
452 double maxDotProdHT = rcParams.getRCDotPrTolerance();
453
454 maxDistH1T2 = distTolerance;
455 maxDistH2T1 = distTolerance;
456 maxDistH2T2 = lenH + lenT;
457
458 boolean closeThisBnd = rc.isClosable(minDistH1T2, maxDistH1T2,
459 minDistH2T1, maxDistH2T1,
460 minDistH2T2, maxDistH2T2,
461 maxDotProdHT,
462 logger);
463
464 if (closeThisBnd)
465 {
466 BondType bndTyp = rcaA.getRCBondType();
467 if (bndTyp.hasCDKAnalogue())
468 {
469 mol.addBond(rcaA.getSrcAtom(),rcaB.getSrcAtom(),rc, bndTyp);
470 } else {
471 logger.log(Level.WARNING, "WARNING! "
472 + "Attempt to add ring closing bond "
473 + "did not add any actual chemical bond because the "
474 + "bond type of the chord is '" + bndTyp +"'.");
475 }
476 rcaA.setUsed();
477 rcaB.setUsed();
478 }
479 }
480 }
481
482//------------------------------------------------------------------------------
483
499 throws DENOPTIMException
500 {
501 IAtomContainer fmol = mol.getIAtomContainer();
502 ZMatrix zmat = mol.getZMatrix();
503 String duSymbol = DENOPTIMConstants.DUMMYATMSYMBOL;
504 for (RingClosingAttractor rca : mol.getAttractorsList())
505 {
506 if (rca.isUsed())
507 {
508 // Used RCA are changed to inert dummy atoms (to keep ZMatrix)
509 IAtom fatm = rca.getIAtom();
510 ZMatrixAtom zatm = zmat.getAtom(fmol.indexOf(fatm));
511 zatm.setSymbol(duSymbol);
512
513 IAtom newAtm = new PseudoAtom(duSymbol,new Point3d(fatm.getPoint3d()));
514 newAtm.setProperties(fatm.getProperties());
515 AtomContainerManipulator.replaceAtomByAtom(
516 mol.getIAtomContainer(),fatm,newAtm);
517 rca.setIAtom(newAtm);
518 }
519 else
520 {
521 // Unused RCA are replaced by capping group
522
523 //TODO: select capping group (if any) and use that to saturate the free AP
524 // Note that to do that the capping og the RingClosure-related APclasses must be
525 // reported in the CompatibilityMatrix. Thus, it is also necessary to make DenoptimGA
526 // prefer RingClosure-related APclasses over other capping groups
527 /*
528 //Choose capping group
529 String freeAPClass = rca.getApClass();
530 ArrayList<String> capAPClasses =
531 CGParameters.getCompatibilityMap().get(freeAPClass);
532 */
533 // We force the conversion to H with a fixed bond length
534 // This code is temporary as will be removed by the introduction
535 // proper capping group selection and use (TODO)
536 IAtom fatm = rca.getIAtom();
537 ZMatrixAtom zatm = zmat.getAtom(fmol.indexOf(fatm));
538 zatm.setSymbol("H");
539 zatm.setBondLength(1.10);
540 //UPGRADE: this cannot be done since CDK 2.*. So, we must
541 // create a new IAtom object to replace the old one.
542 /*
543 ((PseudoAtom) fatm).setLabel("H");
544 fatm.setSymbol("H");
545 */
546 IAtom newAtm = new PseudoAtom("H",new Point3d(fatm.getPoint3d()));
547 newAtm.setProperties(fatm.getProperties());
548 AtomContainerManipulator.replaceAtomByAtom(
549 mol.getIAtomContainer(),fatm,newAtm);
550 rca.setIAtom(newAtm);
551 }
552 }
553
554 // Update XYZ
555 mol.updateXYZFromINT();
556 }
557
558//------------------------------------------------------------------------------
559}
General set of constants used in DENOPTIM.
static final String MOLERRORTAG
SDF tag containing errors during execution of molecule specific tasks.
static final String DUMMYATMSYMBOL
Symbol of dummy atom.
static void deleteFilesContaining(String path, String pattern)
Delete all files with pathname containing a given string.
Definition: FileUtils.java:289
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
IAtom getSrcAtom()
Get the atom in the parent fragment that holds the attachment point occupied by this RingClosingAttra...
void setUsed()
Set this RingClosingAttractor to 'used'.
IAtom getIAtom()
Get the atom corresponding to this RingClosingAttractor in the molecular representation.
BondType getRCBondType()
Get the type of bond this attractor is meant to close.
RingClosure represents the arrangement of atoms and PseudoAtoms identifying the head and tail of a ch...
boolean isClosable(ArrayList< Double > clsablConds, Logger logger)
Evaluate closability by comparing the distances and the dot product with the given critera.
Parameters and setting related to handling ring closures.
Sends the request to produce a socket server running the RingClosingMM service.
static synchronized RCOSocketServerClient getInstance(String hostname, Integer port)
Gets the singleton instance of RCOSocketServerClient.
void setRecordRequestsFileName(String requestFileName)
Sets the pathname to file where to record requests sent to the server.
void runConformationalOptimization(ChemicalObjectModel chemObj, Logger logger)
Runs a conformational optimization using the services provided by the socket server configured for th...
Tool to perform conformational search via Tinker PSSROT program.
static void performPSSROT(ArrayList< ChemicalObjectModel > mols, Map< String, Integer > atmTypeMap, String runLabel, String ffFilePathName, List< String > keyFileLines, List< String > subParamsInit, List< String > subParamsRest, String pssExePathName, String xyzintPathName, String workDir, int taskId, Logger logger)
Performs PSSROT conformational search for all chemical objects in the list.
Exceptions resulting from a failure of Tinker.
String solution
Proposed solution to the failure, or empty string.
Collector of molecular information, related to a single chemical object, that is deployed within the ...
double getAtomOverlapScore()
Return the atoms overlap score which is calculated for all atoms pairs not in 1-4 or lower relationsh...
double getNewRingClosuresQuality()
Return the overal evaluation of the whole list of RingClosures.
ChemicalObjectModel deepcopy()
Return a new Molecule3DBuilder having exactly the same features of this Molecule3DBuilder.
List< Set< ObjectPair > > getRCACombinations()
Returns the list of combinations of RingClosingAttractor.
IAtomContainer getIAtomContainer()
Returns the CDK representation of the molecular system.
void addBond(IAtom atmA, IAtom atmB, RingClosure nRc, BondType bndTyp)
Modify the molecule adding a cyclic bond between two atoms.
List< RingClosure > getNewRingClosures()
Return the list of RingClosures that have been identified as closable head/tail of atom chains during...
Compares the Molecule3DBuilder afters ring closing-biased conformational adaptation.
int compare(ChemicalObjectModel mA, ChemicalObjectModel mB)
Toolkit to perform ring closing conformational search.
void closeRings(ChemicalObjectModel mol, Set< ObjectPair > rcaCombination)
Makes new rings by connecting pairs of atoms that hold properly arranged RingClosingAttractors.
int itn
Iteration counter for making unique filenames.
MMBuilderParameters settings
Settings controlling the calculation.
void saturateRingClosingAttractor(ChemicalObjectModel mol)
Looks for unused RingClosingAttractors and attach proper capping group saturating the free valency/bo...
ArrayList< ChemicalObjectModel > attemptAllRingClosures(ChemicalObjectModel mol)
Performs one or more attempts to close rings by conformational adaptation.
RingClosureTool(MMBuilderParameters settings)
Construct an empty RingClosureTool.
ChemicalObjectModel attemptRingClosureWithRCOServer(ChemicalObjectModel chemObj, Set< ObjectPair > rcaCombination)
Attempts to close rings by finding the conformation that allows to join heads and tails of specific a...
ChemicalObjectModel attemptRingClosureWithTinker(ChemicalObjectModel chemObj, Set< ObjectPair > rcaCombination)
Attempts to close rings by finding the conformation that allows to join heads and tails of specific a...
Logger logger
Program.specific logger.
Representation of an atom in the ZMatrix.
Definition: ZMatrixAtom.java:9
void setBondLength(Double bondLength)
Set the bond length.
void setSymbol(String symbol)
Set the symbol of the atom.
Representation of an atom container's geometry with internal coordinates.
Definition: ZMatrix.java:27
ZMatrixAtom getAtom(int index)
Get the atom at the given index.
Definition: ZMatrix.java:223
boolean containsParameters(ParametersType type)
RunTimeParameters getParameters(ParametersType type)
Logger getLogger()
Get the name of the program specific logger.
Parameters for the conformer generator (3D builder).
This class is the equivalent of the Pair data structure used in C++ Although AbstractMap....
Definition: ObjectPair.java:30
Possible chemical bond types an edge can represent.
Definition: Edge.java:305
boolean hasCDKAnalogue()
Checks if it is possible to convert this edge type into a CDK bond.
Definition: Edge.java:330
RC_PARAMS
Parameters pertaining to ring closures in graphs.