Skip to content

Commit

Permalink
Merge pull request #216 from owlcollab/merge-fixes
Browse files Browse the repository at this point in the history
Merge fixes
  • Loading branch information
cmungall authored Sep 27, 2017
2 parents d910e80 + 885cc21 commit 4879157
Show file tree
Hide file tree
Showing 5 changed files with 242 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,45 @@ else if (result.size() == 1) {
return result;
}

/**
* Append annotations to an existing axiom
*
* @param axiom
* @param annotations
* @param ontology
* @return
*/
public static OWLAxiom appendAxiomAnnotations(OWLAxiom axiom, Set<OWLAnnotation> annotations, OWLOntology ontology) {
// filter existing
Set<OWLAnnotation> newAnnotations = new HashSet<OWLAnnotation>(axiom.getAnnotations());
newAnnotations.addAll(annotations);
final OWLAxiom newAxiom = changeAxiomAnnotations(axiom, newAnnotations, ontology);
return newAxiom;
}

/**
* Append xref annotations onto an existing axiom
*
* @param axiom
* @param xrefs
* @param ontology
* @return
*/
public static OWLAxiom appendXrefAnnotations(OWLAxiom axiom, Set<String> xrefs, OWLOntology ontology) {
// filter existing
Set<OWLAnnotation> newAnnotations = new HashSet<OWLAnnotation>(axiom.getAnnotations());
final OWLOntologyManager manager = ontology.getOWLOntologyManager();
final OWLDataFactory factory = manager.getOWLDataFactory();

for (String x : xrefs) {
OWLAnnotationProperty p = factory.getOWLAnnotationProperty(IRI.create("http://www.geneontology.org/formats/oboInOwl#hasDbXref"));
OWLLiteral v = factory.getOWLLiteral(x);
newAnnotations.add(factory.getOWLAnnotation(p, v));
}
final OWLAxiom newAxiom = changeAxiomAnnotations(axiom, newAnnotations, ontology);
return newAxiom;
}


