1package denoptim.fragmenter;
4import java.io.FileInputStream;
5import java.io.IOException;
6import java.util.ArrayList;
7import java.util.Arrays;
8import java.util.HashMap;
9import java.util.HashSet;
13import java.util.logging.Level;
14import java.util.logging.Logger;
16import javax.vecmath.Point3d;
17import javax.vecmath.Vector3d;
19import org.openscience.cdk.Atom;
20import org.openscience.cdk.Bond;
21import org.openscience.cdk.DefaultChemObjectBuilder;
22import org.openscience.cdk.PseudoAtom;
23import org.openscience.cdk.config.Isotopes;
24import org.openscience.cdk.exception.CDKException;
25import org.openscience.cdk.geometry.alignment.KabschAlignment;
26import org.openscience.cdk.interfaces.IAtom;
27import org.openscience.cdk.interfaces.IAtomContainer;
28import org.openscience.cdk.interfaces.IBond;
29import org.openscience.cdk.interfaces.IIsotope;
30import org.openscience.cdk.io.iterator.IteratingSDFReader;
31import org.openscience.cdk.isomorphism.Mappings;
32import org.openscience.cdk.isomorphism.Pattern;
33import org.openscience.cdk.silent.SilentChemObjectBuilder;
34import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
36import denoptim.constants.DENOPTIMConstants;
37import denoptim.exception.DENOPTIMException;
38import denoptim.files.FileFormat;
39import denoptim.files.UndetectedFileFormatException;
40import denoptim.graph.APClass;
41import denoptim.graph.AttachmentPoint;
42import denoptim.graph.DGraph;
43import denoptim.graph.Edge;
44import denoptim.graph.Fragment;
45import denoptim.graph.Template;
46import denoptim.graph.Vertex;
47import denoptim.graph.Vertex.BBType;
48import denoptim.graph.rings.RingClosingAttractor;
49import denoptim.io.DenoptimIO;
50import denoptim.io.IteratingAtomContainerReader;
51import denoptim.molecularmodeling.ThreeDimTreeBuilder;
52import denoptim.programs.RunTimeParameters.ParametersType;
53import denoptim.programs.fragmenter.CuttingRule;
54import denoptim.programs.fragmenter.FragmenterParameters;
55import denoptim.programs.fragmenter.MatchedBond;
56import denoptim.utils.CartesianSpaceUtils;
57import denoptim.utils.DummyAtomHandler;
58import denoptim.utils.FormulaUtils;
59import denoptim.utils.ManySMARTSQuery;
60import denoptim.utils.MathUtils;
61import denoptim.utils.MoleculeUtils;
62import denoptim.utils.Randomizer;
84 File output, Logger logger)
87 FileInputStream fis =
new FileInputStream(input);
88 IteratingSDFReader reader =
new IteratingSDFReader(fis,
89 DefaultChemObjectBuilder.getInstance());
92 int maxBufferSize = 2000;
93 ArrayList<IAtomContainer> buffer =
new ArrayList<IAtomContainer>(500);
95 while (reader.hasNext())
100 logger.log(Level.FINE,
"Checking elemental analysis of "
101 +
"structure " + index);
103 IAtomContainer mol = reader.next();
107 +
"' not found in molecule " + index +
" in file "
108 + input +
". Cannot compare formula with elemental"
121 logger.log(Level.INFO,
"Inconsistency between elemental "
122 +
"analysis of structure and molecular formula."
123 +
" Rejecting structure " + index +
": "
129 if (buffer.size() >= maxBufferSize)
140 if (buffer.size() < maxBufferSize)
175 }
catch (CDKException e)
177 if (e.getMessage().contains(
"Cannot assign Kekulé structure"))
181 settings.
getLogger().log(Level.WARNING,
"Some bond order "
182 +
"are unset and attempt to kekulize the "
183 +
"system has failed "
184 +
"for structure " + index +
". "
185 +
"This hampers use of SMARTS queries, which "
187 +
"not work as expected. Structure " + index
188 +
" will be rejected. "
189 +
"You can avoid rejection by using "
192 +
"UNSETTOSINGLEBO, but you'll "
193 +
"still be using a peculiar connectivity "
195 +
"many bonds are artificially marked as "
197 +
"avoid use of 'UNSET' bond order. "
198 +
"Further details on the problem: "
202 settings.
getLogger().log(Level.WARNING,
"Failed "
204 +
"for structure " + index
205 +
" but UNSETTOSINGLEBO "
206 +
"keyword used. Forcing use of single bonds to "
207 +
"replace bonds with unset order.");
208 for (IBond bnd : mol.bonds())
210 if (bnd.getOrder().equals(IBond.Order.UNSET))
212 bnd.setOrder(IBond.Order.SINGLE);
235 File output, Logger logger)
238 FileInputStream fis =
new FileInputStream(input);
239 IteratingSDFReader reader =
new IteratingSDFReader(fis,
240 DefaultChemObjectBuilder.getInstance());
243 Map<String, String> smartsMap =
new HashMap<String, String>();
244 for (String s : smarts)
247 smartsMap.put(
"prefilter-"+i, s);
251 int maxBufferSize = 2000;
252 ArrayList<IAtomContainer> buffer =
new ArrayList<IAtomContainer>(500);
254 while (reader.hasNext())
259 logger.log(Level.FINE,
"Prefiltering structure " + index);
261 IAtomContainer mol = reader.next();
266 String msg =
"WARNING! Problems while searching for "
267 +
"specific atoms/bonds using SMARTS: "
273 if (allMatches.size()==0)
278 for (String s : allMatches.keySet())
279 hits = hits + DenoptimIO.NL + smartsMap.get(s);
282 logger.log(Level.INFO,
"Found match for " + hits
283 +
"Rejecting structure " + index +
": "
289 if (buffer.size() >= maxBufferSize)
299 if (buffer.size() < maxBufferSize)
330 List<Vertex> fragments = graph.getVertexList();
333 List<Vertex> keptFragments =
new ArrayList<Vertex>();
335 for (
Vertex frag : fragments)
340 keptFragments, logger);
344 logger.log(Level.FINE,
"Fragments surviving post-"
345 +
"processing: " + keptFragments.size());
348 if (keptFragments.size()>0)
350 totalProd += keptFragments.size();
352 keptFragments,
true);
371 List<Vertex> fragments =
new ArrayList<Vertex>();
372 if (settings.getFragmentationTmpls().size()>0)
374 fragments =
fragmentation(mol, settings.getFragmentationTmpls(),
375 settings.getMaxBufferShellSize(),
376 settings.getRandomizer(), settings.getLogger());
379 settings.getLogger());
406 File output, Logger logger)
throws CDKException, IOException,
421 logger.log(Level.FINE,
"Fragmenting structure " + index);
423 IAtomContainer mol = iterator.
next();
424 String molName =
"noname-mol" + index;
425 if (mol.getTitle()!=
null && !mol.getTitle().isBlank())
426 molName = mol.getTitle();
432 logger.log(Level.FINE,
"Fragmentation produced "
433 + fragments.size() +
" fragments.");
435 totalProd += fragments.size();
438 List<Vertex> keptFragments =
new ArrayList<Vertex>();
440 for (
Vertex frag : fragments)
443 String fragIdStr =
"From_" + molName +
"_" + fragCounter;
444 frag.setProperty(
"cdk:Title", fragIdStr);
447 keptFragments, logger);
451 logger.log(Level.FINE,
"Fragments surviving post-"
452 +
"processing: " + keptFragments.size());
454 totalKept += keptFragments.size();
455 if (!settings.doManageIsomorphicFamilies() && totalKept>0)
470 logger.log(Level.WARNING,
"No fragment produced. Cutting rules "
471 +
"were ineffective on the given structures.");
474 }
else if (totalKept==0)
478 logger.log(Level.WARNING,
"No fragment kept out of " + totalProd
479 +
" produced fragments. Filtering criteria might be "
480 +
"too restrictive.");
503 List<DGraph> templates,
int maxBufferShellSize,
509 List<Vertex> fragments =
new ArrayList<Vertex>();
510 int maxNumIsomorfFrgs = -1;
511 for (
DGraph templateGraph : templates)
514 if (!templateGraph.isConnected())
522 +
"Cannot use it for fragmentation. Please check the "
523 +
"template graph and make sure it is connected.");
540 List<Vertex> fragsFromThisTemplate =
new ArrayList<>();
541 int maxNumIsomorfFrgsFromThisTmpl = -1;
545 List<Vertex> templateVertexes = templateGraph.getVertexAnyLevel();
546 int maxTheoreticalScorePerMapping = 0;
547 for (
int iva=0; iva<templateVertexes.size(); iva++)
549 Vertex va = templateVertexes.get(iva);
554 for (
int ivb=0; ivb<templateVertexes.size(); ivb++)
556 Vertex vb = templateVertexes.get(ivb);
564 maxTheoreticalScorePerMapping++;
565 }
else if (((
Fragment) va).isIsomorphicTo(vb))
567 maxTheoreticalScorePerMapping++;
574 for (
int bufferShellSize = 0; bufferShellSize < maxBufferShellSize; bufferShellSize++)
579 reducedTemplateMol, mol, logger);
582 List<Map<IAtom,IAtom>> atomMappings =
new ArrayList<>();
583 for (Map<IAtom,IAtom> reducedMapping : reducedAtomMappings)
585 Map<IAtom,IAtom> fullMapping =
new HashMap<>();
586 for (Map.Entry<IAtom,IAtom> entry : reducedMapping.entrySet())
588 IAtom reducedAtom = entry.getKey();
589 IAtom molAtom = entry.getValue();
592 Object indexObj = reducedAtom.getProperty(
"DENOPTIM_ORIGINAL_ATOM_INDEX");
593 if (indexObj !=
null)
595 int originalIndex = ((Number) indexObj).intValue();
596 IAtom originalAtom = templateMol.getAtom(originalIndex);
597 if (originalAtom !=
null)
599 fullMapping.put(originalAtom, molAtom);
603 if (!fullMapping.isEmpty())
605 atomMappings.add(fullMapping);
617 for (Map<IAtom,IAtom> atomMapping : atomMappings)
621 masterFrag, masterFragIAC, mol, atomMapping);
622 }
catch (Throwable e) {
624 logger.log(Level.WARNING,
"Error while exploring the template graph: " + e.getMessage());
630 List<Vertex> locfragments =
new ArrayList<Vertex>();
631 Set<Integer> doneAlready =
new HashSet<Integer>();
634 if (doneAlready.contains(idx))
640 atmsToKeep.stream().forEach(atm -> doneAlready.add(iac.indexOf(atm)));
642 Set<IAtom> atmsToRemove =
new HashSet<IAtom>();
643 for (IAtom atm : cloneOfMaster.
atoms())
645 if (!atmsToKeep.contains(atm))
647 atmsToRemove.add(atm);
652 locfragments.add(cloneOfMaster);
656 for (
Vertex frag : locfragments)
662 for (
Vertex templateVertex : templateGraph.getVertexList())
664 if (((
Fragment) frag).isIsomorphicTo(templateVertex))
671 if (localScore > maxNumIsomorfFrgsFromThisTmpl)
673 maxNumIsomorfFrgsFromThisTmpl = localScore;
674 fragsFromThisTemplate = locfragments;
675 if (maxNumIsomorfFrgsFromThisTmpl ==
676 maxTheoreticalScorePerMapping*atomMappings.size())
683 if (maxNumIsomorfFrgsFromThisTmpl > maxNumIsomorfFrgs)
685 maxNumIsomorfFrgs = maxNumIsomorfFrgsFromThisTmpl;
686 fragments = fragsFromThisTemplate;
703 Fragment masterFrag, IAtomContainer masterFragIAC, IAtomContainer mol,
704 Map<IAtom,IAtom> graphToMolMapping)
708 for (
Edge edge : graph.getEdgeList())
711 int srcAPIdx = edge.getSrcAP().getAtomPositionNumberInMol();
712 int trgAPIdx = edge.getTrgAP().getAtomPositionNumberInMol();
713 IAtom graphAtmSrc = graphIAC.getAtom(srcAPIdx);
714 IAtom graphAtmTrg = graphIAC.getAtom(trgAPIdx);
716 IAtom masterFragAtmSrc = masterFragIAC.getAtom(mol.indexOf(graphToMolMapping.get(graphAtmSrc)));
717 IAtom masterFragAtmTrg = masterFragIAC.getAtom(mol.indexOf(graphToMolMapping.get(graphAtmTrg)));
719 IBond bnd = masterFragIAC.getBond(masterFragAtmSrc, masterFragAtmTrg);
722 masterFragIAC.removeBond(bnd);
726 edge.getSrcAP().getAPClass(),
730 edge.getTrgAP().getAPClass(),
735 for (
Vertex v : graph.getVertexList())
747 if (!ap.isAvailable())
751 IAtom graphAtmSrc = graphIAC.getAtom(ap.getAtomPositionNumberInMol());
752 IAtom masterFragAtmSrc = masterFragIAC.getAtom(mol.indexOf(graphToMolMapping.get(graphAtmSrc)));
756 graphIAC, masterFragIAC, mol, graphToMolMapping);
759 masterFrag.addAPOnAtom(masterFragAtmSrc, ap.getAPClass(), apHead);
783 IAtom graphAtmSrc, IAtomContainer graphIAC, IAtomContainer masterFragIAC,
788 if (!graphIAC.contains(graphAtmSrc))
790 throw new DENOPTIMException(
"The atom " + graphAtmSrc.getSymbol() +
" is not in the graphIAC.");
792 if (mol.getAtomCount() != masterFragIAC.getAtomCount())
794 throw new DENOPTIMException(
"The number of atoms in the molecule and the master fragment are not the same.");
803 IAtom graphAtmSrcOnMolA = molA.getAtom(mol.indexOf(graphToMolMapping.get(graphAtmSrc)));
806 IAtom dummyAtm =
new Atom(
"He");
807 dummyAtm.setPoint3d(ap.getDirectionVector());
808 molB.addAtom(dummyAtm);
810 List<IAtom> closestNeighborsOnGrphIAC = graphIAC.getConnectedAtomsList(graphAtmSrc);
811 List<IAtom> closestNeighborsOnMolA = molA.getConnectedAtomsList(graphAtmSrcOnMolA);
812 int minNumClosestNeighbors = Math.min(closestNeighborsOnGrphIAC.size(), closestNeighborsOnMolA.size());
813 if (minNumClosestNeighbors < 1)
817 double dist = graphAtmSrc.getPoint3d().distance(ap.getDirectionVector());
818 Point3d apHead =
new Point3d(
819 graphAtmSrcOnMolA.getPoint3d().x + dist,
820 graphAtmSrcOnMolA.getPoint3d().y,
821 graphAtmSrcOnMolA.getPoint3d().z);
823 }
else if (minNumClosestNeighbors == 1) {
825 double dist = graphAtmSrc.getPoint3d().distance(ap.getDirectionVector());
827 closestNeighborsOnGrphIAC.get(0).getPoint3d(),
828 graphAtmSrc.getPoint3d(),
829 ap.getDirectionVector());
830 IAtom nbrAtmOnMolA = molA.getAtom(mol.indexOf(graphToMolMapping.get(closestNeighborsOnGrphIAC.get(0))));
831 Point3d pSrc = graphAtmSrcOnMolA.getPoint3d();
832 Point3d pNbr = nbrAtmOnMolA.getPoint3d();
833 Point3d pSrcTmpl = graphAtmSrc.getPoint3d();
834 Point3d pNbrTmpl = closestNeighborsOnGrphIAC.get(0).getPoint3d();
835 Point3d pApTmpl = ap.getDirectionVector();
844 double angleRad = Math.toRadians(angle);
845 Vector3d apDir =
new Vector3d();
846 apDir.scale(Math.cos(angleRad), uMol);
847 double sinAngle = Math.sin(angleRad);
850 Vector3d vRefTmpl =
new Vector3d(wTmpl);
851 vRefTmpl.scaleAdd(-uTmpl.dot(wTmpl), uTmpl, vRefTmpl);
852 vRefTmpl.normalize();
853 Vector3d rotAxis =
new Vector3d();
854 rotAxis.cross(uTmpl, uMol);
855 double sinRot = rotAxis.length();
856 double cosRot = uTmpl.dot(uMol);
860 double rotAng = Math.toDegrees(Math.atan2(sinRot, cosRot));
863 else if (cosRot < 0.0)
868 vRefTmpl.scale(sinAngle);
872 Point3d apHead =
new Point3d(
873 pSrc.x + dist * apDir.x,
874 pSrc.y + dist * apDir.y,
875 pSrc.z + dist * apDir.z);
879 Map<IAtom,IAtom> molToGraphMappingAroundAPSrc =
new HashMap<>();
880 Set<IAtom> atomsAlreadyUsed =
new HashSet<>();
881 for (Map.Entry<IAtom,IAtom> pair : graphToMolMapping.entrySet())
883 IAtom atmGraphIAC = pair.getKey();
884 if (graphIAC.getConnectedAtomsList(graphAtmSrc).contains(atmGraphIAC)
885 || atmGraphIAC == graphAtmSrc)
887 atomsAlreadyUsed.add(atmGraphIAC);
888 molToGraphMappingAroundAPSrc.put(
889 molA.getAtom(mol.indexOf(pair.getValue())),
890 molB.getAtom(graphIAC.indexOf(atmGraphIAC)));
894 if (minNumClosestNeighbors<3)
896 for (Map.Entry<IAtom,IAtom> pair : graphToMolMapping.entrySet())
898 IAtom atmGraphIAC = pair.getKey();
899 if (closestNeighborsOnGrphIAC.contains(atmGraphIAC)
900 && !atomsAlreadyUsed.contains(atmGraphIAC))
902 atomsAlreadyUsed.add(atmGraphIAC);
903 molToGraphMappingAroundAPSrc.put(
904 molA.getAtom(mol.indexOf(pair.getValue())),
905 molB.getAtom(graphIAC.indexOf(atmGraphIAC)));
911 IAtom[] lstA =
new IAtom[molToGraphMappingAroundAPSrc.size()];
912 IAtom[] lstB =
new IAtom[molToGraphMappingAroundAPSrc.size()];
914 for (Map.Entry<IAtom,IAtom> pair : molToGraphMappingAroundAPSrc.entrySet())
916 lstA[k] = pair.getKey();
917 lstB[k] = pair.getValue();
925 sa =
new KabschAlignment(lstA, lstB);
927 }
catch (Throwable t) {
932 sa.rotateAtomContainer(molB);
935 Point3d cm = sa.getCenterOfMass();
936 for (
int ib = 0; ib < molB.getAtomCount(); ib++)
938 IAtom a = molB.getAtom(ib);
940 Point3d newPlace =
new Point3d(oldPlace.x + cm.x,
943 a.setPoint3d(newPlace);
966 Map<String, List<MatchedBond>> matchingbonds =
973 String ruleName = rule.getName();
976 if (!matchingbonds.keySet().contains(ruleName))
981 IAtom atmA = tb.getAtmSubClass0();
982 IAtom atmB = tb.getAtmSubClass1();
985 if (!fragsMol.getConnectedAtomsList(atmA).contains(atmB))
1001 IAtom centralAtm = atmA;
1005 ArrayList<IAtom> candidatesForHapto =
new ArrayList<IAtom>();
1006 for (
MatchedBond tbForHapto : matchingbonds.get(ruleName))
1009 if (tbForHapto.getAtmSubClass0() == centralAtm)
1010 candidatesForHapto.add(tbForHapto.getAtmSubClass1());
1015 Set<IAtom> atmsInHapto =
new HashSet<IAtom>();
1016 atmsInHapto.add(tb.getAtmSubClass1());
1018 centralAtm, candidatesForHapto, fragsMol);
1019 if (atmsInHapto.size() == 1)
1021 logger.log(Level.WARNING,
"Unable to find more than one "
1022 +
"bond involved in high-hapticity ligand! "
1028 boolean isSystemIntact =
true;
1029 for (IAtom ligAtm : atmsInHapto)
1031 List<IAtom> nbrsOfLigAtm =
1032 fragsMol.getConnectedAtomsList(ligAtm);
1033 if (!nbrsOfLigAtm.contains(centralAtm))
1035 isSystemIntact =
false;
1042 if (!isSystemIntact)
1045 srcAPA = centralAtm;
1046 srcAPB =
getAPSourceAtom(masterFrag,
new ArrayList<>(atmsInHapto), Arrays.asList(centralAtm));
1050 List<List<List<IAtom>>> listOfAtomPairs =
new ArrayList<>();
1051 List<List<APClass>> listOfAPClasses =
new ArrayList<>();
1052 listOfAtomPairs.add(Arrays.asList(Arrays.asList(srcAPA), Arrays.asList(srcAPB)));
1053 listOfAPClasses.add(Arrays.asList(rule.getAPClass0(), rule.getAPClass1()));
1055 makeAPPairs(masterFrag, listOfAtomPairs, listOfAPClasses, cutId);
1079 List<List<List<IAtom>>> atomPairs, List<List<APClass>> apClasses)
1086 List<List<List<IAtom>>> projectedAtomPairs =
new ArrayList<>();
1087 for (List<List<IAtom>> atomPair : atomPairs)
1089 List<List<IAtom>> projectedAtomPair =
new ArrayList<>();
1090 for (List<IAtom> leftOrRightMembers : atomPair)
1092 List<IAtom> projectedLeftOrRightMembers =
new ArrayList<>();
1093 for (IAtom atm : leftOrRightMembers)
1095 projectedLeftOrRightMembers.add(fragsMol.getAtom(mol.indexOf(atm)));
1097 projectedAtomPair.add(projectedLeftOrRightMembers);
1099 projectedAtomPairs.add(projectedAtomPair);
1101 makeAPPairs(masterFrag, projectedAtomPairs, apClasses, 1);
1110 List<Vertex> fragments =
new ArrayList<Vertex>();
1111 Set<Integer> doneAlready =
new HashSet<Integer>();
1112 for (
int idx=0 ; idx<masterFrag.getAtomCount(); idx++)
1114 if (doneAlready.contains(idx))
1120 atmsToKeep.stream().forEach(atm -> doneAlready.add(iac.indexOf(atm)));
1122 Set<IAtom> atmsToRemove =
new HashSet<IAtom>();
1123 for (IAtom atm : cloneOfMaster.
atoms())
1125 if (!atmsToKeep.contains(atm))
1127 atmsToRemove.add(atm);
1132 fragments.add(cloneOfMaster);
1153 List<List<List<IAtom>>> atomPairs, List<List<APClass>> apClasses, Integer cutId)
1156 for (
int i = 0; i < atomPairs.size(); i++)
1160 List<List<IAtom>> atomPair = atomPairs.get(i);
1161 APClass apClassA = apClasses.get(i).get(0);
1162 APClass apClassB = apClasses.get(i).get(1);
1164 IAtom srcAPA =
getAPSourceAtom(masterFrag, atomPair.get(0), atomPair.get(1));
1165 IAtom srcAPB =
getAPSourceAtom(masterFrag, atomPair.get(1), atomPair.get(0));
1168 IBond bnd = masterFrag.getIAtomContainer().getBond(srcAPA,srcAPB);
1171 masterFrag.removeBond(bnd);
1202 if (atmsInHapto.size() == 1)
1204 return atmsInHapto.get(0);
1207 IAtomContainer fragsMol = masterFrag.getIAtomContainer();
1210 Point3d dummyP3d =
new Point3d();
1211 for (IAtom ligAtm : atmsInHapto)
1214 dummyP3d.x = dummyP3d.x + ligP3d.x;
1215 dummyP3d.y = dummyP3d.y + ligP3d.y;
1216 dummyP3d.z = dummyP3d.z + ligP3d.z;
1219 dummyP3d.x = dummyP3d.x / (double) atmsInHapto.size();
1220 dummyP3d.y = dummyP3d.y / (double) atmsInHapto.size();
1221 dummyP3d.z = dummyP3d.z / (double) atmsInHapto.size();
1225 IAtom dummyAtm =
null;
1226 for (IAtom oldDu : fragsMol.atoms())
1231 Point3d oldDuP3d = oldDu.getPoint3d();
1232 if (oldDuP3d.distance(dummyP3d) < 0.002)
1244 dummyAtm.setPoint3d(dummyP3d);
1245 fragsMol.addAtom(dummyAtm);
1251 IBond.Order border = IBond.Order.valueOf(
"SINGLE");
1253 for (IAtom ligAtm : atmsInHapto)
1255 List<IAtom> nbrsOfDu = fragsMol.getConnectedAtomsList(
1257 if (!nbrsOfDu.contains(ligAtm))
1260 Bond bnd =
new Bond(dummyAtm,ligAtm,border);
1261 fragsMol.addBond(bnd);
1264 for (IAtom atmOutsideHapto : atmsOutsideHapto)
1266 IBond oldBnd = fragsMol.getBond(atmOutsideHapto,ligAtm);
1267 fragsMol.removeBond(oldBnd);
1288 ArrayList<IAtom> candidates, IAtomContainer mol)
1290 Set<IAtom> atmsInHapto =
new HashSet<IAtom>();
1291 atmsInHapto.add(seed);
1292 ArrayList<IAtom> toVisitAtoms =
new ArrayList<IAtom>();
1293 toVisitAtoms.add(seed);
1294 ArrayList<IAtom> visitedAtoms =
new ArrayList<IAtom>();
1295 while (toVisitAtoms.size()>0)
1297 ArrayList<IAtom> toVisitLater =
new ArrayList<IAtom>();
1298 for (IAtom atomInFocus : toVisitAtoms)
1300 if (visitedAtoms.contains(atomInFocus)
1301 || atomInFocus==centralAtom)
1304 visitedAtoms.add(atomInFocus);
1306 if (candidates.contains(atomInFocus))
1308 atmsInHapto.add(atomInFocus);
1309 toVisitLater.addAll(mol.getConnectedAtomsList(atomInFocus));
1312 toVisitAtoms.clear();
1313 toVisitAtoms.addAll(toVisitLater);
1329 Set<IAtom> atmsReachableFromSeed =
new HashSet<IAtom>();
1330 ArrayList<IAtom> toVisitAtoms =
new ArrayList<IAtom>();
1331 toVisitAtoms.add(seed);
1332 ArrayList<IAtom> visitedAtoms =
new ArrayList<IAtom>();
1333 while (toVisitAtoms.size()>0)
1335 ArrayList<IAtom> toVisitLater =
new ArrayList<IAtom>();
1336 for (IAtom atomInFocus : toVisitAtoms)
1338 if (visitedAtoms.contains(atomInFocus))
1341 visitedAtoms.add(atomInFocus);
1343 atmsReachableFromSeed.add(atomInFocus);
1344 toVisitLater.addAll(mol.getConnectedAtomsList(atomInFocus));
1346 toVisitAtoms.clear();
1347 toVisitAtoms.addAll(toVisitLater);
1349 return atmsReachableFromSeed;
1363 IAtomContainer mol, List<CuttingRule> rules, Logger logger)
1366 Map<String,String> smarts =
new HashMap<String,String>();
1369 smarts.put(rule.getName(),rule.getWholeSMARTSRule());
1373 Map<String, List<MatchedBond>> bondsMatchingRules =
1374 new HashMap<String, List<MatchedBond>>();
1378 if (msq.hasProblems())
1382 logger.log(Level.WARNING,
"Problem matching SMARTS: "
1383 + msq.getMessage());
1385 return bondsMatchingRules;
1390 String ruleName = rule.getName();
1392 if (msq.getNumMatchesOfQuery(ruleName) == 0)
1398 Mappings purgedPairs = msq.getMatchesOfSMARTS(ruleName);
1401 ArrayList<MatchedBond> bondsMatched =
new ArrayList<MatchedBond>();
1402 for (
int[] pair : purgedPairs)
1406 throw new Error(
"Cutting rule: " + ruleName
1407 +
" has identified " + pair.length +
" atoms "
1408 +
"instead of 2. Modify rule to make it find a "
1409 +
"pair of atoms.");
1412 mol.getAtom(pair[1]), rule);
1416 bondsMatched.add(tb);
1419 if (!bondsMatched.isEmpty())
1420 bondsMatchingRules.put(ruleName, bondsMatched);
1423 return bondsMatchingRules;
1438 FileInputStream fis =
new FileInputStream(input);
1439 IteratingSDFReader reader =
new IteratingSDFReader(fis,
1440 DefaultChemObjectBuilder.getInstance());
1443 int maxBufferSize = 2000;
1444 ArrayList<Vertex> buffer =
new ArrayList<Vertex>(500);
1446 while (reader.hasNext())
1451 logger.log(Level.FINE,
"Processing fragment " + index);
1458 if (buffer.size() >= maxBufferSize)
1468 if (buffer.size() < maxBufferSize)
1497 List<Vertex> collector, Logger logger)
1508 if (settings.getIgnorableFragments().size() > 0)
1510 if (settings.getIgnorableFragments().stream()
1511 .anyMatch(ignorable -> ((
Fragment)frag)
1512 .isIsomorphicTo(ignorable)))
1516 logger.log(Level.FINE,
"Fragment " + fragCounter
1517 +
" is ignorable.");
1524 if (settings.getTargetFragments().size() > 0)
1526 if (!settings.getTargetFragments().stream()
1527 .anyMatch(ignorable -> ((
Fragment)frag)
1528 .isIsomorphicTo(ignorable)))
1532 logger.log(Level.FINE,
"Fragment " + fragCounter
1533 +
" doesn't match any target: rejected.");
1541 && settings.doAddDuOnLinearity())
1544 settings.getLinearAngleLimit());
1551 if (settings.doManageIsomorphicFamilies())
1553 synchronized (settings.MANAGEMWSLOTSSLOCK)
1556 settings.getMWSlotSize());
1558 File mwFileUnq = settings.getMWSlotFileNameUnqFrags(
1560 File mwFileAll = settings.getMWSlotFileNameAllFrags(
1564 Vertex unqVersion =
null;
1565 if (mwFileUnq.exists())
1567 ArrayList<Vertex> knownFrags =
1569 unqVersion = knownFrags.stream()
1570 .filter(knownFrag ->
1571 ((
Fragment)frag).isIsomorphicTo(knownFrag))
1575 if (unqVersion!=
null)
1584 int sampleSize = settings.getIsomorphsCount()
1586 if (sampleSize < settings.getIsomorphicSampleSize())
1592 settings.getIsomorphsCount().put(isoFamID,
1596 collector.add(frag);
1617 String isoFamID = settings.newIsomorphicFamilyID();
1621 settings.getIsomorphsCount().put(isoFamID, 1);
1626 collector.add(frag);
1631 collector.add(frag);
1669 for (IAtom atm : frag.
atoms())
1680 logger.log(Level.FINE,
"Removing fragment contains non-element '"
1690 Point3d ap3d = ap.getDirectionVector();
1693 for (IAtom atm : frag.
atoms())
1696 double dist = ap3d.distance(atm3d);
1699 logger.log(Level.FINE,
"Removing fragment with AP"
1711 for (IAtom atm : frag.
atoms())
1716 if (atm.getMassNumber() ==
null)
1720 int a = atm.getMassNumber();
1722 IIsotope major = Isotopes.getInstance().getMajorIsotope(symb);
1723 if (a != major.getMassNumber())
1725 logger.log(Level.FINE,
"Removing fragment containing "
1726 +
"isotope "+symb+a+
".");
1729 }
catch (Throwable t) {
1730 logger.log(Level.WARNING,
"Not able to perform Isotope"
1742 for (IAtom atm : frag.
atoms())
1747 logger.log(Level.FINE,
"Removing fragment containing '"
1760 for (Map<String,Double> criterion :
1763 for (String el : criterion.keySet())
1765 if (eaMol.containsKey(el))
1768 if (eaMol.get(el) - criterion.get(el) > 0.5)
1770 logger.log(Level.FINE,
"Removing fragment that "
1771 +
"contains too much '" + el +
"' "
1772 +
"as requested by formula"
1773 +
"-based (more-than) settings (" + el
1774 + eaMol.get(el) +
" > " + criterion +
").");
1782 for (String el : criterion.keySet())
1784 if (!eaMol.containsKey(el))
1786 logger.log(Level.FINE,
"Removing fragment that does not "
1787 +
"contain '" + el +
"' as requested by formula"
1788 +
"-based (less-than) settings.");
1792 if (eaMol.get(el) - criterion.get(el) < -0.5)
1794 logger.log(Level.FINE,
"Removing fragment that "
1795 +
"contains too little '" + el +
"' "
1796 +
"as requested by formula"
1797 +
"-based settings (" + el
1798 + eaMol.get(el) +
" < " + criterion +
").");
1812 if (apc.toString().startsWith(s))
1814 logger.log(Level.FINE,
"Removing fragment with APClass "
1824 loopOverCombinations:
1827 for (
int ip=0; ip<conditions.length; ip++)
1829 String condition = conditions[ip];
1830 boolean found =
false;
1833 if (apc.toString().startsWith(condition))
1840 continue loopOverCombinations;
1846 String allCondsAsString =
"";
1847 for (
int i=0; i<conditions.length; i++)
1848 allCondsAsString = allCondsAsString +
" " + conditions[i];
1850 logger.log(Level.FINE,
"Removing fragment with combination of "
1851 +
"APClasses matching '" + allCondsAsString +
"'.");
1859 int totHeavyAtm = 0;
1860 for (IAtom atm : frag.
atoms())
1865 if ((!symb.equals(
"H")) && (!symb.equals(
1873 logger.log(Level.FINE,
"Removing fragment with too many atoms ("
1874 + totHeavyAtm +
" < "
1882 logger.log(Level.FINE,
"Removing fragment with too few atoms ("
1883 + totHeavyAtm +
" < "
1896 logger.log(Level.WARNING,
"Problems evaluating SMARTS-based "
1897 +
"rejection criteria. " + msq.
getMessage());
1904 logger.log(Level.FINE,
"Removing fragment that matches "
1905 +
"SMARTS-based rejection criteria '" + criterion
1918 logger.log(Level.WARNING,
"Problems evaluating SMARTS-based "
1919 +
"rejection criteria. " + msq.
getMessage());
1922 boolean matchesAny =
false;
1933 logger.log(Level.FINE,
"Removing fragment that does not "
1934 +
"match any SMARTS-based retention criteria.");
1954 if (a.getImplicitHydrogenCount()==
null)
1955 a.setImplicitHydrogenCount(0);
1958 int slotNum = (int) (mw / (Double.valueOf(slotSize)));
1959 return slotNum*slotSize +
"-" + (slotNum+1)*slotSize;
1967 IAtomContainer mol = SilentChemObjectBuilder.getInstance()
1968 .newAtomContainer();
1969 Point3d apv = ap.getDirectionVector();
1973 Double.valueOf(apv.x),
1974 Double.valueOf(apv.y),
1975 Double.valueOf(apv.z))));
1981 ap.getOwner().getIAtomContainer().getAtom(
1982 ap.getAtomPositionNumber()));
1983 rcv.
addAP(0, rcvApClass,
new Point3d(
1984 Double.valueOf(aps.x),
1985 Double.valueOf(aps.y),
1986 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.
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.