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 List<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 if (currentLength > 1.0E-8)
1187 vector.x = srcP3d.x + (trgP3d.x - srcP3d.x)
1188 * (idealLength / currentLength);
1189 vector.y = srcP3d.y + (trgP3d.y - srcP3d.y)
1190 * (idealLength / currentLength);
1191 vector.z = srcP3d.z + (trgP3d.z - srcP3d.z)
1192 * (idealLength / currentLength);
1196 vector.x = srcP3d.x + idealLength;
1197 vector.y = srcP3d.y;
1198 vector.z = srcP3d.z;
1202 apcMap.get(trgAtmInIAC), vector);
1205 for (IBond bnd : frag.
bonds())
1207 if (bnd.contains(trgAtm))
1209 bondsToRemove.add(bnd);
1212 atmosToRemove.add(trgAtm);
1216 for (IBond bnd : bondsToRemove)
1220 for (IAtom a : atmosToRemove)
1241 final int not2or3D = -1;
1246 for (IAtom atm : mol.atoms())
1248 Point2d p2d =
new Point2d();
1249 Point3d p3d =
new Point3d();
1250 p2d = atm.getPoint2d();
1251 boolean have2D =
true;
1255 p3d = atm.getPoint3d();
1261 ArrayList<Double> pointer =
new ArrayList<Double>();
1274 }
catch (Throwable t) {
1279 if (numOf2D == mol.getAtomCount())
1281 else if (numOf3D == mol.getAtomCount())
1298 IAtomContainer mol, Map<IAtom, IAtom> templateToMolMap)
1300 double totalAngleDifference = 0.0;
1302 double totalChiralityPenalty = 0.0;
1303 int chiralityCount = 0;
1304 boolean hasAngles =
false;
1306 for (IAtom templateAtom : templateMol.atoms())
1308 if (templateAtom.getBondCount() > 1)
1315 for (IAtom templateAtom : templateMol.atoms())
1317 IAtom molAtom = templateToMolMap.get(templateAtom);
1318 if (molAtom ==
null)
1324 if (templatePos ==
null || molPos ==
null)
1328 List<IAtom> templateNeighbors = templateMol.getConnectedAtomsList(templateAtom);
1329 if (templateNeighbors.size() < 2)
1333 List<IAtom> molNeighbors =
new ArrayList<>();
1334 for (IAtom templateNeighbor : templateNeighbors)
1336 IAtom molNeighbor = templateToMolMap.get(templateNeighbor);
1337 if (molNeighbor !=
null)
1339 molNeighbors.add(molNeighbor);
1343 if (molNeighbors.size() < 2)
1347 for (
int i = 0; i < templateNeighbors.size(); i++)
1349 for (
int j = i + 1; j < templateNeighbors.size(); j++)
1351 IAtom neighbor1 = templateNeighbors.get(i);
1352 IAtom neighbor2 = templateNeighbors.get(j);
1354 IAtom molNeighbor1 = templateToMolMap.get(neighbor1);
1355 IAtom molNeighbor2 = templateToMolMap.get(neighbor2);
1357 if (molNeighbor1 ==
null || molNeighbor2 ==
null)
1365 if (pos1 ==
null || pos2 ==
null || molPos1 ==
null || molPos2 ==
null)
1369 double[] templateA = {pos1.x, pos1.y, pos1.z};
1370 double[] templateB = {templatePos.x, templatePos.y, templatePos.z};
1371 double[] templateC = {pos2.x, pos2.y, pos2.z};
1375 double[] molA = {molPos1.x, molPos1.y, molPos1.z};
1376 double[] molB = {molPos.x, molPos.y, molPos.z};
1377 double[] molC = {molPos2.x, molPos2.y, molPos2.z};
1381 totalAngleDifference += Math.abs(templateAngle - molAngle);
1388 if (templateNeighbors.size() >= 3 && molNeighbors.size() >= 3)
1391 IAtom n1 = templateNeighbors.get(0);
1392 IAtom n2 = templateNeighbors.get(1);
1393 IAtom n3 = templateNeighbors.get(2);
1395 IAtom molN1 = templateToMolMap.get(n1);
1396 IAtom molN2 = templateToMolMap.get(n2);
1397 IAtom molN3 = templateToMolMap.get(n3);
1399 if (molN1 !=
null && molN2 !=
null && molN3 !=
null)
1408 if (p1 !=
null && p2 !=
null && p3 !=
null &&
1409 molP1 !=
null && molP2 !=
null && molP3 !=
null)
1412 double[] v1Template = {p1.x - templatePos.x, p1.y - templatePos.y, p1.z - templatePos.z};
1413 double[] v2Template = {p2.x - templatePos.x, p2.y - templatePos.y, p2.z - templatePos.z};
1414 double[] v3Template = {p3.x - templatePos.x, p3.y - templatePos.y, p3.z - templatePos.z};
1416 double[] v1Mol = {molP1.x - molPos.x, molP1.y - molPos.y, molP1.z - molPos.z};
1417 double[] v2Mol = {molP2.x - molPos.x, molP2.y - molPos.y, molP2.z - molPos.z};
1418 double[] v3Mol = {molP3.x - molPos.x, molP3.y - molPos.y, molP3.z - molPos.z};
1424 double stpTemplate = v1Template[0] * crossTemplate[0] +
1425 v1Template[1] * crossTemplate[1] +
1426 v1Template[2] * crossTemplate[2];
1427 double stpMol = v1Mol[0] * crossMol[0] +
1428 v1Mol[1] * crossMol[1] +
1429 v1Mol[2] * crossMol[2];
1433 double chiralityPenalty = 0.0;
1434 if (Math.signum(stpTemplate) != Math.signum(stpMol))
1437 chiralityPenalty = 1000.0 + Math.abs(stpTemplate - stpMol);
1442 chiralityPenalty = Math.abs(stpTemplate - stpMol);
1445 totalChiralityPenalty += chiralityPenalty;
1453 if (angleCount == 0 && chiralityCount == 0)
1462 return new double[]{0.0, 0.0, 0.0, 0.0};
1467 return new double[]{totalAngleDifference, angleCount, totalChiralityPenalty, chiralityCount};
1479 if (rawData ==
null)
1481 return Double.MAX_VALUE;
1484 double totalAngleDifference = rawData[0];
1485 double angleCount = rawData[1];
1486 double totalChiralityPenalty = rawData[2];
1487 double chiralityCount = rawData[3];
1490 if (angleCount == 0 && chiralityCount == 0)
1496 double angleScore = angleCount > 0 ? totalAngleDifference / angleCount : 0.0;
1497 double chiralityScore = chiralityCount > 0 ? totalChiralityPenalty / chiralityCount : 0.0;
1501 return angleScore + chiralityScore;
1515 IAtomContainer substructure, IAtomContainer mol, Logger logger)
1518 double bestScore = Double.MAX_VALUE;
1519 Map<IAtom,IAtom> bestTemplateToMolMap =
new HashMap<>();
1520 for (Map<IAtom,IAtom> templateToMolMap : uniqueAtomMappings)
1524 if (score < bestScore)
1527 bestTemplateToMolMap = templateToMolMap;
1530 return bestTemplateToMolMap;
1544 IAtomContainer substructure, IAtomContainer mol, Logger logger)
1555 Pattern pattern = Pattern.findSubstructure(substructure);
1558 if (!pattern.matches(mol))
1562 return new ArrayList<>();
1566 Mappings mappings = pattern.matchAll(mol);
1567 if (!mappings.iterator().hasNext())
1569 return new ArrayList<>();
1575 Map<String,Map<IAtom,IAtom>> uniqueAtomMappingsByKey =
new HashMap<>();
1576 Map<String,Double> bestScores =
new HashMap<>();
1580 Map<String,Set<String>> badAssignmentsByKey =
new HashMap<>();
1581 for (
int[] mapping : mappings)
1586 Map<IAtom, IAtom> templateToMolMap =
new HashMap<>();
1587 List<Integer> targetIndices =
new ArrayList<>();
1588 for (
int i = 0; i < mapping.length; i++)
1590 IAtom templateAtom = substructure.getAtom(i);
1591 IAtom targetAtom = mol.getAtom(mapping[i]);
1592 templateToMolMap.put(templateAtom, targetAtom);
1593 targetIndices.add(mapping[i]);
1596 Collections.sort(targetIndices);
1597 String key = targetIndices.toString();
1601 if (badAssignmentsByKey.containsKey(key))
1603 Set<String> badAssignments = badAssignmentsByKey.get(key);
1604 boolean hasBadAssignment =
false;
1605 for (Map.Entry<IAtom, IAtom> entry : templateToMolMap.entrySet())
1608 String assignment = entry.getKey().getIndex() +
"->" + entry.getValue().getIndex();
1609 if (badAssignments.contains(assignment))
1611 hasBadAssignment =
true;
1615 if (hasBadAssignment)
1627 if (!bestScores.containsKey(key) || score < bestScores.get(key))
1630 if (bestScores.containsKey(key) && uniqueAtomMappingsByKey.containsKey(key))
1632 Map<IAtom, IAtom> previousMapping = uniqueAtomMappingsByKey.get(key);
1633 Set<String> badAssignments = badAssignmentsByKey.computeIfAbsent(key, k ->
new HashSet<>());
1636 for (Map.Entry<IAtom, IAtom> entry : previousMapping.entrySet())
1638 IAtom templateAtom = entry.getKey();
1639 IAtom oldTargetAtom = entry.getValue();
1640 IAtom newTargetAtom = templateToMolMap.get(templateAtom);
1644 if (!oldTargetAtom.equals(newTargetAtom))
1646 String badAssignment = templateAtom.getIndex() +
"->" + oldTargetAtom.getIndex();
1647 badAssignments.add(badAssignment);
1652 bestScores.put(key, score);
1653 uniqueAtomMappingsByKey.put(key, templateToMolMap);
1659 logger.log(Level.FINE,
"Error processing mapping: " + e.getMessage());
1663 return new ArrayList<>(uniqueAtomMappingsByKey.values());
1667 logger.log(Level.WARNING,
"Error finding MCS: " + e.getMessage());
1668 return new ArrayList<>();
1684 IAtom end, Map<IAtom, Long> atomToVertexId)
1686 if (start.equals(end))
1688 return new ArrayList<>();
1692 Map<IAtom, IAtom> parent =
new HashMap<>();
1693 Set<IAtom> visited =
new HashSet<>();
1694 List<IAtom> queue =
new ArrayList<>();
1698 parent.put(start,
null);
1700 while (!queue.isEmpty())
1702 IAtom current = queue.remove(0);
1704 if (current.equals(end))
1707 List<IAtom> path =
new ArrayList<>();
1709 while (node !=
null)
1712 node = parent.get(node);
1717 List<IAtom> neighbors = mol.getConnectedAtomsList(current);
1718 for (IAtom neighbor : neighbors)
1720 if (!visited.contains(neighbor))
1723 Long currentVid = atomToVertexId.get(current);
1724 Long neighborVid = atomToVertexId.get(neighbor);
1726 if (currentVid !=
null && neighborVid !=
null)
1729 boolean canTraverse = currentVid.equals(neighborVid);
1739 visited.add(neighbor);
1740 parent.put(neighbor, current);
1741 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 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 Map< Vertex, ArrayList< Integer > > getVertexToAtomIdMap(List< Vertex > vertLst, IAtomContainer mol)
Method to generate the map making in relation DENOPTIMVertex ID and atom index in the IAtomContainer ...
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.