/**
* Update the given axiom to a new set of axiom annotation.<br>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,13 @@ else if (a.getValue() instanceof IRI) {
graph.getManager().removeAxioms(ont, rmXrefAxioms);
}

// Merge all properties together
// some properties may be desired to have cardinality = 1
// Remove annotation assertions for cardinality=1 properties
// unless it is on the clique leader for that property
// (note this may be different than the overall clique leader)
for (OWLAnnotationProperty p : propertyPrefixScoreMap.keySet()) {
Map<String, Double> pmap = propertyPrefixScoreMap.get(p);

// find the clique leader for property p
OWLEntity representativeForProp = null;
Double bestForProp = null;
for (OWLEntity c : n.getEntities()) {
Expand Down Expand Up @@ -272,12 +275,16 @@ else if (a.getValue() instanceof IRI) {
rmAxioms.add(a);
}
}

// sometimes we end up with A=A post-merge; remove these
for (OWLEquivalentClassesAxiom a : ont.getAxioms(AxiomType.EQUIVALENT_CLASSES)) {
if (a.getClassExpressions().size() < 2) {
LOG.info("UNARY: "+a);
rmAxioms.add(a);
}
}

// not interested in this property
for (OWLAnnotationAssertionAxiom a : ont.getAxioms(AxiomType.ANNOTATION_ASSERTION)) {
if (a.getProperty().getIRI().equals(IRI.create("http://www.geneontology.org/formats/oboInOwl#id"))) {
rmAxioms.add(a);
Expand Down
144 changes: 143 additions & 1 deletion OWLTools-Runner/src/main/java/owltools/cli/CommandRunner.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.eclipse.jetty.server.Server;
import org.forester.phylogeny.data.Annotation;
import org.geneontology.reasoner.ExpressionMaterializingReasoner;
import org.geneontology.reasoner.ExpressionMaterializingReasonerFactory;
import org.geneontology.reasoner.OWLExtendedReasoner;
Expand Down Expand Up @@ -71,6 +72,7 @@
import org.semanticweb.owlapi.model.AddImport;
import org.semanticweb.owlapi.model.AddOntologyAnnotation;
import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.HasIRI;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
Expand Down Expand Up @@ -1329,6 +1331,104 @@ else if (opts.nextEq("--rename-entity")) {
List<OWLOntologyChange> changes = oer.changeIRI(IRI.create(opts.nextOpt()),IRI.create(opts.nextOpt()));
g.getManager().applyChanges(changes);
}
else if (opts.nextEq("--merge-axiom-annotations")) {
opts.info("", "merges logically equivalent axioms making union of all annotations");
OWLOntology ontology = g.getSourceOntology();
Set<OWLAxiom> axioms = ontology.getAxioms(Imports.EXCLUDED);
Map<OWLAxiom, Set<OWLAnnotation>> amap = new HashMap<>();
for (OWLAxiom a : axioms) {
OWLAxiom k = a.getAxiomWithoutAnnotations();
if (!amap.containsKey(k))
amap.put(k, new HashSet<>());
amap.get(k).addAll(a.getAnnotations());
}
Set<OWLAxiom> newAxioms = new HashSet<>();
for (OWLAxiom a : amap.keySet()) {
newAxioms.add(a.getAnnotatedAxiom(amap.get(a)));
}
g.getManager().removeAxioms(ontology, axioms);
g.getManager().addAxioms(ontology, newAxioms);
}
else if (opts.nextEq("--interpret-xrefs")) {
opts.info("", "interprets xrefs using logical axioms, adds as annotations on xrefs");
boolean showOther = false;
while (opts.hasOpts()) {
if (opts.nextEq("--show-others")) {
opts.info("", "if set, who relationship type 'other'");
showOther = true;
}
else
break;
}
OWLOntology ont = g.getSourceOntology();
for (OWLClass c : g.getAllOWLClasses()) {
List<String> xrefs = g.getXref(c);
boolean hasWrittenTerm = false;
for (String x : xrefs) {
IRI xiri = g.getIRIByIdentifier(x);
OWLClass xc = g.getDataFactory().getOWLClass(xiri);

if (xc == null) {
System.err.println("NO CLASS: "+xc);
continue;
}
String rel = null;
if (reasoner.getSuperClasses(c, false).containsEntity(xc)) {
rel = "subClassOf";
}
else if (reasoner.getSuperClasses(xc, false).containsEntity(c)) {
rel = "superClassOf";
}
else if (reasoner.getEquivalentClasses(c).contains(xc)) {
rel = "equivalentTo";
}
else {
if (!showOther)
continue;
rel = "other";
}

if (!hasWrittenTerm) {
System.out.println("[Term]");
System.out.println("id: " + g.getIdentifier(c)+" ! "+g.getLabel(c));
hasWrittenTerm = true;
}
System.out.println("xref: " + x+" {xref=\"MONDO:"+rel+"\"}");
}
System.out.println();
}
}

else if (opts.nextEq("--add-xref-axiom-annotations")) {
opts.info("-l", "adds xref/provenance annotations to all axioms, excluding labels");
boolean includeLogical = false;
while (opts.hasOpts()) {
if (opts.nextEq("-l|--logical")) {
opts.info("", "include logical axioms (excluded by default");
includeLogical = true;
}
else
break;
}
OWLOntology ont = g.getSourceOntology();
for (OWLClass c : g.getAllOWLClasses()) {
Set<String> xrefs = new HashSet<String>();
xrefs.add(g.getIdentifier(c));
Set<OWLAxiom> axioms = new HashSet<>();
if (includeLogical)
axioms.addAll(ont.getAxioms(c, Imports.EXCLUDED));
for (OWLAnnotationAssertionAxiom a : ont.getAnnotationAssertionAxioms(c.getIRI())) {
if (a.getProperty().isLabel())
continue;
axioms.add(a);
}

Set<OWLAxiom> newAxioms = axioms.stream().map(
a -> AxiomAnnotationTools.appendXrefAnnotations(a, xrefs, ont)).collect(Collectors.toSet());
g.getManager().removeAxioms(ont, axioms);
g.getManager().addAxioms(ont, newAxioms);
}
}
else if (opts.nextEq("--merge-equivalence-sets")) {
opts.info("[-s PREFIX SCORE]* [-l PREFIX SCORE]* [-c PREFIX SCORE]* [-d PREFIX SCORE]* [-x]", "merges sets of equivalent classes. Prefix-based priorities used to determine representative member");
EquivalenceSetMergeUtil esmu = new EquivalenceSetMergeUtil(g, reasoner);
Expand Down Expand Up @@ -3166,6 +3266,48 @@ else if (opts.nextEq("--obsolete-class")) {

System.err.println("TODO");
}
else if (opts.nextEq("--obsolete-replace")) {
opts.info("ID REPLACEMENT-ID", "Add a deprecation axiom");
OWLObject obj = resolveEntity( opts);
OWLObject repl = resolveEntity( opts);
OWLEntityRenamer oer = new OWLEntityRenamer(g.getManager(), g.getAllOntologies());
Set<OWLAxiom> rmAxioms = new HashSet<>();
OWLOntology ont = g.getSourceOntology();
IRI objIRI = ((HasIRI) obj).getIRI();
String label = "obsolete "+g.getLabel(obj);
for (OWLAnnotationAssertionAxiom a : ont.getAnnotationAssertionAxioms(objIRI)) {
if (a.getProperty().isLabel()) {
rmAxioms.add(a);
}
if (a.getProperty().isComment()) {
rmAxioms.add(a);
}
if (a.getProperty().getIRI().equals(Obo2OWLVocabulary.IRI_IAO_0000115.getIRI())) {
//if (g.getDef(((HasIRI) repl).getIRI()) != null) {
rmAxioms.add(a);
//}
}
}
LOG.info("REMOVING: "+rmAxioms);
g.getManager().removeAxioms(ont, rmAxioms);

Map<OWLEntity,IRI> e2iri = new HashMap<OWLEntity,IRI>();
e2iri.put((OWLEntity) obj, ((HasIRI) repl).getIRI());
List<OWLOntologyChange> changes = oer.changeIRI(e2iri);
g.getManager().applyChanges(changes);
OWLDataFactory df = g.getDataFactory();
Set<OWLAxiom> newAxioms = new HashSet<>();
newAxioms.add(df.getOWLDeclarationAxiom((OWLClass)obj));
newAxioms.add(df.getOWLAnnotationAssertionAxiom(df.getOWLDeprecated(), objIRI, df.getOWLLiteral(true)));
newAxioms.add(df.getOWLAnnotationAssertionAxiom(df.getRDFSLabel(), objIRI, df.getOWLLiteral(label)));

OWLAnnotationProperty rp = df.getOWLAnnotationProperty(Obo2OWLVocabulary.IRI_IAO_0100001.getIRI());
newAxioms.add(df.getOWLAnnotationAssertionAxiom(rp, objIRI,
df.getOWLLiteral(g.getIdentifier(repl))));

g.getManager().addAxioms(ont, newAxioms);

}
else if (opts.nextEq("-d") || opts.nextEq("--draw")) {
opts.info("[-o FILENAME] [-f FMT] LABEL/ID", "generates a file tmp.png made using QuickGO code");
String imgf = "tmp.png";
Expand Down Expand Up @@ -3529,7 +3671,7 @@ else if (opts.nextEq("--extract-subset")) {
opts.info("[-x] SUBSET", "Extract a subset (aka slim) from an ontology, storing subset in place of existing ontology");
boolean isRemoveDangling = false;
while (opts.hasOpts()) {
if (opts.nextEq("-x|--remove-dangling")) {
if (opts.nextEq("-x|--remove-dangling")) {
opts.info("",
"if specified, dangling axioms (ie pointing to removed classes) are removed");
isRemoveDangling = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,28 @@ public void testMergeEquivalentIndividuals() throws Exception {

}

@Test
public void testMergeEquivalentPreserveProvenance() throws Exception {
load("merge-equiv-test.obo");

run("--add-xref-axiom-annotations -l");
run("--reasoner elk");
// note: ID space is actually "U" in file
run("--merge-equivalence-sets -s MA 1 -s FMA 2 -s U 3 -s HP 1 -s MP 2");
run("--merge-axiom-annotations");
run("--interpret-xrefs");
run("-o -f obo --no-check target/equiv-set-merged-xrefs.obo");

}

@Test
public void testObsoleteReplace() throws Exception {
load("merge-equiv-test.obo");

run("--obsolete-replace FMA:1 U:1");
run("-o -f obo --no-check target/obs-repl.obo");

}


}
27 changes: 27 additions & 0 deletions OWLTools-Runner/src/test/resources/merge-equiv-test.obo
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ def: "test mp1" []
synonym: "mp syn1" EXACT []
synonym: "mp syn2" EXACT [MP:MP]
comment: comment mp1
is_a: MP:2
intersection_of: PATO:1
intersection_of: r MA:1

Expand All @@ -14,6 +15,7 @@ name: hp1
def: "test hp1" []
synonym: "hp syn2" EXACT [HP:HP]
comment: comment hp1
is_a: HP:2
intersection_of: PATO:1
intersection_of: r FMA:1

Expand All @@ -23,6 +25,7 @@ name: ma1
comment: ma1 comment
synonym: "ma1 syn1" EXACT []
synonym: "ma1 syn2" EXACT []
is_a: MA:0

[Term]
id: FMA:1
Expand All @@ -31,13 +34,37 @@ comment: fma1 comment
def: "fma1 def" [FMA:FMA]
synonym: "fma1 syn1" EXACT []
synonym: "fma1 syn2" EXACT []
is_a: FMA:0

[Term]
id: U:1
name: u1
def: "u1 def" [U:U]
equivalent_to: FMA:1
equivalent_to: MA:1
is_a: U:0

[Term]
id: MA:0
name: ma0
comment: ma0 comment
synonym: "ma0 syn1" EXACT []
synonym: "ma0 syn2" EXACT []

[Term]
id: FMA:0
name: fma0
comment: fma0 comment
def: "fma0 def" [FMA:FMA]
synonym: "fma0 syn1" EXACT []
synonym: "fma0 syn2" EXACT []

[Term]
id: U:0
name: u0
def: "u0 def" [U:U]
equivalent_to: MA:0
equivalent_to: FMA:0



Expand Down

0 comments on commit 4879157

Please sign in to comment.