20package denoptim.utils;
23import java.util.ArrayList;
24import java.util.Arrays;
25import java.util.Collections;
26import java.util.HashMap;
27import java.util.HashSet;
31import java.util.logging.Level;
32import java.util.logging.Logger;
34import javax.vecmath.Point2d;
35import javax.vecmath.Point3d;
37import org.openscience.cdk.Atom;
38import org.openscience.cdk.AtomContainer;
39import org.openscience.cdk.AtomRef;
40import org.openscience.cdk.CDKConstants;
41import org.openscience.cdk.Mapping;
42import org.openscience.cdk.PseudoAtom;
43import org.openscience.cdk.aromaticity.Kekulization;
44import org.openscience.cdk.config.IsotopeFactory;
45import org.openscience.cdk.config.Isotopes;
46import org.openscience.cdk.depict.Depiction;
47import org.openscience.cdk.depict.DepictionGenerator;
48import org.openscience.cdk.exception.CDKException;
49import org.openscience.cdk.geometry.GeometryUtil;
50import org.openscience.cdk.graph.ConnectivityChecker;
51import org.openscience.cdk.inchi.InChIGenerator;
52import org.openscience.cdk.inchi.InChIGeneratorFactory;
53import org.openscience.cdk.interfaces.IAtom;
54import org.openscience.cdk.interfaces.IAtomContainer;
55import org.openscience.cdk.interfaces.IAtomContainerSet;
56import org.openscience.cdk.interfaces.IAtomType.Hybridization;
57import org.openscience.cdk.interfaces.IBond;
58import org.openscience.cdk.interfaces.IChemObjectBuilder;
59import org.openscience.cdk.interfaces.IElement;
60import org.openscience.cdk.isomorphism.Mappings;
61import org.openscience.cdk.isomorphism.Pattern;
62import org.openscience.cdk.layout.StructureDiagramGenerator;
63import org.openscience.cdk.qsar.DescriptorValue;
64import org.openscience.cdk.qsar.IMolecularDescriptor;
65import org.openscience.cdk.qsar.descriptors.molecular.RotatableBondsCountDescriptor;
66import org.openscience.cdk.qsar.descriptors.molecular.WeightDescriptor;
67import org.openscience.cdk.qsar.result.DoubleResult;
68import org.openscience.cdk.qsar.result.IntegerResult;
69import org.openscience.cdk.silent.SilentChemObjectBuilder;
70import org.openscience.cdk.smiles.SmiFlavor;
71import org.openscience.cdk.smiles.SmilesGenerator;
72import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
74import denoptim.constants.DENOPTIMConstants;
75import denoptim.exception.DENOPTIMException;
76import denoptim.graph.APClass;
77import denoptim.graph.AttachmentPoint;
78import denoptim.graph.DGraph;
79import denoptim.graph.Edge.BondType;
80import denoptim.graph.Fragment;
81import denoptim.graph.Ring;
82import denoptim.graph.Vertex;
83import denoptim.graph.Vertex.BBType;
84import denoptim.graph.rings.RingClosingAttractor;
85import denoptim.io.DenoptimIO;
86import denoptim.logging.StaticLogger;
87import io.github.dan2097.jnainchi.InchiFlag;
88import io.github.dan2097.jnainchi.InchiOptions;
89import io.github.dan2097.jnainchi.InchiStatus;
99 private static final StructureDiagramGenerator
SDG =
100 new StructureDiagramGenerator();
101 private static final SmilesGenerator
SMGEN =
new SmilesGenerator(
103 private static final IChemObjectBuilder
builder =
104 SilentChemObjectBuilder.getInstance();
114 WeightDescriptor wd =
new WeightDescriptor();
115 Object[] pars = {
"*"};
116 wd.setParameters(pars);
117 ret_wd = ((DoubleResult) wd.calculate(mol).getValue())
155 String symbol = atom.getSymbol();
171 IsotopeFactory ifact =
null;
173 ifact = Isotopes.getInstance();
174 if (ifact.isElement(symbol))
176 @SuppressWarnings(
"unused")
177 IElement el = ifact.getElement(symbol);
180 }
catch (Throwable t) {
181 throw new Error(
"ERROR! Unable to create Isotope.");
197 for (IAtom a : mol.atoms())
199 boolean isRca =
false;
201 for (String rcaEl : rcaElSymbols)
211 IAtom newAtm =
new Atom(
"H",
new Point3d(a.getPoint3d()));
212 newAtm.setProperties(a.getProperties());
213 AtomContainerManipulator.replaceAtomByAtom(mol,a,newAtm);
232 ArrayList<Vertex> usedRcvs = graph.getUsedRCVertices();
233 Map<Vertex,ArrayList<Integer>> vIdToAtmId =
235 if (vIdToAtmId.size() == 0)
240 ArrayList<IAtom> atmsToRemove =
new ArrayList<>();
241 ArrayList<Boolean> doneVertices =
242 new ArrayList<>(Collections.nCopies(usedRcvs.size(),
false));
246 if (doneVertices.get(usedRcvs.indexOf(v)))
250 ArrayList<Ring> rings = graph.getRingsInvolvingVertex(v);
251 if (rings.size() != 1)
253 String s =
"Unexpected inconsistency between used RCV list "
254 + v +
" in {" + usedRcvs +
"}"
255 +
"and list of DENOPTIMRings "
256 +
"{" + rings +
"}. Check Code!";
259 Vertex vH = rings.get(0).getHeadVertex();
260 Vertex vT = rings.get(0).getTailVertex();
261 IAtom aH = mol.getAtom(vIdToAtmId.get(vH).get(0));
262 IAtom aT = mol.getAtom(vIdToAtmId.get(vT).get(0));
263 if (mol.getConnectedAtomsList(aH).size() == 0
264 || mol.getConnectedAtomsList(aT).size() == 0)
269 int iSrcH = mol.indexOf(mol.getConnectedAtomsList(aH).get(0));
270 int iSrcT = mol.indexOf(mol.getConnectedAtomsList(aT).get(0));
271 atmsToRemove.add(aH);
272 atmsToRemove.add(aT);
274 BondType bndTyp = rings.get(0).getBondType();
279 logger.log(Level.WARNING,
"WARNING! "
280 +
"Attempt to add ring closing bond "
281 +
"did not add any actual chemical bond because the "
282 +
"bond type of the chord is '" + bndTyp +
"'.");
285 doneVertices.set(usedRcvs.indexOf(vH),
true);
286 doneVertices.set(usedRcvs.indexOf(vT),
true);
290 ArrayList<Integer> removedIds =
new ArrayList<Integer>();
291 for (IAtom a : atmsToRemove)
293 removedIds.add(mol.indexOf(a));
295 Collections.sort(removedIds);
296 for (
Vertex v : graph.getVertexList())
300 int apSrcId = ap.getAtomPositionNumberInMol();
301 int countOfAtmsBEforeSrc = 0;
302 for (Integer removingId : removedIds)
304 if (removingId < apSrcId)
306 countOfAtmsBEforeSrc++;
307 }
else if (removingId > apSrcId)
312 ap.setAtomPositionNumberInMol(apSrcId-countOfAtmsBEforeSrc);
317 for (IAtom a : atmsToRemove)
336 IAtomContainer fmol =
builder.newAtomContainer();
341 catch (CloneNotSupportedException e)
362 smiles =
SMGEN.create(fmol);
367 String fileName =
"failed_generation_of_SMILES.sdf";
368 logger.log(Level.WARNING,
"WARNING: Skipping calculation of SMILES. "
369 +
"See file '" + fileName +
"'");
371 smiles =
"calculation_or_SMILES_crashed";
391 IAtomContainer fmol =
builder.newAtomContainer();
396 catch (CloneNotSupportedException e)
410 IAtomContainer ac2d =
builder.newAtomContainer();
411 IAtomContainerSet som = ConnectivityChecker.partitionIntoMolecules(
414 for (
int n = 0; n < som.getAtomContainerCount(); n++)
418 IAtomContainer mol = som.getAtomContainer(n);
419 SDG.setMolecule(mol,
true);
423 SDG.generateCoordinates();
424 mol =
SDG.getMolecule();
435 return GeometryUtil.has2DCoordinates(ac2d) ? ac2d :
null;
453 InchiOptions options =
new InchiOptions.InchiOptionsBuilder()
454 .withFlag(InchiFlag.AuxNone)
455 .withFlag(InchiFlag.RecMet)
456 .withFlag(InchiFlag.SUU)
473 IAtomContainer fmol =
builder.newAtomContainer();
494 InChIGeneratorFactory factory = InChIGeneratorFactory.getInstance();
495 InChIGenerator gen = factory.getInChIGenerator(fmol, options);
496 InchiStatus ret = gen.getStatus();
497 if (ret == InchiStatus.WARNING)
503 else if (ret != InchiStatus.SUCCESS)
507 inchikey = gen.getInchiKey();
509 catch (CDKException cdke)
513 if (inchikey.length() > 0)
533 IMolecularDescriptor descriptor =
534 new RotatableBondsCountDescriptor();
535 descriptor.setParameters(
new Object[]{Boolean.FALSE,Boolean.FALSE});
536 DescriptorValue result = descriptor.calculate(mol);
537 value = ((IntegerResult)result.getValue()).intValue();
539 catch (CDKException cdke)
557 for (IAtom atm : mol.atoms())
578 for (IAtom atm : mol.atoms())
580 if (atm.getSymbol().equals(symbol))
600 ArrayList<Vertex> vertLst,
604 ArrayList<Long> vertIDs =
new ArrayList<>();
605 for (
Vertex v : vertLst) {
606 vertIDs.add(v.getVertexId());
609 Map<Vertex,ArrayList<Integer>> map =
new HashMap<>();
610 for (IAtom atm : mol.atoms())
612 long vID = Long.parseLong(atm.getProperty(
614 if (vertIDs.contains(vID))
616 Vertex v = vertLst.get(vertIDs.indexOf(vID));
617 int atmID = mol.indexOf(atm);
618 if (map.containsKey(v))
620 map.get(v).add(atmID);
624 ArrayList<Integer> atmLst =
new ArrayList<>();
646 IAtomContainer iac = mol;
648 if (!GeometryUtil.has2DCoordinates(mol))
660 Depiction depiction =
new DepictionGenerator().depict(iac);
661 depiction.writeTo(filename);
662 }
catch (Exception e)
679 Point3d p = atm.getPoint3d();
683 Point2d p2d = atm.getPoint2d();
686 p =
new Point3d(0.0, 0.0, 0.0);
688 p =
new Point3d(p2d.x, p2d.y, 0.0);
704 for (IAtom atm : iac.atoms()) {
705 atm.setImplicitHydrogenCount(0);
716 AtomContainerManipulator.convertImplicitToExplicitHydrogens(mol);
733 }
catch (CDKException e) {
735 +
"Bond orders will be unreliable as all unset bonds are"
736 +
"now converted to single-order bonds.");
738 for (IBond bnd : iac.bonds())
740 if (bnd.getOrder().equals(IBond.Order.UNSET))
742 bnd.setOrder(IBond.Order.SINGLE);
759 Kekulization.kekulize(iac);
761 for (IBond bnd : iac.bonds())
763 if (bnd.getOrder().equals(IBond.Order.UNSET))
765 bnd.setOrder(IBond.Order.SINGLE);
782 for (IAtom atm : mol.atoms())
785 if (atm.getSymbol().equals(
"C") && atm.getFormalCharge() == 0
786 && mol.getConnectedBondsCount(atm) == 3)
788 if (atm.getFlag(CDKConstants.ISAROMATIC))
793 cause =
"Aromatic atom " +
getAtomRef(atm,mol)
794 +
" has 3 connected atoms but no double bonds";
798 for (IAtom nbr : mol.getConnectedAtomsList(atm))
800 if (nbr.getSymbol().equals(
"C"))
802 if (nbr.getFormalCharge() == 0)
804 if (mol.getConnectedBondsCount(nbr) == 3)
810 if ((nNbr == 3) && (nAtm == 3))
812 cause =
"Connected atoms "
815 +
" have 3 connected atoms "
816 +
"but no double bond. They are "
817 +
"likely to be aromatic but no "
818 +
"aromaticity has been reported.";
845 for (IBond bnd : mol.getConnectedBondsList(atm))
847 if (bnd.getOrder() == order)
866 IChemObjectBuilder
builder = SilentChemObjectBuilder.getInstance();
867 IAtomContainer iac =
builder.newAtomContainer();
869 for (IAtom oAtm : mol.atoms())
875 for (IBond oBnd : mol.bonds())
877 if (oBnd.getAtomCount() != 2)
880 +
"involving more than two atoms.");
882 int ia = mol.indexOf(oBnd.getAtom(0));
883 int ib = mol.indexOf(oBnd.getAtom(1));
884 iac.addBond(ia,ib,oBnd.getOrder());
924 boolean ignoreImplicitH)
932 nAtm =
new PseudoAtom(s);
934 if (oAtm.getPoint3d() !=
null)
936 Point3d p3d = oAtm.getPoint3d();
937 nAtm.setPoint3d(
new Point3d(p3d.x, p3d.y, p3d.z));
938 }
else if (oAtm.getPoint2d() !=
null)
940 Point2d p2d = oAtm.getPoint2d();
941 nAtm.setPoint3d(
new Point3d(p2d.x, p2d.y, 0.00001));
943 if (oAtm.getFormalCharge() !=
null)
944 nAtm.setFormalCharge(oAtm.getFormalCharge());
945 if (oAtm.getBondOrderSum() !=
null)
946 nAtm.setBondOrderSum(oAtm.getBondOrderSum());
947 if (oAtm.getCharge() !=
null)
948 nAtm.setCharge(oAtm.getCharge());
949 if (oAtm.getValency() !=
null && !ignoreValence)
950 nAtm.setValency(oAtm.getValency());
951 if (oAtm.getExactMass() !=
null)
952 nAtm.setExactMass(oAtm.getExactMass());
953 if (oAtm.getMassNumber() !=
null)
954 nAtm.setMassNumber(oAtm.getMassNumber());
955 if (oAtm.getFormalNeighbourCount() !=
null)
956 nAtm.setFormalNeighbourCount(oAtm.getFormalNeighbourCount());
957 if (oAtm.getFractionalPoint3d() !=
null)
958 nAtm.setFractionalPoint3d(
new Point3d(oAtm.getFractionalPoint3d()));
959 if (oAtm.getHybridization() !=
null)
960 nAtm.setHybridization(Hybridization.valueOf(
961 oAtm.getHybridization().toString()));
962 if (oAtm.getImplicitHydrogenCount() !=
null && !ignoreImplicitH)
963 nAtm.setImplicitHydrogenCount(oAtm.getImplicitHydrogenCount());
964 if (oAtm.getMaxBondOrder() !=
null)
965 nAtm.setMaxBondOrder(oAtm.getMaxBondOrder());
966 if (oAtm.getNaturalAbundance() !=
null)
967 nAtm.setNaturalAbundance(oAtm.getNaturalAbundance());
993 if (atm instanceof AtomRef)
995 a = ((AtomRef) atm).deref();
996 if (a instanceof PseudoAtom)
998 s = ((PseudoAtom) a).getLabel();
1004 }
else if (atm instanceof PseudoAtom)
1006 s = ((PseudoAtom) atm).getLabel();
1020 return atm.getSymbol() + (mol.indexOf(atm) +1);
1032 Point3d c =
new Point3d(0,0,0);
1033 for (IAtom atm : mol.atoms())
1037 c.scale(1.0 / ((
double) mol.getAtomCount()));
1070 Set<Long> wantedVIDs =
new HashSet<Long>();
1071 Map<Long,Vertex> wantedVertexesMap =
new HashMap<>();
1072 for (
Vertex v : subGraph.getVertexList())
1079 +
"vertex " + v +
", but is needed to extract "
1082 wantedVIDs.add(((Long) o).longValue());
1083 wantedVertexesMap.put(((Long) o).longValue(), v);
1087 IAtomContainer toRemove =
new AtomContainer();
1088 Map<IAtom,IAtom> toAP =
new HashMap<IAtom,IAtom>();
1089 Map<IAtom,AttachmentPoint> mapAtmToAPInG =
1090 new HashMap<IAtom,AttachmentPoint>();
1091 Map<IAtom,APClass> apcMap =
new HashMap<IAtom,APClass>();
1092 for (
int i=0; i<wholeIAC.getAtomCount(); i++)
1094 IAtom cpAtm = iac.getAtom(i);
1095 IAtom oriAtm = wholeIAC.getAtom(i);
1101 +
"' not defined in atom "
1102 + oriAtm.getSymbol() + wholeIAC.indexOf(oriAtm)
1103 +
", but is needed to extract substructure.");
1105 long vid = ((Long) o).longValue();
1106 if (wantedVIDs.contains(vid))
1111 boolean willBecomeAP =
false;
1112 for (IAtom nbr : wholeIAC.getConnectedAtomsList(oriAtm))
1119 +
"' not defined in atom "
1120 + nbr.getSymbol() + wholeIAC.indexOf(nbr)
1121 +
", but is needed to extract substructure.");
1123 long nbrVid = ((Long) oNbr).longValue();
1124 if (wantedVIDs.contains(nbrVid))
1129 toAP.put(cpAtm,iac.getAtom(wholeIAC.indexOf(nbr)));
1131 wholeGraph.getAPOnLeftVertexID(nbrVid,vid);
1132 if (apInWholeGraph ==
null)
1134 String debugFile =
"failedAPIdentificationIACSubGraph"
1135 + wholeGraph.getGraphId() +
".sdf";
1137 wholeGraph, willBecomeAP, logger, randomizer);
1139 + nbrVid +
" " + vid +
" on " + wholeGraph
1140 +
" See " + debugFile);
1143 wantedVertexesMap.get(nbrVid).getAP(apInWholeGraph.
getIndexInOwner());
1144 mapAtmToAPInG.put(cpAtm, apInSubGraph);
1146 apcMap.put(cpAtm, apc);
1147 willBecomeAP =
true;
1152 toRemove.addAtom(cpAtm);
1155 iac.remove(toRemove);
1160 List<IAtom> atmosToRemove =
new ArrayList<>();
1161 List<IBond> bondsToRemove =
new ArrayList<>();
1162 for (IAtom trgAtmInIAC : toAP.keySet())
1164 IAtom trgAtm = frag.
getAtom(iac.indexOf(trgAtmInIAC));
1165 IAtom srcAtmInISC = toAP.get(trgAtmInIAC);
1166 IAtom srcAtm = frag.
getAtom(iac.indexOf(srcAtmInISC));
1173 double currentLength = srcP3d.distance(trgP3d);
1177 double idealLength = 1.53;
1182 Point3d vector =
new Point3d();
1183 vector.x = srcP3d.x + (trgP3d.x - srcP3d.x)*(idealLength/currentLength);
1184 vector.y = srcP3d.y + (trgP3d.y - srcP3d.y)*(idealLength/currentLength);
1185 vector.z = srcP3d.z + (trgP3d.z - srcP3d.z)*(idealLength/currentLength);
1188 apcMap.get(trgAtmInIAC), vector);
1191 for (IBond bnd : frag.
bonds())
1193 if (bnd.contains(trgAtm))
1195 bondsToRemove.add(bnd);
1198 atmosToRemove.add(trgAtm);
1202 for (IBond bnd : bondsToRemove)
1206 for (IAtom a : atmosToRemove)
1227 final int not2or3D = -1;
1232 for (IAtom atm : mol.atoms())
1234 Point2d p2d =
new Point2d();
1235 Point3d p3d =
new Point3d();
1236 p2d = atm.getPoint2d();
1237 boolean have2D =
true;
1241 p3d = atm.getPoint3d();
1247 ArrayList<Double> pointer =
new ArrayList<Double>();
1260 }
catch (Throwable t) {
1265 if (numOf2D == mol.getAtomCount())
1267 else if (numOf3D == mol.getAtomCount())
1284 IAtomContainer mol, Map<IAtom, IAtom> templateToMolMap)
1286 double totalAngleDifference = 0.0;
1288 double totalChiralityPenalty = 0.0;
1289 int chiralityCount = 0;
1290 boolean hasAngles =
false;
1292 for (IAtom templateAtom : templateMol.atoms())
1294 if (templateAtom.getBondCount() > 1)
1301 for (IAtom templateAtom : templateMol.atoms())
1303 IAtom molAtom = templateToMolMap.get(templateAtom);
1304 if (molAtom ==
null)
1310 if (templatePos ==
null || molPos ==
null)
1314 List<IAtom> templateNeighbors = templateMol.getConnectedAtomsList(templateAtom);
1315 if (templateNeighbors.size() < 2)
1319 List<IAtom> molNeighbors =
new ArrayList<>();
1320 for (IAtom templateNeighbor : templateNeighbors)
1322 IAtom molNeighbor = templateToMolMap.get(templateNeighbor);
1323 if (molNeighbor !=
null)
1325 molNeighbors.add(molNeighbor);
1329 if (molNeighbors.size() < 2)
1333 for (
int i = 0; i < templateNeighbors.size(); i++)
1335 for (
int j = i + 1; j < templateNeighbors.size(); j++)
1337 IAtom neighbor1 = templateNeighbors.get(i);
1338 IAtom neighbor2 = templateNeighbors.get(j);
1340 IAtom molNeighbor1 = templateToMolMap.get(neighbor1);
1341 IAtom molNeighbor2 = templateToMolMap.get(neighbor2);
1343 if (molNeighbor1 ==
null || molNeighbor2 ==
null)
1351 if (pos1 ==
null || pos2 ==
null || molPos1 ==
null || molPos2 ==
null)
1355 double[] templateA = {pos1.x, pos1.y, pos1.z};
1356 double[] templateB = {templatePos.x, templatePos.y, templatePos.z};
1357 double[] templateC = {pos2.x, pos2.y, pos2.z};
1361 double[] molA = {molPos1.x, molPos1.y, molPos1.z};
1362 double[] molB = {molPos.x, molPos.y, molPos.z};
1363 double[] molC = {molPos2.x, molPos2.y, molPos2.z};
1367 totalAngleDifference += Math.abs(templateAngle - molAngle);
1374 if (templateNeighbors.size() >= 3 && molNeighbors.size() >= 3)
1377 IAtom n1 = templateNeighbors.get(0);
1378 IAtom n2 = templateNeighbors.get(1);
1379 IAtom n3 = templateNeighbors.get(2);
1381 IAtom molN1 = templateToMolMap.get(n1);
1382 IAtom molN2 = templateToMolMap.get(n2);
1383 IAtom molN3 = templateToMolMap.get(n3);
1385 if (molN1 !=
null && molN2 !=
null && molN3 !=
null)
1394 if (p1 !=
null && p2 !=
null && p3 !=
null &&
1395 molP1 !=
null && molP2 !=
null && molP3 !=
null)
1398 double[] v1Template = {p1.x - templatePos.x, p1.y - templatePos.y, p1.z - templatePos.z};
1399 double[] v2Template = {p2.x - templatePos.x, p2.y - templatePos.y, p2.z - templatePos.z};
1400 double[] v3Template = {p3.x - templatePos.x, p3.y - templatePos.y, p3.z - templatePos.z};
1402 double[] v1Mol = {molP1.x - molPos.x, molP1.y - molPos.y, molP1.z - molPos.z};
1403 double[] v2Mol = {molP2.x - molPos.x, molP2.y - molPos.y, molP2.z - molPos.z};
1404 double[] v3Mol = {molP3.x - molPos.x, molP3.y - molPos.y, molP3.z - molPos.z};
1410 double stpTemplate = v1Template[0] * crossTemplate[0] +
1411 v1Template[1] * crossTemplate[1] +
1412 v1Template[2] * crossTemplate[2];
1413 double stpMol = v1Mol[0] * crossMol[0] +
1414 v1Mol[1] * crossMol[1] +
1415 v1Mol[2] * crossMol[2];
1419 double chiralityPenalty = 0.0;
1420 if (Math.signum(stpTemplate) != Math.signum(stpMol))
1423 chiralityPenalty = 1000.0 + Math.abs(stpTemplate - stpMol);
1428 chiralityPenalty = Math.abs(stpTemplate - stpMol);
1431 totalChiralityPenalty += chiralityPenalty;
1439 if (angleCount == 0 && chiralityCount == 0)
1448 return new double[]{0.0, 0.0, 0.0, 0.0};
1453 return new double[]{totalAngleDifference, angleCount, totalChiralityPenalty, chiralityCount};
1465 if (rawData ==
null)
1467 return Double.MAX_VALUE;
1470 double totalAngleDifference = rawData[0];
1471 double angleCount = rawData[1];
1472 double totalChiralityPenalty = rawData[2];
1473 double chiralityCount = rawData[3];
1476 if (angleCount == 0 && chiralityCount == 0)
1482 double angleScore = angleCount > 0 ? totalAngleDifference / angleCount : 0.0;
1483 double chiralityScore = chiralityCount > 0 ? totalChiralityPenalty / chiralityCount : 0.0;
1487 return angleScore + chiralityScore;
1501 IAtomContainer substructure, IAtomContainer mol, Logger logger)
1504 double bestScore = Double.MAX_VALUE;
1505 Map<IAtom,IAtom> bestTemplateToMolMap =
new HashMap<>();
1506 for (Map<IAtom,IAtom> templateToMolMap : uniqueAtomMappings)
1510 if (score < bestScore)
1513 bestTemplateToMolMap = templateToMolMap;
1516 return bestTemplateToMolMap;
1530 IAtomContainer substructure, IAtomContainer mol, Logger logger)
1541 Pattern pattern = Pattern.findSubstructure(substructure);
1544 if (!pattern.matches(mol))
1548 return new ArrayList<>();
1552 Mappings mappings = pattern.matchAll(mol);
1553 if (!mappings.iterator().hasNext())
1555 return new ArrayList<>();
1561 Map<String,Map<IAtom,IAtom>> uniqueAtomMappingsByKey =
new HashMap<>();
1562 Map<String,Double> bestScores =
new HashMap<>();
1566 Map<String,Set<String>> badAssignmentsByKey =
new HashMap<>();
1567 for (
int[] mapping : mappings)
1572 Map<IAtom, IAtom> templateToMolMap =
new HashMap<>();
1573 List<Integer> targetIndices =
new ArrayList<>();
1574 for (
int i = 0; i < mapping.length; i++)
1576 IAtom templateAtom = substructure.getAtom(i);
1577 IAtom targetAtom = mol.getAtom(mapping[i]);
1578 templateToMolMap.put(templateAtom, targetAtom);
1579 targetIndices.add(mapping[i]);
1582 Collections.sort(targetIndices);
1583 String key = targetIndices.toString();
1587 if (badAssignmentsByKey.containsKey(key))
1589 Set<String> badAssignments = badAssignmentsByKey.get(key);
1590 boolean hasBadAssignment =
false;
1591 for (Map.Entry<IAtom, IAtom> entry : templateToMolMap.entrySet())
1594 String assignment = entry.getKey().getIndex() +
"->" + entry.getValue().getIndex();
1595 if (badAssignments.contains(assignment))
1597 hasBadAssignment =
true;
1601 if (hasBadAssignment)
1613 if (!bestScores.containsKey(key) || score < bestScores.get(key))
1616 if (bestScores.containsKey(key) && uniqueAtomMappingsByKey.containsKey(key))
1618 Map<IAtom, IAtom> previousMapping = uniqueAtomMappingsByKey.get(key);
1619 Set<String> badAssignments = badAssignmentsByKey.computeIfAbsent(key, k ->
new HashSet<>());
1622 for (Map.Entry<IAtom, IAtom> entry : previousMapping.entrySet())
1624 IAtom templateAtom = entry.getKey();
1625 IAtom oldTargetAtom = entry.getValue();
1626 IAtom newTargetAtom = templateToMolMap.get(templateAtom);
1630 if (!oldTargetAtom.equals(newTargetAtom))
1632 String badAssignment = templateAtom.getIndex() +
"->" + oldTargetAtom.getIndex();
1633 badAssignments.add(badAssignment);
1638 bestScores.put(key, score);
1639 uniqueAtomMappingsByKey.put(key, templateToMolMap);
1645 logger.log(Level.FINE,
"Error processing mapping: " + e.getMessage());
1649 return new ArrayList<>(uniqueAtomMappingsByKey.values());
1653 logger.log(Level.WARNING,
"Error finding MCS: " + e.getMessage());
1654 return new ArrayList<>();
1670 IAtom end, Map<IAtom, Long> atomToVertexId)
1672 if (start.equals(end))
1674 return new ArrayList<>();
1678 Map<IAtom, IAtom> parent =
new HashMap<>();
1679 Set<IAtom> visited =
new HashSet<>();
1680 List<IAtom> queue =
new ArrayList<>();
1684 parent.put(start,
null);
1686 while (!queue.isEmpty())
1688 IAtom current = queue.remove(0);
1690 if (current.equals(end))
1693 List<IAtom> path =
new ArrayList<>();
1695 while (node !=
null)
1698 node = parent.get(node);
1703 List<IAtom> neighbors = mol.getConnectedAtomsList(current);
1704 for (IAtom neighbor : neighbors)
1706 if (!visited.contains(neighbor))
1709 Long currentVid = atomToVertexId.get(current);
1710 Long neighborVid = atomToVertexId.get(neighbor);
1712 if (currentVid !=
null && neighborVid !=
null)
1715 boolean canTraverse = currentVid.equals(neighborVid);
1725 visited.add(neighbor);
1726 parent.put(neighbor, current);
1727 queue.add(neighbor);
General set of constants used in DENOPTIM.
static final String ATMPROPVERTEXID
String tag of Atom property used to store the unique ID of the Vertex corresponding to the molecular ...
static final String DUMMYATMSYMBOL
Symbol of dummy atom.
static final Object STOREDVID
Key of the property remembering vertex IDs.
static final Object LINKAPS
Key of property used to records references of APs.
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
APClass getAPClass()
Returns the Attachment Point class.
void setProperty(Object key, Object property)
Container for the list of vertices and the edges that connect them.
Class representing a continuously connected portion of chemical object holding attachment points.
IBond removeBond(int position)
AttachmentPoint addAPOnAtom(IAtom srcAtm, APClass apc, Point3d vector)
Add an attachment point to the specifies atom.
IAtom getAtom(int number)
void removeAtom(IAtom atom)
IAtomContainer getIAtomContainer()
void updateAPs()
Changes the properties of each APs as to reflect the current atom list.
Iterable< IBond > bonds()
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
static final Map< String, String > RCATYPEMAP
Recognized types of RingClosingAttractor and compatible types.
Utility methods for input/output.
static void writeSDFFile(String fileName, IAtomContainer mol)
Writes IAtomContainer to SDF file.
static void writeGraphToSDF(File file, DGraph graph, boolean append, boolean make3D, Logger logger, Randomizer randomizer)
Writes the graph to SDF file.
Logger class for DENOPTIM.
static final Logger appLogger
Toll to add/remove dummy atoms from linearities or multi-hapto sites.
IAtomContainer removeDummy(IAtomContainer mol)
Removes all dummy atoms and the bonds connecting them to other atoms.
IAtomContainer removeDummyInHapto(IAtomContainer mol)
Some useful math operations.
static double getAngle(double[] A, double[] B, double[] C)
Calculates angle (in degrees) between vectors BA and BC.
static double[] computeCrossProduct(double[] v0, double[] v1)
Compute the cross product of two vectors.
Utilities for molecule conversion.
static double[] calculateBondAngleAgreement(IAtomContainer templateMol, IAtomContainer mol, Map< IAtom, IAtom > templateToMolMap)
Calculates bond angle agreement and returns raw data.
static int numOfBondsWithBO(IAtom atm, IAtomContainer mol, IBond.Order order)
Returns the number of bonds, with a certain bond order, surrounding the given atom.
static final StructureDiagramGenerator SDG
static String getInChIKeyForMolecule(IAtomContainer mol, Logger logger)
Generates the InChI key for the given atom container.
static void removeUsedRCA(IAtomContainer mol, DGraph graph, Logger logger)
Replace used RCAs (i.e., those involved in Rings) while adding the ring closing bonds.
static double normalizeBondAngleScore(double[] rawData)
Normalizes the raw bond angle agreement data to a single score.
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 IAtom makeSameAtomAs(IAtom oAtm, boolean ignoreValence, boolean ignoreImplicitH)
Method that constructs an atom that reflect the same atom given as parameter in terms of element symb...
static int getNumberOfRotatableBonds(IAtomContainer mol)
Count number of rotatable bonds.
static int countAtomsOfElement(IAtomContainer mol, String symbol)
Count atoms with the given elemental symbol.
static int getDimensions(IAtomContainer mol)
Determines the dimensionality of the given chemical object.
static String getSMILESForMolecule(IAtomContainer mol, Logger logger)
Returns the SMILES representation of the molecule.
static IAtomContainer generate2DCoordinates(IAtomContainer ac, Logger logger)
Generates 2D coordinates for the molecule.
static void removeRCA(IAtomContainer mol)
Replace any PseudoAtoms representing ring closing attractors with H.
static double getMolecularWeight(IAtomContainer mol)
static String missmatchingAromaticity(IAtomContainer mol)
Looks for carbon atoms that are flagged as aromatic, but do not have any double bond and are,...
static IAtom makeSameAtomAs(IAtom oAtm)
Method that constructs an atom that reflect the same atom given as parameter in terms of element symb...
static Map< IAtom, IAtom > findBestAtomMapping(IAtomContainer substructure, IAtomContainer mol, Logger logger)
Finds the maximum common substructure (MCS) between two molecules.
static final IChemObjectBuilder builder
static String getSymbolOrLabel(IAtom atm)
Gets either the elemental symbol (for standard atoms) of the label (for pseudo-atoms).
static void ensureNoUnsetBondOrdersSilent(IAtomContainer iac)
Sets bond order = single to all otherwise unset bonds.
static boolean isDummy(IAtom atm)
Checks if the given atom is a dummy atom based on the elemental symbol and the string used for dummy ...
static List< Map< IAtom, IAtom > > findUniqueAtomMappings(IAtomContainer substructure, IAtomContainer mol, Logger logger)
Finds the maximum common substructure (MCS) between two molecules.
static String getAtomRef(IAtom atm, IAtomContainer mol)
static final SmilesGenerator SMGEN
static void ensureNoUnsetBondOrders(IAtomContainer iac)
Sets bond order = single to all otherwise unset bonds.
static Map< Vertex, ArrayList< Integer > > getVertexToAtomIdMap(ArrayList< Vertex > vertLst, IAtomContainer mol)
Method to generate the map making in relation DENOPTIMVertex ID and atom index in the IAtomContainer ...
static void explicitHydrogens(IAtomContainer mol)
Converts all the implicit hydrogens to explicit.
static void moleculeToPNG(IAtomContainer mol, String filename, Logger logger)
Generate a PNG image from molecule mol
static Point3d calculateCentroid(IAtomContainer mol)
Calculated the centroid of the given molecule.
static List< IAtom > findShortestPath(IAtomContainer mol, IAtom start, IAtom end, Map< IAtom, Long > atomToVertexId)
Finds the shortest path between two atoms in a molecule using BFS.
static Point3d getPoint3d(IAtom atm)
Return the 3D coordinates, if present.
static boolean isElement(String symbol)
Check element symbol corresponds to real element of Periodic Table.
static IAtomContainer extractIACForSubgraph(IAtomContainer wholeIAC, DGraph subGraph, DGraph wholeGraph, Logger logger, Randomizer randomizer)
Selects only the atoms that originate from a subgraph of a whole graph that originated the whole mole...
static boolean isElement(IAtom atom)
Check element symbol corresponds to real element of Periodic Table.
static int getHeavyAtomCount(IAtomContainer mol)
The heavy atom count.
static String getInChIKeyForMolecule(IAtomContainer mol, InchiOptions options, Logger logger)
Generates the INCHI key for the molecule.
Tool to generate random numbers and random decisions.
Possible chemical bond types an edge can represent.
boolean hasCDKAnalogue()
Checks if it is possible to convert this edge type into a CDK bond.
The type of building block.