1package denoptim.fragspace;
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.assertTrue;
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.HashMap;
28import java.util.HashSet;
31import java.util.Random;
32import java.util.function.Supplier;
33import java.util.stream.Collectors;
34import java.util.stream.IntStream;
36import javax.vecmath.Point3d;
38import org.junit.jupiter.api.Test;
39import org.junit.jupiter.api.io.TempDir;
40import org.openscience.cdk.Atom;
41import org.openscience.cdk.DefaultChemObjectBuilder;
42import org.openscience.cdk.PseudoAtom;
43import org.openscience.cdk.interfaces.IAtom;
44import org.openscience.cdk.interfaces.IAtomContainer;
45import org.openscience.cdk.interfaces.IChemObjectBuilder;
46import org.openscience.cdk.silent.Bond;
48import denoptim.exception.DENOPTIMException;
49import denoptim.files.FileUtils;
50import denoptim.graph.APClass;
51import denoptim.graph.AttachmentPoint;
52import denoptim.graph.DGraph;
53import denoptim.graph.Edge;
54import denoptim.graph.Edge.BondType;
55import denoptim.graph.Fragment;
56import denoptim.graph.Ring;
57import denoptim.graph.SymmetricAPs;
58import denoptim.graph.Template;
59import denoptim.graph.Vertex;
60import denoptim.graph.Vertex.BBType;
61import denoptim.graph.rings.RingClosingAttractor;
62import denoptim.io.DenoptimIO;
63import denoptim.molecularmodeling.ThreeDimTreeBuilder;
64import denoptim.utils.GraphUtils;
65import denoptim.utils.MoleculeUtils;
75 private static final String
SEP = System.getProperty(
"file.separator");
80 private final Random
rng =
new Random();
84 private static final String
RULAPCS =
"apc-S";
85 private static final String
RULAPC1 =
"apc-1";
86 private static final String
RULAPC2 =
"apc-2";
87 private static final String
RULAPC3 =
"apc-3";
88 private static final String
RULAPC4 =
"apc-4";
89 private static final String
RULAPC5 =
"apc-5";
90 private static final String
RULAPC6 =
"apc-6";
91 private static final String
RULAPCC1 =
"cap-1";
92 private static final String
RULAPCC2 =
"cap-2";
110 assertTrue(
tempDir.isDirectory(),
"Should be a directory ");
128 String rootName =
tempDir.getAbsolutePath() +
SEP;
130 ArrayList<Vertex> fragLib =
new ArrayList<Vertex>();
132 Atom a1 =
new Atom(
"C",
new Point3d(
new double[]{0.0, 1.1, 2.2}));
133 Atom a2 =
new Atom(
"C",
new Point3d(
new double[]{1.0, 1.1, 2.2}));
134 Atom a3 =
new Atom(
"C",
new Point3d(
new double[]{2.0, 1.1, 2.2}));
138 frg1.
addBond(
new Bond(a1, a2));
139 frg1.
addBond(
new Bond(a2, a3));
148 Atom a21 =
new Atom(
"N",
new Point3d(
new double[]{0.0, 1.1, 2.2}));
149 Atom a22 =
new Atom(
"H",
new Point3d(
new double[]{1.0, 1.1, 2.2}));
152 frg2.
addBond(
new Bond(a21, a22));
159 Atom a31 =
new Atom(
"P",
new Point3d(
new double[]{0.0, 1.1, 2.2}));
168 Atom a81 =
new Atom(
"C",
new Point3d(
new double[]{0.0, 1.1, -2.2}));
169 Atom a82 =
new Atom(
"C",
new Point3d(
new double[]{1.0, 1.1, -2.2}));
170 Atom a83 =
new Atom(
"C",
new Point3d(
new double[]{2.0, 1.1, -2.2}));
174 frg8.
addBond(
new Bond(a81, a82));
175 frg8.
addBond(
new Bond(a82, a83));
176 frg8.
addAPOnAtom(a83,
APC4,
new Point3d(
new double[]{0.0, 2.2, -3.3}));
177 frg8.
addAPOnAtom(a83,
APC4,
new Point3d(
new double[]{0.0, 0.0, -3.3}));
178 frg8.
addAPOnAtom(a83,
APC6,
new Point3d(
new double[]{0.0, 0.0, -1.1}));
179 frg8.
addAPOnAtom(a82,
APC5,
new Point3d(
new double[]{1.0, 0.1, -2.2}));
180 frg8.
addAPOnAtom(a82,
APC5,
new Point3d(
new double[]{1.0, 0.1, -1.2}));
181 frg8.
addAPOnAtom(a82,
APC5,
new Point3d(
new double[]{1.0, 2.1, -2.2}));
182 frg8.
addAPOnAtom(a81,
APC5,
new Point3d(
new double[]{3.0, 0.0, -3.3}));
186 String fragLibFile = rootName +
"frags.sdf";
189 ArrayList<Vertex> scaffLib =
new ArrayList<Vertex>();
191 Atom a41 =
new Atom(
"O",
new Point3d(
new double[]{0.0, 1.1, 2.2}));
192 Atom a42 =
new Atom(
"C",
new Point3d(
new double[]{1.0, 1.1, 2.2}));
193 Atom a43 =
new Atom(
"Ru",
new Point3d(
new double[]{2.0, 1.1, 2.2}));
197 scaf0.
addBond(
new Bond(a41, a42));
198 scaf0.
addBond(
new Bond(a42, a43));
199 scaf0.
addAPOnAtom(a43,
APCS,
new Point3d(
new double[]{0.0, 2.2, 3.3}));
200 scaf0.
addAPOnAtom(a43,
APCS,
new Point3d(
new double[]{0.0, 0.0, 3.3}));
201 scaf0.
addAPOnAtom(a43,
APCS,
new Point3d(
new double[]{0.0, 0.0, 1.1}));
202 scaf0.
addAPOnAtom(a41,
APCS,
new Point3d(
new double[]{3.0, 0.0, 3.3}));
207 Atom a51 =
new Atom(
"Zn",
new Point3d(
new double[]{5.0, 1.1, 2.2}));
209 scaf1.
addAPOnAtom(a51,
APCS,
new Point3d(
new double[]{5.0, 2.2, 3.3}));
210 scaf1.
addAPOnAtom(a51,
APCS,
new Point3d(
new double[]{5.0, 0.0, 3.3}));
211 scaf1.
addAPOnAtom(a51,
APCS,
new Point3d(
new double[]{5.0, 0.0, 1.1}));
215 String scaffLibFile = rootName +
"scaff.sdf";
218 ArrayList<Vertex> cappLib =
new ArrayList<Vertex>();
220 Atom a61 =
new Atom(
"H",
new Point3d(
new double[]{10.0, 1.1, 2.2}));
227 Atom a71 =
new Atom(
"Cl",
new Point3d(
new double[]{10.0, 1.1, 2.2}));
233 String capLibFile = rootName +
"caps.sdf";
236 HashMap<APClass,ArrayList<APClass>> cpMap =
237 new HashMap<APClass,ArrayList<APClass>>();
238 ArrayList<APClass> lst1 =
new ArrayList<APClass>();
241 cpMap.put(
APCS, lst1);
242 ArrayList<APClass> lst2 =
new ArrayList<APClass>();
244 cpMap.put(
APC1, lst2);
245 ArrayList<APClass> lst3 =
new ArrayList<APClass>();
248 cpMap.put(
APC2, lst3);
250 HashMap<APClass,APClass> capMap =
new HashMap<APClass,APClass>();
255 HashSet<APClass> ends =
new HashSet<APClass>();
258 String cpmFile = rootName +
"cpm.dat";
269 capLibFile, cpmFile);
285 "Number of symmetric sets of APs");
287 Map<APClass,Integer> expectedCount =
new HashMap<APClass,Integer>();
288 expectedCount.put(
APC4, 2);
289 expectedCount.put(
APC5, 3);
292 APClass apc = ss.get(0).getAPClass();
293 assertEquals(expectedCount.get(apc),ss.size(),
294 "Number of APs in symmetric set for APClass "+apc);
305 assertTrue(fs.
isDefined(),
"FragmentSpace is defined");
307 assertEquals(4,l.size(),
"Wrong size of AP IDs with given APClass.");
314 id.getVertexMolId(),
id.getVertexMolType(), fs);
328 assertTrue(fs.
isDefined(),
"FragmentSpace is defined");
331 assertEquals(4,lst.size(),
"Size of compatible APs list is wrong.");
338 id.getVertexMolId(),
id.getVertexMolType(), fs);
341 "Incompatible choice at "+i);
352 assertTrue(fs.
isDefined(),
"FragmentSpace is defined");
355 ArrayList<IdFragmentAndAP> srcAPs =
new ArrayList<IdFragmentAndAP>();
380 assertEquals(4,lst.size(),
"Size of compatible APs list is wrong.");
387 id.getVertexMolId(),
id.getVertexMolType(), fs);
391 "Incompatible choice at "+i);
402 assertTrue(fs.
isDefined(),
"FragmentSpace is defined");
405 ArrayList<IdFragmentAndAP> srcAPs =
new ArrayList<IdFragmentAndAP>();
412 assertEquals(3,lst.size(),
"Wrong number of compatible fragments.");
426 HashMap<APClass,ArrayList<APClass>> cpMap =
427 new HashMap<APClass,ArrayList<APClass>>();
428 ArrayList<APClass> lstA =
new ArrayList<APClass>();
430 cpMap.put(apcA, lstA);
431 ArrayList<APClass> lstB =
new ArrayList<APClass>();
434 cpMap.put(apcB, lstB);
436 HashMap<APClass,ArrayList<APClass>> rcCPMap =
437 new HashMap<APClass,ArrayList<APClass>>();
438 ArrayList<APClass> lstC =
new ArrayList<APClass>();
440 rcCPMap.put(apcA, lstC);
442 ArrayList<Vertex> fragments =
new ArrayList<Vertex>();
445 Atom a21 =
new Atom(
"N",
new Point3d(
new double[]{0.0, 1.1, 2.2}));
446 Atom a22 =
new Atom(
"H",
new Point3d(
new double[]{1.0, 1.1, 2.2}));
449 frg2.
addBond(
new Bond(a21, a22));
450 frg2.
addAP(1, apcB,
new Point3d(
new double[]{0.0, 2.2, 3.3}));
451 frg2.
addAP(1, apcA,
new Point3d(
new double[]{0.0, 0.0, 3.3}));
458 rcv1.
addAP(0, rcvP,
new Point3d(1.0, 0, 0));
466 rcv2.
addAP(0, rcvM,
new Point3d(-1.0, 0, 0));
474 rcv3.
addAP(0, rcvM,
new Point3d(-2.0, 0, 0));
478 HashMap<APClass,APClass> capMap =
new HashMap<APClass,APClass>();
479 HashSet<APClass> forbEnds =
new HashSet<APClass>();
483 new ArrayList<Vertex>(),
485 new ArrayList<Vertex>(),
486 cpMap, capMap, forbEnds, cpMap);
490 assertEquals(1, rcvs1.size());
491 assertEquals(rcvP, rcvs1.get(0).getAP(0).getAPClass());
493 assertEquals(3, rcvs2.size());
498 if (rcvP == rcv.getAP(0).getAPClass())
503 assertEquals(1, countP);
504 assertEquals(2, countM);
506 assertEquals(0, rcvs3.size());
520 HashMap<APClass,ArrayList<APClass>> cpMap =
521 new HashMap<APClass,ArrayList<APClass>>();
522 ArrayList<APClass> lstA =
new ArrayList<APClass>();
524 cpMap.put(apcA, lstA);
525 ArrayList<APClass> lstB =
new ArrayList<APClass>();
528 cpMap.put(apcB, lstB);
530 HashMap<APClass,ArrayList<APClass>> rcCPMap =
531 new HashMap<APClass,ArrayList<APClass>>();
532 ArrayList<APClass> lstC =
new ArrayList<APClass>();
534 rcCPMap.put(apcA, lstC);
536 ArrayList<Vertex> fragments =
new ArrayList<Vertex>();
539 Atom a21 =
new Atom(
"N",
new Point3d(
new double[]{0.0, 1.1, 2.2}));
540 Atom a22 =
new Atom(
"H",
new Point3d(
new double[]{1.0, 1.1, 2.2}));
543 frg2.
addBond(
new Bond(a21, a22));
544 frg2.
addAP(1, apcB,
new Point3d(
new double[]{0.0, 2.2, 3.3}));
545 frg2.
addAP(1, apcA,
new Point3d(
new double[]{0.0, 0.0, 3.3}));
552 rcv1.
addAP(0, rcvP,
new Point3d(1.0, 0, 0));
560 rcv2.
addAP(0, rcvM,
new Point3d(-1.0, 0, 0));
564 HashMap<APClass,APClass> capMap =
new HashMap<APClass,APClass>();
565 HashSet<APClass> forbEnds =
new HashSet<APClass>();
569 new ArrayList<Vertex>(),
571 new ArrayList<Vertex>(),
572 cpMap, capMap, forbEnds, cpMap);
576 assertEquals(1, rcvs1.size());
577 assertTrue(rcv1.
sameAs(rcvs1.get(0)));
580 assertEquals(1, rcvs2.size());
581 assertTrue(rcv2.
sameAs(rcvs2.get(0)));
600 fsp.fragmentLibFile =
"dummyFilename_DenoptimTest_Frag";
601 fsp.scaffoldLibFile =
"dummyFilename_DenoptimTest_Scaff";
615 assertEquals(1, fragLib.size());
616 Vertex actual = fragLib.get(0);
617 StringBuilder sb =
new StringBuilder();
619 "Problem is "+sb.toString());
633 fsp.fragmentLibFile =
"dummyFilename_DenoptimTest_Frag";
634 fsp.scaffoldLibFile =
"dummyFilename_DenoptimTest_Scaff";
652 assertEquals(1, scaffLib.size());
653 Vertex actual = scaffLib.get(0);
654 assertTrue(testCase.
expected.
sameAs(actual,
new StringBuilder()));
663 fsp.fragmentLibFile =
"dummyFilename_DenoptimTest_Frag";
664 fsp.scaffoldLibFile =
"dummyFilename_DenoptimTest_Scaff";
667 final int TRY_ADDING = 10;
668 List<DGraph> sameGraphs = IntStream
669 .range(0, TRY_ADDING)
671 .peek(t -> t.renumberGraphVertices())
672 .collect(Collectors.toList());
677 for (
DGraph g : sameGraphs) {
685 assertEquals(1, fragLib.size());
719 Ring r124 =
new Ring(Arrays.asList(rcv14, c1, c2, c4,
721 Ring r425 =
new Ring(Arrays.asList(rcv45, c4, c2, c5,
740 .indexOfVertexWithID(c3.getVertexId()));
753 IChemObjectBuilder builder = DefaultChemObjectBuilder.getInstance();
754 IAtom carbon = builder.newAtom();
755 carbon.setSymbol(
"C");
756 IAtomContainer mol = builder.newAtomContainer();
762 for (
int i = 0; i < 4; i++) {
772 IChemObjectBuilder builder = DefaultChemObjectBuilder
774 IAtomContainer dummyMol = builder.newAtomContainer();
775 IAtom dummyAtom = builder.newAtom();
776 dummyMol.addAtom(dummyAtom);
789 int precision = 10 * 10 * 10 * 10;
791 Supplier<Double> randomCoord = () ->
792 (
double) (Math.round(
rng.nextDouble() * (double) precision)) /
793 ((
double) precision);
795 return new Point3d(randomCoord.get(), randomCoord.get(),
839 fsp.fragmentLibFile =
"dummyFilename_DenoptimTest_Frag";
840 fsp.scaffoldLibFile =
"dummyFilename_DenoptimTest_Scaff";
843 IAtom s1 =
new Atom(
"C",
new Point3d(0,0,0));
854 IAtom a1 =
new Atom(
"C",
new Point3d(0,0,0));
855 IAtom a2 =
new Atom(
"C",
new Point3d(0,0,1));
856 IAtom a3 =
new Atom(
"C",
new Point3d(0,0,2));
871 IAtom a4 =
new PseudoAtom(
"ATN",
new Point3d(0,0,0));
941 wholeGraph.
clone(),
true);
944 for (
int i=0; i<wholeMol.getAtomCount(); i++)
946 IAtom atm = wholeMol.getAtom(i);
947 if (atm instanceof PseudoAtom)
948 ((PseudoAtom) atm).setLabel(
"Du");
951 atm.setPoint3d(
new Point3d(r*Math.cos(Math.toRadians(360/34 * i)),
952 r*Math.sin(Math.toRadians(360/34 * i)),0));
958 String scafFile =
tempDir.getAbsolutePath() +
SEP +
"newScaf.sdf";
959 String fragFile =
tempDir.getAbsolutePath() +
SEP +
"newFrag.sdf";
960 fsp.scaffoldLibFile = scafFile;
961 fsp.fragmentLibFile = fragFile;
967 "Size scaffolds library");
969 "Size fragments library");
974 "#APs on new scaffold");
981 assertEquals(10,nP,
"#P in new scaffold");
986 "#APs on new fragment");
993 assertEquals(9,nP,
"#P in new fragment");
static void deleteFile(String fileName)
Delete the file.
Class defining a space of building blocks.
ArrayList< Vertex > getFragmentsCompatibleWithTheseAPs(ArrayList< IdFragmentAndAP > srcAPs)
Searches for all building blocks that are compatible with the given list of APs.
void appendVertexToLibrary(Vertex v, Vertex.BBType bbt, ArrayList< Vertex > library)
Takes a vertex and add it to a given library.
ArrayList< IdFragmentAndAP > getFragAPsCompatibleWithTheseAPs(ArrayList< IdFragmentAndAP > srcAPs)
Searches for all APs that are compatible with the given list of APs.
boolean isDefined()
Checks for valid definition of this fragment space.
Vertex getVertexFromLibrary(Vertex.BBType bbType, int bbIdx)
Returns a clone of the requested building block.
void setAPclassBasedApproach(boolean useAPC)
Set the fragment space to behave according to APClass-based approach.
ArrayList< IdFragmentAndAP > getFragsWithAPClass(APClass apc)
Returns the list of attachment points with the given class.
List< Vertex > getRCVsWithAPClass(APClass apc)
Searches for all building blocks that are ring-closing vertexes and hold an AP with the given class.
ArrayList< IdFragmentAndAP > getFragAPsCompatibleWithClass(APClass aPC1)
Returns the list of attachment points found in the fragment space and that are compatible with a give...
void addFusedRingsToFragmentLibrary(DGraph graph)
Extracts a system of one or more fused rings and adds them to the fragment space if not already prese...
ArrayList< Vertex > getScaffoldLibrary()
ArrayList< Vertex > getFragmentLibrary()
List< Vertex > getRCVsForAPClass(APClass apc)
Searches for all building blocks that are ring-closing vertexes and are compatible with the given AP.
Parameters defining the fragment space.
String getPathnameToAppendedFragments()
FragmentSpace getFragmentSpace()
String getPathnameToAppendedScaffolds()
TestCase(DGraph g, Template expected)
Unit test for fragment space.
void testGetFragAPsCompatibleWithTheseAPs()
static final String RULAPCS
void testGetRCVsForAPClass()
static final String RULAPC4
static final String RULAPC1
void testFusedRingAddedToScaffoldLibrary()
Checks that a graph with a fused ring containing a scaffold vertex is added to the scaffold library.
void testUseWholeMolGeometryForExtractedTemplates()
Works with this graph:
void testFusedRingAddedToFragmentLibrary()
Check that the following graph's fused ring gets added to the fragment library.
void testGetFragsWithAPClass()
void testFusedRingOnlyAddedOnce()
static final String RULAPC3
static final String RULAPCC1
static final BBType BBTFRAG
Fragment getCarbonVertex()
static final String RULAPCC2
static final String RULAPC6
void testGetFragmentsCompatibleWithTheseAPs()
Point3d getRandomVector()
void testGetRCVsWithAPClass()
static final String RULAPC5
static final int APSUBRULE
FragmentSpaceParameters buildFragmentSpace()
void testGetFragAPsCompatibleWithClass()
Template getExpectedTemplate(DGraph g, Vertex c3)
static final String RULAPC2
Data structure containing information that identifies a single AP of a vertex/fragment.
BBType getVertexMolType()
boolean isCPMapCompatibleWith(APClass other, FragmentSpace fragSpace)
Check compatibility as defined in the compatibility matrix considering this AP as source and the othe...
static final APClass RCACLASSPLUS
Conventional class of attachment points on ring-closing vertexes.
static final APClass RCACLASSMINUS
Conventional class of attachment points on ring-closing vertexes.
static APClass make(String ruleAndSubclass)
Creates an APClass if it does not exist already, or returns the reference to the existing instance.
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.
Container for the list of vertices and the edges that connect them.
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
void removeVertex(Vertex vertex)
Remove a vertex from this graph.
Vertex getVertexAtPosition(int pos)
Returns the vertex that is in the given position of the list of vertices belonging to this graph.
void appendVertexOnAP(AttachmentPoint srcAP, AttachmentPoint trgAP)
Append a vertex to this graph: adds the new vertex to the list of vertices belonging to the graph,...
List< Vertex > getVertexList()
DGraph clone()
Returns almost "deep-copy" of this graph.
void renumberGraphVertices()
Reassign vertex IDs to all vertices of this graph.
void addEdge(Edge edge)
Adds the edge to the list of edges belonging to this graph.
This class represents the edge between two vertices.
Class representing a continuously connected portion of chemical object holding attachment points.
boolean sameAs(Fragment other, StringBuilder reason)
Compares this and another fragment ignoring vertex IDs.
void addAP(int atomPositionNumber)
Adds an attachment point with a dummy APClass.
AttachmentPoint addAPOnAtom(IAtom srcAtm, APClass apc, Point3d vector)
Add an attachment point to the specifies atom.
void projectAPsToProperties()
Finds the DENOPTIMAttachmentPoint objects defined as properties of the atoms in this container,...
This class represents the closure of a ring in a spanning tree.
A collection of AttachmentPoints that are related by a relation that we call "symmetry",...
void setInnerGraph(DGraph innerGraph)
boolean sameAs(Template other, StringBuilder reason)
Compares this and another template ignoring vertex IDs.
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
void setAsRCV(boolean isRCV)
abstract List< AttachmentPoint > getAttachmentPoints()
void setBuildingBlockId(int buildingBlockId)
abstract List< SymmetricAPs > getSymmetricAPSets()
void setBuildingBlockType(Vertex.BBType buildingBlockType)
abstract IAtomContainer getIAtomContainer()
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
static Vertex newVertexFromLibrary(int bbId, Vertex.BBType bbt, FragmentSpace fragSpace)
Builds a new molecular fragment kind of vertex.
The RingClosingAttractor represent the available valence/connection that allows to close a ring.
static final HashMap< APClass, String > RCALABELPERAPCLASS
Conventional labels for attractor pseudoatom.
Utility methods for input/output.
static void writeCompatibilityMatrix(String fileName, HashMap< APClass, ArrayList< APClass > > cpMap, HashMap< APClass, APClass > capMap, HashSet< APClass > ends)
The class compatibility matrix.
static void writeVertexesToSDF(File file, List< Vertex > vertexes, boolean append)
Write a list of vertexes to file.
Tool to build build three-dimensional (3D) tree-like molecular structures from DGraph.
IAtomContainer convertGraphTo3DAtomContainer(DGraph graph)
Created a three-dimensional molecular representation from a given DGraph.
Logger getLogger()
Get the name of the program specific logger.
Randomizer getRandomizer()
Returns the current program-specific randomizer.
static synchronized long getUniqueVertexIndex()
Unique counter for the number of graph vertices generated.
Utilities for molecule conversion.
static String getSymbolOrLabel(IAtom atm)
Gets either the elemental symbol (for standard atoms) of the label (for pseudo-atoms).
Possible chemical bond types an edge can represent.
The type of building block.