$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 // Prepare SDF-like string for atom container. 0-based to 1-based
783 // index conversion done in here
784 iac.setProperty(DENOPTIMConstants.APSTAG,
786
787 iac.setProperty(DENOPTIMConstants.VERTEXJSONTAG,this.toJson());
788
789 iac.removeProperty(DENOPTIMConstants.GRAPHJSONTAG);
790 iac.removeProperty(DENOPTIMConstants.GRAPHTAG);
791 iac.removeProperty(DENOPTIMConstants.PROVENANCE);
792 iac.removeProperty(DENOPTIMConstants.GCODETAG);
793
794 // We store the result in a field of this instance
795 mol = iac;
796 return mol;
797 } catch (DENOPTIMException e)
798 {
799 //TODO: deal with the situation: report error or state given
800 // assumption that allows to go on
801 e.printStackTrace();
802 }
803 return null;
804 }
805
806//-----------------------------------------------------------------------------
807
809 AttachmentPoint outerAP) {
810
811 // TODO: Check if another solution exists that can remove nested
812 // for-loop. Suggestion: make an outerToInnerAPMap.
813
814 // Very inefficient solution
815 for (Map.Entry<AttachmentPoint, AttachmentPoint> entry
816 : innerToOuterAPs.entrySet())
817 {
818 if (outerAP == entry.getValue())
819 {
820 return entry.getKey();
821 }
822 }
823 return null;
824 }
825
826//-----------------------------------------------------------------------------
827
829 AttachmentPoint innerAP)
830 {
831 return innerToOuterAPs.get(innerAP);
832 }
833
834//------------------------------------------------------------------------------
835
836 @Override
837 public List<MutationType> getMutationTypes(List<MutationType> ignoredTypes)
838 {
840 {
841 List<MutationType> scaffCompatTypes = new ArrayList<MutationType>();
842 if (getNumberOfAPs() != 0)
843 {
844 scaffCompatTypes.add(MutationType.EXTEND);
845 scaffCompatTypes.add(MutationType.CHANGELINK);
846 if (!getChilddren().isEmpty())
847 {
848 scaffCompatTypes.add(MutationType.ADDLINK);
849 }
850 }
851
852 scaffCompatTypes.removeAll(ignoredTypes);
853 return scaffCompatTypes;
854 }
855 return super.getMutationTypes(ignoredTypes);
856 }
857
858//------------------------------------------------------------------------------
859
871 @Override
872 public List<Vertex> getMutationSites(List<MutationType> ignoredTypes)
873 {
874 List<Vertex> lst = new ArrayList<Vertex>();
875 // capping groups are not considered mutable sites
877 {
878 return lst;
879 }
880
881 switch (contractLevel)
882 {
883 case FIXED:
884 if (getMutationTypes(ignoredTypes).size()>0)
885 lst.add(this);
886 break;
887
888 case FIXED_STRUCT:
890 for (Vertex v : innerGraph.gVertices)
891 {
892 lst.addAll(v.getMutationSites(ignoredTypes));
893 }
894 break;
895
896 case FREE:
897 for (Vertex v : innerGraph.gVertices)
898 {
899 lst.addAll(v.getMutationSites(ignoredTypes));
900 }
901 break;
902 }
903 return lst;
904 }
905
906//------------------------------------------------------------------------------
907
909 {
910 List<MutationType> toBeRemoved = new ArrayList<MutationType>();
911 toBeRemoved.add(MutationType.DELETE);
912 toBeRemoved.add(MutationType.DELETECHAIN);
913 toBeRemoved.add(MutationType.CHANGEBRANCH);
914 toBeRemoved.add(MutationType.ADDLINK);
915 toBeRemoved.add(MutationType.DELETELINK);
916 toBeRemoved.add(MutationType.EXTEND);
917 for (Vertex v : innerGraph.gVertices)
918 {
919 for (MutationType mt : toBeRemoved)
920 v.removeMutationType(mt);
921
922 if (v instanceof Template)
923 ((Template) v).setContractLevel(
925 }
926 }
927
928//------------------------------------------------------------------------------
929
935 public void addRequiredAP(Point3d pt, APClass apClass) {
937 if (getInnerGraph() != null) {
938 throw new IllegalArgumentException("cannot add more required APs " +
939 "after setting the inner graph");
940 }
941 AttachmentPoint ap = new AttachmentPoint(this, -1, pt,
942 apClass);
943 requiredAPs.add(ap);
944 }
945
946//------------------------------------------------------------------------------
947
956 public boolean sameAs(Template other, StringBuilder reason)
957 {
958 if (this.contractLevel != other.contractLevel)
959 {
960 reason.append("Different contract level ("
961 + this.getBuildingBlockId()+":"
962 + other.getBuildingBlockId()+"); ");
963 return false;
964 }
965
966 if (this.requiredAPs.size() == other.requiredAPs.size())
967 {
968 for (AttachmentPoint tAP : this.requiredAPs)
969 {
970 for (AttachmentPoint oAP : other.requiredAPs)
971 {
972 if (!tAP.sameAs(oAP))
973 {
974 reason.append("No required AP corresponding to "+tAP);
975 return false;
976 }
977 }
978 }
979 } else {
980 reason.append("Different size of required APs("
981 + this.requiredAPs.size()+":"
982 + other.requiredAPs.size()+"); ");
983 return false;
984 }
985
986 if (!this.getInnerGraph().sameAs(other.getInnerGraph(),reason))
987 {
988 return false;
989 }
990
991 return sameVertexFeatures(other, reason);
992 }
993
994//------------------------------------------------------------------------------
995
996 private List<AttachmentPoint> getRequiredAPs() {
997 return requiredAPs;
998 }
999
1000//------------------------------------------------------------------------------
1001
1008 public String toJson()
1009 {
1010 // To serialize mapping of APs (i.e., innerToOuterAPs) we must ensure
1011 // the uniqueness of AP's IDs in the inner graph
1012 if (innerGraph!=null)
1014
1015 Gson gson = DENOPTIMgson.getWriter();
1016 String jsonOutput = gson.toJson(this);
1017 return jsonOutput;
1018 }
1019
1020//------------------------------------------------------------------------------
1021
1028 public static Template fromJson(String json)
1029 {
1030 Gson gson = DENOPTIMgson.getReader();
1031
1032 // This deserializes many "easy" fields, but not the embedded graph
1033 // which is not "easy" as it need its own deserializer to
1034 // recreate all the references to APs/edges/vertices.
1035 Template t = gson.fromJson(json, Template.class);
1036
1037 // Now, recover the missing bits (if present) from the original string
1038 JsonObject jsonObject = (JsonObject) Streams.parse(new JsonReader(
1039 new StringReader(json)));
1040
1041 if (jsonObject.has("innerGraph"))
1042 {
1043 JsonObject innerGraphJson = jsonObject.getAsJsonObject(
1044 "innerGraph");
1045 DGraph innerGraph = DGraph.fromJson(innerGraphJson.toString());
1047
1048 if (jsonObject.has("innerToOuterAPs"))
1049 {
1050 Type type = new TypeToken<TreeMap<Integer,
1051 AttachmentPoint>>(){}.getType();
1052 TreeMap<Integer,AttachmentPoint> map = gson.fromJson(
1053 jsonObject.getAsJsonObject("innerToOuterAPs"), type);
1054 t.updateInnerToOuter(map);
1055 }
1056 }
1057
1059 {
1060 ap.setOwner(t);
1061 }
1062
1063 // WARNING: other fields, such as 'owner' and AP 'user' are
1064 // recovered upon deserializing the graph containing this
1065 // vertex, if any
1066
1067 return t;
1068 }
1069
1070//------------------------------------------------------------------------------
1071
1072}
1073
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:6922
ArrayList< AttachmentPoint > getAvailableAPs()
Returns the list of available attachment points contained in this graph.
Definition: DGraph.java:3988
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1097
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:4035
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:3935
List< Vertex > getSymVerticesForVertex(Vertex v)
Definition: DGraph.java:335
static DGraph fromJson(String json)
Reads a JSON string and returns an instance of this class.
Definition: DGraph.java:6685
Template templateJacket
Reference to the Template embedding this graph.
Definition: DGraph.java:149
boolean removeBranchStartingAt(Vertex v, boolean symmetry)
Deletes the branch, i.e., the specified vertex and its children.
Definition: DGraph.java:4788
int getHeavyAtomsCount()
Calculate the number of atoms from the graph representation.
Definition: DGraph.java:3953
void addEdge(Edge edge)
Adds the edge to the list of edges belonging to this graph.
Definition: DGraph.java:1021
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:872
static Template fromJson(String json)
Reads a JSON string and returns an instance of this class.
Definition: Template.java:1028
boolean isValidInnerGraph(DGraph g)
Definition: Template.java:422
void updateMutTypeToFixedSTructure()
Definition: Template.java:908
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:956
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:935
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:837
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:828
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:808
DGraph innerGraph
Graph that is embedded in this vertex.
Definition: Template.java:84
List< AttachmentPoint > getRequiredAPs()
Definition: Template.java:996
String toJson()
Produces a string that represents this vertex and that adheres to the JSON format.
Definition: Template.java:1008
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
Set< String > uniquefyingPropertyKeys
List of properties required to make Vertex#sameAs(Vertex, StringBuilder) method return false when pro...
Definition: Vertex.java:154
void setMutationTypes(List< MutationType > lst)
Definition: Vertex.java:809
List< MutationType > getMutationTypes()
Returns the list of mutation types.
Definition: Vertex.java:846
void setProperties(Map< Object, Object > properties)
Definition: Vertex.java:1195
int getBuildingBlockId()
Returns the index of the building block that should correspond to the position of the building block ...
Definition: Vertex.java:284
void setVertexId(long vertexId2)
Definition: Vertex.java:261
int getIndexOfAP(AttachmentPoint ap)
Returns the position of the given AP in the list of APs of this vertex.
Definition: Vertex.java:949
Vertex.BBType getBuildingBlockType()
Definition: Vertex.java:298
List< MutationType > getUnfilteredMutationTypes()
Returns the mutation types that are constitutionally configures for this vertex irrespectively on the...
Definition: Vertex.java:823
List< Vertex > getMutationSites()
A list of mutation sites from within this vertex.
Definition: Vertex.java:790
DGraph getGraphOwner()
Returns the graph this vertex belongs to or null.
Definition: Vertex.java:779
Map< Object, Object > copyStringBasedProperties()
Copies all the string-based properties and properties defined in the Vertex#uniquefyingPropertyKeys s...
Definition: Vertex.java:1174
boolean sameVertexFeatures(Vertex other, StringBuilder reason)
Compares this and another vertex ignoring vertex IDs.
Definition: Vertex.java:644
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:1085
void setBuildingBlockId(int buildingBlockId)
Definition: Vertex.java:291
SymmetricAPs getSymmetricAPs(AttachmentPoint ap)
For the given attachment point index locate the symmetric partners i.e.
Definition: Vertex.java:333
boolean removeMutationType(MutationType mt)
Removes the specified mutation type.
Definition: Vertex.java:835
void setBuildingBlockType(Vertex.BBType buildingBlockType)
Definition: Vertex.java:305
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:920
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:86
Flag declaring the type of Vertex implementation.
Definition: Vertex.java:172
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...