$darkmode
DENOPTIM
PathSubGraph.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2019 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.graph.rings;
20
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.Iterator;
27import java.util.LinkedList;
28import java.util.List;
29import java.util.Map;
30import java.util.Set;
31import java.util.logging.Logger;
32
33import javax.vecmath.Point3d;
34
35import org.openscience.cdk.graph.ShortestPaths;
36import org.openscience.cdk.interfaces.IAtom;
37import org.openscience.cdk.interfaces.IAtomContainer;
38import org.openscience.cdk.interfaces.IBond;
39
40import denoptim.constants.DENOPTIMConstants;
41import denoptim.exception.DENOPTIMException;
42import denoptim.graph.AttachmentPoint;
43import denoptim.graph.DGraph;
44import denoptim.graph.Edge;
45import denoptim.graph.Vertex;
46import denoptim.io.DenoptimIO;
47import denoptim.molecularmodeling.ThreeDimTreeBuilder;
48import denoptim.utils.Randomizer;
49
50
58public class PathSubGraph
59{
64 private DGraph graph;
65
69 private String chainID;
70 private String revChainID;
71 private ArrayList<String> allPossibleChainIDs = new ArrayList<String>();
72
76 private Vertex vA;
77
81 private Vertex vB;
82
86 private List<Vertex> vertPathVAVB;
87
91 private List<Edge> edgesPathVAVB;
92
96 private IAtomContainer iacPathVAVB;
97
101 private List<IAtom> atomsPathVAVB;
102
108 private List<IBond> bondsPathVAVB;
109
113 private ArrayList<ArrayList<Point3d>> dihedralRefPts;
114
119 private boolean hasMolRepr = false;
120
124 private String atmNumStr;
125
130
131 // Set to true to write useful debug data to file and log
132 private boolean debug = false;
133
134
135//-----------------------------------------------------------------------------
136
146 {
147 this(vA, vB, new HashMap<Vertex, List<Vertex>>());
148 }
149
150//-----------------------------------------------------------------------------
151
164 public PathSubGraph(Vertex vA, Vertex vB, Map<Vertex, List<Vertex>> adjacency)
165 throws DENOPTIMException
166 {
167 this(vA, vB, adjacency, true);
168 }
169
170//-----------------------------------------------------------------------------
171
186 public PathSubGraph(Vertex vA, Vertex vB, Map<Vertex, List<Vertex>> adjacency,
187 boolean combineAdjacencyAndActualEdges) throws DENOPTIMException
188 {
189 // Check assumption that vA and vB are in the same graph.
190 if (vA == null || vB == null)
191 {
192 throw new IllegalArgumentException("Null vertex cannot be used to build a "
193 + this.getClass().getSimpleName() + " object.");
194 }
195 DGraph graphA = vA.getGraphOwner();
196 DGraph graphB = vB.getGraphOwner();
197 if (graphA == null || graphB == null)
198 {
199 Vertex noGraphVertex = null;
200 if (graphA == null)
201 {
202 noGraphVertex = vA;
203 } else {
204 noGraphVertex = vB;
205 }
206 throw new IllegalArgumentException("Vertex " + noGraphVertex.getVertexId()
207 + " is not in a graph. "
208 + "Cannot build a " + this.getClass().getSimpleName() + " object.");
209 }
210 if (graphA != graphB)
211 {
212 throw new IllegalArgumentException("Vertices " + vA.getVertexId() + " and "
213 + vB.getVertexId() + " are not in the same graph. "
214 + "Cannot build a " + this.getClass().getSimpleName() + " object.");
215 }
216
217 // Build the adjacency map, optionally combining given and edge-based adjacency.
218 Map<Vertex, List<Vertex>> adjacencyFromEdges = buildAdjacencyFromGraph(
219 vA.getGraphOwner());
220 if (combineAdjacencyAndActualEdges)
221 {
222 // Add the actual edges to the adjacency map
223 for (Map.Entry<Vertex, List<Vertex>> entry : adjacencyFromEdges.entrySet())
224 {
225 Vertex vertex = entry.getKey();
226 List<Vertex> neighbors = entry.getValue();
227 for (Vertex neighbor : neighbors) {
228 adjacency.computeIfAbsent(vertex, k -> new ArrayList<Vertex>()).add(neighbor);
229 adjacency.computeIfAbsent(neighbor, k -> new ArrayList<Vertex>()).add(vertex);
230 }
231 }
232 }
233
234 // Initialize the object.
235 this.vA = vA;
236 this.vB = vB;
237
238 // Find the shortest path between vA and vB.
239 vertPathVAVB = findShortestPath(vA, vB, adjacency);
240 if (vertPathVAVB.isEmpty())
241 {
242 throw new DENOPTIMException("No path found between vertices "
243 + vA.getVertexId() + " and " + vB.getVertexId());
244 }
245
246 // Build the corresponding edge path, but may add null.
247 // Here we also set the turning point vertex, if any.
248 edgesPathVAVB = new ArrayList<Edge>();
249 for (int i=1; i<vertPathVAVB.size(); i++)
250 {
251 Vertex vPrev = vertPathVAVB.get(i-1);
252 Vertex vCurr = vertPathVAVB.get(i);
253 Edge edge = vPrev.getEdgeWith(vCurr);
254 if (edge != null)
255 {
256 edgesPathVAVB.add(edge);
257 } else {
258 edgesPathVAVB.add(null);
259 }
260 }
262 }
263
264//-----------------------------------------------------------------------------
265
271 private static Map<Vertex, List<Vertex>> buildAdjacencyFromGraph(DGraph graph)
272 {
273 Map<Vertex, List<Vertex>> adjacency = new HashMap<Vertex, List<Vertex>>();
274 for (Edge e : graph.getEdgeList())
275 {
276 Vertex srcVertex = e.getSrcAP().getOwner();
277 Vertex trgVertex = e.getTrgAP().getOwner();
278 adjacency.computeIfAbsent(srcVertex, k -> new ArrayList<Vertex>())
279 .add(trgVertex);
280 adjacency.computeIfAbsent(trgVertex, k -> new ArrayList<Vertex>())
281 .add(srcVertex);
282 }
283 return adjacency;
284 }
285
286//-----------------------------------------------------------------------------
287
297 private static List<Vertex> findShortestPath(Vertex vA, Vertex vB,
298 Map<Vertex, List<Vertex>> neighbours)
299 {
300 if (vA == vB)
301 {
302 return new ArrayList<Vertex>(Arrays.asList(vA));
303 }
304
305 Map<Vertex, Vertex> parent = new HashMap<Vertex, Vertex>();
306 Set<Long> visited = new HashSet<Long>();
307 List<Vertex> queue = new ArrayList<Vertex>();
308
309 queue.add(vA);
310 visited.add(vA.getVertexId());
311 parent.put(vA, null);
312
313 while (!queue.isEmpty())
314 {
315 Vertex current = queue.remove(0);
316
317 if (current == vB)
318 {
319 return reconstructVertexPath(vA, vB, parent);
320 }
321
322 List<Vertex> neighbors = neighbours.get(current);
323 if (neighbors == null)
324 {
325 continue;
326 }
327
328 for (Vertex neighbor : neighbors)
329 {
330 if (visited.add(neighbor.getVertexId()))
331 {
332 parent.put(neighbor, current);
333 queue.add(neighbor);
334 if (neighbor == vB)
335 {
336 return reconstructVertexPath(vA, vB, parent);
337 }
338 }
339 }
340 }
341
342 return new ArrayList<Vertex>();
343 }
344
345//-----------------------------------------------------------------------------
346
355 private static List<Vertex> reconstructVertexPath(Vertex vA, Vertex vB,
356 Map<Vertex, Vertex> parent)
357 {
358 // NB: we start from vB and climb towards vA.
359 LinkedList<Vertex> path = new LinkedList<Vertex>();
360 for (Vertex node = vB; node != null; node = parent.get(node))
361 {
362 path.addFirst(node);
363 }
364 return path;
365 }
366
367//-----------------------------------------------------------------------------
368
372 private void setGraphAndChainIDs()
373 {
374 // Build the graph and chain IDs for this sub graph
375 chainID = "";
376 revChainID = "";
377 ArrayList<Vertex> gVertices = new ArrayList<Vertex>();
378 ArrayList<Edge> gEdges = new ArrayList<Edge>();
379 for (int i=1; i < vertPathVAVB.size()-1; i++)
380 {
381 Vertex vertBack = vertPathVAVB.get(i-1);
382 Vertex vertHere = vertPathVAVB.get(i);
383 Vertex vertFrnt = vertPathVAVB.get(i+1);
384 Edge edgeToBack = edgesPathVAVB.get(i-1); //NB: may be null!
385 Edge edgeToFrnt = edgesPathVAVB.get(i); //NB: may be null!
386
387 AttachmentPoint apBackToHere = null;
388 AttachmentPoint apHereToBack = null;
389 AttachmentPoint apHereToFrnt = null;
390 AttachmentPoint apFrntToHere = null;
391 if (edgeToBack!=null)
392 {
393 if (edgeToBack.getSrcAP().getOwner() == vertHere)
394 {
395 apHereToBack = edgeToBack.getSrcAP();
396 apBackToHere = edgeToBack.getTrgAP();
397 } else {
398 apHereToBack = edgeToBack.getTrgAP();
399 apBackToHere = edgeToBack.getSrcAP();
400 }
401 }
402 if (edgeToFrnt!=null)
403 {
404 if (edgeToFrnt.getSrcAP().getOwner() == vertHere)
405 {
406 apHereToFrnt = edgeToFrnt.getSrcAP();
407 apFrntToHere = edgeToFrnt.getTrgAP();
408 } else {
409 apHereToFrnt = edgeToFrnt.getTrgAP();
410 apFrntToHere = edgeToFrnt.getSrcAP();
411 }
412 }
413
414 // Build string representation of the path
415 if (i==1)
416 {
417 // Syntax from vertex.getPathIDs() is used:
418 String str = vertBack.getBuildingBlockId() + "/"
419 + vertBack.getBuildingBlockType() + "/" +
420 + vertBack.getIndexOfAP(apBackToHere);
421 chainID = str + "_";
422 revChainID = "_" + str;
423 }
424 String[] ids = vertHere.getPathIDs(apHereToBack, apHereToFrnt);
425 chainID = chainID + ids[0];
426 revChainID = ids[1] + revChainID;
427 if (i==vertPathVAVB.size()-2)
428 {
429 String str = vertFrnt.getBuildingBlockId() + "/"
430 + vertFrnt.getBuildingBlockType() + "/" +
431 + vertFrnt.getIndexOfAP(apFrntToHere);
432 chainID = chainID + "_" + str;
433 revChainID = str + "_" + revChainID;
434 }
435
436 // To build the graph make clones of the actual vertices/edges
437 Vertex cloneVertBack = vertBack.clone();
438 Vertex cloneVertHere = vertHere.clone();
439 Vertex cloneVertFrnt = vertFrnt.clone();
440
441 // Collect vertices and make edges to build a graph from A to B
442 if (i == 1) {
443 gVertices.add(cloneVertBack);
444 } else if (i > 1)
445 {
446 // Need to collect the reference to the vertex defined in the
447 // previous cycle.
448 cloneVertBack = gVertices.get(gVertices.size()-1);
449 }
450 gVertices.add(cloneVertHere);
451 if (edgeToBack!=null) {
452 gEdges.add(new Edge(cloneVertBack.getAP(vertBack.getIndexOfAP(apBackToHere)),
453 cloneVertHere.getAP(vertHere.getIndexOfAP(apHereToBack)),
454 edgeToBack.getBondType()));
455 }
456 if (i == vertPathVAVB.size()-2)
457 {
458 gVertices.add(cloneVertFrnt);
459 if (edgeToFrnt!=null) {
460 gEdges.add(new Edge(cloneVertHere.getAP(vertHere.getIndexOfAP(apHereToFrnt)),
461 cloneVertFrnt.getAP(vertFrnt.getIndexOfAP(apFrntToHere)),
462 edgeToFrnt.getBondType()));
463 }
464 }
465 }
466
467 // Build the DENOPTIMGraph with edges directed from VA to VB
468 this.graph = new DGraph(gVertices,gEdges);
469
470 // prepare alternative chain IDs
471 String[] pA = chainID.split("_");
472 String[] pB = revChainID.split("_");
473 for (int i=1; i<pA.length; i++)
474 {
475 String altrnA = "";
476 String altrnB = "";
477 for (int j=0; j<pA.length; j++)
478 {
479 if ((i+j) < pA.length)
480 {
481 altrnA = altrnA + pA[i+j] + "_";
482 altrnB = altrnB + pB[i+j] + "_";
483 } else {
484 altrnA = altrnA + pA[i+j-pA.length] + "_";
485 altrnB = altrnB + pB[i+j-pA.length] + "_";
486 }
487 }
488 }
489 }
490
491//------------------------------------------------------------------------------
492
506 public static DGraph findPath(Vertex from, Vertex to) {
507 DGraph g = new DGraph();
508 try {
509 if (from == to) {
510 return g;
511 }
512
513 Iterator<AttachmentPoint> path = findPath(from, to,
514 new HashSet<>()).iterator();
515
516 if (!path.hasNext()) {
517 return g;
518 }
519
520 AttachmentPoint srcAP = path.next().clone();
521 Vertex srcVertex = srcAP.getOwner().clone();
522 srcAP.setOwner(srcVertex);
523
524 g.addVertex(srcVertex);
525
526 AttachmentPoint trgAP = path.next().clone();
527 Vertex trgVertex = trgAP.getOwner().clone();
528 trgAP.setOwner(trgVertex);
529
530 g.appendVertexOnAP(srcAP, trgAP);
531
532 while (path.hasNext()) {
533 srcAP = path.next().clone();
534 srcVertex = srcAP.getOwner().clone();
535 srcAP.setOwner(srcVertex);
536
537 trgAP = path.next().clone();
538 trgVertex = trgAP.getOwner().clone();
539 trgAP.setOwner(trgVertex);
540
541 g.appendVertexOnAP(srcAP, trgAP);
542 }
543 } catch (DENOPTIMException e) {
544 e.printStackTrace();
545 }
546 return g;
547 }
548
549//------------------------------------------------------------------------------
550
560 private static Iterable<AttachmentPoint> findPath(
561 Vertex from, Vertex to, Set<Long> visited) {
562
563 long fromId = from.getVertexId();
564 if (visited.contains(fromId)) {
565 return new ArrayList<>();
566 }
567 visited.add(fromId);
568
569 for (AttachmentPoint fromAP : from.getAttachmentPoints()) {
570 Edge e = fromAP.getEdgeUser();
571 AttachmentPoint adjAP = e.getSrcVertex() == fromId ?
572 e.getTrgAP() : e.getSrcAP();
573 Vertex adj = adjAP.getOwner();
574
575 if (adj == to) {
576 return Arrays.asList(fromAP, adjAP);
577 }
578
579 Iterable<AttachmentPoint> path = findPath(adj, to, visited);
580 // Non-empty if there exists a path
581 if (path.iterator().hasNext()) {
582 List<AttachmentPoint> extendedPath =
583 new ArrayList<AttachmentPoint>(Arrays.asList(
584 fromAP, adjAP));
585 path.iterator().forEachRemaining(extendedPath::add);
586 return extendedPath;
587 }
588 }
589 // Dead end
590 return Collections.emptyList();
591 }
592
593//------------------------------------------------------------------------------
594
605 public void makeMolecularRepresentation(IAtomContainer mol, boolean make3D,
606 Logger logger, Randomizer randomizer) throws DENOPTIMException
607 {
608 // Build molecular representation
609 ThreeDimTreeBuilder tb = new ThreeDimTreeBuilder(logger, randomizer);
611 Map<IAtom,ArrayList<AttachmentPoint>> apsPerAtom =
613 Map<IBond,ArrayList<AttachmentPoint>> apsPerBond =
615
616 if (debug)
617 {
618 String f = "/tmp/pathSubGraph.sdf";
619 System.out.println("Find SDF representation of path in: " + f);
620 try {
622 DenoptimIO.writeSDFFile(f,mol,true);
623 } catch (Throwable t) {
624 throw new Error("Could not save debug file '" + f + "'.");
625 }
626 }
627
628 // Get shortest atom path between the two ends of the chain
630
631 // Identify which atoms in mol represent the RCA in the current chain.
632 // Since we are looking for the verteces of the RCA atoms
633 // there is only one atom per each of the two vertexID required
634
635 IAtom e0 = null;
636 IAtom e1 = null;
637 for (IAtom atm : mol.atoms())
638 {
639 long vrtId = (Long) atm.getProperty(
641 if (vrtId == vertPathVAVB.get(0).getVertexId())
642 e0 = atm;
643
644 if (vrtId == vertPathVAVB.get(vertPathVAVB.size()-1).getVertexId())
645 e1 = atm;
646
647 if (e0 != null && e1 != null)
648 break;
649 }
650 List<IAtom> ends = new ArrayList<IAtom>();
651 ends.add(e0);
652 ends.add(e1);
653
654 // Get path in mol that corresponds to the shortest path in iacPathVAVB
655 // This is done to get the bond properties from mol that is a
656 // fully defined molecule.
657 // Note that multiple paths with length equal to the shortest length
658 // are possible if there are rings within fragments (vertices),
659 // but in such case the alternative paths involve only non-rotatable.
660 // Therefore, the actual identity of the bond doesn't matter in
661 // this particular context.
662 List<IAtom> pathInFullMol = new ArrayList<IAtom>();
663
664 IAtom currentAtm = null;
665 long prevAtmInPathVID = -1;
666 long currAtmInPathVID = -1;
667 long nextAtmInPathVID = -1;
668 List<IAtom> candidates = new ArrayList<IAtom>();
669 for (int i=1; i<(atomsPathVAVB.size()); i++)
670 {
671 //We have already found the atoms corresponding to the extremes
672 if (i==1)
673 {
674 currentAtm = ends.get(0);
675 pathInFullMol.add(currentAtm);
676 candidates.addAll(mol.getConnectedAtomsList(currentAtm));
677 } else if (i==(atomsPathVAVB.size()-1))
678 {
679 pathInFullMol.add(ends.get(1));
680 break;
681 }
682
683 // Now, standard behaviour for all other non-extreme cases
684 prevAtmInPathVID = getVertexIdInPath(atomsPathVAVB.get(i-1));
685 currAtmInPathVID = getVertexIdInPath(atomsPathVAVB.get(i));
686 nextAtmInPathVID = getVertexIdInPath(atomsPathVAVB.get(i+1));
687
688 if (prevAtmInPathVID != currAtmInPathVID)
689 {
690 for (IAtom c : candidates)
691 {
692 if (getVertexIdInPath(c) == currAtmInPathVID)
693 {
694 currentAtm = c;
695 pathInFullMol.add(currentAtm);
696 candidates.clear();
697
698 for (IAtom c2 : mol.getConnectedAtomsList(c))
699 {
700 if (!pathInFullMol.contains(c2))
701 candidates.add(c2);
702 }
703 break;
704 }
705 }
706 continue;
707 } else {
708 //NB: currentAtm remains the same
709 List<IAtom> newCandidates = new ArrayList<IAtom>();
710 for (IAtom nbr : candidates)
711 {
712 boolean foundNextLevel = false;
713 for (IAtom nbrNbr : mol.getConnectedAtomsList(nbr))
714 {
715 if (pathInFullMol.contains(nbrNbr)
716 || candidates.contains(nbrNbr))
717 continue;
718
719 long vid = getVertexIdInPath(nbrNbr);
720 if (vid == nextAtmInPathVID
721 && currAtmInPathVID!=nextAtmInPathVID)
722 {
723 ShortestPaths sp = new ShortestPaths(mol,
724 currentAtm);
725 List<IAtom> itnraVertPath = new ArrayList<IAtom>(
726 Arrays.asList(sp.atomsTo(nbr)));
727
728 // currentAtm was already added: skip it
729 for (int j=1; j<itnraVertPath.size(); j++)
730 pathInFullMol.add(itnraVertPath.get(j));
731
732 currentAtm = nbr;
733 newCandidates.clear();
734 newCandidates.add(nbrNbr);
735 foundNextLevel = true;
736 break;
737 } else {
738 if (vid == currAtmInPathVID)
739 {
740 newCandidates.add(nbrNbr);
741 }
742 }
743 }
744 if (foundNextLevel)
745 break;
746 }
747 candidates.clear();
748 candidates.addAll(newCandidates);
749 continue;
750 }
751 }
752 if (pathInFullMol.size() != atomsPathVAVB.size())
753 {
754 throw new IllegalStateException("Paths have different size! "
755 + "Unable to "
756 + "proceed in the evaluation of ring closability. "
757 + "Please report this to the author.");
758 }
759
760 // Identify the path of bonds between head and tail
761 // This is taken from the fully defined mol to inherit rotatability
762 // and allow identification of bonds used in multiple rings-closing
763 // chains.
764 bondsPathVAVB = new ArrayList<IBond>();
765 for (int i=0; i < pathInFullMol.size()-1; i++)
766 {
767 IBond bnd = mol.getBond(pathInFullMol.get(i),
768 pathInFullMol.get(i+1));
769 bondsPathVAVB.add(bnd);
770 }
771
772 // Define points used to calculate dihedral angle of each bond
773 // excluding the first and last
774 dihedralRefPts = new ArrayList<ArrayList<Point3d>>();
775 String keyPropVrtID = DENOPTIMConstants.ATMPROPVERTEXID;
776 for (int it=3; it<atomsPathVAVB.size(); it++)
777 {
778 ArrayList<Point3d> fourPoints = new ArrayList<Point3d>();
779 Point3d p0;
780 Point3d p1;
781 Point3d p2;
782 Point3d p3;
783 IAtom a0 = atomsPathVAVB.get(it-3);
784 IAtom a1 = atomsPathVAVB.get(it-2);
785 IAtom a2 = atomsPathVAVB.get(it-1);
786 IAtom a3 = atomsPathVAVB.get(it);
787 long vIdA0 = a0.getProperty(keyPropVrtID);
788 long vIdA1 = a1.getProperty(keyPropVrtID);
789 long vIdA2 = a2.getProperty(keyPropVrtID);
790 long vIdA3 = a3.getProperty(keyPropVrtID);
791 IBond bndA1A2 = iacPathVAVB.getBond(a1,a2);
792
793 // trivial for points 1 and 2
794 p0 = a0.getPoint3d(); // only initialization
795 p1 = a1.getPoint3d();
796 p2 = a2.getPoint3d();
797 p3 = a3.getPoint3d(); // only initialization
798
799 // chose point 0
800 if (vIdA0 != vIdA1)
801 {
802 // use the point identified by the ap on atom a1 that
803 // has the lowest index in the list of aps on a1,
804 // but is not the AP used to bind a1 and a2
805 for (AttachmentPoint ap : apsPerAtom.get(a1))
806 {
807 if (apsPerBond.keySet().contains(bndA1A2))
808 {
809 if (apsPerBond.get(bndA1A2).contains(ap))
810 {
811 continue;
812 }
813 }
814 p0 = new Point3d(ap.getDirectionVector());
815 break;
816 }
817 }
818 else
819 {
820 // Choose the atom connected to a1 that has the lowest index
821 // in the IAtomContainer and is not a2
822 List<IAtom> nbrsOfA1 = iacPathVAVB.getConnectedAtomsList(a1);
823 int lowIDs = 10000000;
824 for (IAtom nbrOfA1 : nbrsOfA1)
825 {
826 if (nbrOfA1 == a2)
827 {
828 continue;
829 }
830 int atmID = iacPathVAVB.indexOf(nbrOfA1);
831 if (atmID < lowIDs)
832 {
833 lowIDs = atmID;
834 }
835 }
836 p0 = new Point3d(iacPathVAVB.getAtom(lowIDs).getPoint3d());
837 }
838
839 // choose point 3 (as done for point 0)
840 if (vIdA2 != vIdA3)
841 {
842 // use the point identified by the ap on atom a2 that
843 // has the lowest index in the list of aps on a2,
844 // but is not the AP used to bind a1 and a1
845 for (AttachmentPoint ap : apsPerAtom.get(a2))
846 {
847 if (apsPerBond.keySet().contains(bndA1A2))
848 {
849 if (apsPerBond.get(bndA1A2).contains(ap))
850 {
851 continue;
852 }
853 }
854 p3 = new Point3d(ap.getDirectionVector());
855 break;
856 }
857 }
858 else
859 {
860 // Choose the atom connected to a2 that has the lowest index
861 // in the IAtomContainer and is not a1.
862 List<IAtom> nbrsOfA2 = iacPathVAVB.getConnectedAtomsList(a2);
863 int lowIDs = 10000000;
864 for (IAtom nbrOfA2 : nbrsOfA2)
865 {
866 if (nbrOfA2 == a1)
867 {
868 continue;
869 }
870 int atmID = iacPathVAVB.indexOf(nbrOfA2);
871 if (atmID < lowIDs)
872 {
873 lowIDs = atmID;
874 }
875 }
876 p3 = new Point3d(iacPathVAVB.getAtom(lowIDs).getPoint3d());
877 }
878
879 fourPoints.add(p0);
880 fourPoints.add(p1);
881 fourPoints.add(p2);
882 fourPoints.add(p3);
883
884 dihedralRefPts.add(fourPoints);
885 }
886
887 if (debug)
888 {
889 System.out.println("Points for dihedral angle definition: ");
890 for (ArrayList<Point3d> fp : dihedralRefPts)
891 {
892 for (Point3d p : fp)
893 {
894 System.out.println(" "+p);
895 }
896 System.out.println(" ");
897 }
898 }
899
900 // set flag
901 hasMolRepr = true;
902 }
903
904//-----------------------------------------------------------------------------
905
913 public static List<IAtom> findAtomPath(IAtomContainer iac)
914 {
915 IAtom head = iac.getAtom(0);
916 IAtom tail = iac.getAtom(iac.getAtomCount()-1);
917 ShortestPaths sp = new ShortestPaths(iac, head);
918 List<IAtom> path = new ArrayList<IAtom>(Arrays.asList(
919 sp.atomsTo(tail)));
920 return path;
921 }
922
923//-----------------------------------------------------------------------------
924
925 private long getVertexIdInPath(IAtom a)
926 {
927 return a.getProperty(DENOPTIMConstants.ATMPROPVERTEXID, Long.class)
928 .longValue();
929 }
930
931//-----------------------------------------------------------------------------
932
937 public String getChainID()
938 {
939 return chainID;
940 }
941
942//-----------------------------------------------------------------------------
943
949 public List<String> getAllAlternativeChainIDs()
950 {
951 return allPossibleChainIDs;
952 }
953
954//-----------------------------------------------------------------------------
955
961 {
962 return vA;
963 }
964
965//-----------------------------------------------------------------------------
966
972 {
973 return vB;
974 }
975
976//-----------------------------------------------------------------------------
977
982 public int getPathLength()
983 {
984 return edgesPathVAVB.size();
985 }
986//-----------------------------------------------------------------------------
987
992 public List<Vertex> getVertecesPath()
993 {
994 return vertPathVAVB;
995 }
996
997//-----------------------------------------------------------------------------
998
1007 public List<Edge> getEdgesPath()
1008 {
1009 return edgesPathVAVB;
1010 }
1011
1012//-----------------------------------------------------------------------------
1013
1019 {
1020 return hasMolRepr;
1021 }
1022
1023//-----------------------------------------------------------------------------
1024
1028 public IAtomContainer getMolecularRepresentation()
1029 {
1030 return iacPathVAVB;
1031 }
1032
1033//-----------------------------------------------------------------------------
1034
1039 public List<IAtom> getAtomPath()
1040 {
1041 return atomsPathVAVB;
1042 }
1043
1044//-----------------------------------------------------------------------------
1045
1051 public String getAtomRefStr()
1052 {
1053 return atmNumStr;
1054 }
1055
1056//-----------------------------------------------------------------------------
1057
1064 public List<IBond> getBondPath()
1065 {
1066 return bondsPathVAVB;
1067 }
1068
1069//-----------------------------------------------------------------------------
1070
1077 public ArrayList<ArrayList<Point3d>> getDihedralRefPoints()
1078 {
1079 return dihedralRefPts;
1080 }
1081
1082//-----------------------------------------------------------------------------
1083
1089 {
1090 return rcc;
1091 }
1092
1093//-----------------------------------------------------------------------------
1094
1100 {
1101 this.rcc = rcc;
1102 }
1103
1104//-----------------------------------------------------------------------------
1105
1110 @Override
1111 public String toString()
1112 {
1113 StringBuilder sb = new StringBuilder();
1114 boolean first = true;
1115 for (Vertex v : vertPathVAVB)
1116 {
1117 if (!first)
1118 {
1119 sb.append("-");
1120 }
1121 sb.append(v.getVertexId());
1122 first = false;
1123 }
1124 return sb.toString();
1125 }
1126
1127 public DGraph getGraph() {
1128 return graph;
1129 }
1130
1131//-----------------------------------------------------------------------------
1132
1133}
General set of constants used in DENOPTIM.
static final Object MOLPROPAPxBOND
Key for IAtomContainer property containing the map of AttachmentPoints per atom.
static final String ATMPROPVERTEXID
String tag of Atom property used to store the unique ID of the Vertex corresponding to the molecular ...
static final Object MOLPROPAPxATOM
Key for IAtomContainer property containing the map of AttachmentPoints per vertex ID.
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
void setOwner(Vertex owner)
Sets the reference to the vertex that owns this attachment point.
AttachmentPoint clone()
Returns a deep clone of this attachment point.
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:104
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1391
void appendVertexOnAP(AttachmentPoint srcAP, AttachmentPoint trgAP)
Append a vertex to this graph: adds the new vertex to the list of vertices belonging to the graph,...
Definition: DGraph.java:6476
List< Edge > getEdgeList()
Definition: DGraph.java:1020
This class represents the edge between two vertices.
Definition: Edge.java:38
AttachmentPoint getTrgAP()
Definition: Edge.java:115
long getSrcVertex()
Definition: Edge.java:122
AttachmentPoint getSrcAP()
Definition: Edge.java:94
BondType getBondType()
Definition: Edge.java:166
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
abstract Vertex clone()
Returns a deep-copy of this vertex.
int getBuildingBlockId()
Returns the index of the building block that should correspond to the position of the building block ...
Definition: Vertex.java:304
String[] getPathIDs(AttachmentPoint apA, AttachmentPoint apB)
Produces a pair of strings that identify the "path" between two given attachment points.
Definition: Vertex.java:1402
int getIndexOfAP(AttachmentPoint ap)
Returns the position of the given AP in the list of APs of this vertex.
Definition: Vertex.java:1036
Vertex.BBType getBuildingBlockType()
Definition: Vertex.java:318
DGraph getGraphOwner()
Returns the graph this vertex belongs to or null.
Definition: Vertex.java:851
abstract List< AttachmentPoint > getAttachmentPoints()
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:1007
Edge getEdgeWith(Vertex other)
Finds the edge between this and the other vertex, if it exists.
Definition: Vertex.java:1514
This object represents a path in a DGraph.
PathSubGraph(Vertex vA, Vertex vB, Map< Vertex, List< Vertex > > adjacency, boolean combineAdjacencyAndActualEdges)
Constructs a new path sub graph specifying the first and last vertex of the path.
RingClosingConformations rcc
The list of closable conformations, if any is found.
boolean hasMolRepr
The flag defining whether this object has already a molecular representation or not.
String getAtomRefStr()
Returns the string with atom symbols and number for an easy identification of the path in a molecular...
static Iterable< AttachmentPoint > findPath(Vertex from, Vertex to, Set< Long > visited)
Returns a sequence of APs that is the path from vertex from to vertex to.
List< IBond > getBondPath()
Returns the list of bonds in the path between the head and the tail.
RingClosingConformations getRCC()
Returns the ring closing conformations.
String atmNumStr
The string of atoms involved (atom numbers from full molecule list)
int getPathLength()
Returns the length of the list of edges involved in this path.
void makeMolecularRepresentation(IAtomContainer mol, boolean make3D, Logger logger, Randomizer randomizer)
Creates the molecular representation, list of atoms and bonds involved in the path between the head a...
List< Vertex > getVertecesPath()
Returns the list of verteces involved.
Vertex vA
The vertex representing the first RCA: head of the path.
IAtomContainer getMolecularRepresentation()
Returns the molecular representation.
PathSubGraph(Vertex vA, Vertex vB, Map< Vertex, List< Vertex > > adjacency)
Constructs a new path sub graph specifying the first and last vertex of the path.
String chainID
The string identifier of this path.
String getChainID()
Returns the string representation of the path.
Vertex vB
The vertex representing the second RCA: the tail of the path.
static List< Vertex > reconstructVertexPath(Vertex vA, Vertex vB, Map< Vertex, Vertex > parent)
Reconstructs the vertex path from the parent map.
List< IBond > bondsPathVAVB
The list of bonds in the shortest path.
IAtomContainer iacPathVAVB
The molecular representation of the fragment in the path.
List< IAtom > getAtomPath()
Returns the list of atoms in the path between the head and the tail.
boolean hasMolecularRepresentation()
Returns true if the molecular representation has been set.
static List< Vertex > findShortestPath(Vertex vA, Vertex vB, Map< Vertex, List< Vertex > > neighbours)
Finds the shortest vertex path from vA to vB using BFS.
List< Edge > edgesPathVAVB
The list of edges of the original graph and involved in the path.
static Map< Vertex, List< Vertex > > buildAdjacencyFromGraph(DGraph graph)
Builds an adjacency map from a graph.
Vertex getHeadVertex()
Returns the vertex representing the head of the chain.
List< IAtom > atomsPathVAVB
The list of atoms in the shortest path.
ArrayList< ArrayList< Point3d > > dihedralRefPts
Per each bond the pair of point used to define the torsion.
static List< IAtom > findAtomPath(IAtomContainer iac)
Finds the shortest path of atoms between the first and last atom in the given atom container.
PathSubGraph(Vertex vA, Vertex vB)
Constructs a new path sub graph specifying the first and last vertex of the path.
void setGraphAndChainIDs()
Sets the graph and chain IDs for the path sub graph.
ArrayList< ArrayList< Point3d > > getDihedralRefPoints()
Returns the list of point to be used to define the torsion of a bond uniquely (independently on the s...
Vertex getTailVertex()
Returns the vertex representing the tail of the chain.
List< Vertex > vertPathVAVB
The list of vertices of the original graph and involved in the path.
static DGraph findPath(Vertex from, Vertex to)
Returns a path subgraph from the first given vertex to the second one.
List< Edge > getEdgesPath()
Returns the list of edges involved, if any.
ArrayList< String > allPossibleChainIDs
void setRCC(RingClosingConformations rcc)
Set the ring closing conformations to this object.
DGraph graph
The graph representation of this path.
List< String > getAllAlternativeChainIDs()
Returns all the possible IDs for this chain.
Serializable object to store/get a list of conformations that allow to close a ring from an open chai...
Utility methods for input/output.
static void writeSDFFile(String fileName, IAtomContainer mol)
Writes IAtomContainer to SDF file.
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.
Tool to generate random numbers and random decisions.
Definition: Randomizer.java:35