Skip to content

Commit

Permalink
Implement option to preserve evidence when copying a model. (#514)
Browse files Browse the repository at this point in the history
* Implement option to preserve evidence when copying a model.

* Need to copy links from object property axioms to evidence nodes.
  • Loading branch information
balhoff authored May 24, 2023
1 parent 659db23 commit c6f9f07
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ public static class M3Argument extends MinervaRequest.MinervaArgument {
JsonOwlObject[] expressions;
JsonAnnotation[] values;

@SerializedName("preserve-evidence")
Boolean preserveEvidence;

String query;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,11 @@ ModelContainer createModel(String userId, Set<String> providerGroups, UndoMetada
return model;
}

ModelContainer copyModel(IRI sourceModelId, String userId, Set<String> providerGroups, UndoMetadata token, Set<OWLAnnotation> modelAnnotations) throws UnknownIdentifierException, OWLOntologyCreationException, RepositoryException, IOException, OWLOntologyStorageException {
ModelContainer copyModel(IRI sourceModelId, String userId, Set<String> providerGroups, UndoMetadata token, Set<OWLAnnotation> modelAnnotations, boolean preserveEvidence) throws UnknownIdentifierException, OWLOntologyCreationException, RepositoryException, IOException, OWLOntologyStorageException {
OWLDataFactory df = OWLManager.getOWLDataFactory();
Set<OWLAnnotationProperty> evidenceProperties = new HashSet<>();
evidenceProperties.add(df.getOWLAnnotationProperty(AnnotationShorthand.with.getAnnotationProperty()));
evidenceProperties.add(df.getOWLAnnotationProperty(AnnotationShorthand.source.getAnnotationProperty()));
ModelContainer sourceModel = m3.getModel(sourceModelId);
boolean titleIsProvided = modelAnnotations.stream()
.anyMatch(ann -> ann.getProperty().getIRI().equals(AnnotationShorthand.title.getAnnotationProperty()));
Expand Down Expand Up @@ -105,15 +108,37 @@ ModelContainer copyModel(IRI sourceModelId, String userId, Set<String> providerG
.map(aa -> aa.getValue().asIRI().get())
.collect(Collectors.toSet());
evidenceNodeIRIs.addAll(axiomEvidenceNodeIRIs);
Set<IRI> excludeNodes;
if (preserveEvidence) {
excludeNodes = new HashSet<>();
} else {
excludeNodes = evidenceNodeIRIs;
}
Map<OWLNamedIndividual, OWLNamedIndividual> oldToNew = m3.getIndividuals(sourceModelId).stream()
.filter(i -> !evidenceNodeIRIs.contains(i.getIRI()))
.filter(i -> !excludeNodes.contains(i.getIRI()))
.collect(Collectors.toMap(sourceIndividual -> sourceIndividual, sourceIndividual -> m3.createIndividualNonReasoning(model, generatedAnnotations, token)));
sourceModel.getAboxOntology().getAxioms(AxiomType.CLASS_ASSERTION, Imports.EXCLUDED).stream()
.filter(ca -> !evidenceNodeIRIs.contains(ca.getIndividual().asOWLNamedIndividual().getIRI()))
.filter(ca -> !excludeNodes.contains(ca.getIndividual().asOWLNamedIndividual().getIRI()))
.forEach(ca -> m3.addType(model, oldToNew.get(ca.getIndividual().asOWLNamedIndividual()), ca.getClassExpression(), token));
sourceModel.getAboxOntology().getAxioms(AxiomType.OBJECT_PROPERTY_ASSERTION, Imports.EXCLUDED).stream()
.filter(opa -> !evidenceNodeIRIs.contains(opa.getSubject().asOWLNamedIndividual().getIRI()) && !evidenceNodeIRIs.contains(opa.getObject().asOWLNamedIndividual().getIRI()))
.forEach(opa -> m3.addFact(model, opa.getProperty(), oldToNew.get(opa.getSubject().asOWLNamedIndividual()), oldToNew.get(opa.getObject().asOWLNamedIndividual()), generatedAnnotations, token));
.filter(opa -> !excludeNodes.contains(opa.getSubject().asOWLNamedIndividual().getIRI()) && !excludeNodes.contains(opa.getObject().asOWLNamedIndividual().getIRI()))
.forEach(opa -> {
final Set<OWLAnnotation> axiomAnnotations = new HashSet<>(generatedAnnotations);
if (preserveEvidence) axiomAnnotations.addAll(
opa.getAnnotations(df.getOWLAnnotationProperty(AnnotationShorthand.evidence.getAnnotationProperty())).stream()
.filter(ann -> ann.getValue().isIRI())
.map(ann -> df.getOWLAnnotation(ann.getProperty(), oldToNew.get(df.getOWLNamedIndividual(ann.getValue().asIRI().get())).getIRI()))
.collect(Collectors.toSet())
);
m3.addFact(model, opa.getProperty(), oldToNew.get(opa.getSubject().asOWLNamedIndividual()), oldToNew.get(opa.getObject().asOWLNamedIndividual()), axiomAnnotations, token);
});
if (preserveEvidence) {
// copy annotation assertions for evidence nodes
sourceModel.getAboxOntology().getAxioms(AxiomType.ANNOTATION_ASSERTION, Imports.EXCLUDED).stream()
.filter(aa -> aa.getSubject().isIRI() && evidenceNodeIRIs.contains((IRI) aa.getSubject()))
.filter(aa -> evidenceProperties.contains(aa.getProperty()))
.forEach(aa -> m3.addAxiom(model, df.getOWLAnnotationAssertionAxiom(aa.getProperty(), oldToNew.get(df.getOWLNamedIndividual((IRI) aa.getSubject())).getIRI(), aa.getValue()), token));
}
final Set<OWLAnnotation> modelAnnotationsWithState = addDefaultModelState(modelAnnotations, model.getOWLDataFactory());
modelAnnotationsWithState.add(df.getOWLAnnotation(df.getOWLAnnotationProperty(AnnotationShorthand.wasDerivedFrom.getAnnotationProperty()), sourceModelId));
maybeNewTitle.ifPresent(modelAnnotationsWithState::add);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,11 @@ String handleRequestForModel(M3Request request, M3BatchResponse response, Operat
values.nonMeta = true;
requireNotNull(request.arguments, "request.arguments");
values.model = checkModelId(values.model, request);
boolean preserveEvidence = false;
if (request.arguments.preserveEvidence != null) preserveEvidence = request.arguments.preserveEvidence;
Set<OWLAnnotation> modelAnnotations = extract(request.arguments.values, userId, providerGroups, values, values.model);
values.renderBulk = true;
values.model = copyModel(values.model.getModelId(), userId, providerGroups, token, modelAnnotations);
values.model = copyModel(values.model.getModelId(), userId, providerGroups, token, modelAnnotations, preserveEvidence);
} else if (Operation.updateImports == operation) {
values.nonMeta = true;
requireNotNull(request.arguments, "request.arguments");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ public void testModelCopy() {
final M3BatchResponse response1 = executeBatch(batch1, false);

String newModelTitle = "new model title";
M3Request r2 = BatchTestTools.copyModel(sourceModelId, newModelTitle);
M3Request r2 = BatchTestTools.copyModel(sourceModelId, newModelTitle, false);
M3BatchResponse response2 = execute(r2, false);
Assert.assertEquals(5, response1.data.individuals.length);
Assert.assertEquals(2, response2.data.individuals.length);
Expand All @@ -655,6 +655,50 @@ public void testModelCopy() {
Assert.assertEquals(newModelTitle, titleValue.value);
}

@Test
public void testModelCopyPreservingEvidence() {
final List<M3Request> batch1 = new ArrayList<M3Request>();
final String sourceModelId = generateBlankModel();
// evidence1
M3Request r = BatchTestTools.addIndividual(sourceModelId, "ECO:0000000"); // evidence from ECO
r.arguments.assignToVariable = "evidence-var1";
r.arguments.values = BatchTestTools.singleAnnotation(AnnotationShorthand.source, "PMID:000000");
batch1.add(r);
// evidence2
r = BatchTestTools.addIndividual(sourceModelId, "ECO:0000001"); // evidence from ECO
r.arguments.assignToVariable = "evidence-var2";
r.arguments.values = BatchTestTools.singleAnnotation(AnnotationShorthand.source, "PMID:000001");
batch1.add(r);
// evidence3
r = BatchTestTools.addIndividual(sourceModelId, "ECO:0000002"); // evidence from ECO
r.arguments.assignToVariable = "evidence-var3";
r.arguments.values = BatchTestTools.singleAnnotation(AnnotationShorthand.source, "PMID:000002");
batch1.add(r);
r = BatchTestTools.addIndividual(sourceModelId, "GO:0003674"); // molecular function
r.arguments.assignToVariable = "mf";
r.arguments.values = BatchTestTools.singleAnnotation(AnnotationShorthand.evidence, "evidence-var1");
batch1.add(r);
r = BatchTestTools.addIndividual(sourceModelId, "GO:0008150"); // biological process
r.arguments.values = BatchTestTools.singleAnnotation(AnnotationShorthand.evidence, "evidence-var3");
r.arguments.assignToVariable = "bp";
batch1.add(r);
// activity -> process
r = BatchTestTools.addEdge(sourceModelId, "mf", "BFO:0000050", "bp"); // part_of
r.arguments.values = BatchTestTools.singleAnnotation(AnnotationShorthand.evidence, "evidence-var2");
batch1.add(r); // part_of
final M3BatchResponse response1 = executeBatch(batch1, false);

String newModelTitle = "new model title";
M3Request r2 = BatchTestTools.copyModel(sourceModelId, newModelTitle, true);
M3BatchResponse response2 = execute(r2, false);
Assert.assertEquals(5, response1.data.individuals.length);
Assert.assertEquals(5, response2.data.individuals.length);
JsonAnnotation providedByValue = Arrays.stream(response2.data.annotations).filter(a -> a.key.equals("wasDerivedFrom")).findAny().get();
Assert.assertEquals(response1.data.modelId, providedByValue.value);
JsonAnnotation titleValue = Arrays.stream(response2.data.annotations).filter(a -> a.key.equals("title")).findAny().get();
Assert.assertEquals(newModelTitle, titleValue.value);
}

@Test
public void testDeleteEvidenceIndividuals() throws Exception {
//models.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@

public class BatchTestTools {

static M3Request copyModel(String modelId, String title) {
static M3Request copyModel(String modelId, String title, boolean preserveEvidence) {
M3Request r = new M3Request();
r.entity = Entity.model;
r.operation = Operation.copy;
r.arguments = new M3Argument();
r.arguments.modelId = modelId;
r.arguments.preserveEvidence = preserveEvidence;
r.arguments.values = new JsonAnnotation[]{JsonTools.create(AnnotationShorthand.title, title, null)};
return r;
}
Expand Down

0 comments on commit c6f9f07

Please sign in to comment.