1package denoptim.fragmenter;
4import java.io.FileInputStream;
5import java.io.IOException;
6import java.util.ArrayList;
7import java.util.HashMap;
8import java.util.HashSet;
12import java.util.logging.Level;
13import java.util.logging.Logger;
15import javax.vecmath.Point3d;
16import javax.vecmath.Vector3d;
18import org.openscience.cdk.Atom;
19import org.openscience.cdk.Bond;
20import org.openscience.cdk.DefaultChemObjectBuilder;
21import org.openscience.cdk.PseudoAtom;
22import org.openscience.cdk.config.Isotopes;
23import org.openscience.cdk.exception.CDKException;
24import org.openscience.cdk.geometry.alignment.KabschAlignment;
25import org.openscience.cdk.interfaces.IAtom;
26import org.openscience.cdk.interfaces.IAtomContainer;
27import org.openscience.cdk.interfaces.IBond;
28import org.openscience.cdk.interfaces.IIsotope;
29import org.openscience.cdk.io.iterator.IteratingSDFReader;
30import org.openscience.cdk.isomorphism.Mappings;
31import org.openscience.cdk.isomorphism.Pattern;
32import org.openscience.cdk.silent.SilentChemObjectBuilder;
33import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
35import denoptim.constants.DENOPTIMConstants;
36import denoptim.exception.DENOPTIMException;
37import denoptim.files.FileFormat;
38import denoptim.files.UndetectedFileFormatException;
39import denoptim.graph.APClass;
40import denoptim.graph.AttachmentPoint;
41import denoptim.graph.DGraph;
42import denoptim.graph.Edge;
43import denoptim.graph.Fragment;
44import denoptim.graph.Template;
45import denoptim.graph.Vertex;
46import denoptim.graph.Vertex.BBType;
47import denoptim.graph.rings.RingClosingAttractor;
48import denoptim.io.DenoptimIO;
49import denoptim.io.IteratingAtomContainerReader;
50import denoptim.molecularmodeling.ThreeDimTreeBuilder;
51import denoptim.programs.RunTimeParameters.ParametersType;
52import denoptim.programs.fragmenter.CuttingRule;
53import denoptim.programs.fragmenter.FragmenterParameters;
54import denoptim.programs.fragmenter.MatchedBond;
55import denoptim.utils.CartesianSpaceUtils;
56import denoptim.utils.DummyAtomHandler;
57import denoptim.utils.FormulaUtils;
58import denoptim.utils.ManySMARTSQuery;
59import denoptim.utils.MathUtils;
60import denoptim.utils.MoleculeUtils;
61import denoptim.utils.Randomizer;
83 File output, Logger logger)
86 FileInputStream fis =
new FileInputStream(input);
87 IteratingSDFReader reader =
new IteratingSDFReader(fis,
88 DefaultChemObjectBuilder.getInstance());
91 int maxBufferSize = 2000;
92 ArrayList<IAtomContainer> buffer =
new ArrayList<IAtomContainer>(500);
94 while (reader.hasNext())
99 logger.log(Level.FINE,
"Checking elemental analysis of "
100 +
"structure " + index);
102 IAtomContainer mol = reader.next();
106 +
"' not found in molecule " + index +
" in file "
107 + input +
". Cannot compare formula with elemental"
120 logger.log(Level.INFO,
"Inconsistency between elemental "
121 +
"analysis of structure and molecular formula."
122 +
" Rejecting structure " + index +
": "
128 if (buffer.size() >= maxBufferSize)
139 if (buffer.size() < maxBufferSize)
174 }
catch (CDKException e)
176 if (e.getMessage().contains(
"Cannot assign Kekulé structure"))
180 settings.
getLogger().log(Level.WARNING,
"Some bond order "
181 +
"are unset and attempt to kekulize the "
182 +
"system has failed "
183 +
"for structure " + index +
". "
184 +
"This hampers use of SMARTS queries, which "
186 +
"not work as expected. Structure " + index
187 +
" will be rejected. "
188 +
"You can avoid rejection by using "
191 +
"UNSETTOSINGLEBO, but you'll "
192 +
"still be using a peculiar connectivity "
194 +
"many bonds are artificially marked as "
196 +
"avoid use of 'UNSET' bond order. "
197 +
"Further details on the problem: "
201 settings.
getLogger().log(Level.WARNING,
"Failed "
203 +
"for structure " + index
204 +
" but UNSETTOSINGLEBO "
205 +
"keyword used. Forcing use of single bonds to "
206 +
"replace bonds with unset order.");
207 for (IBond bnd : mol.bonds())
209 if (bnd.getOrder().equals(IBond.Order.UNSET))
211 bnd.setOrder(IBond.Order.SINGLE);
234 File output, Logger logger)
237 FileInputStream fis =
new FileInputStream(input);
238 IteratingSDFReader reader =
new IteratingSDFReader(fis,
239 DefaultChemObjectBuilder.getInstance());
242 Map<String, String> smartsMap =
new HashMap<String, String>();
243 for (String s : smarts)
246 smartsMap.put(
"prefilter-"+i, s);
250 int maxBufferSize = 2000;
251 ArrayList<IAtomContainer> buffer =
new ArrayList<IAtomContainer>(500);
253 while (reader.hasNext())
258 logger.log(Level.FINE,
"Prefiltering structure " + index);
260 IAtomContainer mol = reader.next();
265 String msg =
"WARNING! Problems while searching for "
266 +
"specific atoms/bonds using SMARTS: "
272 if (allMatches.size()==0)
277 for (String s : allMatches.keySet())
278 hits = hits + DenoptimIO.NL + smartsMap.get(s);
281 logger.log(Level.INFO,
"Found match for " + hits
282 +
"Rejecting structure " + index +
": "
288 if (buffer.size() >= maxBufferSize)
298 if (buffer.size() < maxBufferSize)
329 List<Vertex> fragments = graph.getVertexList();
332 List<Vertex> keptFragments =
new ArrayList<Vertex>();
334 for (
Vertex frag : fragments)
339 keptFragments, logger);
343 logger.log(Level.FINE,
"Fragments surviving post-"
344 +
"processing: " + keptFragments.size());
347 if (keptFragments.size()>0)
349 totalProd += keptFragments.size();
351 keptFragments,
true);
370 List<Vertex> fragments =
new ArrayList<Vertex>();
371 if (settings.getFragmentationTmpls().size()>0)
373 fragments =
fragmentation(mol, settings.getFragmentationTmpls(),
374 settings.getMaxBufferShellSize(),
375 settings.getRandomizer(), settings.getLogger());
378 settings.getLogger());
405 File output, Logger logger)
throws CDKException, IOException,
420 logger.log(Level.FINE,
"Fragmenting structure " + index);
422 IAtomContainer mol = iterator.
next();
423 String molName =
"noname-mol" + index;
424 if (mol.getTitle()!=
null && !mol.getTitle().isBlank())
425 molName = mol.getTitle();
431 logger.log(Level.FINE,
"Fragmentation produced "
432 + fragments.size() +
" fragments.");
434 totalProd += fragments.size();
437 List<Vertex> keptFragments =
new ArrayList<Vertex>();
439 for (
Vertex frag : fragments)
442 String fragIdStr =
"From_" + molName +
"_" + fragCounter;
443 frag.setProperty(
"cdk:Title", fragIdStr);
446 keptFragments, logger);
450 logger.log(Level.FINE,
"Fragments surviving post-"
451 +
"processing: " + keptFragments.size());
453 totalKept += keptFragments.size();
454 if (!settings.doManageIsomorphicFamilies() && totalKept>0)
469 logger.log(Level.WARNING,
"No fragment produced. Cutting rules "
470 +
"were ineffective on the given structures.");
473 }
else if (totalKept==0)
477 logger.log(Level.WARNING,
"No fragment kept out of " + totalProd
478 +
" produced fragments. Filtering criteria might be "
479 +
"too restrictive.");
502 List<DGraph> templates,
int maxBufferShellSize,
508 List<Vertex> fragments =
new ArrayList<Vertex>();
509 int maxNumIsomorfFrgs = -1;
510 for (
DGraph templateGraph : templates)
513 if (!templateGraph.isConnected())
521 +
"Cannot use it for fragmentation. Please check the "
522 +
"template graph and make sure it is connected.");
539 List<Vertex> fragsFromThisTemplate =
new ArrayList<>();
540 int maxNumIsomorfFrgsFromThisTmpl = -1;
544 List<Vertex> templateVertexes = templateGraph.getVertexAnyLevel();
545 int maxTheoreticalScorePerMapping = 0;
546 for (
int iva=0; iva<templateVertexes.size(); iva++)
548 Vertex va = templateVertexes.get(iva);
553 for (
int ivb=0; ivb<templateVertexes.size(); ivb++)
555 Vertex vb = templateVertexes.get(ivb);
563 maxTheoreticalScorePerMapping++;
564 }
else if (((
Fragment) va).isIsomorphicTo(vb))
566 maxTheoreticalScorePerMapping++;
573 for (
int bufferShellSize = 0; bufferShellSize < maxBufferShellSize; bufferShellSize++)
578 reducedTemplateMol, mol, logger);
581 List<Map<IAtom,IAtom>> atomMappings =
new ArrayList<>();
582 for (Map<IAtom,IAtom> reducedMapping : reducedAtomMappings)
584 Map<IAtom,IAtom> fullMapping =
new HashMap<>();
585 for (Map.Entry<IAtom,IAtom> entry : reducedMapping.entrySet())
587 IAtom reducedAtom = entry.getKey();
588 IAtom molAtom = entry.getValue();
591 Object indexObj = reducedAtom.getProperty(
"DENOPTIM_ORIGINAL_ATOM_INDEX");
592 if (indexObj !=
null)
594 int originalIndex = ((Number) indexObj).intValue();
595 IAtom originalAtom = templateMol.getAtom(originalIndex);
596 if (originalAtom !=
null)
598 fullMapping.put(originalAtom, molAtom);
602 if (!fullMapping.isEmpty())
604 atomMappings.add(fullMapping);
616 for (Map<IAtom,IAtom> atomMapping : atomMappings)
620 masterFrag, masterFragIAC, mol, atomMapping);
621 }
catch (Throwable e) {
623 logger.log(Level.WARNING,
"Error while exploring the template graph: " + e.getMessage());
629 List<Vertex> locfragments =
new ArrayList<Vertex>();
630 Set<Integer> doneAlready =
new HashSet<Integer>();
633 if (doneAlready.contains(idx))
639 atmsToKeep.stream().forEach(atm -> doneAlready.add(iac.indexOf(atm)));
641 Set<IAtom> atmsToRemove =
new HashSet<IAtom>();
642 for (IAtom atm : cloneOfMaster.
atoms())
644 if (!atmsToKeep.contains(atm))
646 atmsToRemove.add(atm);
651 locfragments.add(cloneOfMaster);
655 for (
Vertex frag : locfragments)
661 for (
Vertex templateVertex : templateGraph.getVertexList())
663 if (((
Fragment) frag).isIsomorphicTo(templateVertex))
670 if (localScore > maxNumIsomorfFrgsFromThisTmpl)
672 maxNumIsomorfFrgsFromThisTmpl = localScore;
673 fragsFromThisTemplate = locfragments;
674 if (maxNumIsomorfFrgsFromThisTmpl ==
675 maxTheoreticalScorePerMapping*atomMappings.size())
682 if (maxNumIsomorfFrgsFromThisTmpl > maxNumIsomorfFrgs)
684 maxNumIsomorfFrgs = maxNumIsomorfFrgsFromThisTmpl;
685 fragments = fragsFromThisTemplate;
702 Fragment masterFrag, IAtomContainer masterFragIAC, IAtomContainer mol,
703 Map<IAtom,IAtom> graphToMolMapping)
707 for (
Edge edge : graph.getEdgeList())
710 int srcAPIdx = edge.getSrcAP().getAtomPositionNumberInMol();
711 int trgAPIdx = edge.getTrgAP().getAtomPositionNumberInMol();
712 IAtom graphAtmSrc = graphIAC.getAtom(srcAPIdx);
713 IAtom graphAtmTrg = graphIAC.getAtom(trgAPIdx);
715 IAtom masterFragAtmSrc = masterFragIAC.getAtom(mol.indexOf(graphToMolMapping.get(graphAtmSrc)));
716 IAtom masterFragAtmTrg = masterFragIAC.getAtom(mol.indexOf(graphToMolMapping.get(graphAtmTrg)));
718 IBond bnd = masterFragIAC.getBond(masterFragAtmSrc, masterFragAtmTrg);
721 masterFragIAC.removeBond(bnd);
725 edge.getSrcAP().getAPClass(),
729 edge.getTrgAP().getAPClass(),
734 for (
Vertex v : graph.getVertexList())
746 if (!ap.isAvailable())
750 IAtom graphAtmSrc = graphIAC.getAtom(ap.getAtomPositionNumberInMol());
751 IAtom masterFragAtmSrc = masterFragIAC.getAtom(mol.indexOf(graphToMolMapping.get(graphAtmSrc)));
755 graphIAC, masterFragIAC, mol, graphToMolMapping);
758 masterFrag.addAPOnAtom(masterFragAtmSrc, ap.getAPClass(), apHead);
782 IAtom graphAtmSrc, IAtomContainer graphIAC, IAtomContainer masterFragIAC,
787 if (!graphIAC.contains(graphAtmSrc))
789 throw new DENOPTIMException(
"The atom " + graphAtmSrc.getSymbol() +
" is not in the graphIAC.");
791 if (mol.getAtomCount() != masterFragIAC.getAtomCount())
793 throw new DENOPTIMException(
"The number of atoms in the molecule and the master fragment are not the same.");
802 IAtom graphAtmSrcOnMolA = molA.getAtom(mol.indexOf(graphToMolMapping.get(graphAtmSrc)));
805 IAtom dummyAtm =
new Atom(
"He");
806 dummyAtm.setPoint3d(ap.getDirectionVector());
807 molB.addAtom(dummyAtm);
809 List<IAtom> closestNeighborsOnGrphIAC = graphIAC.getConnectedAtomsList(graphAtmSrc);
810 List<IAtom> closestNeighborsOnMolA = molA.getConnectedAtomsList(graphAtmSrcOnMolA);
811 int minNumClosestNeighbors = Math.min(closestNeighborsOnGrphIAC.size(), closestNeighborsOnMolA.size());
812 if (minNumClosestNeighbors < 1)
816 double dist = graphAtmSrc.getPoint3d().distance(ap.getDirectionVector());
817 Point3d apHead =
new Point3d(
818 graphAtmSrcOnMolA.getPoint3d().x + dist,
819 graphAtmSrcOnMolA.getPoint3d().y,
820 graphAtmSrcOnMolA.getPoint3d().z);
822 }
else if (minNumClosestNeighbors == 1) {
824 double dist = graphAtmSrc.getPoint3d().distance(ap.getDirectionVector());
826 closestNeighborsOnGrphIAC.get(0).getPoint3d(),
827 graphAtmSrc.getPoint3d(),
828 ap.getDirectionVector());
829 IAtom nbrAtmOnMolA = molA.getAtom(mol.indexOf(graphToMolMapping.get(closestNeighborsOnGrphIAC.get(0))));
830 Point3d pSrc = graphAtmSrcOnMolA.getPoint3d();
831 Point3d pNbr = nbrAtmOnMolA.getPoint3d();
832 Point3d pSrcTmpl = graphAtmSrc.getPoint3d();
833 Point3d pNbrTmpl = closestNeighborsOnGrphIAC.get(0).getPoint3d();
834 Point3d pApTmpl = ap.getDirectionVector();
843 double angleRad = Math.toRadians(angle);
844 Vector3d apDir =
new Vector3d();
845 apDir.scale(Math.cos(angleRad), uMol);
846 double sinAngle = Math.sin(angleRad);
849 Vector3d vRefTmpl =
new Vector3d(wTmpl);
850 vRefTmpl.scaleAdd(-uTmpl.dot(wTmpl), uTmpl, vRefTmpl);
851 vRefTmpl.normalize();
852 Vector3d rotAxis =
new Vector3d();
853 rotAxis.cross(uTmpl, uMol);
854 double sinRot = rotAxis.length();
855 double cosRot = uTmpl.dot(uMol);
859 double rotAng = Math.toDegrees(Math.atan2(sinRot, cosRot));
862 else if (cosRot < 0.0)
867 vRefTmpl.scale(sinAngle);
871 Point3d apHead =
new Point3d(
872 pSrc.x + dist * apDir.x,
873 pSrc.y + dist * apDir.y,
874 pSrc.z + dist * apDir.z);
878 Map<IAtom,IAtom> molToGraphMappingAroundAPSrc =
new HashMap<>();
879 Set<IAtom> atomsAlreadyUsed =
new HashSet<>();
880 for (Map.Entry<IAtom,IAtom> pair : graphToMolMapping.entrySet())
882 IAtom atmGraphIAC = pair.getKey();
883 if (graphIAC.getConnectedAtomsList(graphAtmSrc).contains(atmGraphIAC)
884 || atmGraphIAC == graphAtmSrc)
886 atomsAlreadyUsed.add(atmGraphIAC);
887 molToGraphMappingAroundAPSrc.put(
888 molA.getAtom(mol.indexOf(pair.getValue())),
889 molB.getAtom(graphIAC.indexOf(atmGraphIAC)));
893 if (minNumClosestNeighbors<3)
895 for (Map.Entry<IAtom,IAtom> pair : graphToMolMapping.entrySet())
897 IAtom atmGraphIAC = pair.getKey();
898 if (closestNeighborsOnGrphIAC.contains(atmGraphIAC)
899 && !atomsAlreadyUsed.contains(atmGraphIAC))
901 atomsAlreadyUsed.add(atmGraphIAC);
902 molToGraphMappingAroundAPSrc.put(
903 molA.getAtom(mol.indexOf(pair.getValue())),
904 molB.getAtom(graphIAC.indexOf(atmGraphIAC)));
910 IAtom[] lstA =
new IAtom[molToGraphMappingAroundAPSrc.size()];
911 IAtom[] lstB =
new IAtom[molToGraphMappingAroundAPSrc.size()];
913 for (Map.Entry<IAtom,IAtom> pair : molToGraphMappingAroundAPSrc.entrySet())
915 lstA[k] = pair.getKey();
916 lstB[k] = pair.getValue();
924 sa =
new KabschAlignment(lstA, lstB);
926 }
catch (Throwable t) {
931 sa.rotateAtomContainer(molB);
934 Point3d cm = sa.getCenterOfMass();
935 for (
int ib = 0; ib < molB.getAtomCount(); ib++)
937 IAtom a = molB.getAtom(ib);
939 Point3d newPlace =
new Point3d(oldPlace.x + cm.x,
942 a.setPoint3d(newPlace);
965 Map<String, List<MatchedBond>> matchingbonds =
972 String ruleName = rule.getName();
975 if (!matchingbonds.keySet().contains(ruleName))
980 IAtom atmA = tb.getAtmSubClass0();
981 IAtom atmB = tb.getAtmSubClass1();
984 if (!fragsMol.getConnectedAtomsList(atmA).contains(atmB))
995 IAtom centralAtm = atmA;
999 ArrayList<IAtom> candidatesForHapto =
new ArrayList<IAtom>();
1000 for (
MatchedBond tbForHapto : matchingbonds.get(ruleName))
1003 if (tbForHapto.getAtmSubClass0() == centralAtm)
1004 candidatesForHapto.add(tbForHapto.getAtmSubClass1());
1009 Set<IAtom> atmsInHapto =
new HashSet<IAtom>();
1010 atmsInHapto.add(tb.getAtmSubClass1());
1012 centralAtm, candidatesForHapto, fragsMol);
1013 if (atmsInHapto.size() == 1)
1015 logger.log(Level.WARNING,
"Unable to find more than one "
1016 +
"bond involved in high-hapticity ligand! "
1022 boolean isSystemIntact =
true;
1023 for (IAtom ligAtm : atmsInHapto)
1025 List<IAtom> nbrsOfLigAtm =
1026 fragsMol.getConnectedAtomsList(ligAtm);
1027 if (!nbrsOfLigAtm.contains(centralAtm))
1029 isSystemIntact =
false;
1036 if (!isSystemIntact)
1041 Point3d dummyP3d =
new Point3d();
1042 for (IAtom ligAtm : atmsInHapto)
1045 dummyP3d.x = dummyP3d.x + ligP3d.x;
1046 dummyP3d.y = dummyP3d.y + ligP3d.y;
1047 dummyP3d.z = dummyP3d.z + ligP3d.z;
1050 dummyP3d.x = dummyP3d.x / (double) atmsInHapto.size();
1051 dummyP3d.y = dummyP3d.y / (double) atmsInHapto.size();
1052 dummyP3d.z = dummyP3d.z / (double) atmsInHapto.size();
1056 IAtom dummyAtm =
null;
1057 for (IAtom oldDu : fragsMol.atoms())
1062 Point3d oldDuP3d = oldDu.getPoint3d();
1063 if (oldDuP3d.distance(dummyP3d) < 0.002)
1074 dummyAtm.setPoint3d(dummyP3d);
1075 fragsMol.addAtom(dummyAtm);
1081 IBond.Order border = IBond.Order.valueOf(
"SINGLE");
1083 for (IAtom ligAtm : atmsInHapto)
1085 List<IAtom> nbrsOfDu = fragsMol.getConnectedAtomsList(
1087 if (!nbrsOfDu.contains(ligAtm))
1090 Bond bnd =
new Bond(dummyAtm,ligAtm,border);
1091 fragsMol.addBond(bnd);
1094 IBond oldBnd = fragsMol.getBond(centralAtm,ligAtm);
1095 fragsMol.removeBond(oldBnd);
1112 IBond bnd = fragsMol.getBond(atmA,atmB);
1113 fragsMol.removeBond(bnd);
1130 List<Vertex> fragments =
new ArrayList<Vertex>();
1131 Set<Integer> doneAlready =
new HashSet<Integer>();
1134 if (doneAlready.contains(idx))
1140 atmsToKeep.stream().forEach(atm -> doneAlready.add(iac.indexOf(atm)));
1142 Set<IAtom> atmsToRemove =
new HashSet<IAtom>();
1143 for (IAtom atm : cloneOfMaster.
atoms())
1145 if (!atmsToKeep.contains(atm))
1147 atmsToRemove.add(atm);
1152 fragments.add(cloneOfMaster);
1173 ArrayList<IAtom> candidates, IAtomContainer mol)
1175 Set<IAtom> atmsInHapto =
new HashSet<IAtom>();
1176 atmsInHapto.add(seed);
1177 ArrayList<IAtom> toVisitAtoms =
new ArrayList<IAtom>();
1178 toVisitAtoms.add(seed);
1179 ArrayList<IAtom> visitedAtoms =
new ArrayList<IAtom>();
1180 while (toVisitAtoms.size()>0)
1182 ArrayList<IAtom> toVisitLater =
new ArrayList<IAtom>();
1183 for (IAtom atomInFocus : toVisitAtoms)
1185 if (visitedAtoms.contains(atomInFocus)
1186 || atomInFocus==centralAtom)
1189 visitedAtoms.add(atomInFocus);
1191 if (candidates.contains(atomInFocus))
1193 atmsInHapto.add(atomInFocus);
1194 toVisitLater.addAll(mol.getConnectedAtomsList(atomInFocus));
1197 toVisitAtoms.clear();
1198 toVisitAtoms.addAll(toVisitLater);
1214 Set<IAtom> atmsReachableFromSeed =
new HashSet<IAtom>();
1215 ArrayList<IAtom> toVisitAtoms =
new ArrayList<IAtom>();
1216 toVisitAtoms.add(seed);
1217 ArrayList<IAtom> visitedAtoms =
new ArrayList<IAtom>();
1218 while (toVisitAtoms.size()>0)
1220 ArrayList<IAtom> toVisitLater =
new ArrayList<IAtom>();
1221 for (IAtom atomInFocus : toVisitAtoms)
1223 if (visitedAtoms.contains(atomInFocus))
1226 visitedAtoms.add(atomInFocus);
1228 atmsReachableFromSeed.add(atomInFocus);
1229 toVisitLater.addAll(mol.getConnectedAtomsList(atomInFocus));
1231 toVisitAtoms.clear();
1232 toVisitAtoms.addAll(toVisitLater);
1234 return atmsReachableFromSeed;
1248 IAtomContainer mol, List<CuttingRule> rules, Logger logger)
1251 Map<String,String> smarts =
new HashMap<String,String>();
1254 smarts.put(rule.getName(),rule.getWholeSMARTSRule());
1258 Map<String, List<MatchedBond>> bondsMatchingRules =
1259 new HashMap<String, List<MatchedBond>>();
1263 if (msq.hasProblems())
1267 logger.log(Level.WARNING,
"Problem matching SMARTS: "
1268 + msq.getMessage());
1270 return bondsMatchingRules;
1275 String ruleName = rule.getName();
1277 if (msq.getNumMatchesOfQuery(ruleName) == 0)
1283 Mappings purgedPairs = msq.getMatchesOfSMARTS(ruleName);
1286 ArrayList<MatchedBond> bondsMatched =
new ArrayList<MatchedBond>();
1287 for (
int[] pair : purgedPairs)
1291 throw new Error(
"Cutting rule: " + ruleName
1292 +
" has identified " + pair.length +
" atoms "
1293 +
"instead of 2. Modify rule to make it find a "
1294 +
"pair of atoms.");
1297 mol.getAtom(pair[1]), rule);
1301 bondsMatched.add(tb);
1304 if (!bondsMatched.isEmpty())
1305 bondsMatchingRules.put(ruleName, bondsMatched);
1308 return bondsMatchingRules;
1323 FileInputStream fis =
new FileInputStream(input);
1324 IteratingSDFReader reader =
new IteratingSDFReader(fis,
1325 DefaultChemObjectBuilder.getInstance());
1328 int maxBufferSize = 2000;
1329 ArrayList<Vertex> buffer =
new ArrayList<Vertex>(500);
1331 while (reader.hasNext())
1336 logger.log(Level.FINE,
"Processing fragment " + index);
1343 if (buffer.size() >= maxBufferSize)
1353 if (buffer.size() < maxBufferSize)
1382 List<Vertex> collector, Logger logger)
1393 if (settings.getIgnorableFragments().size() > 0)
1395 if (settings.getIgnorableFragments().stream()
1396 .anyMatch(ignorable -> ((
Fragment)frag)
1397 .isIsomorphicTo(ignorable)))
1401 logger.log(Level.FINE,
"Fragment " + fragCounter
1402 +
" is ignorable.");
1409 if (settings.getTargetFragments().size() > 0)
1411 if (!settings.getTargetFragments().stream()
1412 .anyMatch(ignorable -> ((
Fragment)frag)
1413 .isIsomorphicTo(ignorable)))
1417 logger.log(Level.FINE,
"Fragment " + fragCounter
1418 +
" doesn't match any target: rejected.");
1426 && settings.doAddDuOnLinearity())
1429 settings.getLinearAngleLimit());
1436 if (settings.doManageIsomorphicFamilies())
1438 synchronized (settings.MANAGEMWSLOTSSLOCK)
1441 settings.getMWSlotSize());
1443 File mwFileUnq = settings.getMWSlotFileNameUnqFrags(
1445 File mwFileAll = settings.getMWSlotFileNameAllFrags(
1449 Vertex unqVersion =
null;
1450 if (mwFileUnq.exists())
1452 ArrayList<Vertex> knownFrags =
1454 unqVersion = knownFrags.stream()
1455 .filter(knownFrag ->
1456 ((
Fragment)frag).isIsomorphicTo(knownFrag))
1460 if (unqVersion!=
null)
1469 int sampleSize = settings.getIsomorphsCount()
1471 if (sampleSize < settings.getIsomorphicSampleSize())
1477 settings.getIsomorphsCount().put(isoFamID,
1481 collector.add(frag);
1502 String isoFamID = settings.newIsomorphicFamilyID();
1506 settings.getIsomorphsCount().put(isoFamID, 1);
1511 collector.add(frag);
1516 collector.add(frag);
1554 for (IAtom atm : frag.
atoms())
1565 logger.log(Level.FINE,
"Removing fragment contains non-element '"
1575 Point3d ap3d = ap.getDirectionVector();
1578 for (IAtom atm : frag.
atoms())
1581 double dist = ap3d.distance(atm3d);
1584 logger.log(Level.FINE,
"Removing fragment with AP"
1596 for (IAtom atm : frag.
atoms())
1601 if (atm.getMassNumber() ==
null)
1605 int a = atm.getMassNumber();
1607 IIsotope major = Isotopes.getInstance().getMajorIsotope(symb);
1608 if (a != major.getMassNumber())
1610 logger.log(Level.FINE,
"Removing fragment containing "
1611 +
"isotope "+symb+a+
".");
1614 }
catch (Throwable t) {
1615 logger.log(Level.WARNING,
"Not able to perform Isotope"
1627 for (IAtom atm : frag.
atoms())
1632 logger.log(Level.FINE,
"Removing fragment containing '"
1645 for (Map<String,Double> criterion :
1648 for (String el : criterion.keySet())
1650 if (eaMol.containsKey(el))
1653 if (eaMol.get(el) - criterion.get(el) > 0.5)
1655 logger.log(Level.FINE,
"Removing fragment that "
1656 +
"contains too much '" + el +
"' "
1657 +
"as requested by formula"
1658 +
"-based (more-than) settings (" + el
1659 + eaMol.get(el) +
" > " + criterion +
").");
1667 for (String el : criterion.keySet())
1669 if (!eaMol.containsKey(el))
1671 logger.log(Level.FINE,
"Removing fragment that does not "
1672 +
"contain '" + el +
"' as requested by formula"
1673 +
"-based (less-than) settings.");
1677 if (eaMol.get(el) - criterion.get(el) < -0.5)
1679 logger.log(Level.FINE,
"Removing fragment that "
1680 +
"contains too little '" + el +
"' "
1681 +
"as requested by formula"
1682 +
"-based settings (" + el
1683 + eaMol.get(el) +
" < " + criterion +
").");
1697 if (apc.toString().startsWith(s))
1699 logger.log(Level.FINE,
"Removing fragment with APClass "
1709 loopOverCombinations:
1712 for (
int ip=0; ip<conditions.length; ip++)
1714 String condition = conditions[ip];
1715 boolean found =
false;
1718 if (apc.toString().startsWith(condition))
1725 continue loopOverCombinations;
1731 String allCondsAsString =
"";
1732 for (
int i=0; i<conditions.length; i++)
1733 allCondsAsString = allCondsAsString +
" " + conditions[i];
1735 logger.log(Level.FINE,
"Removing fragment with combination of "
1736 +
"APClasses matching '" + allCondsAsString +
"'.");
1744 int totHeavyAtm = 0;
1745 for (IAtom atm : frag.
atoms())
1750 if ((!symb.equals(
"H")) && (!symb.equals(
1758 logger.log(Level.FINE,
"Removing fragment with too many atoms ("
1759 + totHeavyAtm +
" < "
1767 logger.log(Level.FINE,
"Removing fragment with too few atoms ("
1768 + totHeavyAtm +
" < "
1781 logger.log(Level.WARNING,
"Problems evaluating SMARTS-based "
1782 +
"rejection criteria. " + msq.
getMessage());
1789 logger.log(Level.FINE,
"Removing fragment that matches "
1790 +
"SMARTS-based rejection criteria '" + criterion
1803 logger.log(Level.WARNING,
"Problems evaluating SMARTS-based "
1804 +
"rejection criteria. " + msq.
getMessage());
1807 boolean matchesAny =
false;
1818 logger.log(Level.FINE,
"Removing fragment that does not "
1819 +
"match any SMARTS-based retention criteria.");
1839 if (a.getImplicitHydrogenCount()==
null)
1840 a.setImplicitHydrogenCount(0);
1843 int slotNum = (int) (mw / (Double.valueOf(slotSize)));
1844 return slotNum*slotSize +
"-" + (slotNum+1)*slotSize;
1852 IAtomContainer mol = SilentChemObjectBuilder.getInstance()
1853 .newAtomContainer();
1854 Point3d apv = ap.getDirectionVector();
1858 Double.valueOf(apv.x),
1859 Double.valueOf(apv.y),
1860 Double.valueOf(apv.z))));
1866 ap.getOwner().getIAtomContainer().getAtom(
1867 ap.getAtomPositionNumber()));
1868 rcv.
addAP(0, rcvApClass,
new Point3d(
1869 Double.valueOf(aps.x),
1870 Double.valueOf(aps.y),
1871 Double.valueOf(aps.z)));
General set of constants used in DENOPTIM.
static final Object FORMULASTR
Property name used to store molecular formula as string in an atom container.
static final double FLOATCOMPARISONTOLERANCE
Smallest difference for comparison of double and float numbers.
static final String DUMMYATMSYMBOL
Symbol of dummy atom.
static final Object ISOMORPHICFAMILYID
Property used to store the identifier of the family of isomorphic fragments that owns a fragment.
IAtomContainer getTemplateWithBufferShell(int bufferShellSize)
Produced a new IAtomContainer containing all the atoms needed to define the topology of the original ...
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
Container for the list of vertices and the edges that connect them.
This class represents the edge between two vertices.
Class representing a continuously connected portion of chemical object holding attachment points.
void addAP(int atomPositionNumber)
Adds an attachment point with a dummy APClass.
AttachmentPoint addAPOnAtom(IAtom srcAtm, APClass apc, Point3d vector)
Add an attachment point to the specifies atom.
List< AttachmentPoint > getAttachmentPoints()
Fragment clone()
Returns a deep copy of this fragments.
Iterable< IAtom > atoms()
IAtomContainer getIAtomContainer()
void removeAtoms(Collection< IAtom > atoms)
Removes a list of atoms and updates the list of attachment points.
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
ArrayList< APClass > getAllAPClasses()
Returns the list of all APClasses present on this vertex.
void setAsRCV(boolean isRCV)
Object getProperty(Object property)
abstract IAtomContainer getIAtomContainer()
void setProperty(Object key, Object property)
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
static final HashMap< APClass, String > RCALABELPERAPCLASS
Conventional labels for attractor pseudoatom.
Utility methods for input/output.
static File writeVertexesToFile(File file, FileFormat format, List< Vertex > vertexes)
Writes vertexes to file.
static void writeSDFFile(String fileName, IAtomContainer mol)
Writes IAtomContainer to SDF file.
static File writeVertexToFile(File file, FileFormat format, Vertex vertex, boolean append)
Writes vertexes to file.
static ArrayList< DGraph > readDENOPTIMGraphsFromFile(File inFile)
Reads a list of DGraphs from file.
static ArrayList< Vertex > readVertexes(File file, Vertex.BBType bbt)
Reads Vertexes from any file that can contain such items.
An iterator that take IAtomContainers from a file, possibly using an available iterating reader,...
void close()
Close the memory-efficient iterator if any is open.
Tool to build build three-dimensional (3D) tree-like molecular structures from DGraph.
IAtomContainer convertGraphTo3DAtomContainer(DGraph graph)
Created a three-dimensional molecular representation from a given DGraph.
Logger getLogger()
Get the name of the program specific logger.
A cutting rule with three SMARTS queries (atom 1, bond, atom2) and options.
Parameters controlling execution of the fragmenter.
boolean doRejectWeirdIsotopes
Flag requesting to reject fragments with minor isotopes.
Map< String, Double > getRejectedFormulaLessThan()
int getMinFragHeavyAtomCount()
Set< String > getRejectedElements()
Map< String, String > getFragRetentionSMARTS()
int getMaxFragHeavyAtomCount()
Set< Map< String, Double > > getRejectedFormulaMoreThan()
Map< String, String > getFragRejectionSMARTS()
Set< String[]> getRejectedAPClassCombinations()
boolean addExplicitH
Flag requesting to add explicit H atoms.
Set< String > getRejectedAPClasses()
boolean acceptUnsetToSingeBO()
Boolean satisfiesRuleOptions
Flag indicating that we have checked the additional option from the cutting rule (otherwise this flag...
Utilities for working in the Cartesian space.
static Vector3d getNormalDirection(Vector3d dir)
Generate a vector that is perpendicular to the given one.
static Vector3d getVectorFromTo(Point3d a, Point3d b)
Creates an object Vector3d that originates from point a and goes to point b.
static void rotatedVectorWAxisAngle(Vector3d v, Vector3d axis, double ang)
Rotate a vector according to a given rotation axis and angle.
Toll to add/remove dummy atoms from linearities or multi-hapto sites.
static void addDummiesOnLinearities(Fragment frag, double angLim)
Append dummy atoms on otherwise linear arrangements of atoms.
Container of lists of atoms matching a list of SMARTS.
Map< String, Mappings > getAllMatches()
int getNumMatchesOfQuery(String query)
Some useful math operations.
static double angle(Point3d a, Point3d b, Point3d c)
Calculate the angle between the 3 points.
Utilities for molecule conversion.
static void setZeroImplicitHydrogensToAllAtoms(IAtomContainer iac)
Sets zero implicit hydrogen count to all atoms.
static IAtomContainer makeSameAs(IAtomContainer mol)
Constructs a copy of an atom container, i.e., a molecule that reflects the one given in the input arg...
static int getDimensions(IAtomContainer mol)
Determines the dimensionality of the given chemical object.
static String getSymbolOrLabel(IAtom atm)
Gets either the elemental symbol (for standard atoms) of the label (for pseudo-atoms).
static List< Map< IAtom, IAtom > > findUniqueAtomMappings(IAtomContainer substructure, IAtomContainer mol, Logger logger)
Finds the maximum common substructure (MCS) between two molecules.
static void ensureNoUnsetBondOrders(IAtomContainer iac)
Sets bond order = single to all otherwise unset bonds.
static void explicitHydrogens(IAtomContainer mol)
Converts all the implicit hydrogens to explicit.
static Point3d getPoint3d(IAtom atm)
Return the 3D coordinates, if present.
static boolean isElement(IAtom atom)
Check element symbol corresponds to real element of Periodic Table.
Tool to generate random numbers and random decisions.
The type of building block.
Identifier of the type of parameters.
FRG_PARAMS
Parameters controlling the fragmenter.