$darkmode
DENOPTIM
FragmentSpaceTest.java
Go to the documentation of this file.
1package denoptim.fragspace;
2
3import static org.junit.jupiter.api.Assertions.assertEquals;
4import static org.junit.jupiter.api.Assertions.assertTrue;
5
6/*
7 * DENOPTIM
8 * Copyright (C) 2019 Marco Foscato <marco.foscato@uib.no>
9 *
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published
12 * by the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
19 *
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24import java.io.File;
25import java.util.ArrayList;
26import java.util.Arrays;
27import java.util.HashMap;
28import java.util.HashSet;
29import java.util.List;
30import java.util.Map;
31import java.util.Random;
32import java.util.function.Supplier;
33import java.util.stream.Collectors;
34import java.util.stream.IntStream;
35
36import javax.vecmath.Point3d;
37
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;
47
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;
66
74{
75 private static final String SEP = System.getProperty("file.separator");
76
77 @TempDir
78 static File tempDir;
79
80 private final Random rng = new Random();
81
82 private static final int APSUBRULE = 0;
83
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";
93
94 private static final BBType BBTFRAG = BBType.FRAGMENT;
95
96 private static APClass APCS;
97 private static APClass APC1;
98 private static APClass APC2;
99 private static APClass APC3;
100 private static APClass APC4;
101 private static APClass APC5;
102 private static APClass APC6;
103 private static APClass APCC1;
104 private static APClass APCC2;
105
106//------------------------------------------------------------------------------
107
109 {
110 assertTrue(tempDir.isDirectory(),"Should be a directory ");
111
112 try
113 {
123 } catch (DENOPTIMException e)
124 {
125 //This will not happen
126 }
127
128 String rootName = tempDir.getAbsolutePath() + SEP;
129
130 ArrayList<Vertex> fragLib = new ArrayList<Vertex>();
131 Fragment frg1 = new Fragment();
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}));
135 frg1.addAtom(a1);
136 frg1.addAtom(a2);
137 frg1.addAtom(a3);
138 frg1.addBond(new Bond(a1, a2));
139 frg1.addBond(new Bond(a2, a3));
140 frg1.addAPOnAtom(a3, APC1, new Point3d(new double[]{0.0, 2.2, 3.3}));
141 frg1.addAPOnAtom(a3, APC1, new Point3d(new double[]{0.0, 0.0, 3.3}));
142 frg1.addAPOnAtom(a3, APC2, new Point3d(new double[]{0.0, 0.0, 1.1}));
143 frg1.addAPOnAtom(a1, APC3, new Point3d(new double[]{3.0, 0.0, 3.3}));
145 fragLib.add(frg1);
146
147 Fragment frg2 = new Fragment();
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}));
150 frg2.addAtom(a21);
151 frg2.addAtom(a22);
152 frg2.addBond(new Bond(a21, a22));
153 frg2.addAPOnAtom(a22, APC2, new Point3d(new double[]{0.0, 2.2, 3.3}));
154 frg2.addAPOnAtom(a22, APC2, new Point3d(new double[]{0.0, 0.0, 3.3}));
156 fragLib.add(frg2);
157
158 Fragment frg3 = new Fragment();
159 Atom a31 = new Atom("P", new Point3d(new double[]{0.0, 1.1, 2.2}));
160 frg3.addAtom(a31);
161 frg3.addAPOnAtom(a31, APC1, new Point3d(new double[]{0.0, 2.2, 3.3}));
162 frg3.addAPOnAtom(a31, APC2, new Point3d(new double[]{0.0, 0.0, 3.3}));
163 frg3.addAPOnAtom(a31, APC3, new Point3d(new double[]{0.0, 0.0, 1.1}));
165 fragLib.add(frg3);
166
167 Fragment frg8 = new Fragment();
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}));
171 frg8.addAtom(a81);
172 frg8.addAtom(a82);
173 frg8.addAtom(a83);
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}));
184 fragLib.add(frg8);
185
186 String fragLibFile = rootName + "frags.sdf";
187 DenoptimIO.writeVertexesToSDF(new File(fragLibFile), fragLib, false);
188
189 ArrayList<Vertex> scaffLib = new ArrayList<Vertex>();
190 Fragment scaf0 = new Fragment();
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}));
194 scaf0.addAtom(a41);
195 scaf0.addAtom(a42);
196 scaf0.addAtom(a43);
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}));
204 scaffLib.add(scaf0);
205
206 Fragment scaf1 = new Fragment();
207 Atom a51 = new Atom("Zn", new Point3d(new double[]{5.0, 1.1, 2.2}));
208 scaf1.addAtom(a51);
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}));
213 scaffLib.add(scaf1);
214
215 String scaffLibFile = rootName + "scaff.sdf";
216 DenoptimIO.writeVertexesToSDF(new File(scaffLibFile), scaffLib, false);
217
218 ArrayList<Vertex> cappLib = new ArrayList<Vertex>();
219 Fragment cap1 = new Fragment();
220 Atom a61 = new Atom("H", new Point3d(new double[]{10.0, 1.1, 2.2}));
221 cap1.addAtom(a61);
222 cap1.addAPOnAtom(a61, APCC1, new Point3d(new double[]{13.0, 0.0, 3.3}));
224 cappLib.add(cap1);
225
226 Fragment cap2 = new Fragment();
227 Atom a71 = new Atom("Cl", new Point3d(new double[]{10.0, 1.1, 2.2}));
228 cap2.addAtom(a71);
229 cap2.addAPOnAtom(a71, APCC2, new Point3d(new double[]{13.0, 0.0, 3.3}));
231 cappLib.add(cap2);
232
233 String capLibFile = rootName + "caps.sdf";
234 DenoptimIO.writeVertexesToSDF(new File(capLibFile), cappLib, false);
235
236 HashMap<APClass,ArrayList<APClass>> cpMap =
237 new HashMap<APClass,ArrayList<APClass>>();
238 ArrayList<APClass> lst1 = new ArrayList<APClass>();
239 lst1.add(APC1);
240 lst1.add(APC2);
241 cpMap.put(APCS, lst1);
242 ArrayList<APClass> lst2 = new ArrayList<APClass>();
243 lst2.add(APC2);
244 cpMap.put(APC1, lst2);
245 ArrayList<APClass> lst3 = new ArrayList<APClass>();
246 lst3.add(APC2);
247 lst3.add(APC3);
248 cpMap.put(APC2, lst3);
249
250 HashMap<APClass,APClass> capMap = new HashMap<APClass,APClass>();
251 capMap.put(APCS, APCC2);
252 capMap.put(APC1, APCC1);
253 capMap.put(APC2, APCC1);
254
255 HashSet<APClass> ends = new HashSet<APClass>();
256 ends.add(APC3);
257
258 String cpmFile = rootName + "cpm.dat";
259 DenoptimIO.writeCompatibilityMatrix(cpmFile, cpMap, capMap,ends);
260
261 /*
262 //Just in case one day we want to have also an RC-CPMap
263 HashMap<APClass,ArrayList<APClass>> rcCpMap =
264 new HashMap<APClass,ArrayList<APClass>>();
265 */
266
268 new FragmentSpace(fsp, scaffLibFile, fragLibFile,
269 capLibFile, cpmFile);
270 return fsp;
271 }
272
273//-----------------------------------------------------------------------------
274
275 @Test
276 public void testSymmetry() throws Exception
277 {
279 assertTrue(fsp.getFragmentSpace().isDefined(),"FragmentSpace is defined");
282 fsp.getFragmentSpace());
283
284 assertEquals(2,v.getSymmetricAPSets().size(),
285 "Number of symmetric sets of APs");
286
287 Map<APClass,Integer> expectedCount = new HashMap<APClass,Integer>();
288 expectedCount.put(APC4, 2);
289 expectedCount.put(APC5, 3);
290 for (SymmetricAPs ss : v.getSymmetricAPSets())
291 {
292 APClass apc = ss.get(0).getAPClass();
293 assertEquals(expectedCount.get(apc),ss.size(),
294 "Number of APs in symmetric set for APClass "+apc);
295 }
296 }
297
298//-----------------------------------------------------------------------------
299
300 @Test
301 public void testGetFragsWithAPClass() throws Exception
302 {
305 assertTrue(fs.isDefined(),"FragmentSpace is defined");
306 ArrayList<IdFragmentAndAP> l = fs.getFragsWithAPClass(APC2);
307 assertEquals(4,l.size(),"Wrong size of AP IDs with given APClass.");
308
309 int i = -1;
310 for (IdFragmentAndAP id : l)
311 {
312 i++;
314 id.getVertexMolId(), id.getVertexMolType(), fs);
315 assertEquals(APC2, v.getAP(id.getApId()).getAPClass(),
316 "APClass of "+i);
317 }
318 }
319
320//-----------------------------------------------------------------------------
321
322 @Test
323 public void testGetFragAPsCompatibleWithClass() throws Exception
324 {
325
328 assertTrue(fs.isDefined(),"FragmentSpace is defined");
329 ArrayList<IdFragmentAndAP> lst = fs.getFragAPsCompatibleWithClass(APC1);
330
331 assertEquals(4,lst.size(),"Size of compatible APs list is wrong.");
332
333 int i = -1;
334 for (IdFragmentAndAP id : lst)
335 {
336 i++;
338 id.getVertexMolId(), id.getVertexMolType(), fs);
339 AttachmentPoint ap = v.getAP(id.getApId());
340 assertTrue(APC1.isCPMapCompatibleWith(ap.getAPClass(), fs),
341 "Incompatible choice at "+i);
342 }
343 }
344
345//------------------------------------------------------------------------------
346
347 @Test
348 public void testGetFragAPsCompatibleWithTheseAPs() throws Exception
349 {
352 assertTrue(fs.isDefined(),"FragmentSpace is defined");
353 IdFragmentAndAP src1 = new IdFragmentAndAP(-1,2,BBTFRAG,0,-1,-1);
354 IdFragmentAndAP src2 = new IdFragmentAndAP(-1,2,BBTFRAG,1,-1,-1);
355 ArrayList<IdFragmentAndAP> srcAPs = new ArrayList<IdFragmentAndAP>();
356 srcAPs.add(src1);
357 srcAPs.add(src2);
359 src1.getVertexMolId(), src1.getVertexMolType(), fs);
360 APClass src1APC = src1V.getAP(src1.getApId()).getAPClass();
362 src2.getVertexMolId(), src2.getVertexMolType(), fs);
363 APClass src2APC = src2V.getAP(src2.getApId()).getAPClass();
364
365
366 /*
367 System.out.println("SRC1 "+fs.getAPClassForFragment(src1)+" => "
368 +fs.getCompatibleAPClasses(fs.getAPClassForFragment(src1)));
369 System.out.println("SRC2 "+fs.getAPClassForFragment(src2)+" => "
370 +fs.getCompatibleAPClasses(fs.getAPClassForFragment(src2)));
371 System.out.println("Frags with SRC1: "+fs.getFragAPsCompatibleWithClass(
372 fs.getAPClassForFragment(src1)));
373 System.out.println("Frags with SRC2: "+fs.getFragAPsCompatibleWithClass(
374 fs.getAPClassForFragment(src2)));
375 */
376
377 ArrayList<IdFragmentAndAP> lst = fs.getFragAPsCompatibleWithTheseAPs(
378 srcAPs);
379
380 assertEquals(4,lst.size(),"Size of compatible APs list is wrong.");
381
382 int i = -1;
383 for (IdFragmentAndAP id : lst)
384 {
385 i++;
387 id.getVertexMolId(), id.getVertexMolType(), fs);
388 AttachmentPoint ap = v.getAP(id.getApId());
389 assertTrue(src1APC.isCPMapCompatibleWith(ap.getAPClass(), fs)
390 || src2APC.isCPMapCompatibleWith(ap.getAPClass(), fs),
391 "Incompatible choice at "+i);
392 }
393 }
394
395//------------------------------------------------------------------------------
396
397 @Test
398 public void testGetFragmentsCompatibleWithTheseAPs() throws Exception
399 {
402 assertTrue(fs.isDefined(),"FragmentSpace is defined");
403 IdFragmentAndAP src1 = new IdFragmentAndAP(-1,2,BBTFRAG,0,-1,-1);
404 IdFragmentAndAP src2 = new IdFragmentAndAP(-1,2,BBTFRAG,1,-1,-1);
405 ArrayList<IdFragmentAndAP> srcAPs = new ArrayList<IdFragmentAndAP>();
406 srcAPs.add(src1);
407 srcAPs.add(src2);
408
409 ArrayList<Vertex> lst = fs.getFragmentsCompatibleWithTheseAPs(
410 srcAPs);
411
412 assertEquals(3,lst.size(),"Wrong number of compatible fragments.");
413 }
414
415//------------------------------------------------------------------------------
416
417 @Test
418 public void testGetRCVsForAPClass() throws Exception
419 {
422
423 APClass apcA = APClass.make("A",0);
424 APClass apcB = APClass.make("B",0);
425
426 HashMap<APClass,ArrayList<APClass>> cpMap =
427 new HashMap<APClass,ArrayList<APClass>>();
428 ArrayList<APClass> lstA = new ArrayList<APClass>();
429 lstA.add(rcvP);
430 cpMap.put(apcA, lstA);
431 ArrayList<APClass> lstB = new ArrayList<APClass>();
432 lstB.add(rcvP);
433 lstB.add(rcvM);
434 cpMap.put(apcB, lstB);
435
436 HashMap<APClass,ArrayList<APClass>> rcCPMap =
437 new HashMap<APClass,ArrayList<APClass>>();
438 ArrayList<APClass> lstC = new ArrayList<APClass>();
439 lstC.add(apcB);
440 rcCPMap.put(apcA, lstC);
441
442 ArrayList<Vertex> fragments = new ArrayList<Vertex>();
443
444 Fragment frg2 = new Fragment();
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}));
447 frg2.addAtom(a21);
448 frg2.addAtom(a22);
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}));
452 fragments.add(frg2);
453
454 Fragment rcv1 = new Fragment();
455 Atom at1 = new PseudoAtom(RingClosingAttractor.RCALABELPERAPCLASS.get(rcvP),
456 new Point3d());
457 rcv1.addAtom(at1);
458 rcv1.addAP(0, rcvP, new Point3d(1.0, 0, 0));
459 rcv1.setAsRCV(true);
460 fragments.add(rcv1);
461
462 Fragment rcv2 = new Fragment();
463 Atom at2 = new PseudoAtom(RingClosingAttractor.RCALABELPERAPCLASS.get(rcvM),
464 new Point3d());
465 rcv2.addAtom(at2);
466 rcv2.addAP(0, rcvM, new Point3d(-1.0, 0, 0));
467 rcv2.setAsRCV(true);
468 fragments.add(rcv2);
469
470 Fragment rcv3 = new Fragment();
471 Atom at3 = new PseudoAtom(RingClosingAttractor.RCALABELPERAPCLASS.get(rcvM),
472 new Point3d());
473 rcv3.addAtom(at3);
474 rcv3.addAP(0, rcvM, new Point3d(-2.0, 0, 0));
475 rcv3.setAsRCV(true);
476 fragments.add(rcv3);
477
478 HashMap<APClass,APClass> capMap = new HashMap<APClass,APClass>();
479 HashSet<APClass> forbEnds = new HashSet<APClass>();
480
482 FragmentSpace fs = new FragmentSpace(fsp,
483 new ArrayList<Vertex>(), // scaffolds
484 fragments,
485 new ArrayList<Vertex>(), // caps
486 cpMap, capMap, forbEnds, cpMap);
488
489 List<Vertex> rcvs1 = fs.getRCVsForAPClass(apcA);
490 assertEquals(1, rcvs1.size());
491 assertEquals(rcvP, rcvs1.get(0).getAP(0).getAPClass());
492 List<Vertex> rcvs2 = fs.getRCVsForAPClass(apcB);
493 assertEquals(3, rcvs2.size());
494 int countP = 0;
495 int countM = 0;
496 for (Vertex rcv : rcvs2)
497 {
498 if (rcvP == rcv.getAP(0).getAPClass())
499 countP++;
500 else
501 countM++;
502 }
503 assertEquals(1, countP);
504 assertEquals(2, countM);
505 List<Vertex> rcvs3 = fs.getRCVsForAPClass(APClass.make("C",0));
506 assertEquals(0, rcvs3.size());
507 }
508
509//------------------------------------------------------------------------------
510
511 @Test
512 public void testGetRCVsWithAPClass() throws Exception
513 {
516
517 APClass apcA = APClass.make("A",0);
518 APClass apcB = APClass.make("B",0);
519
520 HashMap<APClass,ArrayList<APClass>> cpMap =
521 new HashMap<APClass,ArrayList<APClass>>();
522 ArrayList<APClass> lstA = new ArrayList<APClass>();
523 lstA.add(rcvP);
524 cpMap.put(apcA, lstA);
525 ArrayList<APClass> lstB = new ArrayList<APClass>();
526 lstB.add(rcvP);
527 lstB.add(rcvM);
528 cpMap.put(apcB, lstB);
529
530 HashMap<APClass,ArrayList<APClass>> rcCPMap =
531 new HashMap<APClass,ArrayList<APClass>>();
532 ArrayList<APClass> lstC = new ArrayList<APClass>();
533 lstC.add(apcB);
534 rcCPMap.put(apcA, lstC);
535
536 ArrayList<Vertex> fragments = new ArrayList<Vertex>();
537
538 Fragment frg2 = new Fragment();
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}));
541 frg2.addAtom(a21);
542 frg2.addAtom(a22);
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}));
546 fragments.add(frg2);
547
548 Fragment rcv1 = new Fragment();
549 Atom at1 = new PseudoAtom(RingClosingAttractor.RCALABELPERAPCLASS.get(rcvP),
550 new Point3d());
551 rcv1.addAtom(at1);
552 rcv1.addAP(0, rcvP, new Point3d(1.0, 0, 0));
553 rcv1.setAsRCV(true);
554 fragments.add(rcv1);
555
556 Fragment rcv2 = new Fragment();
557 Atom at2 = new PseudoAtom(RingClosingAttractor.RCALABELPERAPCLASS.get(rcvM),
558 new Point3d());
559 rcv2.addAtom(at2);
560 rcv2.addAP(0, rcvM, new Point3d(-1.0, 0, 0));
561 rcv2.setAsRCV(true);
562 fragments.add(rcv2);
563
564 HashMap<APClass,APClass> capMap = new HashMap<APClass,APClass>();
565 HashSet<APClass> forbEnds = new HashSet<APClass>();
566
568 FragmentSpace fs = new FragmentSpace(fsp,
569 new ArrayList<Vertex>(), // scaffolds
570 fragments,
571 new ArrayList<Vertex>(), // caps
572 cpMap, capMap, forbEnds, cpMap);
574
575 List<Vertex> rcvs1 = fs.getRCVsWithAPClass(rcvP);
576 assertEquals(1, rcvs1.size());
577 assertTrue(rcv1.sameAs(rcvs1.get(0)));
578
579 List<Vertex> rcvs2 = fs.getRCVsWithAPClass(rcvM);
580 assertEquals(1, rcvs2.size());
581 assertTrue(rcv2.sameAs(rcvs2.get(0)));
582 }
583
584//------------------------------------------------------------------------------
585
596 @Test
597 public void testFusedRingAddedToFragmentLibrary() throws Exception
598 {
600 fsp.fragmentLibFile = "dummyFilename_DenoptimTest_Frag";
601 fsp.scaffoldLibFile = "dummyFilename_DenoptimTest_Scaff";
603
604 TestCase testCase = getTestCase();
605
606 List<Vertex> fragLib = fs.getFragmentLibrary();
607 fragLib.clear();
608
610
611 //Cleanup tmp files
614
615 assertEquals(1, fragLib.size());
616 Vertex actual = fragLib.get(0);
617 StringBuilder sb = new StringBuilder();
618 assertTrue(testCase.expected.sameAs(actual, sb),
619 "Problem is "+sb.toString());
620 }
621
622//------------------------------------------------------------------------------
623
629 @Test
630 public void testFusedRingAddedToScaffoldLibrary() throws Exception
631 {
633 fsp.fragmentLibFile = "dummyFilename_DenoptimTest_Frag";
634 fsp.scaffoldLibFile = "dummyFilename_DenoptimTest_Scaff";
636 TestCase testCase = getTestCase();
637 testCase.graph.getVertexList().get(0)
638 .setBuildingBlockType(BBType.SCAFFOLD);
640 testCase.expected.getInnerGraph().getVertexList().get(0)
641 .setBuildingBlockType(BBType.SCAFFOLD);
642
643 List<Vertex> scaffLib = fs.getScaffoldLibrary();
644 scaffLib.clear();
645
647
648 //Cleanup tmp files
651
652 assertEquals(1, scaffLib.size());
653 Vertex actual = scaffLib.get(0);
654 assertTrue(testCase.expected.sameAs(actual, new StringBuilder()));
655 }
656
657//------------------------------------------------------------------------------
658
659 @Test
661 {
663 fsp.fragmentLibFile = "dummyFilename_DenoptimTest_Frag";
664 fsp.scaffoldLibFile = "dummyFilename_DenoptimTest_Scaff";
666 TestCase testCase = getTestCase();
667 final int TRY_ADDING = 10;
668 List<DGraph> sameGraphs = IntStream
669 .range(0, TRY_ADDING)
670 .mapToObj(i -> testCase.graph.clone())
671 .peek(t -> t.renumberGraphVertices())
672 .collect(Collectors.toList());
673
674 List<Vertex> fragLib = fs.getFragmentLibrary();
675 fragLib.clear();
676
677 for (DGraph g : sameGraphs) {
679 }
680
681 //Cleanup tmp files
684
685 assertEquals(1, fragLib.size());
686 }
687
688//------------------------------------------------------------------------------
689
700 {
701 DGraph g = new DGraph();
703 c3 = getCarbonVertex(), c4 = getCarbonVertex(),
704 c5 = getCarbonVertex();
705
706 Vertex rcv14 = getRCV(), rcv41 = getRCV(), rcv45 = getRCV(),
707 rcv54 = getRCV();
708
709 g.addVertex(c1);
710 g.appendVertexOnAP(c1.getAP(0), c2.getAP(0));
711 g.appendVertexOnAP(c1.getAP(1), rcv14.getAP(0));
712 g.appendVertexOnAP(c2.getAP(1), c3.getAP(0));
713 g.appendVertexOnAP(c2.getAP(2), c5.getAP(0));
714 g.appendVertexOnAP(c2.getAP(3), c4.getAP(0));
715 g.appendVertexOnAP(c4.getAP(1), rcv41.getAP(0));
716 g.appendVertexOnAP(c4.getAP(2), rcv45.getAP(0));
717 g.appendVertexOnAP(c5.getAP(1), rcv54.getAP(0));
718
719 Ring r124 = new Ring(Arrays.asList(rcv14, c1, c2, c4,
720 rcv41));
721 Ring r425 = new Ring(Arrays.asList(rcv45, c4, c2, c5,
722 rcv54));
723 g.addRing(r124);
724 g.addRing(r425);
725
727
728 Template t = getExpectedTemplate(g, c3);
729
730 return new TestCase(g, t);
731 }
732
733//------------------------------------------------------------------------------
734
736 Vertex c3) throws DENOPTIMException {
737 DGraph innerGraph = g.clone();
738 innerGraph.renumberGraphVertices();
739 Vertex c3Inner = innerGraph.getVertexAtPosition(g
740 .indexOfVertexWithID(c3.getVertexId()));
741 innerGraph.removeVertex(c3Inner);
742
744 t.setInnerGraph(innerGraph);
746 return t;
747 }
748
749//------------------------------------------------------------------------------
750
752 {
753 IChemObjectBuilder builder = DefaultChemObjectBuilder.getInstance();
754 IAtom carbon = builder.newAtom();
755 carbon.setSymbol("C");
756 IAtomContainer mol = builder.newAtomContainer();
757 mol.addAtom(carbon);
758 Fragment v = new Fragment(
760 mol,
762 for (int i = 0; i < 4; i++) {
763 v.addAP(0, APC1, getRandomVector());
764 }
765 return v;
766 }
767
768//------------------------------------------------------------------------------
769
771 {
772 IChemObjectBuilder builder = DefaultChemObjectBuilder
773 .getInstance();
774 IAtomContainer dummyMol = builder.newAtomContainer();
775 IAtom dummyAtom = builder.newAtom();
776 dummyMol.addAtom(dummyAtom);
777 Fragment rcv = new Fragment(
779 dummyMol,
781 true);
782 rcv.addAP(0, APC1, getRandomVector());
783 return rcv;
784 }
785
786//------------------------------------------------------------------------------
787
788 private Point3d getRandomVector() {
789 int precision = 10 * 10 * 10 * 10;
790
791 Supplier<Double> randomCoord = () ->
792 (double) (Math.round(rng.nextDouble() * (double) precision)) /
793 ((double) precision);
794
795 return new Point3d(randomCoord.get(), randomCoord.get(),
796 randomCoord.get());
797 }
798
799//------------------------------------------------------------------------------
800
801 private static final class TestCase {
804
806 this.graph = g;
807 this.expected = expected;
808 }
809 }
810
811//------------------------------------------------------------------------------
812
835 @Test
836 public void testUseWholeMolGeometryForExtractedTemplates() throws Exception
837 {
839 fsp.fragmentLibFile = "dummyFilename_DenoptimTest_Frag";
840 fsp.scaffoldLibFile = "dummyFilename_DenoptimTest_Scaff";
842 Fragment scaf = new Fragment();
843 IAtom s1 = new Atom("C", new Point3d(0,0,0));
844 scaf.addAtom(s1);
845 scaf.addAPOnAtom(s1, APC2, new Point3d(1,1,0));
846 scaf.addAPOnAtom(s1, APC3, new Point3d(1,-1,0));
847 scaf.addAPOnAtom(s1, APC4, new Point3d(-1,-1,0));
849
851 int sId = fs.getScaffoldLibrary().size() - 1;
852
853 Fragment frg = new Fragment();
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));
857 frg.addAtom(a1);
858 frg.addAtom(a2);
859 frg.addAtom(a3);
860 frg.addBond(new Bond(a1, a2));
861 frg.addBond(new Bond(a2, a3));
862 frg.addAPOnAtom(a1, APC2, new Point3d(1,1,2));
863 frg.addAPOnAtom(a2, APC3, new Point3d(1,-1,0));
864 frg.addAPOnAtom(a3, APC4, new Point3d(-1,-1,0));
866
868 int bbId = fs.getFragmentLibrary().size() - 1;
869
870 Fragment rcv = new Fragment();
871 IAtom a4 = new PseudoAtom("ATN", new Point3d(0,0,0));
872 rcv.addAtom(a4);
873 rcv.addAPOnAtom(a4, APClass.make("ATneutral",0), new Point3d(1,0,0));
875 rcv.setAsRCV(true);
876
878 int rcvId = fs.getFragmentLibrary().size() - 1;
879
880 DGraph wholeGraph = new DGraph();
881 Vertex v1 = fs.getVertexFromLibrary(BBTFRAG, bbId);
882 Vertex v2 = fs.getVertexFromLibrary(BBTFRAG, bbId);
883 Vertex v3 = fs.getVertexFromLibrary(BBTFRAG, bbId);
884 Vertex v4 = fs.getVertexFromLibrary(BBTFRAG, bbId);
885 Vertex v5 = fs.getVertexFromLibrary(BBTFRAG, bbId);
887 Vertex v7 = fs.getVertexFromLibrary(BBTFRAG, bbId);
888 Vertex v8 = fs.getVertexFromLibrary(BBTFRAG, bbId);
889 Vertex v9 = fs.getVertexFromLibrary(BBTFRAG, bbId);
890 Vertex v10 = fs.getVertexFromLibrary(BBTFRAG, rcvId);
891 Vertex v11 = fs.getVertexFromLibrary(BBTFRAG, rcvId);
892 Vertex v12 = fs.getVertexFromLibrary(BBTFRAG, rcvId);
893 Vertex v13 = fs.getVertexFromLibrary(BBTFRAG, rcvId);
898
899 // Disordered... just for the fun of it. Still, do not change it further
900 // as we need to wholeMol to be created consistently
901 wholeGraph.addVertex(v7);
902 wholeGraph.addVertex(v8);
903 wholeGraph.addVertex(v9);
904 wholeGraph.addVertex(v6);
905 wholeGraph.addVertex(v1);
906 wholeGraph.addVertex(v2);
907 wholeGraph.addVertex(v3);
908 wholeGraph.addVertex(v4);
909 wholeGraph.addVertex(v5);
910 wholeGraph.addVertex(v10);
911 wholeGraph.addVertex(v11);
912 wholeGraph.addVertex(v12);
913 wholeGraph.addVertex(v13);
914 wholeGraph.addVertex(c1);
915 wholeGraph.addVertex(c2);
916 wholeGraph.addVertex(c3);
917 wholeGraph.addVertex(c4);
918 wholeGraph.addEdge(new Edge(v6.getAP(0),v4.getAP(1),BondType.SINGLE));
919 wholeGraph.addEdge(new Edge(v6.getAP(1),v10.getAP(0),BondType.SINGLE));
920 wholeGraph.addEdge(new Edge(v4.getAP(0),v2.getAP(1),BondType.SINGLE));
921 wholeGraph.addEdge(new Edge(v2.getAP(0),v3.getAP(0),BondType.SINGLE));
922 wholeGraph.addEdge(new Edge(v3.getAP(1),v11.getAP(0),BondType.SINGLE));
923 wholeGraph.addEdge(new Edge(v2.getAP(2),v1.getAP(2),BondType.SINGLE));
924 wholeGraph.addEdge(new Edge(v6.getAP(2),v9.getAP(0),BondType.SINGLE));
925 wholeGraph.addEdge(new Edge(v9.getAP(1),v5.getAP(0),BondType.SINGLE));
926 wholeGraph.addEdge(new Edge(v5.getAP(1),v7.getAP(0),BondType.SINGLE));
927 wholeGraph.addEdge(new Edge(v5.getAP(2),v8.getAP(0),BondType.SINGLE));
928 wholeGraph.addEdge(new Edge(v7.getAP(1),v12.getAP(0),BondType.SINGLE));
929 wholeGraph.addEdge(new Edge(v8.getAP(2),v13.getAP(0),BondType.SINGLE));
930 wholeGraph.addEdge(new Edge(v3.getAP(2),c1.getAP(0),BondType.SINGLE));
931 wholeGraph.addEdge(new Edge(v4.getAP(2),c2.getAP(0),BondType.SINGLE));
932 wholeGraph.addEdge(new Edge(v7.getAP(2),c3.getAP(0),BondType.SINGLE));
933 wholeGraph.addEdge(new Edge(v8.getAP(1),c4.getAP(0),BondType.SINGLE));
934
935 wholeGraph.addRing(v10, v11, BondType.DOUBLE);
936 wholeGraph.addRing(v12, v13, BondType.DOUBLE);
937
939 fsp.getRandomizer());
940 IAtomContainer wholeMol = tb3d.convertGraphTo3DAtomContainer(
941 wholeGraph.clone(), true);
942
943 double r = 10;
944 for (int i=0; i<wholeMol.getAtomCount(); i++)
945 {
946 IAtom atm = wholeMol.getAtom(i);
947 if (atm instanceof PseudoAtom)
948 ((PseudoAtom) atm).setLabel("Du");
949 else
950 atm.setSymbol("P");
951 atm.setPoint3d(new Point3d(r*Math.cos(Math.toRadians(360/34 * i)),
952 r*Math.sin(Math.toRadians(360/34 * i)),0));
953 }
954
955 int szScafLibPre = fs.getScaffoldLibrary().size();
956 int szFragLibPre = fs.getFragmentLibrary().size();
957
958 String scafFile = tempDir.getAbsolutePath() + SEP + "newScaf.sdf";
959 String fragFile = tempDir.getAbsolutePath() + SEP + "newFrag.sdf";
960 fsp.scaffoldLibFile = scafFile;
961 fsp.fragmentLibFile = fragFile;
962
963 fs.addFusedRingsToFragmentLibrary(wholeGraph, true, true, wholeMol);
964
965 // NB: in here there is cloning of template with mol representation
966 assertEquals(szScafLibPre+1,fs.getScaffoldLibrary().size(),
967 "Size scaffolds library");
968 assertEquals(szFragLibPre+1,fs.getFragmentLibrary().size(),
969 "Size fragments library");
970
971 Vertex newScaff = fs.getVertexFromLibrary(
972 BBType.SCAFFOLD,szScafLibPre); // szScafLibPre+1-1
973 assertEquals(4,newScaff.getAttachmentPoints().size(),
974 "#APs on new scaffold");
975 int nP = 0;
976 for (IAtom a : newScaff.getIAtomContainer().atoms())
977 {
978 if ("P".equals(MoleculeUtils.getSymbolOrLabel(a)))
979 nP++;
980 }
981 assertEquals(10,nP,"#P in new scaffold");
982
983 Vertex newFrag = fs.getVertexFromLibrary(
984 BBType.FRAGMENT,szFragLibPre); // szFragLibPre+1-1
985 assertEquals(3,newFrag.getAttachmentPoints().size(),
986 "#APs on new fragment");
987 nP = 0;
988 for (IAtom a : newFrag.getIAtomContainer().atoms())
989 {
990 if ("P".equals(MoleculeUtils.getSymbolOrLabel(a)))
991 nP++;
992 }
993 assertEquals(9,nP,"#P in new fragment");
994
995 //Cleanup tmp files
998 }
999
1000//------------------------------------------------------------------------------
1001}
static void deleteFile(String fileName)
Delete the file.
Definition: FileUtils.java:256
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.
Unit test for fragment space.
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.
FragmentSpaceParameters buildFragmentSpace()
Template getExpectedTemplate(DGraph g, Vertex c3)
Data structure containing information that identifies a single AP of a vertex/fragment.
boolean isCPMapCompatibleWith(APClass other, FragmentSpace fragSpace)
Check compatibility as defined in the compatibility matrix considering this AP as source and the othe...
Definition: APClass.java:455
static final APClass RCACLASSPLUS
Conventional class of attachment points on ring-closing vertexes.
Definition: APClass.java:84
static final APClass RCACLASSMINUS
Conventional class of attachment points on ring-closing vertexes.
Definition: APClass.java:91
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:136
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.
Definition: DGraph.java:102
void addVertex(Vertex vertex)
Appends a vertex to this graph without creating any edge.
Definition: DGraph.java:1097
void removeVertex(Vertex vertex)
Remove a vertex from this graph.
Definition: DGraph.java:1119
Vertex getVertexAtPosition(int pos)
Returns the vertex that is in the given position of the list of vertices belonging to this graph.
Definition: DGraph.java:2514
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,...
Definition: DGraph.java:5776
List< Vertex > getVertexList()
Definition: DGraph.java:719
DGraph clone()
Returns almost "deep-copy" of this graph.
Definition: DGraph.java:3186
void renumberGraphVertices()
Reassign vertex IDs to all vertices of this graph.
Definition: DGraph.java:5283
void addRing(Ring ring)
Definition: DGraph.java:1030
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
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
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
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
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
This class represents the closure of a ring in a spanning tree.
Definition: Ring.java:40
A collection of AttachmentPoints that are related by a relation that we call "symmetry",...
void setInnerGraph(DGraph innerGraph)
Definition: Template.java:298
boolean sameAs(Template other, StringBuilder reason)
Compares this and another template ignoring vertex IDs.
Definition: Template.java:956
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
void setAsRCV(boolean isRCV)
Definition: Vertex.java:254
abstract List< AttachmentPoint > getAttachmentPoints()
void setBuildingBlockId(int buildingBlockId)
Definition: Vertex.java:291
abstract List< SymmetricAPs > getSymmetricAPSets()
void setBuildingBlockType(Vertex.BBType buildingBlockType)
Definition: Vertex.java:305
abstract IAtomContainer getIAtomContainer()
AttachmentPoint getAP(int i)
Get attachment point i on this vertex.
Definition: Vertex.java:920
static Vertex newVertexFromLibrary(int bbId, Vertex.BBType bbt, FragmentSpace fragSpace)
Builds a new molecular fragment kind of vertex.
Definition: Vertex.java:214
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.
Utilities for graphs.
Definition: GraphUtils.java:40
static synchronized long getUniqueVertexIndex()
Unique counter for the number of graph vertices generated.
Definition: GraphUtils.java:97
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.
Definition: Edge.java:303
The type of building block.
Definition: Vertex.java:86