19package denoptim.molecularmodeling;
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.HashMap;
24import java.util.HashSet;
28import java.util.logging.Level;
29import java.util.logging.Logger;
31import javax.vecmath.Point3d;
32import javax.vecmath.Vector3d;
34import org.openscience.cdk.graph.PathTools;
35import org.openscience.cdk.graph.SpanningTree;
36import org.openscience.cdk.interfaces.IAtom;
37import org.openscience.cdk.interfaces.IAtomContainer;
38import org.openscience.cdk.interfaces.IBond;
39import org.openscience.cdk.interfaces.IRingSet;
40import org.openscience.cdk.silent.RingSet;
42import denoptim.constants.DENOPTIMConstants;
43import denoptim.exception.DENOPTIMException;
44import denoptim.graph.DGraph;
45import denoptim.graph.Edge.BondType;
46import denoptim.graph.Ring;
47import denoptim.graph.rings.RingClosingAttractor;
48import denoptim.graph.rings.RingClosure;
49import denoptim.molecularmodeling.zmatrix.ZMatrix;
50import denoptim.utils.MathUtils;
51import denoptim.utils.ObjectPair;
70 private IAtomContainer
fmol;
152 List<RingClosure> ringClosures,
166 this.newRingClosures = ringClosures;
167 this.overalRCScore = Double.NaN;
168 this.atmOveralScore = Double.NaN;
169 if (this.attractors.size() != 0)
215 this.attractors =
new ArrayList<RingClosingAttractor>();
216 this.attToAtmID =
new HashMap<RingClosingAttractor,Integer>();
218 this.allRCACombs =
new ArrayList<Set<ObjectPair>>();
219 if (this.attractors.size() != 0)
227 this.newRingClosures =
new ArrayList<RingClosure>();
228 this.overalRCScore = Double.NaN;
229 this.atmOveralScore = Double.NaN;
253 for (IAtom atm :
fmol.atoms())
270 Set<ObjectPair> singleRCAcomb =
new HashSet<ObjectPair>();
276 if (ringOwnerI==
null)
283 if (ringOwnerJ==
null)
285 if (ringOwnerI==ringOwnerJ)
287 singleRCAcomb.add(
new ObjectPair(rcaI, rcaJ));
303 for (
int i=0; i<
fmol.getAtomCount(); i++)
305 fmol.getAtom(i).setPoint3d(newCoords.get(i));
318 List<Point3d> newCoords =
new ArrayList<Point3d>();
319 for (
int i=0; i<
fmol.getAtomCount(); i++)
324 if ((ia != -1 && ia > i) || (ib != -1 && ib > i) || (ic != -1 && ic > i))
326 String msg =
"ERROR! Cannot convert internal coordinates of "
327 +
"atom " + i +
". Reference "
328 +
"atoms have higher ID. The atoms list in "
329 +
"Molecule3DBuilder needs to be reordered.";
337 double[] newXYZ = {0.0, 0.0, 0.0};
340 if (ia == -1 && ib == -1 && ic == -1)
344 else if (ib == -1 && ic == -1)
348 String msg =
"ERROR! Cannot convert internal coordinates of "
349 +
"atom " + i +
". Bond length is null.";
358 String msg =
"ERROR! Cannot convert internal coordinates of "
359 +
"atom " + i +
". Bond length is null.";
364 String msg =
"ERROR! Cannot convert internal coordinates of "
365 +
"atom " + i +
". Angle 1 is null.";
368 double s1 = Math.sin(angle1 * 2 * Math.PI / 360.0);
369 double c1 = Math.cos(angle1 * 2 * Math.PI / 360.0);
371 newCoords.get(ia),newCoords.get(ib));
373 newCoords.get(ia),newCoords.get(ib));
374 newXYZ[0] = bond * s1;
375 newXYZ[2] = newCoords.get(ib).z + (rab - bond*c1)*nab.z;
381 String msg =
"ERROR! Cannot convert internal coordinates of "
382 +
"atom " + i +
". Bond length is null.";
387 String msg =
"ERROR! Cannot convert internal coordinates of "
388 +
"atom " + i +
". Angle 1 is null.";
393 String msg =
"ERROR! Cannot convert internal coordinates of "
394 +
"atom " + i +
". Angle 2 is null.";
397 if (chirality ==
null)
399 String msg =
"ERROR! Cannot convert internal coordinates of "
400 +
"atom " + i +
". Chirality is null.";
403 double s1 = Math.sin(angle1 * 2 * Math.PI / 360.0);
404 double s2 = Math.sin(angle2 * 2 * Math.PI / 360.0);
405 double c1 = Math.cos(angle1 * 2 * Math.PI / 360.0);
406 double c2 = Math.cos(angle2 * 2 * Math.PI / 360.0);
408 if (chirality.equals(0))
411 newCoords.get(ia),newCoords.get(ib));
413 newCoords.get(ib),newCoords.get(ic));
414 Vector3d t =
new Vector3d();
416 double c = nab.x*nbc.x + nab.y*nbc.y + nab.z*nbc.z;
417 if (Math.abs(c) > (1.0 - smallDble))
419 String msg =
"ERROR! Linearity does not allow definition "
420 +
"of the dihedral angle for atom " + i
421 +
" (Value of c="+c+
" too close to unity; threshold is "
422 + (1.0 - smallDble) +
"). "
423 +
"You better use dummy atoms to avoid linearities.";
426 t.scale(1/Math.sqrt(Math.max(1.00 - c*c, smallDble)));
427 Vector3d u =
new Vector3d();
429 newXYZ[0] = newCoords.get(ia).x
430 + bond*(u.x*s1*c2 + t.x*s1*s2 - nab.x*c1);
431 newXYZ[1] = newCoords.get(ia).y
432 + bond*(u.y*s1*c2 + t.y*s1*s2 - nab.y*c1);
433 newXYZ[2] = newCoords.get(ia).z
434 + bond*(u.z*s1*c2 + t.z*s1*s2 - nab.z*c1);
436 else if (chirality.equals(1) || chirality.equals(-1))
439 newCoords.get(ib),newCoords.get(ia));
441 newCoords.get(ia),newCoords.get(ic));
442 Vector3d t =
new Vector3d();
444 double c = nba.x*nac.x + nba.y*nac.y + nba.z*nac.z;
445 if (Math.abs(c) > (1.0 - smallDble))
447 logger.log(Level.WARNING,
"WARNING! close-to-linear system "
448 +
"in the definition of atom " + i +
". "
449 +
"You better use dummy atoms to avoid linearities.");
451 double s = Math.max(1.00 - c*c, smallDble);
452 double a = (-c2 - c*c1) / s;
453 double b = (c1 + c*c2) / s;
454 double ci = (1.00 + a*c2 - b*c1) / s;
457 ci = chirality * Math.sqrt(ci);
459 else if (ci < -smallDble)
461 ci = Math.sqrt((a*nac.x+b*nba.x)*(a*nac.x+b*nba.x)
462 + (a*nac.y+b*nba.y)*(a*nac.y+b*nba.y)
463 + (a*nac.z+b*nba.z)*(a*nac.z+b*nba.z));
467 logger.log(Level.WARNING,
"WARNING! close-to-linear system "
468 +
"in the definition of atom " + i +
". "
469 +
"You better use dummy atoms to avoid linearities.");
475 newXYZ[0] = newCoords.get(ia).x
476 + bond*(a*nac.x + b*nba.x + ci*t.x);
477 newXYZ[1] = newCoords.get(ia).y
478 + bond*(a*nac.y + b*nba.y + ci*t.y);
479 newXYZ[2] = newCoords.get(ia).z
480 + bond*(a*nac.z + b*nba.z + ci*t.z);
483 Point3d p3d =
new Point3d(newXYZ[0],newXYZ[1],newXYZ[2]);
633 score = score + rc.getRingClosureQuality();
652 for (IAtom atmA :
fmol.atoms())
654 String elA = atmA.getSymbol();
659 IAtom[] toExclude = PathTools.findClosestByBond(
fmol,atmA,4);
660 for (IAtom atmB :
fmol.atoms())
665 if (Arrays.asList(toExclude).contains(atmB))
668 String elB = atmB.getSymbol();
672 double dist = atmA.getPoint3d().distance(atmB.getPoint3d());
673 score = score + dist;
707 this.newRingClosures.add(nRc);
708 this.overalRCScore = Double.NaN;
710 int iA =
fmol.indexOf(atmA);
711 int iB =
fmol.indexOf(atmB);
716 logger.log(Level.FINE,
"ADDING BOND: "+iA+
" "+iB);
718 logger.log(Level.FINE,
"WARNING! Attempt to add ring closing bond "
719 +
"did not add any actual chemical bond because the "
720 +
"bond type of the chord is '" + bndTyp +
"'.");
741 SpanningTree st =
new SpanningTree(
fmol);
742 IRingSet allRings =
new RingSet();
744 allRings = st.getAllRings();
745 }
catch (Exception ex) {
750 List<ObjectPair> toRemove =
new ArrayList<ObjectPair>();
753 int i1 = ((Integer)op.getFirst()).intValue();
754 int i2 = ((Integer)op.getSecond()).intValue();
756 IBond bnd =
fmol.getBond(
fmol.getAtom(i1),
fmol.getAtom(i2));
757 IRingSet rs = allRings.getRings(bnd);
761 logger.log(Level.FINE,
"Bond " + i1 +
"-" + i2 +
" (TnkID:"
762 + (i1+1) +
"-" + (i2+1) +
") is not rotatable anymore");
784 String nMolName = this.
molName;
786 IAtomContainer nFMol;
788 List<ObjectPair> nRotBnds;
792 nFMol = this.fmol.
clone();
795 catch (CloneNotSupportedException cns)
800 nRotBnds =
new ArrayList<>(this.rotatableBnds);
802 List<RingClosingAttractor> nAttractors =
803 new ArrayList<RingClosingAttractor>();
804 Map<RingClosingAttractor,Integer> nAttToAtmID =
805 new HashMap<RingClosingAttractor,Integer>();
806 Map<RingClosingAttractor,RingClosingAttractor> oldToNewRCA =
807 new HashMap<RingClosingAttractor,RingClosingAttractor>();
808 for (
int iorca=0; iorca<
attractors.size(); iorca++)
811 int ioatm = this.attToAtmID.get(oRca);
812 IAtom atm = nFMol.getAtom(ioatm);
814 nAttractors.add(nRca);
815 nAttToAtmID.put(nRca, ioatm);
816 oldToNewRCA.put(oRca, nRca);
819 List<Set<ObjectPair>> nAllRCACombs =
820 new ArrayList<Set<ObjectPair>>();
821 for (Set<ObjectPair> sop : this.allRCACombs)
823 Set<ObjectPair> nSop =
new HashSet<ObjectPair>();
827 oldToNewRCA.get(op.getFirst()),
828 oldToNewRCA.get(op.getSecond()));
831 nAllRCACombs.add(nSop);
834 List<RingClosure> nNewRingClosures =
new ArrayList<RingClosure>();
837 nNewRingClosures.add(rc.deepCopy());
840 List<Integer> newOldToNewOrder =
new ArrayList<Integer>();
842 newOldToNewOrder.add(i.intValue());
844 List<Integer> newNewToOldOrder =
new ArrayList<Integer>();
846 newNewToOldOrder.add(i.intValue());
858 newNewToOldOrder,
logger);
General set of constants used in DENOPTIM.
static final double FLOATCOMPARISONTOLERANCE
Smallest difference for comparison of double and float numbers.
static final String DUMMYATMSYMBOL
Symbol of dummy atom.
Container for the list of vertices and the edges that connect them.
DGraph clone()
Returns almost "deep-copy" of this graph.
boolean hasOrEmbedsRings()
Check for rings in this graph and in any graph that is embedded at any level in any vertex of this gr...
This class represents the closure of a ring in a spanning tree.
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
Ring getRingUser()
Get the reference to the graph representation of the ring this attractor is meant to close.
boolean isAttractor()
Checks whether the constructed RingClosingAttractor does corresponds to a RingClosingAttractor in the...
RingClosure represents the arrangement of atoms and PseudoAtoms identifying the head and tail of a ch...
Collector of molecular information, related to a single chemical object, that is deployed within the ...
void convertRingsToRCACombinations()
double getAtomOverlapScore()
Return the atoms overlap score which is calculated for all atoms pairs not in 1-4 or lower relationsh...
double overalRCScore
Quality score of the list of ring closures.
List< RingClosure > newRingClosures
List of new ring closing environments.
List< RingClosingAttractor > getAttractorsList()
Returns the list of RuingClosingAttractors.
double getNewRingClosuresQuality()
Return the overal evaluation of the whole list of RingClosures.
Map< RingClosingAttractor, Integer > attToAtmID
Relation between RingClosingAttractor and index in the ZMatrix.
ChemicalObjectModel deepcopy()
Return a new Molecule3DBuilder having exactly the same features of this Molecule3DBuilder.
int getNumberRotatableBonds()
Returns the size of the current list of rotatable bonds.
String molName
Reference name.
DGraph getGraph()
Returns the graph representation of this molecule as it was originally generated by DEOPTIM.
Logger logger
Program-specific logger.
ChemicalObjectModel(DGraph molGraph, IAtomContainer fmol, ZMatrix zmat, String molName, List< ObjectPair > rotatableBnds, List< Integer > oldToNewOrder, List< Integer > newToOldOrder, Logger logger)
Constructs a Molecule3DBuilder specifying all its features.
List< ObjectPair > getRotatableBonds()
Returns the list of rotatable bonds.
List< Set< ObjectPair > > getRCACombinations()
Returns the list of combinations of RingClosingAttractor.
DGraph molGraph
DENOPTIM representation.
String getName()
Return the name of this molecule.
void purgeListRotatableBonds()
Remove the cyclic bonds from the list of rotatable bonds.
int getZMatIdxOfRCA(RingClosingAttractor rca)
IAtomContainer getIAtomContainer()
Returns the CDK representation of the molecular system.
List< Integer > oldToNewOrder
List< ObjectPair > rotatableBnds
List of rotatable bonds.
void addBond(IAtom atmA, IAtom atmB, RingClosure nRc, BondType bndTyp)
Modify the molecule adding a cyclic bond between two atoms.
List< RingClosure > getNewRingClosures()
Return the list of RingClosures that have been identified as closable head/tail of atom chains during...
List< Integer > newToOldOrder
List< Integer > getOldToNewOrder()
ZMatrix getZMatrix()
Returns the ZMatrix representation of the molecule.
void updateXYZ(List< Point3d > newCoords)
currently loaded internal coordinates into Cartesian overwriting the current XYZ.
void updateXYZFromINT()
Converts currently loaded internal coordinates into Cartesian overwriting the current XYZ.
double atmOveralScore
Atom overlap score (for atoms not is 1-4 or lower relationship)
ChemicalObjectModel(DGraph molGraph, IAtomContainer fmol, ZMatrix zmat, String molName, List< ObjectPair > rotatableBnds, List< RingClosingAttractor > attractors, Map< RingClosingAttractor, Integer > attToAtmID, List< Set< ObjectPair > > allRCACombs, List< RingClosure > ringClosures, List< Integer > oldToNewOrder, List< Integer > newToOldOrder, Logger logger)
Constructs an item specifying all its features.
List< Integer > getNewToOldOrder()
int getZMatIdxOfRCASrc(RingClosingAttractor rca)
ZMatrix zmat
ZMatrix representation.
List< RingClosingAttractor > attractors
List of RingClosingAttractors.
IAtomContainer fmol
CDK representation.
List< Set< ObjectPair > > allRCACombs
List of combinations of RingClosingAttractor (i.e., possible set of rings to create)
RingClosingAttractor getAttractor(int i)
Returns the attractor given its position in the list of attractors.
Representation of an atom container's geometry with internal coordinates.
Integer getChiralFlag(int index)
Get the chiral flag for the atom at the given index.
int getBondRefAtomIndex(int index)
Get the index of the bond reference atom for the atom at the given index.
ZMatrix clone()
Clone the ZMatrix.
Double getBondLength(int index)
Get the bond length for the atom at the given index.
void addBond(int a1, int a2)
Add a bond between the two atoms at the given indices.
Double getAngle2Value(int index)
Get the angle2 angle for the atom at the given index.
Double getAngleValue(int index)
Get the bond angle for the atom at the given index.
int getAngle2RefAtomIndex(int index)
Get the index of the second angle reference atom for the atom at the given index.
int getAngleRefAtomIndex(int index)
Get the index of the angle reference atom for the atom at the given index.
Some useful math operations.
static Vector3d normDist(Point3d p1, Point3d p2)
Get normalized distance between two point.
static double distance(Point3d a, Point3d b)
Calculates distance between point a and point b.
This class is the equivalent of the Pair data structure used in C++ Although AbstractMap....
Possible chemical bond types an edge can represent.
boolean hasCDKAnalogue()
Checks if it is possible to convert this edge type into a CDK bond.