$darkmode
DENOPTIM
Template.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2022 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;
20
21import java.io.StringReader;
22import java.lang.reflect.Type;
23import java.util.ArrayList;
24import java.util.Comparator;
25import java.util.HashMap;
26import java.util.LinkedHashMap;
27import java.util.List;
28import java.util.Map;
29import java.util.Map.Entry;
30import java.util.TreeMap;
31import java.util.logging.Logger;
32
33import javax.vecmath.Point3d;
34
35import org.openscience.cdk.interfaces.IAtom;
36import org.openscience.cdk.interfaces.IAtomContainer;
37
38import com.google.gson.Gson;
39import com.google.gson.JsonObject;
40import com.google.gson.internal.Streams;
41import com.google.gson.reflect.TypeToken;
42import com.google.gson.stream.JsonReader;
43
44import denoptim.constants.DENOPTIMConstants;
45import denoptim.exception.DENOPTIMException;
46import denoptim.graph.Edge.BondType;
47import denoptim.json.DENOPTIMgson;
48import denoptim.molecularmodeling.ThreeDimTreeBuilder;
49import denoptim.utils.MoleculeUtils;
50import denoptim.utils.MutationType;
51import denoptim.utils.Randomizer;
52
79public class Template extends Vertex
80{
85
94 private IAtomContainer mol = null;
95
100
104 public enum ContractLevel {
110
117
124 FIXED_STRUCT
126
127 private List<AttachmentPoint> requiredAPs = new ArrayList<>();
128
130
131
132//------------------------------------------------------------------------------
133
134 public Template(Vertex.BBType bbType)
135 {
136 super(VertexType.Template);
137 setBuildingBlockType(bbType);
138 }
139
140//------------------------------------------------------------------------------
141
153 @Override
154 public String[] getPathIDs(AttachmentPoint apA,
155 AttachmentPoint apB)
156 {
157 String a2b = this.getBuildingBlockId() + "/" + this.getBuildingBlockType() + "/ap"
158 + getIndexOfAP(apA) + "ap" + getIndexOfAP(apB) + "_";
159 String b2a = this.getBuildingBlockId() + "/" + this.getBuildingBlockType() + "/ap"
160 + getIndexOfAP(apB) + "ap" + getIndexOfAP(apA) + "_";
161
162 return new String[]{a2b,b2a};
163 }
164
165//------------------------------------------------------------------------------
166
173 throws DENOPTIMException
174 {
175 Template template = new Template(
177 EmptyVertex vrtx = new EmptyVertex(0);
178 EmptyVertex vrtx2 = new EmptyVertex(1);
179
180 vrtx.addAP();
181 vrtx.addAP();
182
183 vrtx2.addAP();
184 vrtx2.addAP();
185 DGraph g = new DGraph();
186 g.addVertex(vrtx);
187 g.addVertex(vrtx2);
188 g.addEdge(new Edge(vrtx.getAP(0),
189 vrtx2.getAP(1), BondType.SINGLE));
190 template.setInnerGraph(g);
191
192 template.contractLevel = contractLevel;
193 return template;
194 }
195
196//------------------------------------------------------------------------------
197
204 {
205 return contractLevel;
206 }
207
208//------------------------------------------------------------------------------
209
214 public void setContractLevel(ContractLevel contract)
215 {
216 if (contract == ContractLevel.FIXED_STRUCT)
218
219 this.contractLevel = contract;
220 }
221
222//------------------------------------------------------------------------------
223
231 public boolean freezeTemplate() {
232 boolean isFrozen = contractLevel == ContractLevel.FIXED;
234 return isFrozen;
235 }
236
237//------------------------------------------------------------------------------
238
244 {
245 Template c = new Template(this.getBuildingBlockType());
246
247 c.setVertexId(this.getVertexId());
249 c.contractLevel = this.contractLevel;
251
252 for (AttachmentPoint ap : this.requiredAPs)
253 {
254 c.addRequiredAP(ap.getDirectionVector(), ap.getAPClass());
255 }
257 if (this.mol!=null)
258 {
259 //NB: We cannot use setIAtomContainer because it implies using
260 // referenced to graph's AP which have been cloned, so the references
261 // are broken.
262 try
263 {
265 for (int i=0; i<this.getAttachmentPoints().size(); i++)
266 {
267 AttachmentPoint thisOutAP =
268 this.getAttachmentPoints().get(i);
269 AttachmentPoint cloneOutAP =
270 c.getAttachmentPoints().get(i);
271 cloneOutAP.setDirectionVector(new Point3d(
272 thisOutAP.getDirectionVector()));
273 cloneOutAP.setAtomPositionNumber(
274 thisOutAP.getAtomPositionNumber());
275 }
276
277 } catch (DENOPTIMException e)
278 {
279 // TODO Auto-generated catch block
280 e.printStackTrace();
281 }
282 }
284 if (uniquefyingPropertyKeys!=null)
286 return c;
287 }
288
289//-----------------------------------------------------------------------------
290
292 {
293 return innerGraph;
294 }
295
296//-----------------------------------------------------------------------------
297
299 throws IllegalArgumentException
300 {
301 // NB: if you change anything here, remember that we can modify the
302 // inner graph, so the change you are implementing here might need to be
303 // reflected in any place where the inner graph is modified (e.g.,
304 // DENOPTIMGraph.insertSingleVertex()
305
308 throw new IllegalArgumentException("inner graph does not have all" +
309 " required APs");
310 }
311 this.innerGraph = innerGraph;
313 this.innerToOuterAPs = new APTreeMap();
314
315 //TODO: we might need to remove unused RCVs from inner graph.
316 // Such RCVs cannot be used outside the template.
317
318 for (AttachmentPoint innerAP : innerGraph.getAvailableAPs()) {
320 }
321 }
322
323//-----------------------------------------------------------------------------
324
325 private void updateInnerToOuter(TreeMap<Integer,AttachmentPoint> map)
326 {
328 this.innerToOuterAPs = new APTreeMap();
329 for (Entry<Integer, AttachmentPoint> e : map.entrySet())
330 {
331 AttachmentPoint innerAP = innerGraph.getAPWithId(e.getKey());
332 AttachmentPoint outerAP = e.getValue();
333 outerAP.setOwner(this);
334 this.innerToOuterAPs.put(innerAP, outerAP);
335 }
336 }
337
338//-----------------------------------------------------------------------------
339
349 {
350 if (innerToOuterAPs.containsKey(newInnerAP))
351 {
352 return;
353 }
354 AttachmentPoint outerAP = newInnerAP.clone();
355 outerAP.setOwner(this);
356 innerToOuterAPs.put(newInnerAP, outerAP);
357 // Recursion on nesting templates to add projections of the AP
358 if (getGraphOwner() != null && getGraphOwner().templateJacket != null)
359 {
361 }
362 }
363
364//-----------------------------------------------------------------------------
365
377 public void updateInnerApID(AttachmentPoint oldInnerAP,
378 AttachmentPoint newInnerAP)
379 {
380 if (!innerToOuterAPs.containsKey(oldInnerAP))
381 {
382 return;
383 }
384 AttachmentPoint outerAP = innerToOuterAPs.get(oldInnerAP);
385 outerAP.setAPClass(newInnerAP.getAPClass());
386
387 innerToOuterAPs.remove(oldInnerAP);
388 innerToOuterAPs.put(newInnerAP, outerAP);
389 }
390
391//-----------------------------------------------------------------------------
392
400 throws DENOPTIMException
401 {
402 if (!innerToOuterAPs.containsKey(oldInnerAP))
403 {
404 return;
405 }
406 AttachmentPoint outer = innerToOuterAPs.get(oldInnerAP);
407 if (!outer.isAvailable())
408 {
409 AttachmentPoint linkedAP = outer.getLinkedAP();
411 }
412 // Recursion on nesting templates to remove all projections of the AP
413 if (getGraphOwner() != null && getGraphOwner().templateJacket != null)
414 {
416 }
417 innerToOuterAPs.remove(oldInnerAP);
418 }
419
420//-----------------------------------------------------------------------------
421
422 private boolean isValidInnerGraph(DGraph g)
423 {
424 if (requiredAPs.size()==0)
425 return true;
426
427 List<AttachmentPoint> innerAPs = g.getAvailableAPs();
428 if (innerAPs.size() < getRequiredAPs().size()) {
429 return false;
430 }
431 Comparator<AttachmentPoint> apClassComparator
432 = Comparator.comparing(AttachmentPoint::getAPClass,
433 Comparator.nullsLast(Comparator.naturalOrder()));
434 innerAPs.sort(apClassComparator);
435 List<AttachmentPoint> reqAPs = getRequiredAPs();
436 reqAPs.sort(apClassComparator);
437 int matchesLeft = reqAPs.size();
438 for (int i = 0, j = 0; matchesLeft > 0 && i < innerAPs.size(); i++)
439 {
440 if (apClassComparator.compare(innerAPs.get(i), reqAPs.get(j)) == 0)
441 {
442 matchesLeft--;
443 j++;
444 }
445 }
446 return matchesLeft == 0;
447 }
448
449//-----------------------------------------------------------------------------
450
457 @Override
458 public ArrayList<AttachmentPoint> getAttachmentPoints()
459 {
460 if (innerToOuterAPs == null)
461 return new ArrayList<>();
462 else
463 return new ArrayList<>(innerToOuterAPs.values());
464 }
465
466//-----------------------------------------------------------------------------
467
473 @Override
474 protected void setSymmetricAPSets(List<SymmetricAPs> sAPs)
475 {
476 // Do nothing... for now.
477 }
478
479 //-----------------------------------------------------------------------------
480
481 @Override
482 protected void addSymmetricAPSet(SymmetricAPs symAPs)
483 {
484 // Do nothing... for now.
485 }
486
487//-----------------------------------------------------------------------------
488
494 @Override
495 public List<SymmetricAPs> getSymmetricAPSets()
496 {
497 List<SymmetricAPs> allSymSets = new ArrayList<SymmetricAPs>();
498
499 List<AttachmentPoint> doneAPs = new ArrayList<AttachmentPoint>();
500 for (AttachmentPoint innerAP : innerToOuterAPs.keySet())
501 {
502 if (doneAPs.contains(innerAP))
503 continue;
504
505 // Must contain outer APs!
506 SymmetricAPs symSetForThisAP = new SymmetricAPs();
507
508 Vertex vrtx = innerAP.getOwner();
509 int innerAPIdx = innerAP.getIndexInOwner();
510 SymmetricAPs sAPsOnVrtx = vrtx.getSymmetricAPs(innerAP);
511 if (sAPsOnVrtx.size()!=0)
512 {
513 for (AttachmentPoint symInnerAP : sAPsOnVrtx)
514 {
515 if (doneAPs.contains(symInnerAP))
516 continue;
517 if (innerToOuterAPs.containsKey(symInnerAP))
518 {
519 symSetForThisAP.add(innerToOuterAPs.get(symInnerAP));
520 doneAPs.add(symInnerAP);
521 }
522 }
523 }
524
525 List<Vertex> symVrtxs = innerGraph.getSymVerticesForVertex(vrtx);
526 for (Vertex symVrtx : symVrtxs)
527 {
528 //NB: we assume that this is the same vertex type as vrtx, but
529 // a different instance. Thus the list of APs should be a match
530 // and we reuse the same index 'innerAPIdx'.
531 AttachmentPoint innerApOnSymVrtx = symVrtx.getAP(innerAPIdx);
532 if (doneAPs.contains(innerApOnSymVrtx))
533 continue;
534
535 SymmetricAPs sAPsOnSymVrtx = symVrtx.getSymmetricAPs(
536 innerApOnSymVrtx);
537 if (sAPsOnSymVrtx.size()!=0)
538 {
539 for (AttachmentPoint symInnerAPOnSymVrtx : sAPsOnSymVrtx)
540 {
541 if (doneAPs.contains(symInnerAPOnSymVrtx))
542 continue;
543 if (innerToOuterAPs.containsKey(symInnerAPOnSymVrtx))
544 {
545 symSetForThisAP.add(innerToOuterAPs.get(
546 symInnerAPOnSymVrtx));
547 doneAPs.add(symInnerAPOnSymVrtx);
548 }
549 }
550 } else {
551 // We need to add the AP at innerAPIdx anyway because even
552 // if it does not have symmetric APs on its vertex owner it
553 // is symmetric to the vrtx by means of the two vertices
554 // being members of the same symmetric set of vertices.
555 if (innerToOuterAPs.containsKey(innerApOnSymVrtx))
556 {
557 symSetForThisAP.add(innerToOuterAPs.get(
558 innerApOnSymVrtx));
559 doneAPs.add(innerApOnSymVrtx);
560 }
561 if (!doneAPs.contains(innerAP))
562 {
563 symSetForThisAP.add(innerToOuterAPs.get(innerAP));
564 doneAPs.add(innerAP);
565 }
566 }
567 }
568 if (symSetForThisAP.size()>1)
569 allSymSets.add(symSetForThisAP);
570 }
571 return allSymSets;
572 }
573
574//-----------------------------------------------------------------------------
575
576 @Override
578 {
580 }
581
582//-----------------------------------------------------------------------------
583
584 @Override
585 public boolean containsAtoms()
586 {
587 //NB: the mol!=null allows templates read-in from file to be displayed
588 // even if their graph's vertices are empty because they were
589 // deserialized from json. Another good reason for having atoms defined
590 // the json format...
591 return mol!=null
592 || innerGraph != null ? innerGraph.containsAtoms() : false;
593 }
594
595//-----------------------------------------------------------------------------
596
601 {
602 this.mol = null;
603 }
604
605//-----------------------------------------------------------------------------
606
621 public void setIAtomContainer(IAtomContainer mol,
622 boolean updateAPsAccordingToIAC) throws DENOPTIMException
623 {
624 //Collects all the links to APs
625 Map<AttachmentPoint,AttachmentPoint>
626 apInnerGraphToApOnMol = new HashMap<>();
627 if (updateAPsAccordingToIAC)
628 {
629 for (IAtom a : mol.atoms())
630 {
631 Object p = a.getProperty(DENOPTIMConstants.ATMPROPAPS);
632 if (p == null)
633 {
634 continue;
635 }
636 @SuppressWarnings("unchecked")
637 ArrayList<AttachmentPoint> apLst =
638 (ArrayList<AttachmentPoint>) p;
639 for (AttachmentPoint apOnMol : apLst)
640 {
641 Object o = apOnMol.getProperty(DENOPTIMConstants.LINKAPS);
642 if (o==null)
643 {
644 throw new DENOPTIMException("Unexpected null link to AP.");
645 }
646 AttachmentPoint linkedAPOnGraph =
647 (AttachmentPoint) o;
648 apInnerGraphToApOnMol.put(linkedAPOnGraph, apOnMol);
649 }
650 }
651 }
652
653 // We have to ensure outer APs point to the correct source atom in
654 // the atom list of the entire molecular representation of the
655 // templates.
656 // And we collects the outer APs per atom at the same time
657 LinkedHashMap<Integer,List<AttachmentPoint>> apsPerAtom =
658 new LinkedHashMap<>();
659 for (AttachmentPoint outAP : getAttachmentPoints())
660 {
661 AttachmentPoint inAPOnGraph = getInnerAPFromOuterAP(outAP);
662 int atmIndexInMol = outAP.getAtomPositionNumber();
663 if (updateAPsAccordingToIAC
664 && apInnerGraphToApOnMol.containsKey(inAPOnGraph))
665 {
666 AttachmentPoint apOnMol = apInnerGraphToApOnMol.get(inAPOnGraph);
667 outAP.setDirectionVector(apOnMol.getDirectionVector());
668 atmIndexInMol = apOnMol.getAtomPositionNumber(); //yes, not InMol!
669 }
670 outAP.setAtomPositionNumber(atmIndexInMol);
671 if (apsPerAtom.containsKey(atmIndexInMol))
672 {
673 apsPerAtom.get(atmIndexInMol).add(outAP);
674 } else {
675 List<AttachmentPoint> list =
676 new ArrayList<AttachmentPoint>();
677 list.add(outAP);
678 apsPerAtom.put(atmIndexInMol, list);
679 }
680 }
681
682 for (int i = 0; i < mol.getAtomCount(); i++) {
683 IAtom a = mol.getAtom(i);
684 a.setProperty(DENOPTIMConstants.ATMPROPORIGINALATMID, i);
686 getVertexId());
687 }
688
689 // Prepare SDF-like string for atom container. 0-based to 1-based
690 // index conversion done in here
691 mol.setProperty(DENOPTIMConstants.APSTAG,
693
694 mol.setProperty(DENOPTIMConstants.VERTEXJSONTAG,this.toJson());
695
696 mol.removeProperty(DENOPTIMConstants.GRAPHJSONTAG);
697 mol.removeProperty(DENOPTIMConstants.GRAPHTAG);
698 mol.removeProperty(DENOPTIMConstants.PROVENANCE);
699 mol.removeProperty(DENOPTIMConstants.GCODETAG);
700
701 this.mol = mol;
702 }
703
704//-----------------------------------------------------------------------------
705
714 @Override
715 public IAtomContainer getIAtomContainer()
716 {
717 Logger logger = Logger.getLogger("DummyLogger");
718 Randomizer rng = new Randomizer();
719 boolean removeUsedRCAs = true;
720 return getIAtomContainer(logger, rng, removeUsedRCAs, false);
721 }
722
723//-----------------------------------------------------------------------------
724
740 @Override
741 public IAtomContainer getIAtomContainer(Logger logger,
742 Randomizer rng, boolean removeUsedRCAs, boolean rebuild)
743 {
744 if (mol!=null && !rebuild)
745 {
746 return mol;
747 }
748 try
749 {
750 ThreeDimTreeBuilder t3b = new ThreeDimTreeBuilder(logger ,rng);
751 IAtomContainer iac = t3b.convertGraphTo3DAtomContainer(
752 innerGraph, removeUsedRCAs);
753
754 // We have to ensure outer APs point to the correct source atom in
755 // the atom list of the entire molecular representation of the
756 // templates.
757 // And we collects the outer APs per atom at the same time
758 LinkedHashMap<Integer,List<AttachmentPoint>> apsPerAtom =
759 new LinkedHashMap<>();
760 for (AttachmentPoint outAP : getAttachmentPoints())
761 {
763 if (inAP.getDirectionVector()==null)
764 {
765 outAP.setDirectionVector(null);
766 } else {
767 outAP.setDirectionVector(inAP.getDirectionVector());
768 }
769 int atmIndexInMol = inAP.getAtomPositionNumberInMol();
770 outAP.setAtomPositionNumber(atmIndexInMol);
771 if (apsPerAtom.containsKey(atmIndexInMol))
772 {
773 apsPerAtom.get(atmIndexInMol).add(outAP);
774 } else {
775 List<AttachmentPoint> list =
776 new ArrayList<AttachmentPoint>();
777 list.add(outAP);
778 apsPerAtom.put(atmIndexInMol, list);
779 }
780 }
781
782 // Remove references to inner APs in atom properties
783 for (IAtom atm : iac.atoms())
784 {
785 atm.removeProperty(DENOPTIMConstants.ATMPROPAPS);
786 }
787
788 // Store references to outer APs in atom properties
789 for (Integer atmId : apsPerAtom.keySet())
790 {
791 IAtom atm = iac.getAtom(atmId);
792 atm.setProperty(DENOPTIMConstants.ATMPROPAPS,
793 apsPerAtom.get(atmId));
794 }
795
796 // Prepare SDF-like string for atom container. 0-based to 1-based
797 // index conversion done in here
798 iac.setProperty(DENOPTIMConstants.APSTAG,
800
801 iac.setProperty(DENOPTIMConstants.VERTEXJSONTAG,this.toJson());
802
803 iac.removeProperty(DENOPTIMConstants.GRAPHJSONTAG);
804 iac.removeProperty(DENOPTIMConstants.GRAPHTAG);
805 iac.removeProperty(DENOPTIMConstants.PROVENANCE);
806 iac.removeProperty(DENOPTIMConstants.GCODETAG);
807
808 // We store the result in a field of this instance
809 mol = iac;
810 return mol;
811 } catch (DENOPTIMException e)
812 {
813 //TODO: deal with the situation: report error or state given
814 // assumption that allows to go on
815 e.printStackTrace();
816 }
817 return null;
818 }
819
820//-----------------------------------------------------------------------------
821
823 AttachmentPoint outerAP) {
824
825 // TODO: Check if another solution exists that can remove nested
826 // for-loop. Suggestion: make an outerToInnerAPMap.
827
828 // Very inefficient solution
829 for (Map.Entry<AttachmentPoint, AttachmentPoint> entry
830 : innerToOuterAPs.entrySet())
831 {
832 if (outerAP == entry.getValue())
833 {
834 return entry.getKey();
835 }
836 }
837 return null;
838 }
839
840//-----------------------------------------------------------------------------
841
843 AttachmentPoint innerAP)
844 {
845 return innerToOuterAPs.get(innerAP);
846 }
847
848//------------------------------------------------------------------------------
849
850 @Override
851 public List<MutationType> getMutationTypes(List<MutationType> ignoredTypes)
852 {
854 {
855 List<MutationType> scaffCompatTypes = new ArrayList<MutationType>();
856 if (getNumberOfAPs() != 0)
857 {
858 scaffCompatTypes.add(MutationType.EXTEND);
859 scaffCompatTypes.add(MutationType.CHANGELINK);
860 if (!getChilddren().isEmpty())
861 {
862 scaffCompatTypes.add(MutationType.ADDLINK);
863 }
864 }
865
866 scaffCompatTypes.removeAll(ignoredTypes);
867 return scaffCompatTypes;
868 }
869 return super.getMutationTypes(ignoredTypes);
870 }
871
872//------------------------------------------------------------------------------
873
885 @Override
886 public List<Vertex> getMutationSites(List<MutationType> ignoredTypes)
887 {
888 List<Vertex> lst = new ArrayList<Vertex>();
889 // capping groups are not considered mutable sites
891 {
892 return lst;
893 }
894
895 switch (contractLevel)
896 {
897 case FIXED:
898 if (getMutationTypes(ignoredTypes).size()>0)
899 lst.add(this);
900 break;
901
902 case FIXED_STRUCT:
904 for (Vertex v : innerGraph.gVertices)
905 {
906 lst.addAll(v.getMutationSites(ignoredTypes));
907 }
908 break;
909
910 case FREE:
911 for (Vertex v : innerGraph.gVertices)
912 {
913 lst.addAll(v.getMutationSites(ignoredTypes));
914 }
915 break;
916 }
917 return lst;
918 }
919
920//------------------------------------------------------------------------------
921
923 {
924 List<MutationType> toBeRemoved = new ArrayList<MutationType>();
925 toBeRemoved.add(MutationType.DELETE);
926 toBeRemoved.add(MutationType.DELETECHAIN);
927 toBeRemoved.add(MutationType.CHANGEBRANCH);
928 toBeRemoved.add(MutationType.ADDLINK);
929 toBeRemoved.add(MutationType.DELETELINK);
930 toBeRemoved.add(MutationType.EXTEND);
931 for (Vertex v : innerGraph.gVertices)
932 {
933 for (MutationType mt : toBeRemoved)
934 v.removeMutationType(mt);
935
936 if (v instanceof Template)
937 ((Template) v).setContractLevel(
939 }
940 }
941
942//------------------------------------------------------------------------------
943
949 public void addRequiredAP(Point3d pt, APClass apClass) {
951 if (getInnerGraph() != null) {
952 throw new IllegalArgumentException("cannot add more required APs " +
953 "after setting the inner graph");
954 }
955 AttachmentPoint ap = new AttachmentPoint(this, -1, pt,
956 apClass);
957 requiredAPs.add(ap);
958 }
959
960//------------------------------------------------------------------------------
961
970 public boolean sameAs(Template other, StringBuilder reason)
971 {
972 if (this.contractLevel != other.contractLevel)
973 {
974 reason.append("Different contract level ("
975 + this.getBuildingBlockId()+":"
976 + other.getBuildingBlockId()+"); ");
977 return false;
978 }
979
980 if (this.requiredAPs.size() == other.requiredAPs.size())
981 {
982 for (AttachmentPoint tAP : this.requiredAPs)
983 {
984 for (AttachmentPoint oAP : other.requiredAPs)
985 {
986 if (!tAP.sameAs(oAP))
987 {
988 reason.append("No required AP corresponding to "+tAP);
989 return false;
990 }
991 }
992 }
993 } else {
994 reason.append("Different size of required APs("
995 + this.requiredAPs.size()+":"
996 + other.requiredAPs.size()+"); ");
997 return false;
998 }
999
1000 if (!this.getInnerGraph().sameAs(other.getInnerGraph(),reason))
1001 {
1002 return false;
1003 }
1004
1005 return sameVertexFeatures(other, reason);
1006 }
1007
1008//------------------------------------------------------------------------------
1009
1010 private List<AttachmentPoint> getRequiredAPs() {
1011 return requiredAPs;
1012 }
1013
1014//------------------------------------------------------------------------------
1015
1022 public String toJson()
1023 {
1024 // To serialize mapping of APs (i.e., innerToOuterAPs) we must ensure
1025 // the uniqueness of AP's IDs in the inner graph
1026 if (innerGraph!=null)
1028
1029 Gson gson = DENOPTIMgson.getWriter();
1030 String jsonOutput = gson.toJson(this);
1031 return jsonOutput;
1032 }
1033
1034//------------------------------------------------------------------------------
1035
1042 public static Template fromJson(String json)
1043 {
1044 Gson gson = DENOPTIMgson.getReader();
1045
1046 // This deserializes many "easy" fields, but not the embedded graph
1047 // which is not "easy" as it need its own deserializer to
1048 // recreate all the references to APs/edges/vertices.
1049 Template t = gson.fromJson(json, Template.class);
1050
1051 // Now, recover the missing bits (if present) from the original string
1052 JsonObject jsonObject = (JsonObject) Streams.parse(new JsonReader(
1053 new StringReader(json)));
1054
1055 if (jsonObject.has("innerGraph"))
1056 {
1057 JsonObject innerGraphJson = jsonObject.getAsJsonObject(
1058 "innerGraph");
1059 DGraph innerGraph = DGraph.fromJson(innerGraphJson.toString());
1061
1062 if (jsonObject.has("innerToOuterAPs"))
1063 {
1064 Type type = new TypeToken<TreeMap<Integer,
1065 AttachmentPoint>>(){}.getType();
1066 TreeMap<Integer,AttachmentPoint> map = gson.fromJson(
1067 jsonObject.getAsJsonObject("innerToOuterAPs"), type);
1068 t.updateInnerToOuter(map);
1069 }
1070 }
1071
1073 {
1074 ap.setOwner(t);
1075 }
1076
1077 // WARNING: other fields, such as 'owner' and AP 'user' are
1078 // recovered upon deserializing the graph containing this
1079 // vertex, if any
1080
1081 return t;
1082 }
1083
1084//------------------------------------------------------------------------------
1085
1086}
1087
General set of constants used in DENOPTIM.
static final String GRAPHTAG
SDF tag containing graph encoding.
static final String VERTEXJSONTAG
SDF tag containing vertex encoding in JSON format.
static final String ATMPROPAPS
String tag of Atom property used to store attachment points.
static final String PROVENANCE
SDF tag containing provenance data for a graph.
static final String APSTAG
SDF tag defining attachment points.
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 GCODETAG
SDF tag containing graph ID.
static final String GRAPHJSONTAG
SDF tag containing graph encoding in JSON format.
static final Object LINKAPS
Key of property used to records references of APs.
static final String ATMPROPORIGINALATMID
Name of Atom property used to store the original position of an atom in the atom list of the fragment...
Attachment point mapping where keys are sorted by natural ordering, i.e., by AttachmentPoint#compareT...
Definition: APTreeMap.java:43
AttachmentPoint put(AttachmentPoint key, AttachmentPoint value)
Definition: APTreeMap.java:79
AttachmentPoint remove(Object key)
Definition: APTreeMap.java:87
AttachmentPoint get(Object key)
Definition: APTreeMap.java:95
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
AttachmentPoint getLinkedAP()
Gets the attachment point (AP) that is connected to this AP via the edge user.
void setAPClass(String apClass)
Set the Attachment Point class.
APClass getAPClass()
Returns the Attachment Point class.
void setAtomPositionNumber(int atomPositionNumber)
Set the index of the source atom in the list of atoms of the fragment.
void setDirectionVector(Point3d dirVec)
Sets the end of the 3D vector defining the direction of the AP in 3D.
void setOwner(Vertex owner)
Sets the reference to the vertex that owns this attachment point.
boolean isAvailable()
Check availability of this attachment point.
int getAtomPositionNumberInMol()
The index of the source atom in the atom list of the entire molecule.
int getAtomPositionNumber()
The index of the source atom in the atom list of the fragment.
AttachmentPoint clone()
Returns a deep clone of this attachment point.
Point3d getDirectionVector()
Returns the end of the direction vector.
static String getAPDefinitionsForSDF(LinkedHashMap< Integer, List< AttachmentPoint > > apsPerIndex)
Prepares the two strings that can be used to define AttachmentPoints in SDF files.
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:102
void setTemplateJacket(Template template)
Sets the reference to a template that embeds this graph, i.e., this graph's "jacket" template.
Definition: DGraph.java:7188
ArrayList< AttachmentPoint > getAvailableAPs()
Returns the list of available attachment points contained in this graph.
Definition: DGraph.java:4217
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1325
AttachmentPoint getAPWithId(int id)
Returns the attachment point with the given identifier, or null if no AP is found with the given iden...
Definition: DGraph.java:4264
List< Vertex > gVertices
The vertices belonging to this graph.
Definition: DGraph.java:106
boolean containsAtoms()
Returns true if this graph has any vertex that contains atoms.
Definition: DGraph.java:4164
List< Vertex > getSymVerticesForVertex(Vertex v)
Definition: DGraph.java:343
static DGraph fromJson(String json)
Reads a JSON string and returns an instance of this class.
Definition: DGraph.java:6951
Template templateJacket
Reference to the Template embedding this graph.
Definition: DGraph.java:150
boolean removeBranchStartingAt(Vertex v, boolean symmetry)
Deletes the branch, i.e., the specified vertex and its children.
Definition: DGraph.java:5017
int getHeavyAtomsCount()
Calculate the number of atoms from the graph representation.
Definition: DGraph.java:4182
void addEdge(Edge edge)
Adds the edge to the list of edges belonging to this graph.
Definition: DGraph.java:1249
This class represents the edge between two vertices.
Definition: Edge.java:38
An empty vertex has the behaviors of a vertex, but has no molecular structure.
void addAP()
Adds an attachment point with no APClass or other attribute.
A collection of AttachmentPoints that are related by a relation that we call "symmetry",...
boolean add(T item)
Adds an item to this list, if not already present.
ContractLevel getContractLevel()
Returns the contract level of this template, i.e., to what extent the content of this template can be...
Definition: Template.java:203
void removeProjectionOfInnerAP(AttachmentPoint oldInnerAP)
Removes the mapping of the given inner AP from this template's surface, if such mapping exists.
Definition: Template.java:399
List< Vertex > getMutationSites(List< MutationType > ignoredTypes)
A list of mutation sites from within this vertex.
Definition: Template.java:886
static Template fromJson(String json)
Reads a JSON string and returns an instance of this class.
Definition: Template.java:1042
boolean isValidInnerGraph(DGraph g)
Definition: Template.java:422
void updateMutTypeToFixedSTructure()
Definition: Template.java:922
void setInnerGraph(DGraph innerGraph)
Definition: Template.java:298
String[] getPathIDs(AttachmentPoint apA, AttachmentPoint apB)
Produces a pair of strings that identify the "path" between two given attachment points.
Definition: Template.java:154
void updateInnerApID(AttachmentPoint oldInnerAP, AttachmentPoint newInnerAP)
Replaces a given link between APs on the surface of this template (i.e., outerAP) and the correspondi...
Definition: Template.java:377
boolean sameAs(Template other, StringBuilder reason)
Compares this and another template ignoring vertex IDs.
Definition: Template.java:970
void addInnerToOuterAPMapping(AttachmentPoint newInnerAP)
Adds the projection of an AP in the template's inner graph (i.e., innerAP) to the list of APs visible...
Definition: Template.java:348
boolean freezeTemplate()
Promotes the contract level of this template to the most constrained one (i.e., ContractLevel#FIXED),...
Definition: Template.java:231
IAtomContainer getIAtomContainer(Logger logger, Randomizer rng, boolean removeUsedRCAs, boolean rebuild)
The molecular representation, if any, is generated by this method and stored until further changes in...
Definition: Template.java:741
IAtomContainer mol
Molecular representation of the content of this template.
Definition: Template.java:94
ArrayList< AttachmentPoint > getAttachmentPoints()
Return the list of attachment points visible from outside the template, i.e., the so-called outer APs...
Definition: Template.java:458
void clearIAtomContainer()
Removes the molecular representation.
Definition: Template.java:600
void updateInnerToOuter(TreeMap< Integer, AttachmentPoint > map)
Definition: Template.java:325
void setSymmetricAPSets(List< SymmetricAPs > sAPs)
This method exists by contract, but does not do anything because the concept of setting the symmetric...
Definition: Template.java:474
void addRequiredAP(Point3d pt, APClass apClass)
Adds attachment point (AP) to the list of required APs on this template.
Definition: Template.java:949
List< SymmetricAPs > getSymmetricAPSets()
The SymmetricSet produced from this method contain indexes of the AttachmentPoints in the list return...
Definition: Template.java:495
static Template getTestTemplate(ContractLevel contractLevel)
Method meant for devel phase only.
Definition: Template.java:172
List< MutationType > getMutationTypes(List< MutationType > ignoredTypes)
Returns the list of mutation types.
Definition: Template.java:851
Template(Vertex.BBType bbType)
Definition: Template.java:134
ContractLevel contractLevel
Denotes the constants in the template.
Definition: Template.java:99
void setContractLevel(ContractLevel contract)
Imposes the given contract to this template.
Definition: Template.java:214
IAtomContainer getIAtomContainer()
The molecular representation, if any, is generated by this method and stored until further changes in...
Definition: Template.java:715
Template clone()
Returns a deep copy of this template.
Definition: Template.java:243
AttachmentPoint getOuterAPFromInnerAP(AttachmentPoint innerAP)
Definition: Template.java:842
void addSymmetricAPSet(SymmetricAPs symAPs)
Definition: Template.java:482
List< AttachmentPoint > requiredAPs
Definition: Template.java:127
void setIAtomContainer(IAtomContainer mol, boolean updateAPsAccordingToIAC)
Attaches a molecular representation to this template.
Definition: Template.java:621
AttachmentPoint getInnerAPFromOuterAP(AttachmentPoint outerAP)
Definition: Template.java:822
DGraph innerGraph
Graph that is embedded in this vertex.
Definition: Template.java:84
List< AttachmentPoint > getRequiredAPs()
Definition: Template.java:1010
String toJson()
Produces a string that represents this vertex and that adheres to the JSON format.
Definition: Template.java:1022
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:62
Set< String > uniquefyingPropertyKeys
List of properties required to make Vertex#sameAs(Vertex, StringBuilder) method return false when pro...
Definition: Vertex.java:155
void setMutationTypes(List< MutationType > lst)
Definition: Vertex.java:882
List< MutationType > getMutationTypes()
Returns the list of mutation types.
Definition: Vertex.java:919
void setProperties(Map< Object, Object > properties)
Definition: Vertex.java:1283
int getBuildingBlockId()
Returns the index of the building block that should correspond to the position of the building block ...
Definition: Vertex.java:305
void setVertexId(long vertexId2)
Definition: Vertex.java:282
int getIndexOfAP(AttachmentPoint ap)
Returns the position of the given AP in the list of APs of this vertex.
Definition: Vertex.java:1037
Vertex.BBType getBuildingBlockType()
Definition: Vertex.java:319
List< MutationType > getUnfilteredMutationTypes()
Returns the mutation types that are constitutionally configures for this vertex irrespectively on the...
Definition: Vertex.java:896
List< Vertex > getMutationSites()
A list of mutation sites from within this vertex.
Definition: Vertex.java:863
DGraph getGraphOwner()
Returns the graph this vertex belongs to or null.
Definition: Vertex.java:852
Map< Object, Object > copyStringBasedProperties()
Copies all the string-based properties and properties defined in the Vertex#uniquefyingPropertyKeys s...
Definition: Vertex.java:1262
boolean sameVertexFeatures(Vertex other, StringBuilder reason)
Compares this and another vertex ignoring vertex IDs.
Definition: Vertex.java:717
ArrayList< Vertex > getChilddren()
Looks into the edges that use any of the APs that belong to this vertex and returns the list of verti...
Definition: Vertex.java:1173
void setBuildingBlockId(int buildingBlockId)
Definition: Vertex.java:312
SymmetricAPs getSymmetricAPs(AttachmentPoint ap)
For the given attachment point index locate the symmetric partners i.e.
Definition: Vertex.java:354
boolean removeMutationType(MutationType mt)
Removes the specified mutation type.
Definition: Vertex.java:908
void setBuildingBlockType(Vertex.BBType buildingBlockType)
Definition: Vertex.java:326
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:1008
Class for de/serializing DENOPTIM graphs from/to JSON format.
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.
Utilities for molecule conversion.
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...
Tool to generate random numbers and random decisions.
Definition: Randomizer.java:35
Possible chemical bond types an edge can represent.
Definition: Edge.java:303
Enum specifying to what extent the template's inner graph can be changed.
Definition: Template.java:104
FREE
Inner graphs are free to change within the confines of the required AttachmentPoints.
Definition: Template.java:109
FIXED
Inner graphs are effectively equivalent to the Fragment class, as no change in the inner structure is...
Definition: Template.java:116
FIXED_STRUCT
Inner graph keep the same structure, but the identify of vertices can change.
Definition: Template.java:124
The type of building block.
Definition: Vertex.java:87
Flag declaring the type of Vertex implementation.
Definition: Vertex.java:173
Types of mutation defined in relation to what happens to the target vertex (i.e., the actual mutation...
DELETE
Removes the target vertex and all child vertices.
DELETELINK
Removes a vertex from a tree and merges remaining branches into the remaining trunk.
CHANGELINK
Replace the target vertex keeping all the child structure.
EXTEND
append vertices on the target vertex according to substitution probability.
CHANGEBRANCH
Replace the target vertex and any of the child vertices.
ADDLINK
Adds a vertex between two previously connected vertexes.
DELETECHAIN
Removes a vertex and all its neighbors recursively until a branching point, i.e., until a vertex that...