package org.nextprot.api.core.utils.graph;
import grph.path.Path;
import org.junit.Assert;
import org.junit.Test;
import org.nextprot.api.commons.constants.TerminologyCv;
import org.nextprot.api.core.domain.CvTerm;
import org.nextprot.api.core.service.TerminologyService;
import org.nextprot.api.core.test.base.CoreUnitBaseTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ActiveProfiles({"dev","cache"})
public class OntologyDAGTest extends CoreUnitBaseTest {
@Autowired
private TerminologyService terminologyService;
@Test
public void shouldCreateValidGeneOntologyGraph() throws Exception {
OntologyDAG graph = new OntologyDAG(TerminologyCv.GoMolecularFunctionCv, terminologyService);
Assert.assertEquals(TerminologyCv.GoMolecularFunctionCv, graph.getTerminologyCv());
Assert.assertEquals(10543, graph.countNodes());
Assert.assertEquals(12797, graph.countEdgesFromTransientGraph());
Assert.assertTrue(graph.isTransientGraphAvailable());
}
@Test
public void nodeGO0005488ShouldHaveChildren() throws Exception {
OntologyDAG graph = new OntologyDAG(TerminologyCv.GoMolecularFunctionCv, terminologyService);
long cvId = graph.getCvTermIdByAccession("GO:0005488");
Assert.assertEquals(50, graph.getChildrenFromTransientGraph(cvId).length);
CvTerm cvTerm = terminologyService.findCvTermByAccession(graph.getCvTermAccessionById(cvId));
Assert.assertEquals(cvTerm.getChildAccession().size(), graph.getChildrenFromTransientGraph(cvId).length);
Assert.assertTrue(Arrays.stream(graph.getChildrenFromTransientGraph(cvId)).boxed()
.map(graph::getCvTermAccessionById).collect(Collectors.toSet()).contains("GO:0030246"));
Assert.assertTrue(Arrays.stream(graph.getChildrenFromTransientGraph(cvId)).boxed()
.map(graph::getCvTermAccessionById).collect(Collectors.toSet()).contains("GO:0001871"));
}
@Test
public void nodeGO0005488ShouldHaveOneParent() throws Exception {
OntologyDAG graph = new OntologyDAG(TerminologyCv.GoMolecularFunctionCv, terminologyService);
long cvId = graph.getCvTermIdByAccession("GO:0005488");
Assert.assertEquals(1, graph.getParentsFromTransientGraph(cvId).length);
Assert.assertTrue(Arrays.stream(graph.getParentsFromTransientGraph(cvId)).boxed()
.map(graph::getCvTermAccessionById).collect(Collectors.toSet()).contains("GO:0003674"));
}
@Test
public void nodeGO0000006ShouldBeALeaf() throws Exception {
OntologyDAG graph = new OntologyDAG(TerminologyCv.GoMolecularFunctionCv, terminologyService);
long cvId = graph.getCvTermIdByAccession("GO:0000006");
Assert.assertEquals(0, graph.getChildrenFromTransientGraph(cvId).length);
}
@Test
public void geneOntologyShouldContainOneRoot() throws Exception {
OntologyDAG graph = new OntologyDAG(TerminologyCv.GoMolecularFunctionCv, terminologyService);
Stream<Long> roots = graph.getRoots();
Assert.assertEquals(1, roots.count());
String rootAccession = graph.getRoots()
.map(graph::getCvTermAccessionById)
.collect(Collectors.toList())
.get(0);
Assert.assertEquals("GO:0003674", rootAccession);
}
@Test
public void GO0005488shouldBeAncestorOfGO0005488() throws Exception {
OntologyDAG graph = new OntologyDAG(TerminologyCv.GoMolecularFunctionCv, terminologyService);
long ancestorId = graph.getCvTermIdByAccession("GO:0005488");
long descendantId = graph.getCvTermIdByAccession("GO:0051378");
Assert.assertTrue(graph.isAncestorOf(ancestorId, descendantId));
Assert.assertTrue(graph.isAncestorOfSlow(ancestorId, descendantId));
Assert.assertTrue(graph.isChildOf(descendantId, ancestorId));
}
@Test
public void roudoudouShouldNotExistInOntology() throws Exception {
OntologyDAG graph = new OntologyDAG(TerminologyCv.GoMolecularFunctionCv, terminologyService);
Assert.assertFalse(graph.hasCvTermAccession("roudoudou"));
}
private void benchmarkingPrecomputations(TerminologyCv terminologyCv, boolean both) throws OntologyDAG.NotFoundInternalGraphException {
System.err.println("Timing isAncestorOf() for all paths of "+terminologyCv+" graph:");
OntologyDAG graph = new OntologyDAG(terminologyCv, terminologyService);
Collection<Path> allPaths = graph.getAllPathsFromTransientGraph();
long precomputationExecTime = 0;
long normalExecTime = 0;
Instant t1 = Instant.now();
for (Path path : allPaths) {
graph.isAncestorOf(path.getSource(), path.getDestination());
}
precomputationExecTime = ChronoUnit.MILLIS.between(t1, Instant.now());
System.err.println("with precomputations: "+precomputationExecTime+" ms");
if (both) {
t1 = Instant.now();
for (Path path : allPaths) {
graph.isAncestorOfSlow(path.getSource(), path.getDestination());
}
normalExecTime = ChronoUnit.MILLIS.between(t1, Instant.now());
System.err.println("without precomputations: "+normalExecTime+ " ms");
// 1232024 ms (20')
}
if (both) {
System.err.println("precomputation speed up: x" + (normalExecTime / precomputationExecTime));
// x18954
}
}
}