$darkmode
DENOPTIM
ThreeDimTreeBuilderTest.java
Go to the documentation of this file.
1package denoptim.molecularmodeling;
2
3/*
4 * DENOPTIM
5 * Copyright (C) 2019 Vishwesh Venkatraman <vishwesh.venkatraman@ntnu.no>
6 * and Marco Foscato <marco.foscato@uib.no>
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published
10 * by the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22import static org.junit.jupiter.api.Assertions.assertEquals;
23
24import java.io.File;
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.HashMap;
28import java.util.HashSet;
29import java.util.logging.Logger;
30
31import javax.vecmath.Point3d;
32
33import org.junit.jupiter.api.Test;
34import org.openscience.cdk.Atom;
35import org.openscience.cdk.PseudoAtom;
36import org.openscience.cdk.interfaces.IAtom;
37import org.openscience.cdk.interfaces.IAtomContainer;
38import org.openscience.cdk.silent.Bond;
39
40import denoptim.fragspace.FragmentSpace;
41import denoptim.fragspace.FragmentSpaceParameters;
42import denoptim.graph.APClass;
43import denoptim.graph.DGraph;
44import denoptim.graph.Edge;
45import denoptim.graph.Edge.BondType;
46import denoptim.graph.EmptyVertex;
47import denoptim.graph.Fragment;
48import denoptim.graph.Vertex;
49import denoptim.graph.Vertex.BBType;
50import denoptim.io.DenoptimIO;
51import denoptim.utils.MoleculeUtils;
52import denoptim.utils.Randomizer;
53
61{
62
63//------------------------------------------------------------------------------
64
65 @Test
66 public void testConversionTo3dTree() throws Exception
67 {
73
74 HashMap<APClass,ArrayList<APClass>> cpMap =
75 new HashMap<APClass,ArrayList<APClass>>();
76 cpMap.put(a0, new ArrayList<APClass>(Arrays.asList(a0, b0)));
77 HashMap<APClass,APClass> capMap = new HashMap<APClass,APClass>();
78 capMap.put(a0, h0);
79 HashSet<APClass> forbEnds = new HashSet<APClass>();
80 forbEnds.add(b0);
81
82
83 Fragment frg1 = new Fragment();
84 IAtom a1 = new Atom("C", new Point3d(new double[]{0.0, 0.0, 0.0}));
85 IAtom a2 = new Atom("C", new Point3d(new double[]{1.0, 0.0, 0.0}));
86 frg1.addAtom(a1);
87 frg1.addAtom(a2);
88 frg1.addBond(new Bond(a1, a2));
89 frg1.addAP(0, a0, new Point3d(new double[]{0.0, 0.0, 1.0}));
90 frg1.addAP(1, a0, new Point3d(new double[]{1.0, 1.0, 1.0}));
92
93 Fragment frg2 = new Fragment();
94 IAtom a3 = new Atom("C", new Point3d(new double[]{0.0, 0.0, 0.0}));
95 frg2.addAtom(a3);
96 frg2.addAP(0, a0, new Point3d(new double[]{0.0, 1.0, 1.0}));
97 frg2.addAP(0, b0, new Point3d(new double[]{0.0, 1.0, -1.0}));
99
100 Fragment frg3 = new Fragment();
101 IAtom a7 = new Atom("C", new Point3d(new double[]{2.0, 0.0, 0.0}));
102 IAtom a8 = new Atom("O", new Point3d(new double[]{3.0, 0.0, 0.0}));
103 frg3.addAtom(a7);
104 frg3.addAtom(a8);
105 frg3.addBond(new Bond(a7, a8));
106 frg3.addAP(0, a0, new Point3d(new double[]{2.0, 1.0, 1.0}));
107 frg3.addAP(0, a0, new Point3d(new double[]{2.0, 1.0, -1.0}));
108 frg3.addAP(0, b0, new Point3d(new double[]{3.0, 1.0, -1.0}));
110
111 Fragment rca1 = new Fragment();
112 IAtom a4 = new PseudoAtom("ATP", new Point3d(
113 new double[]{0.0, 0.0, 0.0}));
114 rca1.addAtom(a4);
115 rca1.addAP(0, ap0, new Point3d(new double[]{0.0, 1.0, 1.0}));
117
118 Fragment rca2 = new Fragment();
119 IAtom a5 = new PseudoAtom("ATM", new Point3d(
120 new double[]{1.0, 0.0, 0.0}));
121 rca2.addAtom(a5);
122 rca2.addAP(0, am0, new Point3d(new double[]{0.0, 1.0, 1.0}));
124
125 Fragment cap = new Fragment();
126 IAtom a6 = new Atom("H", new Point3d(new double[]{0.0, 0.0, 0.0}));
127 cap.addAtom(a6);
128 cap.addAP(0, h0, new Point3d(new double[]{0.0, 1.0, 1.0}));
130
131 ArrayList<Vertex> scaff = new ArrayList<Vertex>();
132 scaff.add(frg1);
133 ArrayList<Vertex> frags = new ArrayList<Vertex>();
134 frags.add(frg2);
135 frags.add(rca1);
136 frags.add(rca2);
137 frags.add(frg3);
138 ArrayList<Vertex> caps = new ArrayList<Vertex>();
139 caps.add(cap);
140
142 FragmentSpace fs = new FragmentSpace(fsp, scaff, frags, caps,
143 cpMap, capMap, forbEnds, cpMap);
145
146 DGraph g1 = new DGraph();
148 BBType.SCAFFOLD, fs);
150 BBType.FRAGMENT, fs);
152 BBType.FRAGMENT, fs);
154 BBType.FRAGMENT, fs);
155 g1.addVertex(v1);
156 g1.addVertex(v2);
157 g1.addVertex(v3);
158 g1.addVertex(v4);
159
160 Edge e1 = new Edge(v1.getAP(1), v2.getAP(0),
162 Edge e2 = new Edge(v2.getAP(1), v3.getAP(0),
164 Edge e3 = new Edge(v1.getAP(0), v4.getAP(0),
166 g1.addEdge(e1);
167 g1.addEdge(e2);
168 g1.addEdge(e3);
169
170 g1.addRing(v3, v4);
171
172 Logger logger = Logger.getLogger("DummyLogger");
173 Randomizer rng = new Randomizer();
174 ThreeDimTreeBuilder t3d = new ThreeDimTreeBuilder(logger, rng);
175
176 IAtomContainer mol = t3d.convertGraphTo3DAtomContainer(g1,false);
177 assertEquals(4, mol.getBondCount(), "Number of bonds without the "
178 + "cyclic one");
179 assertEquals(5, mol.getAtomCount(), "Number of atoms in cyclic molecule"
180 + " before forming ring");
181
182 mol = t3d.convertGraphTo3DAtomContainer(g1,true);
183 // NB: no RCAs anymore, so two atoms less than before (the RCAs),
184 // and two bonds less than the moment when we have made
185 // the ring-closing bond but we have not yet removed the RCAs.
186 // Basically we add 1 bond and remove 2.
187 assertEquals(3, mol.getBondCount(), "Number of bonds, including the "
188 + "cyclic one");
189 assertEquals(3, mol.getAtomCount(), "Number of atoms in cyclic "
190 + "molecule after removal of RCAs");
191
192
193 DGraph g2 = new DGraph();
195 BBType.SCAFFOLD, fs);
197 BBType.FRAGMENT, fs);
199 BBType.FRAGMENT, fs);
201 BBType.FRAGMENT, fs);
202 g2.addVertex(v1b);
203 g2.addVertex(v2b);
204 g2.addVertex(v3b);
205 g2.addVertex(v4b);
206
207 Edge e1b = new Edge(v1b.getAP(1), v2b.getAP(0),
209 Edge e2b = new Edge(v2b.getAP(1), v3b.getAP(0),
211 Edge e3b = new Edge(v1b.getAP(0), v4b.getAP(0),
213 g2.addEdge(e1b);
214 g2.addEdge(e2b);
215 g2.addEdge(e3b);
216
217 IAtomContainer acyclicMol = t3d.convertGraphTo3DAtomContainer(
218 g2,true);
219 assertEquals(4, acyclicMol.getBondCount(), "Number of bonds in acyclic "
220 + "graph with RCAs");
221 assertEquals(5, acyclicMol.getAtomCount(), "Number of atoms in acyclic "
222 + "molecule before forming ring");
223
224
225 DGraph g3 = new DGraph();
226 EmptyVertex v1c = new EmptyVertex(1);
227 v1c.addAP(a0);
228 v1c.addAP(a0);
230 BBType.FRAGMENT, fs);
232 BBType.FRAGMENT, fs);
234 BBType.FRAGMENT, fs);
235 g3.addVertex(v1c);
236 g3.addVertex(v2c);
237 g3.addVertex(v3c);
238 g3.addVertex(v4c);
239
240 Edge e1c = new Edge(v1c.getAP(1), v2c.getAP(0),
242 Edge e2c = new Edge(v2c.getAP(1), v3c.getAP(0),
244 Edge e3c = new Edge(v1c.getAP(0), v4c.getAP(0),
246 g3.addEdge(e1c);
247 g3.addEdge(e2c);
248 g3.addEdge(e3c);
249
250 IAtomContainer molFromEmptyScaff = t3d.convertGraphTo3DAtomContainer(
251 g3,true);
252 assertEquals(1, molFromEmptyScaff.getBondCount(), "Number of bonds in "
253 + "mol with empty scaffold");
254 assertEquals(3, molFromEmptyScaff.getAtomCount(), "Number of atoms in "
255 + "mol with empty scaffold");
256
257
258 DGraph g4 = new DGraph();
259 EmptyVertex v1d = new EmptyVertex(1);
260 v1d.addAP(a0);
261 v1d.addAP(a0);
262 EmptyVertex v2d = new EmptyVertex(2);
263 v2d.addAP(a0);
264 v2d.addAP(b0);
266 BBType.FRAGMENT, fs);
268 BBType.FRAGMENT, fs);
269 EmptyVertex v5d = new EmptyVertex(5);
270 v5d.addAP(b0);
271 v5d.addAP(b0);
273 BBType.FRAGMENT, fs);
275 BBType.FRAGMENT, fs);
276 g4.addVertex(v1d);
277 g4.addVertex(v2d);
278 g4.addVertex(v3d);
279 g4.addVertex(v4d);
280 g4.addVertex(v5d);
281 g4.addVertex(v6d);
282 g4.addVertex(v7d);
283
284 Edge e1d = new Edge(v1d.getAP(1), v2d.getAP(0),
286 Edge e2d = new Edge(v2d.getAP(1), v7d.getAP(1),
288 Edge e3d = new Edge(v1d.getAP(0), v3d.getAP(0),
290 Edge e4d = new Edge(v3d.getAP(1), v4d.getAP(0),
292 Edge e5d = new Edge(v3d.getAP(2), v5d.getAP(1),
294 Edge e6d = new Edge(v5d.getAP(0), v6d.getAP(1),
296 g4.addEdge(e1d);
297 g4.addEdge(e2d);
298 g4.addEdge(e3d);
299 g4.addEdge(e4d);
300 g4.addEdge(e5d);
301 g4.addEdge(e6d);
302
303 IAtomContainer molWithEmptyNodes = t3d.convertGraphTo3DAtomContainer(
304 g4,true);
305 assertEquals(2, molWithEmptyNodes.getBondCount(), "Number of bonds in "
306 + "mol with empty scaffold and other nodes");
307 assertEquals(5, molWithEmptyNodes.getAtomCount(), "Number of atoms in "
308 + "mol with empty scaffold and other nodes");
309 }
310
311//------------------------------------------------------------------------------
312
313 @Test
314 public void testConversionTo3dTreeWithDisconnectedGraphs() throws Exception
315 {
316 APClass a0 = APClass.make("a",0,BondType.SINGLE);
317 APClass b0 = APClass.make("b",0,BondType.SINGLE);
318 APClass h0 = APClass.make("h",0,BondType.SINGLE);
319
320 Fragment frg1 = new Fragment();
321 IAtom a1 = new Atom("C", new Point3d(new double[]{0.0, 0.0, 0.0}));
322 IAtom a2 = new Atom("C", new Point3d(new double[]{1.0, 0.0, 0.0}));
323 frg1.addAtom(a1);
324 frg1.addAtom(a2);
325 frg1.addBond(new Bond(a1, a2));
326 frg1.addAP(0, a0, new Point3d(new double[]{0.0, 0.0, 1.0}));
327 frg1.addAP(1, a0, new Point3d(new double[]{1.0, 1.0, 1.0}));
329
330 Fragment frg3 = new Fragment();
331 IAtom a7 = new Atom("C", new Point3d(new double[]{2.0, 0.0, 0.0}));
332 IAtom a8 = new Atom("O", new Point3d(new double[]{3.0, 0.0, 0.0}));
333 frg3.addAtom(a7);
334 frg3.addAtom(a8);
335 frg3.addBond(new Bond(a7, a8));
336 frg3.addAP(0, a0, new Point3d(new double[]{2.0, 1.0, 1.0}));
337 frg3.addAP(0, a0, new Point3d(new double[]{2.0, 1.0, -1.0}));
338 frg3.addAP(0, b0, new Point3d(new double[]{3.0, 1.0, -1.0}));
340
341 Fragment frg4 = new Fragment();
342 IAtom a41 = new Atom("Si", new Point3d(new double[]{0.0, 5.0, 5.0}));
343 IAtom a42 = new Atom("P", new Point3d(new double[]{1.0, 5.0, 5.0}));
344 frg4.addAtom(a41);
345 frg4.addAtom(a42);
346 frg4.addBond(new Bond(a41, a42));
347 frg4.addAP(0, a0, new Point3d(new double[]{0.0, 5.0, 6.0}));
348 frg4.addAP(1, a0, new Point3d(new double[]{1.0, 6.0, 6.0}));
350
351 Fragment frg5 = new Fragment();
352 IAtom a53 = new Atom("N", new Point3d(new double[]{0.0, 5.0, 5.0}));
353 frg5.addAtom(a53);
354 frg5.addAP(0, a0, new Point3d(new double[]{0.0, 6.0, 6.0}));
355 frg5.addAP(0, b0, new Point3d(new double[]{0.0, 6.0, 4.0}));
357
358 Fragment cap = new Fragment();
359 IAtom a6 = new Atom("H", new Point3d(new double[]{0.0, 0.0, 0.0}));
360 cap.addAtom(a6);
361 cap.addAP(0, h0, new Point3d(new double[]{0.0, 1.0, 1.0}));
363
364
365 Vertex v1d = frg4.clone();
366 v1d.setVertexId(0);
368 Vertex v2d = frg5.clone();
369 v2d.setVertexId(1);
371
372 Vertex v3d = frg1.clone();
373 v3d.setVertexId(3);
375 Vertex v4d = frg3.clone();
376 v4d.setVertexId(4);
378 Vertex v6d = frg1.clone();
379 v6d.setVertexId(6);
381 Vertex v7d = cap.clone();
382 v7d.setVertexId(7);
384 Vertex v8d = cap.clone();
385 v8d.setVertexId(8);
387
388 DGraph g4 = new DGraph();
389 g4.addVertex(v1d);
390 g4.addVertex(v2d);
391 g4.addVertex(v3d);
392 g4.addVertex(v4d);
393 g4.addVertex(v6d);
394 g4.addVertex(v7d);
395 g4.addVertex(v8d);
396
397
398 Edge e0d = new Edge(v2d.getAP(0), v1d.getAP(0),
400
401 Edge e1d = new Edge(v3d.getAP(0), v4d.getAP(1),
403 Edge e2d = new Edge(v4d.getAP(0), v6d.getAP(1),
405 Edge e3d = new Edge(v6d.getAP(0), v7d.getAP(0),
407 Edge e4d = new Edge(v3d.getAP(1), v8d.getAP(0),
409
410 g4.addEdge(e0d);
411 g4.addEdge(e1d);
412 g4.addEdge(e2d);
413 g4.addEdge(e3d);
414 g4.addEdge(e4d);
415
416 Logger logger = Logger.getLogger("DummyLogger");
417 Randomizer rng = new Randomizer();
418 ThreeDimTreeBuilder t3d = new ThreeDimTreeBuilder(logger, rng);
419
420 IAtomContainer mol = t3d.convertGraphTo3DAtomContainer(g4,true);
421
422 assertEquals(3, MoleculeUtils.getDimensions(mol));
423 assertEquals(9, mol.getBondCount());
424 assertEquals(11, mol.getAtomCount());
425
426 //Ensure disconnection ith other subgraph
427 for (IAtom atom : mol.atoms())
428 {
429 if (atom.getSymbol().equals("N"))
430 {
431 assertEquals(1, mol.getConnectedAtomsList(atom).size());
432 assertEquals("Si", mol.getConnectedAtomsList(atom).get(0).getSymbol());
433 }
434 if (atom.getSymbol().equals("P"))
435 {
436 assertEquals(1, mol.getConnectedAtomsList(atom).size());
437 assertEquals("Si", mol.getConnectedAtomsList(atom).get(0).getSymbol());
438 }
439 if (atom.getSymbol().equals("Si"))
440 {
441 assertEquals(2, mol.getConnectedAtomsList(atom).size());
442 assertEquals("P", mol.getConnectedAtomsList(atom).get(0).getSymbol());
443 assertEquals("N", mol.getConnectedAtomsList(atom).get(1).getSymbol());
444 }
445 }
446 //DenoptimIO.writeGraphToSDF(new File("/tmp/g4.sdf"), g4, false, true, logger, rng);
447 }
448
449//------------------------------------------------------------------------------
450
451}
Class defining a space of building blocks.
void setAPclassBasedApproach(boolean useAPC)
Set the fragment space to behave according to APClass-based approach.
Parameters defining the fragment space.
static final APClass RCACLASSPLUS
Conventional class of attachment points on ring-closing vertexes.
Definition: APClass.java:85
static final APClass RCACLASSMINUS
Conventional class of attachment points on ring-closing vertexes.
Definition: APClass.java:92
static APClass make(String ruleAndSubclass)
Creates an APClass if it does not exist already, or returns the reference to the existing instance.
Definition: APClass.java:164
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:104
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1391
void addRing(Ring ring)
Definition: DGraph.java:1304
void addEdge(Edge edge)
Adds the edge to the list of edges belonging to this graph.
Definition: DGraph.java:1295
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.
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
void addAP(int atomPositionNumber)
Adds an attachment point with a dummy APClass.
Definition: Fragment.java:343
void addBond(IBond bond)
Definition: Fragment.java:871
Fragment clone()
Returns a deep copy of this fragments.
Definition: Fragment.java:733
void addAtom(IAtom atom)
Definition: Fragment.java:836
void projectAPsToProperties()
Finds the DENOPTIMAttachmentPoint objects defined as properties of the atoms in this container,...
Definition: Fragment.java:693
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
void setVertexId(long vertexId2)
Definition: Vertex.java:281
void setBuildingBlockType(Vertex.BBType buildingBlockType)
Definition: Vertex.java:325
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:1007
static Vertex newVertexFromLibrary(int bbId, Vertex.BBType bbt, FragmentSpace fragSpace)
Builds a new molecular fragment kind of vertex.
Definition: Vertex.java:214
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 int getDimensions(IAtomContainer mol)
Determines the dimensionality of the given chemical object.
Tool to generate random numbers and random decisions.
Definition: Randomizer.java:35
Possible chemical bond types an edge can represent.
Definition: Edge.java:305
The type of building block.
Definition: Vertex.java:86