$darkmode
DENOPTIM
Fragment.java
Go to the documentation of this file.
1package denoptim.graph;
2
3/*
4 * DENOPTIM
5 * Copyright (C) 2019 Marco Foscato <marco.foscato@uib.no>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published
9 * by the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.Collection;
24import java.util.HashMap;
25import java.util.HashSet;
26import java.util.LinkedHashMap;
27import java.util.List;
28import java.util.Map;
29import java.util.Set;
30import java.util.logging.Logger;
31
32import javax.vecmath.Point3d;
33
34import org.jgrapht.graph.DefaultUndirectedGraph;
35import org.openscience.cdk.interfaces.IAtom;
36import org.openscience.cdk.interfaces.IAtomContainer;
37import org.openscience.cdk.interfaces.IBond;
38import org.openscience.cdk.interfaces.IChemObjectBuilder;
39import org.openscience.cdk.silent.SilentChemObjectBuilder;
40
41import com.google.gson.Gson;
42
43import denoptim.constants.DENOPTIMConstants;
44import denoptim.exception.DENOPTIMException;
45import denoptim.graph.Edge.BondType;
46import denoptim.graph.rings.RingClosingAttractor;
47import denoptim.json.DENOPTIMgson;
48import denoptim.utils.MathUtils;
49import denoptim.utils.MoleculeUtils;
50import denoptim.utils.MutationType;
51import denoptim.utils.Randomizer;
52
60public class Fragment extends Vertex
61{
65 private List<AttachmentPoint> lstAPs;
66
71 private List<SymmetricAPs> lstSymAPs;
72
76 private IAtomContainer mol;
77
81 private DefaultUndirectedGraph<FragIsomorphNode,FragIsomorphEdge>
83
84
85//-----------------------------------------------------------------------------
86
91 public Fragment()
92 {
94 this.lstAPs = new ArrayList<AttachmentPoint>();
95 this.lstSymAPs = new ArrayList<SymmetricAPs>();
96 IChemObjectBuilder builder = SilentChemObjectBuilder.getInstance();
97 this.mol = builder.newAtomContainer();
98 }
99
100//------------------------------------------------------------------------------
101
107 public Fragment(long vertexId)
108 {
110 this.lstAPs = new ArrayList<AttachmentPoint>();
111 this.lstSymAPs = new ArrayList<SymmetricAPs>();
112 IChemObjectBuilder builder = SilentChemObjectBuilder.getInstance();
113 this.mol = builder.newAtomContainer();
114 }
115
116//-----------------------------------------------------------------------------
117
130 public Fragment(long l, IAtomContainer mol, BBType bbt)
131 throws DENOPTIMException
132 {
133 super (VertexType.MolecularFragment, l);
134
135 this.setBuildingBlockType(bbt);
136
137 this.lstAPs = new ArrayList<AttachmentPoint>();
138 this.lstSymAPs = new ArrayList<SymmetricAPs>();
139
140 this.mol = MoleculeUtils.makeSameAs(mol);
142
143 Object prop = mol.getProperty(DENOPTIMConstants.APSTAG);
144 if (prop != null)
145 {
146 projectPropertyToAP(prop.toString());
147 }
148
149 List<SymmetricAPs> simAP = identifySymmetryRelatedAPSets(this.mol,
151 setSymmetricAPSets(simAP);
152
153 this.setAsRCV(getNumberOfAPs() == 1
155 getAttachmentPoints().get(0).getAPClass()));
156
157 Object isomorph = mol.getProperty(DENOPTIMConstants.ISOMORPHICFAMILYID);
158 if (isomorph != null)
159 {
161 isomorph.toString());
162 }
163 }
164
165//------------------------------------------------------------------------------
166
167 public Fragment(long vertexId, IAtomContainer mol, BBType bbt, boolean isRCV)
168 throws DENOPTIMException {
169 this(vertexId, mol, bbt);
170 this.setAsRCV(isRCV);
171 }
172
173//-----------------------------------------------------------------------------
174
183 public Fragment(IAtomContainer mol, BBType bbt)
184 throws DENOPTIMException
185 {
186 this(-1,mol,bbt);
187 }
188
189//------------------------------------------------------------------------------
190
195 public boolean is3D()
196 {
197 double maxDist = 0.0;
198 Point3d origin = new Point3d(0,0,0);
199 for (IAtom atm : atoms())
200 {
201 Point3d p = atm.getPoint3d();
202 if (p==null)
203 return false;
204 double dist = MathUtils.distance(origin, p);
205 if (dist > maxDist)
206 {
207 maxDist = dist;
208 }
209 }
211 {
212 Point3d p = ap.getDirectionVector();
213 if (p==null)
214 return false;
215 double dist = MathUtils.distance(origin, p);
216 if (dist > maxDist)
217 {
218 maxDist = dist;
219 }
220 }
221
222 return maxDist > 0.001;
223 }
224
225//------------------------------------------------------------------------------
226
232 {
235 }
236
237//------------------------------------------------------------------------------
238
239 private static List<SymmetricAPs> identifySymmetryRelatedAPSets(
240 IAtomContainer mol, List<AttachmentPoint> daps)
241 {
242 List<SymmetricAPs> lstCompatible = new ArrayList<>();
243 for (int i=0; i<daps.size()-1; i++)
244 {
245 AttachmentPoint apI = daps.get(i);
246 SymmetricAPs ss = new SymmetricAPs();
247 ss.add(apI);
248
249 boolean alreadyFound = false;
250 for (SymmetricAPs previousSS : lstCompatible)
251 {
252 if (previousSS.contains(apI))
253 {
254 alreadyFound = true;
255 break;
256 }
257 }
258 if (alreadyFound)
259 {
260 continue;
261 }
262
263 for (int j=i+1; j<daps.size(); j++)
264 {
265 AttachmentPoint apJ = daps.get(j);
268 {
269 // check if reactions are compatible w.r.t. symmetry
270 if (apI.getAPClass()!=null && apJ.getAPClass()!=null
271 && apI.getAPClass().compareTo(apJ.getAPClass()) == 0)
272 {
273 ss.add(apJ);
274 }
275 }
276 }
277
278 if (ss.size() > 1)
279 {
280 lstCompatible.add(ss);
281 }
282 }
283
284 return lstCompatible;
285 }
286
287//------------------------------------------------------------------------------
288
298 private static boolean atomsAreCompatible(IAtomContainer mol, int a1, int a2)
299 {
300 // check atom types
301 IAtom atm1 = mol.getAtom(a1);
302 IAtom atm2 = mol.getAtom(a2);
303
304 if (atm1.getSymbol().compareTo(atm2.getSymbol()) != 0)
305 return false;
306
307 // check connected bonds
308 if (mol.getConnectedBondsCount(atm1)!=mol.getConnectedBondsCount(atm2))
309 return false;
310
311 // check connected atoms
312 if (mol.getConnectedBondsCount(atm1)!=mol.getConnectedBondsCount(atm2))
313 return false;
314
315 List<IAtom> la1 = mol.getConnectedAtomsList(atm2);
316 List<IAtom> la2 = mol.getConnectedAtomsList(atm2);
317
318 int k = 0;
319 for (int i=0; i<la1.size(); i++)
320 {
321 IAtom b1 = la1.get(i);
322 for (int j=0; j<la2.size(); j++)
323 {
324 IAtom b2 = la2.get(j);
325 if (b1.getSymbol().compareTo(b2.getSymbol()) == 0)
326 {
327 k++;
328 break;
329 }
330 }
331 }
332
333 return k == la1.size();
334 }
335
336//------------------------------------------------------------------------------
337
343 public void addAP(int atomPositionNumber) {
344 APClass apc = null;
345 addAP(atomPositionNumber, null, apc);
346 }
347
348//------------------------------------------------------------------------------
349
355 public void addAP(int atomPositionNumber, APClass apClass) {
356 addAP(atomPositionNumber, null, apClass);
357 }
358
359//------------------------------------------------------------------------------
360
369 public AttachmentPoint addAP(int atomPositionNumber, Point3d dirVec,
370 APClass apClass)
371 {
372 AttachmentPoint ap = new AttachmentPoint(this,
373 atomPositionNumber, dirVec, apClass);
374 getAttachmentPoints().add(ap);
375
376 IAtom srcAtm = mol.getAtom(atomPositionNumber);
377
378 ArrayList<AttachmentPoint> apList = new ArrayList<>();
379 if (getAPCountOnAtom(srcAtm) > 0) {
380 apList = getAPsFromAtom(srcAtm);
381 }
382 apList.add(ap);
383 srcAtm.setProperty(DENOPTIMConstants.ATMPROPAPS, apList);
384
386
387 return ap;
388 }
389
390//-----------------------------------------------------------------------------
391
404 public void addAP(int srcAtmId, APClass apc, Point3d vector)
405 {
406 IAtom srcAtm = mol.getAtom(srcAtmId);
407 addAPOnAtom(srcAtm, apc, vector);
408 }
409
410//-----------------------------------------------------------------------------
411
424 public AttachmentPoint addAPOnAtom(IAtom srcAtm, APClass apc,
425 Point3d vector)
426 {
427 int atmId = mol.indexOf(srcAtm);
428 return this.addAP(atmId, new Point3d(vector.x, vector.y, vector.z), apc);
429 }
430
431//-----------------------------------------------------------------------------
432
433 public void removeAP(AttachmentPoint ap)
434 {
435 if (!getAttachmentPoints().contains(ap))
436 return;
437
438 IAtom srcAtm = mol.getAtom(ap.getAtomPositionNumber());
439
440 ArrayList<AttachmentPoint> apList = new ArrayList<>();
441 if (getAPCountOnAtom(srcAtm) > 0) {
442 apList = getAPsFromAtom(srcAtm);
443 }
444 apList.remove(ap);
445
446 getAttachmentPoints().remove(ap);
447 srcAtm.setProperty(DENOPTIMConstants.ATMPROPAPS, apList);
448
450 }
451
452//-----------------------------------------------------------------------------
453
454 @SuppressWarnings("unchecked")
455 public ArrayList<AttachmentPoint> getAPsFromAtom(IAtom srcAtm)
456 {
457 ArrayList<AttachmentPoint> apsOnAtm = new ArrayList<AttachmentPoint>();
458 Object prop = srcAtm.getProperty(DENOPTIMConstants.ATMPROPAPS);
459 if (prop!=null)
460 {
461 apsOnAtm = (ArrayList<AttachmentPoint>) prop;
462 }
463 return apsOnAtm;
464 }
465
466//-----------------------------------------------------------------------------
467
475 public int getAPCountOnAtom(int srcAtmId)
476 {
477 IAtom srcAtm = mol.getAtom(srcAtmId);
478 return getAPCountOnAtom(srcAtm);
479 }
480
481//-----------------------------------------------------------------------------
482
490 public int getAPCountOnAtom(IAtom srcAtm)
491 {
492 int num = 0;
493 if (srcAtm.getProperty(DENOPTIMConstants.ATMPROPAPS) != null)
494 {
495 ArrayList<AttachmentPoint> apsOnAtm =
496 getAPsFromAtom(srcAtm);
497 num = apsOnAtm.size();
498 }
499 return num;
500 }
501
502//-----------------------------------------------------------------------------
503
511 public void updateAPs()
512 {
513 for (int atmId = 0; atmId<mol.getAtomCount(); atmId++)
514 {
515 IAtom srcAtm = mol.getAtom(atmId);
516 if (srcAtm.getProperty(DENOPTIMConstants.ATMPROPAPS) != null)
517 {
518 List<AttachmentPoint> apsOnAtm = getAPsFromAtom(srcAtm);
519 for (int i = 0; i < apsOnAtm.size(); i++)
520 {
521 AttachmentPoint ap = apsOnAtm.get(i);
522 ap.setAtomPositionNumber(atmId);
523 }
524 }
525 }
527 }
528
529//-----------------------------------------------------------------------------
530
541 public List<AttachmentPoint> getCurrentAPs()
542 {
543 updateAPs();
544
545 lstAPs.clear();
546
547 for (IAtom srcAtm : mol.atoms())
548 {
549 if (srcAtm.getProperty(DENOPTIMConstants.ATMPROPAPS) != null)
550 {
551 ArrayList<AttachmentPoint> apsOnAtm =
552 getAPsFromAtom(srcAtm);
553 lstAPs.addAll(apsOnAtm);
554 }
555 }
556
557 //Reorder according to DENOPTIMAttachmentPoint priority
559
560 return lstAPs;
561 }
562
563//-----------------------------------------------------------------------------
564
573 {
574 String allAtomsProp = "";
576 {
577 return;
578 }
579 allAtomsProp = getProperty(DENOPTIMConstants.APSTAG).toString();
580 projectPropertyToAP(allAtomsProp);
581 }
582
583//-----------------------------------------------------------------------------
584
594 public void projectPropertyToAP(String allAtomsProp) throws DENOPTIMException
595 {
596 lstAPs.clear();
597 if (allAtomsProp.trim().equals(""))
598 {
599 return;
600 }
601
602 // Cleanup current APs in atom objects
603 for (int ii=0 ; ii<mol.getAtomCount(); ii++)
604 {
605 IAtom atm = mol.getAtom(ii);
606 atm.removeProperty(DENOPTIMConstants.ATMPROPAPS);
607 }
608
609 // Collect all the APs as objects
610 String[] atomsProp = allAtomsProp.split(
612 for (int i = 0; i< atomsProp.length; i++)
613 {
614 String onThisAtm = atomsProp[i];
615 if (onThisAtm.contains(DENOPTIMConstants.SEPARATORAPPROPAPS))
616 {
617 String[] moreAPonThisAtm = onThisAtm.split(
619
620 AttachmentPoint ap =
621 new AttachmentPoint(this, moreAPonThisAtm[0]);
622
623 int atmID = ap.getAtomPositionNumber();
624 //WARNING the atmID is already 0-based
625 lstAPs.add(ap);
626 for (int j = 1; j<moreAPonThisAtm.length; j++ )
627 {
628 //WARNING here we have to switch to 1-based enumeration
629 // because we import from SDF string
630 AttachmentPoint apMany =
631 new AttachmentPoint(this, atmID+1
633 + moreAPonThisAtm[j]);
634 lstAPs.add(apMany);
635 }
636 }
637 else
638 {
639 AttachmentPoint ap =
640 new AttachmentPoint(this, onThisAtm);
641 lstAPs.add(ap);
642 }
643 }
644
646
648 }
649
650//-----------------------------------------------------------------------------
651
660 {
661 // Write attachment points in the atoms
662 for (int i = 0; i < lstAPs.size(); i++)
663 {
664 AttachmentPoint ap = lstAPs.get(i);
665 int atmID = ap.getAtomPositionNumber();
666
667 IAtom atm = mol.getAtom(atmID);
668 if (atm.getProperty(DENOPTIMConstants.ATMPROPAPS) != null)
669 {
670 ArrayList<AttachmentPoint> oldAPs =
671 getAPsFromAtom(atm);
672 oldAPs.add(ap);
673 atm.setProperty(DENOPTIMConstants.ATMPROPAPS,oldAPs);
674 }
675 else
676 {
677 ArrayList<AttachmentPoint> aps =
678 new ArrayList<AttachmentPoint>();
679 aps.add(ap);
680
681 atm.setProperty(DENOPTIMConstants.ATMPROPAPS,aps);
682 }
683 }
684 }
685
686//-----------------------------------------------------------------------------
687
694 {
695
696 // Prepare the string-representation of unused APs on this graph
697 LinkedHashMap<Integer,List<AttachmentPoint>> apsPerAtom =
698 new LinkedHashMap<>();
699 for (IAtom atm : mol.atoms())
700 {
701 if (atm.getProperty(DENOPTIMConstants.ATMPROPAPS) == null)
702 {
703 continue;
704 }
705 int atmID = mol.indexOf(atm);
706 ArrayList<AttachmentPoint> apsOnAtm =
707 getAPsFromAtom(atm);
708 for (AttachmentPoint ap : apsOnAtm)
709 {
710 if (apsPerAtom.containsKey(atmID))
711 {
712 apsPerAtom.get(atmID).add(ap);
713 } else {
714 List<AttachmentPoint> lst =
715 new ArrayList<AttachmentPoint>();
716 lst.add(ap);
717 apsPerAtom.put(atmID,lst);
718 }
719 }
720 }
721 //WARNING! In the mol.property we use 1-to-n+1 instead of 0-to-n
724 }
725
726//-----------------------------------------------------------------------------
727
732 @Override
734 {
735 Fragment clone = new Fragment();
737 try
738 {
739 clone.mol = MoleculeUtils.makeSameAs(mol);
740 } catch (DENOPTIMException e1)
741 {
742 // TODO Auto-generated catch block
743 e1.printStackTrace();
744 }
745
746 // WARNING: here we are not recovering all info from APs: we take only
747 // some info. This can be improved...
748 for (AttachmentPoint ap : lstAPs)
749 {
751 ap.getAtomPositionNumber(),
752 ap.getDirectionVector(),
753 ap.getAPClass());
754 cAp.setCutId(ap.getCutId());
755 cAp.setID(ap.getID());
756 clone.lstAPs.add(cAp);
757 }
758
760
763
765
766 List<SymmetricAPs> cLstSymAPs = new ArrayList<SymmetricAPs>();
767 for (SymmetricAPs symAPs : this.getSymmetricAPSets())
768 {
769 SymmetricAPs cSymAPs = new SymmetricAPs();
770 for (AttachmentPoint ap : symAPs)
771 {
772 cSymAPs.add(clone.getAP(ap.getIndexInOwner()));
773 }
774 cLstSymAPs.add(cSymAPs);
775 }
776 clone.setSymmetricAPSets(cLstSymAPs);
777
778 clone.setAsRCV(this.isRCV());
780 if (uniquefyingPropertyKeys!=null)
782 return clone;
783 }
784
785//-----------------------------------------------------------------------------
786
787 @Override
788 public IAtomContainer getIAtomContainer()
789 {
791 for (int atmPos=0; atmPos<mol.getAtomCount(); atmPos++)
792 {
793 IAtom atm = mol.getAtom(atmPos);
795 atm.setProperty(DENOPTIMConstants.ATMPROPORIGINALATMID, atmPos);
796 }
797 mol.setProperty(DENOPTIMConstants.APSTAG,
799 mol.setProperty(DENOPTIMConstants.VERTEXJSONTAG,this.toJson());
802 return mol;
803 }
804
805//------------------------------------------------------------------------------
806
813 @Override
814 public IAtomContainer getIAtomContainer(Logger logger,
815 Randomizer rng, boolean removeUsedRCAs, boolean rebuild)
816 {
817 return getIAtomContainer();
818 }
819
820//-----------------------------------------------------------------------------
821
822 public Iterable<IAtom> atoms()
823 {
824 return mol.atoms();
825 }
826
827//-----------------------------------------------------------------------------
828
829 public Iterable<IBond> bonds()
830 {
831 return mol.bonds();
832 }
833
834//-----------------------------------------------------------------------------
835
836 public void addAtom(IAtom atom)
837 {
838 mol.addAtom(atom);
839 }
840
841//-----------------------------------------------------------------------------
842
843 public IAtom getAtom(int number)
844 {
845 return mol.getAtom(number);
846 }
847
848//-----------------------------------------------------------------------------
849
850 public int indexOf(IAtom atom)
851 {
852 return mol.indexOf(atom);
853 }
854
855//-----------------------------------------------------------------------------
856
857 public int getAtomCount()
858 {
859 return mol.getAtomCount();
860 }
861
862//-----------------------------------------------------------------------------
863
864 public int getBondCount()
865 {
866 return mol.getBondCount();
867 }
868
869//-----------------------------------------------------------------------------
870
871 public void addBond(IBond bond)
872 {
873 mol.addBond(bond);
874 }
875
876//-----------------------------------------------------------------------------
877
878 public IBond removeBond(int position)
879 {
880 return mol.removeBond(position);
881 }
882
883//-----------------------------------------------------------------------------
884
885 public IBond removeBond(IAtom atom1, IAtom atom2)
886 {
887 return mol.removeBond(atom1, atom2);
888 }
889
890//-----------------------------------------------------------------------------
891
892 public void removeBond(IBond bond)
893 {
894 mol.removeBond(bond);
895 }
896
897//-----------------------------------------------------------------------------
898
899 public void removeAtom(IAtom atom)
900 {
901 removeAtoms(Arrays.asList(atom));
902 }
903
904//-----------------------------------------------------------------------------
905
913 public void removeAtoms(Collection<IAtom> atoms)
914 {
915 for (IAtom atom : atoms)
916 mol.removeAtom(atom);
917
918 lstAPs.clear();
919
920 for (int atmId = 0; atmId<mol.getAtomCount(); atmId++)
921 {
922 IAtom srcAtm = mol.getAtom(atmId);
923 if (srcAtm.getProperty(DENOPTIMConstants.ATMPROPAPS) != null)
924 {
925 ArrayList<AttachmentPoint> apsOnAtm = getAPsFromAtom(srcAtm);
926 for (int i = 0; i < apsOnAtm.size(); i++)
927 {
928 AttachmentPoint ap = apsOnAtm.get(i);
929 ap.setAtomPositionNumber(atmId);
930 }
931 lstAPs.addAll(apsOnAtm);
932 }
933 }
934
935 //Reorder according to DENOPTIMAttachmentPoint priority
937
939 }
940
941//-----------------------------------------------------------------------------
942
943 public List<IAtom> getConnectedAtomsList(IAtom atom)
944 {
945 return mol.getConnectedAtomsList(atom);
946 }
947
948//-----------------------------------------------------------------------------
949
950 public int getConnectedAtomsCount(IAtom atom)
951 {
952 return mol.getConnectedBondsCount(atom);
953 }
954
955//------------------------------------------------------------------------------
956
967 public boolean sameAs(Fragment other, StringBuilder reason)
968 {
969 if (this.containsAtoms() && other.containsAtoms())
970 {
971 if (this.mol.getAtomCount() != other.mol.getAtomCount())
972 {
973 reason.append("Different atom count (" + this.mol.getAtomCount()
974 + ":" + other.mol.getAtomCount() + "); ");
975 }
976 if (this.mol.getBondCount() != other.mol.getBondCount())
977 {
978 reason.append("Different bond count (" + this.mol.getBondCount()
979 + ":" + other.mol.getBondCount() + "); ");
980 }
981 }
982 return sameVertexFeatures(other, reason);
983 }
984
985//------------------------------------------------------------------------------
986
995 public DefaultUndirectedGraph<FragIsomorphNode,FragIsomorphEdge>
997 {
998 if (jGraphFragIsomorphism != null)
999 {
1000 return jGraphFragIsomorphism;
1001 }
1002 jGraphFragIsomorphism = new DefaultUndirectedGraph<>(
1003 FragIsomorphEdge.class);
1004
1005 Map<IAtom,FragIsomorphNode> atmToNode =
1006 new HashMap<IAtom,FragIsomorphNode>();
1007 Set<IAtom> ignoredDu = new HashSet<IAtom>();
1008 for (IAtom atm : mol.atoms())
1009 {
1012 && mol.getConnectedBondsCount(atm)<2)
1013 {
1014 //Ignore Du on linearities
1015 ignoredDu.add(atm);
1016 continue;
1017 }
1018 FragIsomorphNode node = new FragIsomorphNode(atm);
1019 atmToNode.put(atm,node);
1020 jGraphFragIsomorphism.addVertex(node);
1021 }
1022 for (IBond bnd : mol.bonds())
1023 {
1024 if (bnd.getAtomCount() > 2)
1025 {
1026 throw new IllegalArgumentException("Cannot handle bonds that involve "
1027 + "more than two atoms");
1028 }
1029 if (ignoredDu.contains(bnd.getAtom(0))
1030 || ignoredDu.contains(bnd.getAtom(0)))
1031 {
1032 //Ignore Du on linearities
1033 continue;
1034 }
1035
1036 FragIsomorphEdge edge = new FragIsomorphEdge(bnd);
1037 jGraphFragIsomorphism.addEdge(atmToNode.get(bnd.getAtom(0)),
1038 atmToNode.get(bnd.getAtom(1)), edge);
1039 }
1041 {
1042 FragIsomorphNode node = new FragIsomorphNode(ap);
1043 jGraphFragIsomorphism.addVertex(node);
1045 jGraphFragIsomorphism.addEdge(atmToNode.get(mol.getAtom(
1046 ap.getAtomPositionNumber())), node, edge);
1047 }
1048
1049 return jGraphFragIsomorphism;
1050 }
1051
1052//------------------------------------------------------------------------------
1053
1066 public boolean isIsomorphicTo(Vertex other)
1067 {
1068 if (!(other instanceof Fragment))
1069 {
1070 return false;
1071 }
1072 Fragment otherFrag = (Fragment) other;
1073
1074 // NB: do not add a comparison of #atoms or #bonds because they may be
1075 // different as a result of a different number of dummy atoms placed
1076 // on linearities. Such atoms are not considered when checking for
1077 // isomorphism so, de facto, fragments can be isomorphic and have a
1078 // different number of atoms and bonds.
1079
1080 if (this.getAttachmentPoints().size()
1081 != otherFrag.getAttachmentPoints().size())
1082 {
1083 return false;
1084 }
1085
1087 this, otherFrag);
1088 return fii.isomorphismExists();
1089 }
1090
1091//------------------------------------------------------------------------------
1092
1094 {
1096 }
1097
1098//------------------------------------------------------------------------------
1099
1100 public boolean containsAtoms()
1101 {
1102 if (mol.getAtomCount() > 0)
1103 return true;
1104 else
1105 return false;
1106 }
1107
1108//------------------------------------------------------------------------------
1109
1110 @Override
1111 public String toString()
1112 {
1113 return getVertexId() + "_" + (getBuildingBlockId() + 1) + "_" +
1114 getBuildingBlockType().toOldInt();
1115 }
1116
1117//------------------------------------------------------------------------------
1118
1119 @Override
1120 public List<AttachmentPoint> getAttachmentPoints()
1121 {
1122 return lstAPs;
1123 }
1124
1125//------------------------------------------------------------------------------
1126
1127 @Override
1128 protected void setSymmetricAPSets(List<SymmetricAPs> sAPs)
1129 {
1130 this.lstSymAPs = sAPs;
1131 }
1132
1133//-----------------------------------------------------------------------------
1134
1135 @Override
1136 protected void addSymmetricAPSet(SymmetricAPs symAPs)
1137 {
1138 if (this.lstSymAPs==null)
1139 {
1140 this.lstSymAPs = new ArrayList<SymmetricAPs>();
1141 }
1142 this.lstSymAPs.add(symAPs);
1143 }
1144
1145//------------------------------------------------------------------------------
1146
1147 @Override
1148 public List<SymmetricAPs> getSymmetricAPSets()
1149 {
1150 return lstSymAPs;
1151 }
1152
1153//------------------------------------------------------------------------------
1154
1163 @Override
1164 public List<Vertex> getMutationSites(List<MutationType> ignoredTypes)
1165 {
1166 List<Vertex> lst = new ArrayList<Vertex>();
1167 switch (getBuildingBlockType())
1168 {
1169 case CAP:
1170 break;
1171
1172 default:
1173 if (getMutationTypes(ignoredTypes).size()>0)
1174 lst.add(this);
1175 break;
1176 }
1177 return lst;
1178 }
1179
1180//------------------------------------------------------------------------------
1181
1188 public String toJson()
1189 {
1190 Gson gson = DENOPTIMgson.getWriter();
1191 String jsonOutput = gson.toJson(this);
1192 return jsonOutput;
1193 }
1194
1195//------------------------------------------------------------------------------
1196
1207 public static Fragment fromJson(String json)
1208 {
1209 Gson gson = DENOPTIMgson.getReader();
1210 Fragment returnedFrag = gson.fromJson(json,
1211 Fragment.class);
1212
1213 for (AttachmentPoint ap : returnedFrag.getAttachmentPoints())
1214 {
1215 ap.setOwner(returnedFrag);
1216 }
1217
1218 returnedFrag.projectListAPToAtomProperties();
1219
1220 return returnedFrag;
1221 }
1222
1223//------------------------------------------------------------------------------
1224
1235 {
1236 if (ap.getOwner() != this)
1237 return null;
1238
1239 return mol.getAtom(ap.getAtomPositionNumber());
1240 }
1241
1242//------------------------------------------------------------------------------
1243
1244}
General set of constants used in DENOPTIM.
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 APSTAG
SDF tag defining attachment points.
static final String SEPARATORAPPROPAAP
Separator between atom index and APClass in molecular property.
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 SEPARATORAPPROPATMS
Separator between APs on different atoms in molecular property.
static final String DUMMYATMSYMBOL
Symbol of dummy atom.
static final Object ISOMORPHICFAMILYID
Property used to store the identifier of the family of isomorphic fragments that owns a fragment.
static final String SEPARATORAPPROPAPS
Separator between APs on same atom in molecular property.
static final String ATMPROPORIGINALATMID
Name of Atom property used to store the original position of an atom in the atom list of the fragment...
int compareTo(APClass o)
Definition: APClass.java:463
Comparator for DENOPTIMAttachmentPoints.
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
APClass getAPClass()
Returns the Attachment Point class.
void setAtomPositionNumber(int atomPositionNumber)
Set the index of the source atom in the list of atoms of the fragment.
int getAtomPositionNumber()
The index of the source atom in the atom list of the fragment.
void setID(int id)
Sets the unique integer that is used to sort list of attachment points.
static String getAPDefinitionsForSDF(LinkedHashMap< Integer, List< AttachmentPoint > > apsPerIndex)
Prepares the two strings that can be used to define AttachmentPoints in SDF files.
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
List< Vertex > getMutationSites(List< MutationType > ignoredTypes)
A list of mutation sites from within this vertex.
Definition: Fragment.java:1164
IBond removeBond(int position)
Definition: Fragment.java:878
List< IAtom > getConnectedAtomsList(IAtom atom)
Definition: Fragment.java:943
void setSymmetricAPSets(List< SymmetricAPs > sAPs)
Definition: Fragment.java:1128
int getAPCountOnAtom(int srcAtmId)
Returns the number of APs currently defined on a specific atom source.
Definition: Fragment.java:475
List< SymmetricAPs > lstSymAPs
List of AP sets that are related to each other, so that we call them "symmetric" (though symmetry is ...
Definition: Fragment.java:71
IAtomContainer mol
Molecular representation of this fragment.
Definition: Fragment.java:76
boolean sameAs(Fragment other, StringBuilder reason)
Compares this and another fragment ignoring vertex IDs.
Definition: Fragment.java:967
void addAP(int atomPositionNumber)
Adds an attachment point with a dummy APClass.
Definition: Fragment.java:343
void removeBond(IBond bond)
Definition: Fragment.java:892
AttachmentPoint addAPOnAtom(IAtom srcAtm, APClass apc, Point3d vector)
Add an attachment point to the specifies atom.
Definition: Fragment.java:424
void addBond(IBond bond)
Definition: Fragment.java:871
List< AttachmentPoint > getCurrentAPs()
Collects APs currently defined as properties of the atoms.
Definition: Fragment.java:541
List< AttachmentPoint > getAttachmentPoints()
Definition: Fragment.java:1120
Fragment(long vertexId)
Constructor for a molecular fragment kind of vertex.
Definition: Fragment.java:107
Fragment clone()
Returns a deep copy of this fragments.
Definition: Fragment.java:733
Iterable< IAtom > atoms()
Definition: Fragment.java:822
ArrayList< AttachmentPoint > getAPsFromAtom(IAtom srcAtm)
Definition: Fragment.java:455
IBond removeBond(IAtom atom1, IAtom atom2)
Definition: Fragment.java:885
boolean isIsomorphicTo(Vertex other)
Checks for isomorphism of the graph representation of this and another fragment.
Definition: Fragment.java:1066
void projectPropertyToAP(String allAtomsProp)
Uses a string formatted like the molecular property used for defining attachment points to create the...
Definition: Fragment.java:594
void addAtom(IAtom atom)
Definition: Fragment.java:836
IAtom getAtom(int number)
Definition: Fragment.java:843
void removeAtom(IAtom atom)
Definition: Fragment.java:899
IAtomContainer getIAtomContainer()
Definition: Fragment.java:788
DefaultUndirectedGraph< FragIsomorphNode, FragIsomorphEdge > getJGraphFragIsomorphism()
Creates a graph representation of this fragment where both atoms and AttachmentPoints are represented...
Definition: Fragment.java:996
Fragment(long vertexId, IAtomContainer mol, BBType bbt, boolean isRCV)
Definition: Fragment.java:167
void updateAPs()
Changes the properties of each APs as to reflect the current atom list.
Definition: Fragment.java:511
void projectListAPToAtomProperties()
Takes the list of APs from the field of this class and projects the APs into properties of the IAtoms...
Definition: Fragment.java:659
static boolean atomsAreCompatible(IAtomContainer mol, int a1, int a2)
Checks if the atoms at the given positions have similar environments i.e.
Definition: Fragment.java:298
String toString()
Produces a human readable, short string to represent the vertex by its vertex ID, building block ID (...
Definition: Fragment.java:1111
void projectAPsToProperties()
Finds the DENOPTIMAttachmentPoint objects defined as properties of the atoms in this container,...
Definition: Fragment.java:693
Fragment(long l, IAtomContainer mol, BBType bbt)
Constructor from an atom container, which has APs only as molecular properties.
Definition: Fragment.java:130
boolean is3D()
Checks if atoms and APs contained in this fragment have non-zero 3D coordinates.
Definition: Fragment.java:195
void updateSymmetryRelations()
Depends on an healthy list of attachment points with properly set pointers to the source atoms.
Definition: Fragment.java:231
List< SymmetricAPs > getSymmetricAPSets()
Definition: Fragment.java:1148
int getAPCountOnAtom(IAtom srcAtm)
Returns the number of APs currently defined on a specific atom source.
Definition: Fragment.java:490
static Fragment fromJson(String json)
Reads a JSON string and returns an instance of this class.
Definition: Fragment.java:1207
void addSymmetricAPSet(SymmetricAPs symAPs)
Definition: Fragment.java:1136
List< AttachmentPoint > lstAPs
attachment points on this vertex
Definition: Fragment.java:65
void removeAP(AttachmentPoint ap)
Definition: Fragment.java:433
void addAP(int srcAtmId, APClass apc, Point3d vector)
Add an attachment point to the specifies atom.
Definition: Fragment.java:404
static List< SymmetricAPs > identifySymmetryRelatedAPSets(IAtomContainer mol, List< AttachmentPoint > daps)
Definition: Fragment.java:239
IAtomContainer getIAtomContainer(Logger logger, Randomizer rng, boolean removeUsedRCAs, boolean rebuild)
Although this type of vertex contains atoms, its content is fixed.
Definition: Fragment.java:814
AttachmentPoint addAP(int atomPositionNumber, Point3d dirVec, APClass apClass)
Adds an attachment point.
Definition: Fragment.java:369
Fragment()
Constructor of an empty fragment.
Definition: Fragment.java:91
IAtom getAtomHoldingAP(AttachmentPoint ap)
Returns the atom where the given attachment point is rooted, i.e., the atom that is involved in the b...
Definition: Fragment.java:1234
void addAP(int atomPositionNumber, APClass apClass)
Adds an attachment point.
Definition: Fragment.java:355
String toJson()
Produces a string that represents this vertex and that adheres to the JSON format.
Definition: Fragment.java:1188
Fragment(IAtomContainer mol, BBType bbt)
Constructor from another atom container, which has APs only as molecular properties.
Definition: Fragment.java:183
Iterable< IBond > bonds()
Definition: Fragment.java:829
int getConnectedAtomsCount(IAtom atom)
Definition: Fragment.java:950
DefaultUndirectedGraph< FragIsomorphNode, FragIsomorphEdge > jGraphFragIsomorphism
jGraph representation used for detecting fragment isomorphism.
Definition: Fragment.java:82
int indexOf(IAtom atom)
Definition: Fragment.java:850
void projectPropertyToAP()
Uses the molecular property defining attachment points to create the DENOPTIMAttachmentPoint objects ...
Definition: Fragment.java:572
void removeAtoms(Collection< IAtom > atoms)
Removes a list of atoms and updates the list of attachment points.
Definition: Fragment.java:913
boolean isomorphismExists()
Checks if an isomorphism exists between the two fragments.
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.
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
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
void setAsRCV(boolean isRCV)
Definition: Vertex.java:254
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
void setBuildingBlockId(int buildingBlockId)
Definition: Vertex.java:291
Object getProperty(Object property)
Definition: Vertex.java:1136
void setBuildingBlockType(Vertex.BBType buildingBlockType)
Definition: Vertex.java:305
void setProperty(Object key, Object property)
Definition: Vertex.java:1148
long vertexId
Unique identifier associated with the vertex instance.
Definition: Vertex.java:70
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:920
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
static final Set< APClass > RCAAPCLASSSET
Recognized APClass for RingClosingAttractor.
Class for de/serializing DENOPTIM graphs from/to JSON format.
Some useful math operations.
Definition: MathUtils.java:39
static double distance(Point3d a, Point3d b)
Calculates distance between point a and point b.
Definition: MathUtils.java:342
Utilities for molecule conversion.
static void setZeroImplicitHydrogensToAllAtoms(IAtomContainer iac)
Sets zero implicit hydrogen count to all atoms.
static IAtomContainer makeSameAs(IAtomContainer mol)
Constructs a copy of an atom container, i.e., a molecule that reflects the one given in the input arg...
static String getSymbolOrLabel(IAtom atm)
Gets either the elemental symbol (for standard atoms) of the label (for pseudo-atoms).
static int getHeavyAtomCount(IAtomContainer mol)
The heavy atom count.
Tool to generate random numbers and random decisions.
Definition: Randomizer.java:35
The type of building block.
Definition: Vertex.java:86
Flag declaring the type of Vertex implementation.
Definition: Vertex.java:172