From e9d9eb03874ebf08e27a502f341550025759c83b Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Thu, 5 Aug 2021 09:50:54 -0400 Subject: [PATCH 1/2] Do not create root MF annotations based on root BP annotations. --- .../legacy/sparql/GPADSPARQLExport.java | 56 +++++++++++-------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/legacy/sparql/GPADSPARQLExport.java b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/sparql/GPADSPARQLExport.java index 27e8175a..769f474c 100644 --- a/minerva-converter/src/main/java/org/geneontology/minerva/legacy/sparql/GPADSPARQLExport.java +++ b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/sparql/GPADSPARQLExport.java @@ -54,8 +54,8 @@ public class GPADSPARQLExport { private static final String BP = "http://purl.obolibrary.org/obo/GO_0008150"; private static final String CC = "http://purl.obolibrary.org/obo/GO_0005575"; private static final Set rootTerms = new HashSet<>(Arrays.asList(MF, BP, CC)); - private static final String inconsistentQuery = - "PREFIX rdf: " + + private static final String inconsistentQuery = + "PREFIX rdf: " + "PREFIX owl: " + "ASK WHERE { ?s rdf:type owl:Nothing . } "; @@ -107,7 +107,7 @@ public String exportGPAD(WorkingMemory wm, IRI modelIRI) throws InconsistentOnto Set annotations = getGPAD(wm, modelIRI); return new GPADRenderer(curieHandler, relationShorthandIndex).renderAll(annotations); } - + /* This is a bit convoluted in order to minimize redundant queries, for performance reasons. */ public Set getGPAD(WorkingMemory wm, IRI modelIRI) throws InconsistentOntologyException { Model model = ModelFactory.createDefaultModel(); @@ -121,25 +121,25 @@ public Set getGPAD(WorkingMemory wm, IRI modelIRI) throws Inconsistent //String modelID = model.listResourcesWithProperty(RDF.type, OWL.Ontology).mapWith(r -> curieHandler.getCuri(IRI.create(r.getURI()))).next(); String modelID = curieHandler.getCuri(modelIRI); ResultSet results = qe.execSelect(); - Set basicAnnotations = new HashSet<>(); + Set basicAnnotations = new HashSet<>(); while (results.hasNext()) { QuerySolution qs = results.next(); - BasicGPADData basicGPADData = new BasicGPADData(qs.getResource("pr").asNode(), IRI.create(qs.getResource("pr_type").getURI()), IRI.create(qs.getResource("rel").getURI()), qs.getResource("target").asNode(), IRI.create(qs.getResource("target_type").getURI())); + BasicGPADData basicGPADData = new BasicGPADData(qs.getResource("pr").asNode(), IRI.create(qs.getResource("pr_type").getURI()), IRI.create(qs.getResource("rel").getURI()), qs.getResource("target").asNode(), IRI.create(qs.getResource("target_type").getURI())); - /* See whether the query answer contains not-null blank nodes, which are only set if the matching subgraph - * contains the property ComplementOf. If we see such cases, we set the operator field as NOT so that NOT value - * can be printed in GPAD. */ + /* See whether the query answer contains not-null blank nodes, which are only set if the matching subgraph + * contains the property ComplementOf. If we see such cases, we set the operator field as NOT so that NOT value + * can be printed in GPAD. */ if (qs.getResource("blank_comp") != null) basicGPADData.setOperator(GPADOperatorStatus.NOT); basicAnnotations.add(basicGPADData); } qe.close(); - /* The bindings of ?pr_type, ?rel, ?target_type are candidate mappings or values for the final GPAD records + /* The bindings of ?pr_type, ?rel, ?target_type are candidate mappings or values for the final GPAD records * (i.e. not every mapping is used for building the final records of GPAD file; many of them are filtered out later). - * The mappings are - * ?pr_type: DB Object ID (2nd in GPAD), ?rel: Qualifier(3rd), ?target_type: GO ID(4th) + * The mappings are + * ?pr_type: DB Object ID (2nd in GPAD), ?rel: Qualifier(3rd), ?target_type: GO ID(4th) * The rest of fields in GPAD are then constructed by joining the candidate mappings with mappings describing evidences and so on. - * If the output of this exporter (i.e. GPAD files) does not contain the values you expect, + * If the output of this exporter (i.e. GPAD files) does not contain the values you expect, * dump the above "QuerySolution qs" variable and see whether they are included in the dump. */ Set possibleExtensions = possibleExtensions(basicAnnotations, model); Set statementsToExplain = new HashSet<>(); @@ -163,7 +163,7 @@ public Set getGPAD(WorkingMemory wm, IRI modelIRI) throws Inconsistent for (AnnotationExtension extension : possibleExtensions) { if (extension.getTriple().getSubject().equals(annotation.getOntologyClassNode()) && !(extension.getTriple().getObject().equals(annotation.getObjectNode()))) { for (Explanation expl : allExplanations.get(extension.getTriple())) { - boolean allFactsOfExplanationHaveRefMatchingAnnotation = toJava(expl.facts()).stream().map(fact -> allEvidences.getOrDefault(Bridge.jenaFromTriple(fact), Collections.emptySet())).allMatch(evidenceSet -> + boolean allFactsOfExplanationHaveRefMatchingAnnotation = toJava(expl.facts()).stream().map(fact -> allEvidences.getOrDefault(Bridge.jenaFromTriple(fact), Collections.emptySet())).allMatch(evidenceSet -> evidenceSet.stream().anyMatch(ev -> ev.getReference().equals(reference))); if (allFactsOfExplanationHaveRefMatchingAnnotation) { goodExtensions.add(new DefaultConjunctiveExpression(IRI.create(extension.getTriple().getPredicate().getURI()), extension.getValueType())); @@ -181,7 +181,7 @@ public Set getGPAD(WorkingMemory wm, IRI modelIRI) throws Inconsistent } else { doNotAnnotateViolation = false; } if (!rootViolation && !doNotAnnotateViolation) { - DefaultGPADData defaultGPADData = new DefaultGPADData(annotation.getObject(), annotation.getQualifier(), annotation.getOntologyClass(), goodExtensions, + DefaultGPADData defaultGPADData = new DefaultGPADData(annotation.getObject(), annotation.getQualifier(), annotation.getOntologyClass(), goodExtensions, reference, currentEvidence.getEvidence(), currentEvidence.getWithOrFrom(), Optional.empty(), currentEvidence.getDate(), currentEvidence.getAssignedBy(), currentEvidence.getAnnotations()); defaultGPADData.setOperator(annotation.getOperator()); annotations.add(defaultGPADData); @@ -190,7 +190,15 @@ public Set getGPAD(WorkingMemory wm, IRI modelIRI) throws Inconsistent } } } - return annotations; + Set gpsWithRootBPAnnotation = annotations.stream() + .filter(a -> a.getOntologyClass().toString().equals(BP)) + .map(GPADData::getObject) + .collect(Collectors.toSet()); + // Don't output root MF annotations if there is also a root BP annotation + Set filteredAnnotations = annotations.stream() + .filter(a -> !(a.getOntologyClass().toString().equals(MF) && gpsWithRootBPAnnotation.contains(a.getObject()))) + .collect(Collectors.toSet()); + return filteredAnnotations; } private Map getModelAnnotations(Model model) { @@ -213,17 +221,17 @@ private Map getModelAnnotations(Model model) { } /** - * Given a set of triples extracted/generated from the result/answer of query gpad-basic.rq, we find matching evidence subgraphs. + * Given a set of triples extracted/generated from the result/answer of query gpad-basic.rq, we find matching evidence subgraphs. * In other words, if there are no matching evidence (i.e. no bindings for evidence_type), we discard (basic) GPAD instance. - * - * The parameter "facts" consists of triples constructed from a binding of ?pr, ?rel, ?target in gpad_basic.rq. + * + * The parameter "facts" consists of triples constructed from a binding of ?pr, ?rel, ?target in gpad_basic.rq. * (The codes that constructing these triples are executed right before this method is called). - * + * * These triples are then decomposed into values used as the parameters/bindings for objects of the following patterns. - * ?axiom owl:annotatedSource ?subject (i.e. ?pr in gpad_basic.rq) - * ?axiom owl:annotatedProperty ?predicate (i.e., ?rel in gpad_basic.rq, which denotes qualifier in GPAD) + * ?axiom owl:annotatedSource ?subject (i.e. ?pr in gpad_basic.rq) + * ?axiom owl:annotatedProperty ?predicate (i.e., ?rel in gpad_basic.rq, which denotes qualifier in GPAD) * ?axiom owl:annotatedTarget ?object (i.e., ?target in gpad_basic.rq) - * + * * If we find the bindings of ?axioms and the values of these bindings have some rdf:type triples, we proceed. (If not, we discard). * The bindings of the query gpad-relation-evidence-multiple.rq are then used for filling up fields in GPAD records/tuples. */ @@ -329,11 +337,11 @@ private boolean isConsistent(Model model) { ResultSet result = qe.execSelect(); while (result.hasNext()) { QuerySolution qs = result.next(); - Resource bad = qs.getResource("s"); + Resource bad = qs.getResource("s"); LOG.info("owl nothing instance: "+bad.getURI()); } } - + return !inconsistent; } From 9ae5529b93107b19fba2d1ed526cf222100a31b4 Mon Sep 17 00:00:00 2001 From: Jim Balhoff Date: Thu, 5 Aug 2021 10:13:49 -0400 Subject: [PATCH 2/2] Add test. --- .../minerva/legacy/sparql/GPADSPARQLTest.java | 13 + .../test/resources/test_root_mf_filter.ttl | 311 ++++++++++++++++++ 2 files changed, 324 insertions(+) create mode 100644 minerva-converter/src/test/resources/test_root_mf_filter.ttl diff --git a/minerva-converter/src/test/java/org/geneontology/minerva/legacy/sparql/GPADSPARQLTest.java b/minerva-converter/src/test/java/org/geneontology/minerva/legacy/sparql/GPADSPARQLTest.java index 65b409bf..5f283cf4 100644 --- a/minerva-converter/src/test/java/org/geneontology/minerva/legacy/sparql/GPADSPARQLTest.java +++ b/minerva-converter/src/test/java/org/geneontology/minerva/legacy/sparql/GPADSPARQLTest.java @@ -101,4 +101,17 @@ public void testGPADOutputWithNegation() throws Exception { } } } + + @Test + public void testFilterRootMFWhenRootBP() throws Exception { + Model model = ModelFactory.createDefaultModel(); + model.read(this.getClass().getResourceAsStream("/test_root_mf_filter.ttl"), "", "ttl"); + Set triples = model.listStatements().toList().stream().map(s -> Bridge.tripleFromJena(s.asTriple())).collect(Collectors.toSet()); + WorkingMemory mem = arachne.processTriples(JavaConverters.asScalaSetConverter(triples).asScala()); + Set annotations = exporter.getGPAD(mem, IRI.create("http://test.org")); + IRI gene = IRI.create("http://identifiers.org/mgi/MGI:2153470"); + IRI rootMF = IRI.create("http://purl.obolibrary.org/obo/GO_0003674"); + Assert.assertTrue(annotations.stream().noneMatch(a -> a.getObject().equals(gene) && a.getOntologyClass().equals(rootMF))); + } + } diff --git a/minerva-converter/src/test/resources/test_root_mf_filter.ttl b/minerva-converter/src/test/resources/test_root_mf_filter.ttl new file mode 100644 index 00000000..e2d83038 --- /dev/null +++ b/minerva-converter/src/test/resources/test_root_mf_filter.ttl @@ -0,0 +1,311 @@ +@prefix : . +@prefix owl: . +@prefix rdf: . +@prefix xml: . +@prefix xsd: . +@prefix rdfs: . +@base . + + rdf:type owl:Ontology ; + owl:versionIRI ; + "production" ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string , + "https://orcid.org/0000-0003-2689-5511" ; + "2021-06-10" ; + "Scgb3a2 (MGI:MGI:2153470)" ; + "http://informatics.jax.org"^^xsd:string ; + . + +################################################################# +# Annotation properties +################################################################# + +### http://geneontology.org/lego/evidence + rdf:type owl:AnnotationProperty . + + +### http://geneontology.org/lego/evidence-with + rdf:type owl:AnnotationProperty . + + +### http://geneontology.org/lego/modelstate + rdf:type owl:AnnotationProperty . + + +### http://geneontology.org/lego/hint/layout/x + rdf:type owl:AnnotationProperty . + + +### http://geneontology.org/lego/hint/layout/y + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/contributor + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/date + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/source + rdf:type owl:AnnotationProperty . + + +### http://purl.org/dc/elements/1.1/title + rdf:type owl:AnnotationProperty . + + +### http://purl.org/pav/providedBy + rdf:type owl:AnnotationProperty . + + +### https://w3id.org/biolink/vocab/in_taxon + rdf:type owl:AnnotationProperty . + + +################################################################# +# Object Properties +################################################################# + +### http://purl.obolibrary.org/obo/BFO_0000050 + rdf:type owl:ObjectProperty . + + +### http://purl.obolibrary.org/obo/RO_0001025 + rdf:type owl:ObjectProperty . + + +### http://purl.obolibrary.org/obo/RO_0002233 + rdf:type owl:ObjectProperty . + + +### http://purl.obolibrary.org/obo/RO_0002333 + rdf:type owl:ObjectProperty . + + +################################################################# +# Classes +################################################################# + +### http://identifiers.org/mgi/MGI:2153470 + rdf:type owl:Class . + + +### http://purl.obolibrary.org/obo/ECO_0000307 + rdf:type owl:Class . + + +### http://purl.obolibrary.org/obo/ECO_0000314 + rdf:type owl:Class . + + +### http://purl.obolibrary.org/obo/ECO_0000353 + rdf:type owl:Class . + + +### http://purl.obolibrary.org/obo/GO_0003674 + rdf:type owl:Class . + + +### http://purl.obolibrary.org/obo/GO_0005515 + rdf:type owl:Class . + + +### http://purl.obolibrary.org/obo/GO_0005576 + rdf:type owl:Class . + + +### http://purl.obolibrary.org/obo/GO_0008150 + rdf:type owl:Class . + + +### http://purl.obolibrary.org/obo/PR_Q920H1 + rdf:type owl:Class . + + +################################################################# +# Individuals +################################################################# + +### http://model.geneontology.org/MGI_MGI_2153470/aca5c2ae-424d-4f59-b465-6d7ad65b0364 + rdf:type owl:NamedIndividual , + ; + "https://orcid.org/0000-0001-7476-6306" , + "https://orcid.org/0000-0003-2689-5511" ; + "2005-10-03" ; + "http://informatics.jax.org" . + + +### http://model.geneontology.org/MGI_MGI_2153470/cef2071f-7184-445d-b440-56d5f0c28af5 + rdf:type owl:NamedIndividual , + ; + "https://orcid.org/0000-0001-7476-6306" ; + "2001-12-06" ; + "GO_REF:0000015" ; + "http://informatics.jax.org" . + + +### http://model.geneontology.org/MGI_MGI_2153470/f9a82aa0-3280-4530-a787-580828e17f80 + rdf:type owl:NamedIndividual , + ; + ; + ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string , + "https://orcid.org/0000-0003-2689-5511" ; + "2005-10-03" ; + "http://informatics.jax.org"^^xsd:string . + +[ rdf:type owl:Axiom ; + owl:annotatedSource ; + owl:annotatedProperty ; + owl:annotatedTarget ; + ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string , + "https://orcid.org/0000-0003-2689-5511" ; + "2005-10-03" ; + "http://informatics.jax.org"^^xsd:string ; + rdfs:comment "MGI:MGI:2153470 RO:0002327 GO:0005515 MGI:MGI:2152614|PMID:11682631 ECO:0000353 PR:Q920H1 2005-10-03 MGI creation-date=2001-12-06|modification-date=2005-10-03|comment=Scgb3a2|contributor-id=https://orcid.org/0000-0003-2689-5511|contributor-id=https://orcid.org/0000-0001-7476-6306" + ] . + +[ rdf:type owl:Axiom ; + owl:annotatedSource ; + owl:annotatedProperty ; + owl:annotatedTarget ; + ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string , + "https://orcid.org/0000-0003-2689-5511" ; + "2005-10-03" ; + "http://informatics.jax.org"^^xsd:string ; + rdfs:comment "MGI:MGI:2153470 RO:0002327 GO:0005515 MGI:MGI:2152614|PMID:11682631 ECO:0000353 PR:Q920H1 2005-10-03 MGI creation-date=2001-12-06|modification-date=2005-10-03|comment=Scgb3a2|contributor-id=https://orcid.org/0000-0003-2689-5511|contributor-id=https://orcid.org/0000-0001-7476-6306" + ] . + + +### http://model.geneontology.org/MGI_MGI_2153470/0e0f6683-36ca-4d5f-9cbf-cde7d13a48b0 + rdf:type owl:NamedIndividual , + ; + "PR:Q920H1" ; + "https://orcid.org/0000-0001-7476-6306" , + "https://orcid.org/0000-0003-2689-5511" ; + "2005-10-03" ; + "PMID:11682631" ; + "http://informatics.jax.org" ; + rdfs:comment "Scgb3a2" . + + +### http://model.geneontology.org/MGI_MGI_2153470/093ca939-cae5-4bf4-807c-abc809d765d0 + rdf:type owl:NamedIndividual , + ; + "https://orcid.org/0000-0001-7476-6306" ; + "2001-12-06" ; + "http://informatics.jax.org" . + + +### http://model.geneontology.org/MGI_MGI_2153470/2b47ddfa-9573-4f14-acdf-80687c198f93 + rdf:type owl:NamedIndividual , + ; + ; + ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string ; + "2001-12-06" ; + "http://informatics.jax.org"^^xsd:string . + +[ rdf:type owl:Axiom ; + owl:annotatedSource ; + owl:annotatedProperty ; + owl:annotatedTarget ; + ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string ; + "2001-12-06" ; + "http://informatics.jax.org"^^xsd:string ; + rdfs:comment "MGI:MGI:2153470 RO:0002331 GO:0008150 MGI:MGI:2156816|GO_REF:0000015 ECO:0000307 2001-12-06 MGI creation-date=2001-12-06|modification-date=2001-12-06|contributor-id=https://orcid.org/0000-0001-7476-6306" + ] . + +[ rdf:type owl:Axiom ; + owl:annotatedSource ; + owl:annotatedProperty ; + owl:annotatedTarget ; + ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string ; + "2001-12-06" ; + "http://informatics.jax.org"^^xsd:string ; + rdfs:comment "MGI:MGI:2153470 RO:0002331 GO:0008150 MGI:MGI:2156816|GO_REF:0000015 ECO:0000307 2001-12-06 MGI creation-date=2001-12-06|modification-date=2001-12-06|contributor-id=https://orcid.org/0000-0001-7476-6306" + ] . + + +### http://model.geneontology.org/MGI_MGI_2153470/253eceee-056d-4ad0-be0e-386fe6dd9a74 + rdf:type owl:NamedIndividual , + ; + "https://orcid.org/0000-0001-7476-6306" ; + "2001-12-06" ; + "GO_REF:0000015" ; + "http://informatics.jax.org" . + + +### http://model.geneontology.org/MGI_MGI_2153470/3e8914d3-477b-44e8-a0bb-c22468f31ab5 + rdf:type owl:NamedIndividual , + ; + ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string ; + "2001-12-06" ; + "http://informatics.jax.org"^^xsd:string . + +[ rdf:type owl:Axiom ; + owl:annotatedSource ; + owl:annotatedProperty ; + owl:annotatedTarget ; + ; + "https://orcid.org/0000-0001-7476-6306"^^xsd:string ; + "2001-12-06" ; + "http://informatics.jax.org"^^xsd:string ; + rdfs:comment "MGI:MGI:2153470 RO:0001025 GO:0005576 MGI:MGI:2152614|PMID:11682631 ECO:0000314 2001-12-06 MGI creation-date=2001-12-06|modification-date=2001-12-06|contributor-id=https://orcid.org/0000-0001-7476-6306" + ] . + + +### http://model.geneontology.org/MGI_MGI_2153470/3ea6103a-d898-476a-bb56-3d81d4b958c5 + rdf:type owl:NamedIndividual , + ; + "PR:Q920H1" ; + "https://orcid.org/0000-0001-7476-6306" , + "https://orcid.org/0000-0003-2689-5511" ; + "2005-10-03" ; + "PMID:11682631" ; + "http://informatics.jax.org" ; + rdfs:comment "Scgb3a2" . + + +### http://model.geneontology.org/MGI_MGI_2153470/328cfa1b-ddd7-41fc-a3e1-a6ec4beffcf8 + rdf:type owl:NamedIndividual , + ; + "https://orcid.org/0000-0001-7476-6306" ; + "2001-12-06" ; + "http://informatics.jax.org" . + + +### http://model.geneontology.org/MGI_MGI_2153470/53bd018c-2a1b-4009-8da7-53aec2e372cc + rdf:type owl:NamedIndividual , + ; + "https://orcid.org/0000-0001-7476-6306" ; + "2001-12-06" ; + "PMID:11682631" ; + "http://informatics.jax.org" . + + +### http://model.geneontology.org/MGI_MGI_2153470/67440023-3efd-4cd4-8935-8529397af20e + rdf:type owl:NamedIndividual , + ; + "https://orcid.org/0000-0001-7476-6306" ; + "2001-12-06" ; + "http://informatics.jax.org" . + + +### http://model.geneontology.org/MGI_MGI_2153470/861704f7-c8ff-48e4-a216-407f21e38dd6 + rdf:type owl:NamedIndividual , + ; + "https://orcid.org/0000-0001-7476-6306" , + "https://orcid.org/0000-0003-2689-5511" ; + "2005-10-03" ; + "http://informatics.jax.org" . + + +### Generated by the OWL API (version 4.5.15) https://github.com/owlcs/owlapi