diff --git a/.classpath b/.classpath
index e43402fa..aa6ee384 100644
--- a/.classpath
+++ b/.classpath
@@ -1,36 +1,5 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/.gitignore b/.gitignore
index 2f7896d1..d2b96f9e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
target/
+/.DS_Store
diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 00000000..f897a7f1
--- /dev/null
+++ b/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/minerva-cli/.classpath b/minerva-cli/.classpath
new file mode 100644
index 00000000..f619a536
--- /dev/null
+++ b/minerva-cli/.classpath
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/minerva-cli/.gitignore b/minerva-cli/.gitignore
new file mode 100644
index 00000000..2f7896d1
--- /dev/null
+++ b/minerva-cli/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/minerva-cli/.project b/minerva-cli/.project
new file mode 100644
index 00000000..6ffc9639
--- /dev/null
+++ b/minerva-cli/.project
@@ -0,0 +1,23 @@
+
+
+ minerva-cli
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/minerva-cli/.settings/org.eclipse.core.resources.prefs b/minerva-cli/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 00000000..e9441bb1
--- /dev/null
+++ b/minerva-cli/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding/=UTF-8
diff --git a/minerva-cli/.settings/org.eclipse.jdt.core.prefs b/minerva-cli/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..ec4300d5
--- /dev/null
+++ b/minerva-cli/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/minerva-cli/.settings/org.eclipse.m2e.core.prefs b/minerva-cli/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 00000000..f897a7f1
--- /dev/null
+++ b/minerva-cli/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/minerva-cli/pom.xml b/minerva-cli/pom.xml
new file mode 100644
index 00000000..c45028b2
--- /dev/null
+++ b/minerva-cli/pom.xml
@@ -0,0 +1,24 @@
+
+ 4.0.0
+
+ minerva
+ org.geneontology
+ 0.2.2-SNAPSHOT
+
+ minerva-cli
+ Minerva-CommandLineInterface
+
+
+
+ org.geneontology
+ minerva-converter
+ ${project.parent.version}
+
+
+ org.bbop
+ OWLTools-Runner
+
+
+
+
diff --git a/minerva-cli/src/main/java/org/geneontology/minerva/cli/CommandLineInterface.java b/minerva-cli/src/main/java/org/geneontology/minerva/cli/CommandLineInterface.java
new file mode 100644
index 00000000..c5d59002
--- /dev/null
+++ b/minerva-cli/src/main/java/org/geneontology/minerva/cli/CommandLineInterface.java
@@ -0,0 +1,11 @@
+package org.geneontology.minerva.cli;
+
+
+public class CommandLineInterface {
+
+ public static void main(String[] args) throws Exception {
+ MinervaCommandRunner cr = new MinervaCommandRunner();
+ cr.run(args);
+ }
+
+}
diff --git a/minerva-cli/src/main/java/org/geneontology/minerva/cli/MinervaCommandRunner.java b/minerva-cli/src/main/java/org/geneontology/minerva/cli/MinervaCommandRunner.java
new file mode 100644
index 00000000..3aa60ac2
--- /dev/null
+++ b/minerva-cli/src/main/java/org/geneontology/minerva/cli/MinervaCommandRunner.java
@@ -0,0 +1,646 @@
+package org.geneontology.minerva.cli;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.coode.owlapi.manchesterowlsyntax.ManchesterOWLSyntaxOntologyFormat;
+import org.geneontology.minerva.GafToLegoIndividualTranslator;
+import org.geneontology.minerva.GafToLegoTranslator;
+import org.geneontology.minerva.ModelContainer;
+import org.geneontology.minerva.generate.LegoModelGenerator;
+import org.geneontology.minerva.legacy.LegoToGeneAnnotationTranslator;
+import org.geneontology.minerva.util.MinimalModelGenerator;
+import org.semanticweb.elk.owlapi.ElkReasonerFactory;
+import org.semanticweb.owlapi.io.OWLFunctionalSyntaxOntologyFormat;
+import org.semanticweb.owlapi.io.RDFXMLOntologyFormat;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLAxiom;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLEntity;
+import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
+import org.semanticweb.owlapi.model.OWLObjectProperty;
+import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyCreationException;
+import org.semanticweb.owlapi.model.OWLOntologyFormat;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
+
+import owltools.cli.JsCommandRunner;
+import owltools.cli.Opts;
+import owltools.cli.tools.CLIMethod;
+import owltools.gaf.BioentityDocument;
+import owltools.gaf.GafDocument;
+import owltools.gaf.eco.EcoMapperFactory;
+import owltools.gaf.eco.SimpleEcoMapper;
+import owltools.gaf.io.GpadWriter;
+import owltools.graph.OWLGraphWrapper;
+import owltools.io.OWLPrettyPrinter;
+import owltools.vocab.OBOUpperVocabulary;
+import uk.ac.manchester.cs.owlapi.modularity.ModuleType;
+import uk.ac.manchester.cs.owlapi.modularity.SyntacticLocalityModuleExtractor;
+
+public class MinervaCommandRunner extends JsCommandRunner {
+
+ private volatile MinimalModelGenerator mmg = null;
+
+
+ private synchronized MinimalModelGenerator getMinimalModelGenerator(boolean isCreateNewAbox) throws OWLOntologyCreationException {
+
+ if (mmg == null) {
+ OWLReasonerFactory rf = new ElkReasonerFactory();
+ if (isCreateNewAbox) {
+ ModelContainer model = new ModelContainer(g.getSourceOntology(), rf);
+ mmg = new MinimalModelGenerator(model);
+ }
+ else {
+ ModelContainer model = new ModelContainer(g.getSourceOntology(), g.getSourceOntology(), rf);
+ mmg = new MinimalModelGenerator(model);
+ }
+ }
+ return mmg;
+ }
+
+ @CLIMethod("--generate-minimal-model")
+ public void generateMinimalModel(Opts opts) throws Exception {
+ opts.info("[--no-collapse] [--no-reduce] [--reuse-tblox] [-x] [-a] [-s] CLASS", "Generates default/proto individuals for a class");
+ boolean isCollapse = true;
+ boolean isReduce = true;
+ boolean isExtractModule = false;
+ boolean isPrecomputePropertyClassCombinations = true;
+ boolean isCreateNewAbox = true;
+ boolean isAllIndividuals = false;
+ boolean isStrict = true;
+ Set normProps = new HashSet();
+ Set preservedClassSet = null;
+ OWLClass c;
+ while (opts.hasOpts()) {
+ if (opts.nextEq("--no-collapse")) {
+ opts.info("", "if set, do not heuristically collapse individuals");
+ isCollapse = false;
+ }
+ else if (opts.nextEq("--no-reduce")) {
+ opts.info("", "if set, do not perform transitive reduction");
+ isReduce = false;
+ }
+ else if (opts.nextEq("--reuse-tbox")) {
+ opts.info("", "if set, place new individuals in the ontology");
+ isCreateNewAbox = false;
+ }
+ else if (opts.nextEq("-a|--all-individuals")) {
+ isAllIndividuals = true;
+ }
+ else if (opts.nextEq("-s|--is-strict")) {
+ isStrict = true;
+ }
+ else if (opts.nextEq("-x|--extract-module")) {
+ isExtractModule = true;
+ }
+ else if (opts.nextEq("-q|--quick")) {
+ isPrecomputePropertyClassCombinations = false;
+ }
+ else if (opts.nextEq("-p|--property")) {
+ normProps.add(this.resolveObjectProperty(opts.nextOpt()));
+ }
+ else if (opts.nextEq("-l|--plist")) {
+ normProps.addAll(this.resolveObjectPropertyList(opts));
+ }
+ else if (opts.nextEq("--lego")) {
+ preservedClassSet = new HashSet();
+ preservedClassSet.add(g.getDataFactory().getOWLClass(OBOUpperVocabulary.GO_biological_process.getIRI()));
+ preservedClassSet.add(g.getDataFactory().getOWLClass(OBOUpperVocabulary.GO_molecular_function.getIRI()));
+ }
+
+ else {
+ break;
+ }
+ }
+ mmg = getMinimalModelGenerator(isCreateNewAbox);
+ if (isStrict) {
+ mmg.isStrict = true;
+ }
+ mmg.setPrecomputePropertyClassCombinations(isPrecomputePropertyClassCombinations);
+
+ if (isAllIndividuals) {
+ mmg.generateAllNecessaryIndividuals(isCollapse, isReduce);
+ }
+ else {
+ c = this.resolveClass(opts.nextOpt());
+ mmg.generateNecessaryIndividuals(c, isCollapse, isReduce);
+ }
+ for (OWLObjectProperty p : normProps) {
+ mmg.normalizeDirections(p);
+ }
+ if (preservedClassSet != null && preservedClassSet.size() > 0) {
+ mmg.anonymizeIndividualsNotIn(preservedClassSet);
+ }
+ if (isExtractModule) {
+ mmg.extractModule();
+ }
+ g.setSourceOntology(mmg.getModel().getAboxOntology());
+ }
+
+ @CLIMethod("--most-specific-class-expression|--msce")
+ public void msce(Opts opts) throws Exception {
+ opts.info("[-c CLASS] INDIVIDUAL", "Generates MSCE for an individual using MinimalModelGenerator");
+ mmg = getMinimalModelGenerator(false);
+ OWLNamedIndividual ind;
+ OWLClass c = null;
+ while (opts.hasOpts()) {
+ if (opts.nextEq("-c|--class")) {
+ opts.info("CLASS", "if set will add equivalence axioms to CLASS");
+ c = this.resolveClass(opts.nextOpt());
+ }
+ else {
+ break;
+ }
+ }
+ ind = (OWLNamedIndividual) this.resolveEntity(opts);
+ OWLClassExpression ce = mmg.getMostSpecificClassExpression(ind);
+
+ System.out.println(getPrettyPrinter().render(ce));
+ System.out.println(ce);
+
+ if (c != null) {
+ OWLEquivalentClassesAxiom ax = g.getDataFactory().getOWLEquivalentClassesAxiom(c, ce);
+ g.getManager().addAxiom(g.getSourceOntology(), ax);
+ }
+ }
+
+ @CLIMethod("--modalize")
+ public void modalize(Opts opts) throws Exception {
+ opts.info("CLASS", "Take all instances of CLASS and make a generalized statement about them");
+ mmg = getMinimalModelGenerator(false);
+ OWLClass qc = null;
+ OWLObjectProperty p = null;
+ OWLDataFactory df = g.getDataFactory();
+ while (opts.hasOpts()) {
+ if (opts.nextEq("-p|--modal-property")) {
+ p = resolveObjectProperty(opts.nextOpt());
+ opts.info("CLASS", "if set will add equivalence axioms to CLASS");
+ //c = this.resolveClass(opts.nextOpt());
+ }
+ else {
+ break;
+ }
+ }
+ qc = this.resolveClass(opts.nextOpt());
+ Set inds = mmg.getModel().getReasoner().getInstances(qc, false).getFlattened();
+ for (OWLNamedIndividual ind : inds) {
+ OWLClassExpression ce = mmg.getMostSpecificClassExpression(ind);
+ if (ce instanceof OWLObjectIntersectionOf) {
+ for (OWLClassExpression x : ((OWLObjectIntersectionOf)ce).getOperands()) {
+ if (x instanceof OWLObjectSomeValuesFrom) {
+ OWLObjectSomeValuesFrom svf = ((OWLObjectSomeValuesFrom)x);
+
+ }
+ }
+ }
+ Set types = mmg.getModel().getReasoner().getTypes(ind, true).getFlattened();
+
+ System.out.println(getPrettyPrinter().render(ce));
+ System.out.println(ce);
+ for (OWLClass c : types) {
+ df.getOWLSubClassOfAxiom(c, df.getOWLObjectSomeValuesFrom(p, ce));
+ }
+ }
+ }
+
+ @CLIMethod("--gaf2lego")
+ @Deprecated
+ public void gaf2Lego(Opts opts) throws Exception {
+ String output = null;
+ boolean minimize = false;
+ OWLOntologyFormat format = new RDFXMLOntologyFormat();
+ while (opts.hasOpts()) {
+ if (opts.nextEq("-m|--minimize")) {
+ opts.info("", "If set, combine into one model");
+ minimize = true;
+ }
+ else if (opts.nextEq("-o|--output")) {
+ output = opts.nextOpt();
+ }
+ else if (opts.nextEq("--format")) {
+ String formatString = opts.nextOpt();
+ if ("manchester".equalsIgnoreCase(formatString)) {
+ format = new ManchesterOWLSyntaxOntologyFormat();
+ }
+ }
+ else {
+ break;
+ }
+ }
+ if (g != null && gafdoc != null && output != null) {
+ GafToLegoTranslator translator = new GafToLegoTranslator(g, null);
+ OWLOntology lego;
+ if (minimize) {
+ lego = translator.minimizedTranslate(gafdoc);
+ }
+ else {
+ lego = translator.translate(gafdoc);
+ }
+
+ OWLOntologyManager manager = lego.getOWLOntologyManager();
+ OutputStream outputStream = null;
+ try {
+ outputStream = new FileOutputStream(output);
+ manager.saveOntology(lego, format, outputStream);
+ }
+ finally {
+ IOUtils.closeQuietly(outputStream);
+ }
+ }
+ else {
+ if (output == null) {
+ System.err.println("No output file was specified.");
+ }
+ if (g == null) {
+ System.err.println("No graph available for gaf-run-check.");
+ }
+ if (gafdoc == null) {
+ System.err.println("No loaded gaf available for gaf-run-check.");
+ }
+ exit(-1);
+ return;
+ }
+ }
+
+ /**
+ * Translate the GeneAnnotations into a lego all individual OWL representation.
+ *
+ * Will merge the source ontology into the graph by default
+ *
+ * @param opts
+ * @throws Exception
+ */
+ @CLIMethod("--gaf-lego-indivduals")
+ public void gaf2LegoIndivduals(Opts opts) throws Exception {
+ boolean addLineNumber = false;
+ boolean merge = true;
+ boolean minimize = false;
+ String output = null;
+ OWLOntologyFormat format = new RDFXMLOntologyFormat();
+ while (opts.hasOpts()) {
+ if (opts.nextEq("-o|--output")) {
+ output = opts.nextOpt();
+ }
+ else if (opts.nextEq("--format")) {
+ String formatString = opts.nextOpt();
+ if ("manchester".equalsIgnoreCase(formatString)) {
+ format = new ManchesterOWLSyntaxOntologyFormat();
+ }
+ else if ("functional".equalsIgnoreCase(formatString)) {
+ format = new OWLFunctionalSyntaxOntologyFormat();
+ }
+ }
+ else if (opts.nextEq("--add-line-number")) {
+ addLineNumber = true;
+ }
+ else if (opts.nextEq("--skip-merge")) {
+ merge = false;
+ }
+ else if (opts.nextEq("-m|--minimize")) {
+ minimize = true;
+ }
+ else {
+ break;
+ }
+ }
+ if (g != null && gafdoc != null && output != null) {
+ GafToLegoIndividualTranslator tr = new GafToLegoIndividualTranslator(g, addLineNumber);
+ OWLOntology lego = tr.translate(gafdoc);
+
+ if (merge) {
+ new OWLGraphWrapper(lego).mergeImportClosure(true);
+ }
+ if (minimize) {
+ final OWLOntologyManager m = lego.getOWLOntologyManager();
+
+ SyntacticLocalityModuleExtractor sme = new SyntacticLocalityModuleExtractor(m, lego, ModuleType.BOT);
+ Set sig = new HashSet(lego.getIndividualsInSignature());
+ Set moduleAxioms = sme.extract(sig);
+
+ OWLOntology module = m.createOntology(IRI.generateDocumentIRI());
+ m.addAxioms(module, moduleAxioms);
+ lego = module;
+ }
+
+ OWLOntologyManager manager = lego.getOWLOntologyManager();
+ OutputStream outputStream = null;
+ try {
+ outputStream = new FileOutputStream(output);
+ manager.saveOntology(lego, format, outputStream);
+ }
+ finally {
+ IOUtils.closeQuietly(outputStream);
+ }
+ }
+ else {
+ if (output == null) {
+ System.err.println("No output file was specified.");
+ }
+ if (g == null) {
+ System.err.println("No graph available for gaf-run-check.");
+ }
+ if (gafdoc == null) {
+ System.err.println("No loaded gaf available for gaf-run-check.");
+ }
+ exit(-1);
+ return;
+ }
+ }
+
+ @CLIMethod("--generate-molecular-model")
+ @Deprecated
+ public void generateMolecularModel(Opts opts) throws Exception {
+ opts.info("[--owl FILE] [-s SEED-GENE-LIST] [-a] [-r] -p PROCESS", "Generates an activity network (aka lego) from existing GAF and ontology");
+ OWLClass processCls = null;
+ File owlOutputFile = null;
+ boolean isReplaceSourceOntology = false;
+ boolean isPrecomputePropertyClassCombinations = false;
+ boolean isExtractModule = false;
+ List seedGenes = new ArrayList();
+ while (opts.hasOpts()) {
+ if (opts.nextEq("-p")) {
+ processCls = this.resolveClass(opts.nextOpt());
+ }
+ else if (opts.nextEq("-r|--replace")) {
+ isReplaceSourceOntology = true;
+ }
+ else if (opts.nextEq("-q|--quick")) {
+ isPrecomputePropertyClassCombinations = false;
+ }
+ else if (opts.nextEq("-x|--extract-module")) {
+ isExtractModule = true;
+ }
+ else if (opts.nextEq("-a|--all-relation-class-pairs")) {
+ isPrecomputePropertyClassCombinations = true;
+ }
+ else if (opts.nextEq("-s|--seed")) {
+ seedGenes = opts.nextList();
+ }
+ else if (opts.nextEq("--owl")) {
+ owlOutputFile = opts.nextFile();
+ }
+ else {
+ break;
+ }
+ }
+ ModelContainer model = new ModelContainer(g.getSourceOntology(), new ElkReasonerFactory());
+ LegoModelGenerator ni = new LegoModelGenerator(model);
+ ni.setPrecomputePropertyClassCombinations(isPrecomputePropertyClassCombinations);
+ ni.initialize(gafdoc, g);
+
+ String p = g.getIdentifier(processCls);
+ seedGenes.addAll(ni.getGenes(processCls));
+
+ ni.buildNetwork(p, seedGenes);
+
+
+ OWLOntology ont = model.getAboxOntology();
+ if (isExtractModule) {
+ ni.extractModule();
+ }
+ if (owlOutputFile != null) {
+ FileOutputStream os = new FileOutputStream(owlOutputFile);
+ g.getManager().saveOntology(ont, os);
+ }
+ if (isReplaceSourceOntology) {
+ g.setSourceOntology(model.getAboxOntology());
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @CLIMethod("--fetch-candidate-process")
+ @Deprecated
+ public void fetchCandidateProcess(Opts opts) throws Exception {
+ Double pvalThresh = 0.05;
+ Double pvalCorrectedThresh = 0.05;
+ Integer popSize = null;
+ boolean isDirect = false;
+ boolean isReflexive = false;
+ while (opts.hasOpts()) {
+ if (opts.nextEq("-p")) {
+ pvalCorrectedThresh = Double.valueOf(opts.nextOpt());
+ }
+ else if (opts.nextEq("--pval-uncorrected")) {
+ pvalThresh = Double.valueOf(opts.nextOpt());
+ }
+ else if (opts.nextEq("--pop-size")) {
+ popSize = Integer.valueOf(opts.nextOpt());
+ }
+ else if (opts.nextEq("-d")) {
+ isDirect = true;
+ }
+ else if (opts.nextEq("-r")) {
+ isReflexive = true;
+ }
+ else {
+ break;
+ }
+ }
+ OWLClass disease = this.resolveClass(opts.nextOpt());
+
+ OWLPrettyPrinter owlpp = new OWLPrettyPrinter(g);
+ ModelContainer model = new ModelContainer(g.getSourceOntology(), new ElkReasonerFactory());
+ LegoModelGenerator ni = new LegoModelGenerator(model);
+ ni.setPrecomputePropertyClassCombinations(false);
+
+ ni.initialize(gafdoc, g);
+ OWLClass nothing = g.getDataFactory().getOWLNothing();
+ Map smap = ni.fetchScoredCandidateProcesses(disease, popSize);
+ int MAX = 500;
+ int n=0;
+ for (Map.Entry e : smap.entrySet()) {
+ n++;
+ if (n > MAX) {
+ break;
+ }
+ Double score = e.getValue();
+ OWLClass c = e .getKey();
+ System.out.println("PROC\t"+owlpp.render(c)+"\t"+score);
+ }
+ }
+
+ @CLIMethod("--go-multi-enrichment")
+ @Deprecated
+ public void goMultiEnrichment(Opts opts) throws Exception {
+ opts.info("P1 P2", "Generates an activity network (aka lego) from existing GAF and ontology");
+ Double pvalThresh = 0.05;
+ Double pvalCorrectedThresh = 0.05;
+ Integer popSize = null;
+ boolean isDirect = false;
+ boolean isReflexive = false;
+ while (opts.hasOpts()) {
+ if (opts.nextEq("-p")) {
+ pvalCorrectedThresh = Double.valueOf(opts.nextOpt());
+ }
+ else if (opts.nextEq("--pval-uncorrected")) {
+ pvalThresh = Double.valueOf(opts.nextOpt());
+ }
+ else if (opts.nextEq("--pop-size")) {
+ popSize = Integer.valueOf(opts.nextOpt());
+ }
+ else if (opts.nextEq("-d")) {
+ isDirect = true;
+ }
+ else if (opts.nextEq("-r")) {
+ isReflexive = true;
+ }
+ else {
+ break;
+ }
+ }
+ OWLClass rc1 = this.resolveClass(opts.nextOpt());
+ OWLClass rc2 = this.resolveClass(opts.nextOpt());
+ ModelContainer model = new ModelContainer(g.getSourceOntology(), new ElkReasonerFactory());
+ LegoModelGenerator ni = new LegoModelGenerator(model);
+
+ ni.initialize(gafdoc, g);
+ OWLPrettyPrinter owlpp = new OWLPrettyPrinter(g);
+ OWLClass nothing = g.getDataFactory().getOWLNothing();
+ Set sampleSet = model.getReasoner().getSubClasses(rc2, false).getFlattened();
+ sampleSet.remove(nothing);
+ if (isDirect) {
+ sampleSet = Collections.singleton(rc2);
+ }
+ if (isReflexive) {
+ sampleSet.add(rc2);
+ }
+
+ // calc correction factor
+ int numHypotheses = 0;
+ for (OWLClass c1 : model.getReasoner().getSubClasses(rc1, false).getFlattened()) {
+ if (c1.equals(nothing))
+ continue;
+ if (ni.getGenes(c1).size() < 2) {
+ continue;
+ }
+ for (OWLClass c2 : sampleSet) {
+ if (ni.getGenes(c2).size() < 2) {
+ continue;
+ }
+ numHypotheses++;
+ }
+ }
+
+
+ for (OWLClass c1 : model.getReasoner().getSubClasses(rc1, false).getFlattened()) {
+ if (c1.equals(nothing))
+ continue;
+ System.out.println("Sample: "+c1);
+ for (OWLClass c2 : sampleSet) {
+ if (c2.equals(nothing))
+ continue;
+ Double pval = ni.calculatePairwiseEnrichment(c1, c2, popSize);
+ if (pval == null || pval > pvalThresh)
+ continue;
+ Double pvalCorrected = pval * numHypotheses;
+ if (pvalCorrected == null || pvalCorrected > pvalCorrectedThresh)
+ continue;
+ System.out.println("enrich\t"+owlpp.render(c1)+"\t"+owlpp.render(c2)+"\t"+pval+"\t"+pvalCorrected);
+ }
+ }
+ }
+
+ @CLIMethod("--lego-to-gpad")
+ public void legoToAnnotations(Opts opts) throws Exception {
+ String inputName = null;
+ String outputFileName = null;
+ List defaultRefs = null;
+ boolean addLegoModelId = true;
+ while (opts.hasOpts()) {
+ if (opts.nextEq("-i|--input")) {
+ inputName = opts.nextOpt();
+ }
+ else if (opts.nextEq("-o|--output")) {
+ outputFileName = opts.nextOpt();
+ }
+ else if (opts.nextEq("--add-default-ref")) {
+ if (defaultRefs == null) {
+ defaultRefs = new ArrayList();
+ }
+ defaultRefs.add(opts.nextOpt());
+ }
+ else if (opts.nextEq("--remove-lego-model-ids")) {
+ addLegoModelId = false;
+ }
+ else {
+ break;
+ }
+ }
+
+ SimpleEcoMapper mapper = EcoMapperFactory.createSimple();
+ LegoToGeneAnnotationTranslator translator = new LegoToGeneAnnotationTranslator(g, reasoner, mapper);
+ GafDocument annotations = new GafDocument(null, null);
+ BioentityDocument entities = new BioentityDocument(null);
+
+ File inputFile = new File(inputName).getCanonicalFile();
+ OWLOntologyManager m = g.getManager();
+ if (inputFile.isFile()) {
+ OWLOntology model = m.loadOntology(IRI.create(inputFile));
+ String modelId = StringUtils.stripEnd(inputFile.getName(), ".owl");
+ List addtitionalRefs = handleRefs(defaultRefs, addLegoModelId, modelId);
+ translator.translate(model, annotations, entities, addtitionalRefs);
+ }
+ else if (inputFile.isDirectory()) {
+ File[] files = inputFile.listFiles(new FilenameFilter() {
+
+ @Override
+ public boolean accept(File dir, String name) {
+ return StringUtils.trimToEmpty(name).toLowerCase().endsWith(".owl");
+ }
+ });
+ for (File file : files) {
+ String modelId = StringUtils.stripEnd(file.getName(), ".owl");
+ List addtitionalRefs = handleRefs(defaultRefs, addLegoModelId, modelId);
+ OWLOntology model = m.loadOntology(IRI.create(file));
+ translator.translate(model, annotations, entities, addtitionalRefs);
+ }
+ }
+
+ // write GPAD to avoid bioentity data issues
+ PrintWriter fileWriter = null;
+ try {
+ fileWriter = new PrintWriter(new File(outputFileName));
+ GpadWriter writer = new GpadWriter(fileWriter, 1.2d);
+ writer.write(annotations);
+ }
+ finally {
+ IOUtils.closeQuietly(fileWriter);
+ }
+ }
+
+ List handleRefs(List defaultRefs, boolean addLegoModelId, String modelId) {
+ List addtitionalRefs;
+ if (addLegoModelId) {
+ if (defaultRefs == null) {
+ addtitionalRefs = Collections.singletonList(modelId);
+ }
+ else {
+ addtitionalRefs = new ArrayList(defaultRefs.size() + 1);
+ addtitionalRefs.addAll(defaultRefs);
+ addtitionalRefs.add(modelId);
+ }
+ }
+ else {
+ addtitionalRefs = defaultRefs;
+ }
+ return addtitionalRefs;
+ }
+}
diff --git a/minerva-converter/.classpath b/minerva-converter/.classpath
new file mode 100644
index 00000000..b2acffc9
--- /dev/null
+++ b/minerva-converter/.classpath
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/minerva-converter/.gitignore b/minerva-converter/.gitignore
new file mode 100644
index 00000000..2f7896d1
--- /dev/null
+++ b/minerva-converter/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/minerva-converter/.project b/minerva-converter/.project
new file mode 100644
index 00000000..249b612b
--- /dev/null
+++ b/minerva-converter/.project
@@ -0,0 +1,23 @@
+
+
+ minerva-converter
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.m2e.core.maven2Builder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.m2e.core.maven2Nature
+
+
diff --git a/minerva-converter/.settings/org.eclipse.core.resources.prefs b/minerva-converter/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 00000000..e9441bb1
--- /dev/null
+++ b/minerva-converter/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding/=UTF-8
diff --git a/minerva-converter/.settings/org.eclipse.jdt.core.prefs b/minerva-converter/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..ec4300d5
--- /dev/null
+++ b/minerva-converter/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.7
diff --git a/minerva-converter/.settings/org.eclipse.m2e.core.prefs b/minerva-converter/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 00000000..f897a7f1
--- /dev/null
+++ b/minerva-converter/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/minerva-converter/pom.xml b/minerva-converter/pom.xml
new file mode 100644
index 00000000..6234f813
--- /dev/null
+++ b/minerva-converter/pom.xml
@@ -0,0 +1,32 @@
+
+ 4.0.0
+
+ minerva
+ org.geneontology
+ 0.2.2-SNAPSHOT
+
+ minerva-converter
+ Minerva-Converter
+
+
+
+ org.geneontology
+ minerva-core
+ ${project.parent.version}
+
+
+ org.geneontology
+ minerva-json
+ ${project.parent.version}
+ test
+
+
+ org.bbop
+ OWLTools-Core
+ test-jar
+ test
+
+
+
+
diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/GafToLegoIndividualTranslator.java b/minerva-converter/src/main/java/org/geneontology/minerva/GafToLegoIndividualTranslator.java
new file mode 100644
index 00000000..797233d4
--- /dev/null
+++ b/minerva-converter/src/main/java/org/geneontology/minerva/GafToLegoIndividualTranslator.java
@@ -0,0 +1,365 @@
+package org.geneontology.minerva;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
+import org.geneontology.minerva.util.IdStringManager;
+import org.semanticweb.owlapi.model.AddImport;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLAnnotation;
+import org.semanticweb.owlapi.model.OWLAnnotationProperty;
+import org.semanticweb.owlapi.model.OWLAxiom;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLException;
+import org.semanticweb.owlapi.model.OWLImportsDeclaration;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObject;
+import org.semanticweb.owlapi.model.OWLObjectProperty;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyID;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+
+import owltools.gaf.Bioentity;
+import owltools.gaf.ExtensionExpression;
+import owltools.gaf.GafDocument;
+import owltools.gaf.GeneAnnotation;
+import owltools.graph.OWLGraphWrapper;
+import owltools.vocab.OBOUpperVocabulary;
+
+
+/**
+ * Simple translation of {@link GeneAnnotation} to the all individual lego annotation model.
+ *
+ */
+public class GafToLegoIndividualTranslator {
+
+ private static Logger logger = Logger.getLogger(GafToLegoIndividualTranslator.class);
+
+ private final OWLGraphWrapper graph;
+ private final OWLObjectProperty partOf;
+ private final OWLObjectProperty occursIn;
+ private final OWLObjectProperty inTaxon;
+ private OWLClass mf;
+ private OWLObjectProperty enabledBy;
+
+ private Map allOWLObjectsByAltId;
+
+ private final boolean addLineNumber;
+
+ public GafToLegoIndividualTranslator(OWLGraphWrapper graph, boolean addLineNumber) {
+ this.graph = graph;
+ this.addLineNumber = addLineNumber;
+ allOWLObjectsByAltId = graph.getAllOWLObjectsByAltId();
+ OWLDataFactory df = graph.getDataFactory();
+ partOf = OBOUpperVocabulary.BFO_part_of.getObjectProperty(df);
+ occursIn = OBOUpperVocabulary.BFO_occurs_in.getObjectProperty(df);
+
+ mf = OBOUpperVocabulary.GO_molecular_function.getOWLClass(df);
+ enabledBy = OBOUpperVocabulary.GOREL_enabled_by.getObjectProperty(df);
+ inTaxon = graph.getOWLObjectPropertyByIdentifier("RO:0002162"); // in taxon
+ }
+
+ protected void reportError(String error, GeneAnnotation annotation) {
+ logger.error(error+" \t Annotation: "+annotation.toString());
+ }
+
+ protected void reportWarn(String warning, GeneAnnotation annotation) {
+ logger.warn(warning+" \t Annotation: "+annotation.toString());
+ }
+
+ /**
+ * Translate the given {@link GafDocument} into an OWL representation of the LEGO model.
+ *
+ * @param gaf
+ * @return lego ontology
+ * @throws OWLException
+ */
+ public OWLOntology translate(GafDocument gaf) throws OWLException {
+ final OWLOntologyManager m = graph.getManager();
+ OWLOntology lego = m.createOntology(IRI.generateDocumentIRI());
+ OWLOntology sourceOntology = graph.getSourceOntology();
+ OWLOntologyID ontologyID = sourceOntology.getOntologyID();
+ if (ontologyID != null) {
+ IRI ontologyIRI = ontologyID.getOntologyIRI();
+ if (ontologyIRI != null) {
+ OWLDataFactory f = m.getOWLDataFactory();
+ OWLImportsDeclaration importDeclaration = f.getOWLImportsDeclaration(ontologyIRI);
+ m.applyChange(new AddImport(lego, importDeclaration ));
+ }
+ }
+ translate(gaf.getGeneAnnotations(), lego);
+ return lego;
+ }
+
+ /**
+ * Translate the given annotations ({@link GeneAnnotation}) into an OWL representation of the LEGO model.
+ *
+ * @param annotations
+ * @param lego
+ * @throws OWLException
+ */
+ public void translate(Collection annotations, final OWLOntology lego) throws OWLException {
+ final OWLOntologyManager m = graph.getManager();
+
+ Set axioms = new HashSet();
+ for(GeneAnnotation annotation : annotations) {
+ translate(annotation, axioms);
+ }
+ m.addAxioms(lego, axioms);
+ }
+
+ /**
+ * Translate theGeneAnnotation into an OWL representation of the LEGO model.
+ *
+ * @param annotation
+ * @param axioms
+ * @throws OWLException
+ */
+ public void translate(GeneAnnotation annotation, Set axioms) throws OWLException {
+ // skip ND annotations
+ if ("ND".equals(annotation.getShortEvidence())) {
+ reportWarn("Skipping ND annotation", annotation);
+ return;
+ }
+ // skip annotation using a qualifier
+ String rel = StringUtils.trimToNull(annotation.getRelation());
+ if (rel != null) {
+ if ("enables".equals(rel) == false && "part_of".equals(rel) == false && "involved_in".equals(rel) == false) {
+ reportWarn("Skipping annotation with unsupported relation: "+annotation.getRelation(), annotation);
+ return;
+ }
+ }
+
+ final OWLDataFactory f = graph.getDataFactory();
+
+
+ final String annotationClsString = annotation.getCls();
+ final OWLClass c = getOwlClass(annotationClsString);
+ if (c == null) {
+ reportError("Could not find a class for the given identifier: "+annotationClsString, annotation);
+ return;
+ }
+
+ List> extensionExpressionGroups = annotation.getExtensionExpressions();
+ if (extensionExpressionGroups != null && !extensionExpressionGroups.isEmpty()) {
+ Set parsedGroups = new HashSet();
+ for(List group : extensionExpressionGroups) {
+ Set operands = new HashSet();
+ for(ExtensionExpression extension : group) {
+ final String extensionClsString = extension.getCls();
+ final String extensionRelationString = extension.getRelation();
+ OWLClass extensionCls = getOwlClass(extensionClsString);
+ if (extensionCls == null) {
+ IRI extensionIRI = IdStringManager.getIRI(extensionClsString);
+ extensionCls = f.getOWLClass(extensionIRI);
+ }
+ final OWLObjectProperty extensionRelation = graph.getOWLObjectPropertyByIdentifier(extensionRelationString);
+ if (extensionRelation == null) {
+ reportError("Could not find a class for the given extension relation identifier: "+extensionRelationString, annotation);
+ continue;
+ }
+ operands.add(f.getOWLObjectSomeValuesFrom(extensionRelation, extensionCls));
+ }
+ operands.add(c);
+ parsedGroups.add(f.getOWLObjectIntersectionOf(operands));
+ }
+ if (annotation.isNegated()) {
+ OWLClassExpression union = f.getOWLObjectUnionOf(parsedGroups);
+ translate(annotation, union, axioms);
+ }
+ else {
+ for(OWLClassExpression ce : parsedGroups) {
+ translate(annotation, ce, axioms);
+ }
+ }
+ }
+ else {
+ translate(annotation, c, axioms);
+ }
+ }
+
+
+ private void translate(GeneAnnotation annotation, OWLClassExpression ce, Set axioms) throws OWLException {
+ final OWLDataFactory f = graph.getDataFactory();
+
+ // # STEP 1 - Bioentity instance
+ final Bioentity bioentity = annotation.getBioentityObject();
+ final String isoForm = StringUtils.trimToNull(annotation.getGeneProductForm());
+
+ final OWLClass bioentityClass;
+ if (isoForm == null) {
+ // option #1: default bioentity id
+ bioentityClass = addBioentityCls(bioentity.getId(), bioentity.getSymbol(), bioentity.getNcbiTaxonId(), axioms, f);
+ }
+ else {
+ // option #2: ISO-form as subclass of bioentity
+ bioentityClass = addBioentityCls(isoForm, bioentity.getSymbol()+" ISO Form "+isoForm, bioentity.getNcbiTaxonId(), axioms, f);
+ OWLClass bioentityClassSuper = addBioentityCls(bioentity.getId(), bioentity.getSymbol(), bioentity.getNcbiTaxonId(), axioms, f);
+ axioms.add(f.getOWLDeclarationAxiom(bioentityClassSuper));
+ axioms.add(f.getOWLSubClassOfAxiom(bioentityClass, bioentityClassSuper));
+ }
+
+ IRI bioentityInstanceIRI = generateNewIRI("bioentity", bioentityClass);
+ OWLNamedIndividual bioentityInstance = f.getOWLNamedIndividual(bioentityInstanceIRI);
+ axioms.add(f.getOWLDeclarationAxiom(bioentityInstance));
+ axioms.add(f.getOWLClassAssertionAxiom(bioentityClass, bioentityInstance));
+
+ // # STEP 2 - create instance:
+
+ // use Aspect to switch between the three options: P == BP, C == CC, F = MF
+ String aspect = annotation.getAspect();
+ if (aspect == null) {
+ reportError("Error, no aspect defined.", annotation);
+ return;
+ }
+
+ // TODO evidence
+ Set annotations = Collections.emptySet();
+ if (addLineNumber) {
+ int lineNumber = annotation.getSource().getLineNumber();
+ OWLAnnotation source = f.getOWLAnnotation(getLineNumberProperty(axioms, f), f.getOWLLiteral(lineNumber));
+ annotations = Collections.singleton(source);
+ }
+ boolean negated = annotation.isNegated();
+ if (negated) {
+ handleNegated(bioentityClass, aspect, annotations, ce, axioms, f);
+ return;
+ }
+
+ //List sources = annotation.getReferenceIds();
+ if ("F".equals(aspect)) {
+ // create individual
+ OWLNamedIndividual individual = f.getOWLNamedIndividual(generateNewIRI("mf", ce));
+ axioms.add(f.getOWLDeclarationAxiom(individual));
+
+ // types
+ axioms.add(f.getOWLClassAssertionAxiom(ce, individual));
+
+ // link instances
+
+ axioms.add(f.getOWLObjectPropertyAssertionAxiom(enabledBy, individual, bioentityInstance, annotations));
+ }
+ else if ("C".equals(aspect)) {
+ // generic mf instance
+ OWLNamedIndividual mfIndividual = f.getOWLNamedIndividual(generateNewIRI("mf", mf));
+ axioms.add(f.getOWLDeclarationAxiom(mfIndividual));
+
+ // generic mf type
+ axioms.add(f.getOWLClassAssertionAxiom(mf, mfIndividual));
+
+ // link mf to bioentity
+ axioms.add(f.getOWLObjectPropertyAssertionAxiom(enabledBy, mfIndividual, bioentityInstance));
+
+ // cc instance
+ OWLNamedIndividual ccIndividual = f.getOWLNamedIndividual(generateNewIRI("cc", ce));
+ axioms.add(f.getOWLDeclarationAxiom(ccIndividual));
+
+ // cc type
+ axioms.add(f.getOWLClassAssertionAxiom(ce, ccIndividual));
+
+ // link cc and mf
+ axioms.add(f.getOWLObjectPropertyAssertionAxiom(occursIn, ccIndividual, mfIndividual, annotations));
+
+
+ }
+ else if ("P".equals(aspect)) {
+ // generic mf instance
+ OWLNamedIndividual mfIndividual = f.getOWLNamedIndividual(generateNewIRI("mf", mf));
+ axioms.add(f.getOWLDeclarationAxiom(mfIndividual));
+
+ // generic mf type
+ axioms.add(f.getOWLClassAssertionAxiom(mf, mfIndividual));
+
+ // link mf to bioentity
+ axioms.add(f.getOWLObjectPropertyAssertionAxiom(enabledBy, mfIndividual, bioentityInstance));
+
+ // cc instance
+ OWLNamedIndividual bpIndividual = f.getOWLNamedIndividual(generateNewIRI("bp", ce));
+ axioms.add(f.getOWLDeclarationAxiom(bpIndividual));
+
+ // cc type
+ axioms.add(f.getOWLClassAssertionAxiom(ce, bpIndividual));
+
+ // link cc and mf
+ axioms.add(f.getOWLObjectPropertyAssertionAxiom(partOf, bpIndividual, mfIndividual, annotations));
+ }
+ }
+
+ private void handleNegated(OWLClass bioentityClass, String aspect, Set annotations,
+ OWLClassExpression ce, Set axioms, OWLDataFactory f) {
+ if ("F".equals(aspect)) {
+ OWLClassExpression notCE = f.getOWLObjectComplementOf(f.getOWLObjectSomeValuesFrom(enabledBy, ce));
+ axioms.add(f.getOWLSubClassOfAxiom(bioentityClass, notCE, annotations));
+ }
+ else if ("C".equals(aspect)) {
+ OWLClassExpression notCE = f.getOWLObjectComplementOf(f.getOWLObjectSomeValuesFrom(occursIn, ce));
+ axioms.add(f.getOWLSubClassOfAxiom(bioentityClass, notCE, annotations));
+ }
+ else if ("P".equals(aspect)) {
+ OWLClassExpression notCE = f.getOWLObjectComplementOf(f.getOWLObjectSomeValuesFrom(partOf, ce));
+ axioms.add(f.getOWLSubClassOfAxiom(bioentityClass, notCE, annotations));
+ }
+ }
+
+ private OWLClass addBioentityCls(String id, String lbl, String taxon, Set axioms, OWLDataFactory f) {
+ IRI iri = IdStringManager.getIRI(id);
+ OWLClass cls = f.getOWLClass(iri);
+ boolean add = axioms.add(f.getOWLDeclarationAxiom(cls));
+ if (add) {
+ OWLAnnotation annotation = f.getOWLAnnotation(f.getRDFSLabel(), f.getOWLLiteral(lbl));
+ axioms.add(f.getOWLAnnotationAssertionAxiom(iri, annotation));
+ if (taxon != null) {
+ OWLClass taxonClass = f.getOWLClass(IdStringManager.getIRI(taxon));
+ axioms.add(f.getOWLDeclarationAxiom(taxonClass));
+ axioms.add(f.getOWLSubClassOfAxiom(cls,
+ f.getOWLObjectSomeValuesFrom(inTaxon, taxonClass)));
+ }
+ }
+ return cls;
+ }
+
+ /**
+ * @param id
+ * @return cls or null
+ */
+ private OWLClass getOwlClass(String id) {
+ OWLClass cls = graph.getOWLClassByIdentifier(id);
+ if (cls == null) {
+ // check alt ids
+ OWLObject owlObject = allOWLObjectsByAltId.get(id);
+ if (owlObject != null && owlObject instanceof OWLClass) {
+ cls = (OWLClass) owlObject;
+ }
+ }
+ return cls;
+ }
+
+
+ private static final IRI GAF_LINE_NUMBER = IRI.create("http://gaf/line_number");
+
+ private OWLAnnotationProperty getLineNumberProperty(Set axioms, OWLDataFactory f) {
+ OWLAnnotationProperty p = f.getOWLAnnotationProperty(GAF_LINE_NUMBER);
+ axioms.add(f.getOWLDeclarationAxiom(p));
+ return p;
+ }
+
+ private IRI generateNewIRI(String type, OWLClassExpression ce) {
+ if( ce.isAnonymous() == false) {
+ OWLClass c = ce.asOWLClass();
+ String id = StringUtils.replaceOnce(IdStringManager.getId(c.getIRI()), ":", "_");
+ type = type + "-" + id;
+ }
+ return IRI.create("http://geneontology.org/lego/"+type+"-"+UUID.randomUUID().toString());
+
+ }
+
+}
diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/GafToLegoTranslator.java b/minerva-converter/src/main/java/org/geneontology/minerva/GafToLegoTranslator.java
new file mode 100644
index 00000000..65da637a
--- /dev/null
+++ b/minerva-converter/src/main/java/org/geneontology/minerva/GafToLegoTranslator.java
@@ -0,0 +1,492 @@
+package org.geneontology.minerva;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+import org.obolibrary.obo2owl.Obo2OWLConstants;
+import org.semanticweb.owlapi.model.AddImport;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLAnnotationProperty;
+import org.semanticweb.owlapi.model.OWLAxiom;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLDeclarationAxiom;
+import org.semanticweb.owlapi.model.OWLEntity;
+import org.semanticweb.owlapi.model.OWLException;
+import org.semanticweb.owlapi.model.OWLImportsDeclaration;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObject;
+import org.semanticweb.owlapi.model.OWLObjectProperty;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+import org.semanticweb.owlapi.vocab.OWLRDFVocabulary;
+
+import owltools.gaf.Bioentity;
+import owltools.gaf.ExtensionExpression;
+import owltools.gaf.GafDocument;
+import owltools.gaf.GeneAnnotation;
+import owltools.graph.OWLGraphWrapper;
+import owltools.vocab.OBOUpperVocabulary;
+import uk.ac.manchester.cs.owlapi.modularity.ModuleType;
+import uk.ac.manchester.cs.owlapi.modularity.SyntacticLocalityModuleExtractor;
+
+/**
+ *
+Given a set of gene associations, this procedure will generate LEGO individuals.
+
+The set of associations can be specified by a user query. Includes:
+
+ * grepping a GAF and feeding results
+ * selecting all associations for all genes that are involved with some process
+
+# STEP 0 - map GeneAssociation in GAF model
+
+GeneAssociation(
+ bioentity:
+ class:
+ ext:
+ reference:
+ evidence: # TODO
+)
+
+==>
+
+# STEP 1 - calculate class expression
+
+IF
+ THEN let = IntersectionOf()
+ ELSE let =
+
+# STEP 2 - map to protein ID
+
+IF .IRI startsWith "uniProtKB"
+ THEN let =
+ ELSE let = SELECT WHERE SubClassOf encoded_by some ### requires Omeo
+
+# STEP 3 - create instance:
+
+IF SubClassOf MF THEN:
+
+ NamedIndividual(
+ Types:
+ ,
+ enabled_by SOME
+ Facts:
+ source
+
+ELSE IF SubClassOf CC THEN:
+
+ NamedIndividual(
+ Types:
+ 'molecular_function', occurs_in some
+ enabled_by SOME
+ Facts:
+ source
+
+ELSE IF SubClassOf BP THEN:
+
+ # note we create two individuals here
+
+ NamedIndividual(
+ Types:
+
+ Facts:
+ source
+
+
+ NamedIndividual(
+ Types:
+ 'molecular_function'
+ enabled_by SOME
+ Facts:
+ part_of ,
+ source
+
+
+# VARIANT OF ABOVE STEP
+
+(optional)
+
+keep a map of Refs -> generated Ids
+
+when performing , first check map. If an individual Id has already been generated for this , then re-use the existing id from the map.
+
+Note this may result in multiple classification of individuals (MCI). The user can rectify these in Protege.
+
+One variant of this strategy may be to retain the original Id,
+generate new Ids for the collapsed aggregate MF individual, and
+include evidence links back to the atomic MF individuals.
+
+
+
+@see lego-from-gaf.txt
+ */
+@Deprecated
+public class GafToLegoTranslator {
+
+ private static Logger logger = Logger.getLogger(GafToLegoTranslator.class);
+
+ private final OWLGraphWrapper graph;
+ private final Map gp2protein;
+ private OWLObjectProperty partOf;
+ private OWLObjectProperty occursIn;
+ private OWLClass mf;
+ private OWLObjectProperty enabledBy;
+ private OWLObjectProperty geneProductOf;
+
+ private Map allOWLObjectsByAltId;
+
+ public GafToLegoTranslator(OWLGraphWrapper graph, Map gp2protein) {
+ this.graph = graph;
+ allOWLObjectsByAltId = graph.getAllOWLObjectsByAltId();
+ this.gp2protein = gp2protein;
+ OWLDataFactory df = graph.getDataFactory();
+ partOf = OBOUpperVocabulary.BFO_part_of.getObjectProperty(df);
+ occursIn = OBOUpperVocabulary.BFO_occurs_in.getObjectProperty(df);
+
+ mf = OBOUpperVocabulary.GO_molecular_function.getOWLClass(df);
+ enabledBy = OBOUpperVocabulary.GOREL_enabled_by.getObjectProperty(df);
+ geneProductOf = OBOUpperVocabulary.RO_gene_product_of.getObjectProperty(df);
+ }
+
+ protected void reportError(String error, GeneAnnotation annotation) {
+ logger.error(error+" \t Annotation: "+annotation.toString());
+ }
+
+ protected void reportWarn(String warning, GeneAnnotation annotation) {
+ logger.warn(warning+" \t Annotation: "+annotation.toString());
+ }
+
+ /**
+ * Translate the given {@link GafDocument} into an OWL representation of the LEGO model.
+ *
+ * @param gaf
+ * @return lego ontology
+ */
+ public OWLOntology translate(GafDocument gaf) {
+ return translate(gaf.getGeneAnnotations());
+ }
+
+ /**
+ * Translate the given annotations ({@link GeneAnnotation}) into an OWL representation of the LEGO model.
+ *
+ * @param annotations
+ * @return lego ontology
+ */
+ public OWLOntology translate(Collection annotations) {
+ final OWLDataFactory f = graph.getDataFactory();
+ final OWLOntologyManager m = graph.getManager();
+ try {
+ OWLOntology lego = m.createOntology(IRI.generateDocumentIRI());
+ // add all ontologies from the graph wrapper as import to the new ontology
+ Set allOntologies = graph.getAllOntologies();
+ for (OWLOntology importOntology : allOntologies) {
+ IRI importIRI = importOntology.getOntologyID().getOntologyIRI();
+ OWLImportsDeclaration importDeclaration = f.getOWLImportsDeclaration(importIRI);
+ m.applyChange(new AddImport(lego, importDeclaration));
+ }
+
+ for(GeneAnnotation annotation : annotations) {
+ /*
+ * GeneAssociation(
+ * bioentity:
+ * class:
+ * ext:
+ * reference:
+ * evidence: # TODO
+ * )
+ */
+ final String annotationClsString = annotation.getCls();
+ final OWLClass c = getOwlClass(annotationClsString);
+ String classLabel = graph.getLabel(c);
+ if (c == null) {
+ reportError("Could not find a class for the given identifier: "+annotationClsString, annotation);
+ continue;
+ }
+
+ // STEP 1 - calculate class expression
+ //
+ // IF
+ // THEN let = IntersectionOf()
+ // ELSE let =
+
+ final Set ceSet;
+ List> extensionExpressionGroups = annotation.getExtensionExpressions();
+ if (extensionExpressionGroups != null && !extensionExpressionGroups.isEmpty()) {
+ ceSet = new HashSet();
+ for(List group : extensionExpressionGroups) {
+ Set operands = new HashSet();
+ for(ExtensionExpression extension : group) {
+ final String extensionClsString = extension.getCls();
+ final String extensionRelationString = extension.getRelation();
+ OWLClass extensionCls = getOwlClass(extensionClsString);
+ if (extensionCls == null && extensionClsString.startsWith("UniProtKB:")) {
+ IRI iri = IRI.create(Obo2OWLConstants.DEFAULT_IRI_PREFIX+"pr/"+extensionClsString.substring(10));
+ extensionCls = f.getOWLClass(iri);
+ }
+ if (extensionCls == null) {
+ reportError("Could not find a class for the given extension cls identifier: "+extensionClsString, annotation);
+ continue;
+ }
+ final OWLObjectProperty extensionRelation = graph.getOWLObjectPropertyByIdentifier(extensionRelationString);
+ if (extensionRelation == null) {
+ reportError("Could not find a class for the given extension relation identifier: "+extensionRelationString, annotation);
+ continue;
+ }
+ operands.add(f.getOWLObjectSomeValuesFrom(extensionRelation, extensionCls));
+ }
+ // if (operands.size() != extensionExpressions.size()) {
+ // reportError("Problems during the translation of the annotation extensions.", annotation);
+ // continue;
+ // }
+ operands.add(c);
+ ceSet.add(f.getOWLObjectIntersectionOf(operands));
+ }
+ }
+ else {
+ ceSet = Collections.singleton(c);
+ }
+
+ // # STEP 2 - map to protein ID
+ Bioentity bioentity = annotation.getBioentityObject();
+ String dbprefix = bioentity.getDb();
+ String annLabel = bioentity.getSymbol() + " " + classLabel;
+
+ // TODO use ISO form information
+ // IF .IRI startsWith "uniProtKB"
+ // THEN let =
+ OWLClassExpression enabler;
+ if (dbprefix.equalsIgnoreCase("uniProtKB")) {
+ OWLClass pr = f.getOWLClass(IRI.create(Obo2OWLConstants.DEFAULT_IRI_PREFIX+"pr/"+bioentity.getDBID()));
+ addBioEntity(pr, lego, bioentity);
+ enabler = pr;
+ }
+ else {
+ // TODO use gp2protein
+ OWLClass gene = f.getOWLClass(graph.getIRIByIdentifier(bioentity.getId()));
+ OWLClassExpression pr = f.getOWLObjectSomeValuesFrom(geneProductOf, gene);
+ addBioEntity(gene, lego, bioentity);
+ enabler = pr;
+ //reportWarn("Skipping non-uniProtKB bioentity: "+bioentity.getId(), annotation);
+ //continue;
+ }
+
+ // # STEP 3 - create instance:
+
+ // use Aspect to switch between the three options: P == BP, C == CC, F = MF
+ String aspect = annotation.getAspect();
+ if (aspect == null) {
+ reportError("Error, no aspect defined.", annotation);
+ continue;
+ }
+
+ Set axioms = new HashSet();
+ List sources = annotation.getReferenceIds();
+ OWLNamedIndividual annIndividual = null;
+ // IF SubClassOf MF THEN:
+ if ("F".equals(aspect)) {
+ // NamedIndividual(
+ // Types:
+ // ,
+ // enabled_by SOME
+ // Facts:
+ // source
+
+ for(OWLClassExpression ce : ceSet) {
+ // create individual
+ OWLNamedIndividual individual = f.getOWLNamedIndividual(generateNewIRI(lego, "mf"));
+ axioms.add(f.getOWLDeclarationAxiom(individual));
+
+ // facts
+ OWLAnnotationProperty dcsource = getDcSourceProperty(lego, f);
+ for(String source : sources) {
+ axioms.add(f.getOWLAnnotationAssertionAxiom(dcsource, individual.getIRI(), f.getOWLLiteral(source)));
+ }
+
+ // types
+ axioms.add(f.getOWLClassAssertionAxiom(ce, individual));
+ axioms.add(f.getOWLClassAssertionAxiom(f.getOWLObjectSomeValuesFrom(enabledBy, enabler), individual));
+
+ axioms.add(labelAxiom(f, individual, annLabel));
+ }
+ }
+ // ELSE IF SubClassOf CC THEN:
+ else if ("C".equals(aspect)) {
+ // NamedIndividual(
+ // Types:
+ // 'molecular_function', occurs_in some
+ // enabled_by SOME
+ // Facts:
+ // source
+
+ for(OWLClassExpression ce : ceSet) {
+ OWLNamedIndividual individual = f.getOWLNamedIndividual(generateNewIRI(lego, "cc"));
+ axioms.add(f.getOWLDeclarationAxiom(individual));
+
+ // facts
+ OWLAnnotationProperty dcsource = getDcSourceProperty(lego, f);
+ for(String source : sources) {
+ axioms.add(f.getOWLAnnotationAssertionAxiom(dcsource, individual.getIRI(), f.getOWLLiteral(source)));
+ }
+
+ // types
+ axioms.add(f.getOWLClassAssertionAxiom(mf, individual));
+ axioms.add(f.getOWLClassAssertionAxiom(f.getOWLObjectSomeValuesFrom(occursIn, ce), individual));
+ axioms.add(f.getOWLClassAssertionAxiom(f.getOWLObjectSomeValuesFrom(enabledBy, enabler), individual));
+
+ axioms.add(labelAxiom(f, individual, annLabel));
+
+ }
+ }
+ //ELSE IF SubClassOf BP THEN:
+ else if ("P".equals(aspect)) {
+ // # note we create two individuals here
+
+ for(OWLClassExpression ce : ceSet) {
+ // NamedIndividual(
+ // Types:
+ //
+ // Facts:
+ // source
+ // create individual
+ OWLNamedIndividual individualX = f.getOWLNamedIndividual(generateNewIRI(lego, "bp"));
+ axioms.add(f.getOWLDeclarationAxiom(individualX));
+
+ // facts
+ OWLAnnotationProperty dcsource = getDcSourceProperty(lego, f);
+ for(String source : sources) {
+ axioms.add(f.getOWLAnnotationAssertionAxiom(dcsource, individualX.getIRI(), f.getOWLLiteral(source)));
+ }
+
+ // types
+ axioms.add(f.getOWLClassAssertionAxiom(ce, individualX));
+ axioms.add(labelAxiom(f, individualX, classLabel+" "+individualX.getIRI().getFragment()));
+
+
+ // NamedIndividual(
+ // Types:
+ // 'molecular_function'
+ // enabled_by SOME
+ // Facts:
+ // part_of ,
+ // source
+ OWLNamedIndividual individual = f.getOWLNamedIndividual(generateNewIRI(lego, "bp"));
+ axioms.add(f.getOWLDeclarationAxiom(individual));
+
+ axioms.add(labelAxiom(f, individual, annLabel));
+
+ // facts
+ for(String source : sources) {
+ axioms.add(f.getOWLAnnotationAssertionAxiom(dcsource, individual.getIRI(), f.getOWLLiteral(source)));
+ }
+ axioms.add(f.getOWLObjectPropertyAssertionAxiom(partOf, individual, individualX));
+
+ // types
+ axioms.add(f.getOWLClassAssertionAxiom(mf, individual));
+ axioms.add(f.getOWLClassAssertionAxiom(f.getOWLObjectSomeValuesFrom(enabledBy, enabler), individual));
+ }
+ }
+ else {
+ reportError("Error, unknown aspect: "+aspect, annotation);
+ continue;
+ }
+
+ m.addAxioms(lego, axioms);
+ }
+
+ return lego;
+ }
+ catch (OWLException e) {
+ throw new RuntimeException("Could not create lego model.", e);
+ }
+ }
+
+ private OWLAxiom labelAxiom(OWLDataFactory f, OWLNamedIndividual individual, String annLabel) {
+ return
+ f.getOWLAnnotationAssertionAxiom(
+ f.getOWLAnnotationProperty(OWLRDFVocabulary.RDFS_LABEL.getIRI()),
+ individual.getIRI(),
+ f.getOWLLiteral(annLabel));
+ }
+
+ /**
+ * @param id
+ * @return cls or null
+ */
+ private OWLClass getOwlClass(String id) {
+ OWLClass cls = graph.getOWLClassByIdentifier(id);
+ if (cls == null) {
+ // check alt ids
+ OWLObject owlObject = allOWLObjectsByAltId.get(id);
+ if (owlObject != null && owlObject instanceof OWLClass) {
+ cls = (OWLClass) owlObject;
+ }
+ }
+ return cls;
+ }
+
+ private void addBioEntity(OWLClass pr, OWLOntology lego, Bioentity bioentity) {
+ Set declarationAxioms = lego.getDeclarationAxioms(pr);
+ if (declarationAxioms == null || declarationAxioms.isEmpty()) {
+ // add class declaration and add label
+ OWLOntologyManager m = lego.getOWLOntologyManager();
+ OWLDataFactory f = m.getOWLDataFactory();
+
+ Set axioms = new HashSet();
+ axioms.add(f.getOWLDeclarationAxiom(pr));
+
+ String label = bioentity.getSymbol()+" - "+bioentity.getFullName();
+
+ axioms.add(f.getOWLAnnotationAssertionAxiom(f.getRDFSLabel(), pr.getIRI(), f.getOWLLiteral(label)));
+
+ m.addAxioms(lego, axioms);
+ }
+ }
+
+ private static final IRI DC_SOURCE = IRI.create("http://purl.org/dc/terms/source");
+
+ private OWLAnnotationProperty getDcSourceProperty(OWLOntology lego, OWLDataFactory f) {
+ OWLAnnotationProperty p = f.getOWLAnnotationProperty(DC_SOURCE);
+ Set declarationAxioms = lego.getDeclarationAxioms(p);
+ if (declarationAxioms == null || declarationAxioms.isEmpty()) {
+ OWLOntologyManager m = lego.getOWLOntologyManager();
+ m.addAxiom(lego, f.getOWLDeclarationAxiom(p));
+ }
+ return p;
+ }
+
+ private IRI generateNewIRI(OWLOntology ont, String type) {
+ return IRI.create("http://geneontology.org/lego/"+type+"/"+UUID.randomUUID().toString());
+ }
+
+ /**
+ * Translate the given {@link GafDocument} into an OWL representation of the LEGO model.
+ * Additionally minimize the lego model and imports into one ontology module.
+ *
+ * @param gaf
+ * @return minimized lego ontology
+ */
+ public OWLOntology minimizedTranslate(GafDocument gaf) {
+ OWLOntology all = translate(gaf);
+ final OWLOntologyManager m = all.getOWLOntologyManager();
+
+ SyntacticLocalityModuleExtractor sme = new SyntacticLocalityModuleExtractor(m, all, ModuleType.BOT);
+ Set sig = new HashSet(all.getIndividualsInSignature());
+ Set moduleAxioms = sme.extract(sig);
+
+ try {
+ OWLOntology module = m.createOntology(IRI.generateDocumentIRI());
+ m.addAxioms(module, moduleAxioms);
+ return module;
+ } catch (OWLException e) {
+ throw new RuntimeException("Could not create minimized lego model.", e);
+ }
+ }
+}
diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/format/LegeModelVersionConverterMain.java b/minerva-converter/src/main/java/org/geneontology/minerva/format/LegeModelVersionConverterMain.java
new file mode 100644
index 00000000..0877c560
--- /dev/null
+++ b/minerva-converter/src/main/java/org/geneontology/minerva/format/LegeModelVersionConverterMain.java
@@ -0,0 +1,72 @@
+package org.geneontology.minerva.format;
+
+import java.io.File;
+import java.io.FileFilter;
+
+import org.apache.commons.io.FilenameUtils;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLOntology;
+
+import owltools.cli.Opts;
+import owltools.io.CatalogXmlIRIMapper;
+import owltools.io.ParserWrapper;
+
+public class LegeModelVersionConverterMain {
+
+ public static void main(String[] args) throws Exception {
+ ParserWrapper pw = new ParserWrapper();
+ String inputFolder = null;
+ String outputFolder = null;
+ Opts opts = new Opts(args);
+ while (opts.hasOpts()) {
+ if (opts.nextEq("--use-catalog|--use-catalog-xml"))
+ pw.addIRIMapper(new CatalogXmlIRIMapper(new File("catalog-v001.xml").getAbsoluteFile()));
+ else if (opts.nextEq("--catalog-xml"))
+ pw.addIRIMapper(new CatalogXmlIRIMapper(opts.nextOpt()));
+ else if (opts.nextEq("-i|--input-folder")) {
+ inputFolder = opts.nextOpt();
+ }
+ else if (opts.nextEq("-o|--output-folder")) {
+ outputFolder = opts.nextOpt();
+ }
+ else
+ break;
+ }
+ if (inputFolder == null) {
+ throw new Exception("No input folder specified");
+ }
+ if (outputFolder == null) {
+ throw new Exception("No output folder specified");
+ }
+
+ File input = new File(inputFolder).getCanonicalFile();
+ File output = new File(outputFolder).getCanonicalFile();
+
+ File[] owlFiles = input.listFiles(new FileFilter() {
+
+ @Override
+ public boolean accept(File pathname) {
+ String extension = FilenameUtils.getExtension(pathname.getName());
+ if (extension != null) {
+ return "owl".equalsIgnoreCase(extension);
+ }
+ return false;
+ }
+ });
+ if (owlFiles.length == 0) {
+ throw new Exception("No owl files found in input folder: "+inputFolder);
+ }
+
+ LegoModelVersionConverter converter = new LegoModelVersionConverter();
+ for (File owlFile : owlFiles) {
+ final OWLOntology abox = pw.parseOWL(IRI.create(owlFile));
+ final String modelId = FilenameUtils.removeExtension(owlFile.getName());
+ converter.convertLegoModelToAllIndividuals(abox, modelId);
+
+ final File outputFile = new File(output, owlFile.getName());
+ abox.getOWLOntologyManager().saveOntology(abox, IRI.create(outputFile));
+ }
+
+ }
+
+}
diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/format/LegoModelVersionConverter.java b/minerva-converter/src/main/java/org/geneontology/minerva/format/LegoModelVersionConverter.java
new file mode 100644
index 00000000..d5fb8ad7
--- /dev/null
+++ b/minerva-converter/src/main/java/org/geneontology/minerva/format/LegoModelVersionConverter.java
@@ -0,0 +1,256 @@
+package org.geneontology.minerva.format;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.geneontology.minerva.CoreMolecularModelManager;
+import org.geneontology.minerva.util.IdStringManager.AnnotationShorthand;
+import org.semanticweb.owlapi.model.AddAxiom;
+import org.semanticweb.owlapi.model.AxiomType;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLAnnotation;
+import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLAnnotationProperty;
+import org.semanticweb.owlapi.model.OWLAnnotationSubject;
+import org.semanticweb.owlapi.model.OWLAnnotationValue;
+import org.semanticweb.owlapi.model.OWLAnnotationValueVisitor;
+import org.semanticweb.owlapi.model.OWLAnonymousIndividual;
+import org.semanticweb.owlapi.model.OWLAxiom;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLIndividualAxiom;
+import org.semanticweb.owlapi.model.OWLLiteral;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
+import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyChange;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+import org.semanticweb.owlapi.model.RemoveAxiom;
+import org.semanticweb.owlapi.util.OWLAxiomVisitorAdapter;
+
+public class LegoModelVersionConverter {
+
+ static class EvidenceTriple {
+ final Set ecoIRIs = new HashSet();
+ final Set evidenceAnnotations = new HashSet();
+ final Set contributors = new HashSet();
+
+ public static EvidenceTriple createEvidenceTriple(Set axioms, OWLOntology abox, List changes) {
+ final EvidenceTriple triple = new EvidenceTriple();
+ for(OWLAnnotationAssertionAxiom axiom : axioms) {
+ OWLAnnotationProperty property = axiom.getProperty();
+ if (AnnotationShorthand.evidence.getAnnotationProperty().equals(property.getIRI())) {
+ OWLAnnotationValue value = axiom.getValue();
+ value.accept(new OWLAnnotationValueVisitor() {
+
+ @Override
+ public void visit(OWLLiteral literal) {
+ // ignore
+ }
+
+ @Override
+ public void visit(OWLAnonymousIndividual individual) {
+ // ignore
+ }
+
+ @Override
+ public void visit(IRI iri) {
+ triple.ecoIRIs.add(iri);
+ }
+ });
+ changes.add(new RemoveAxiom(abox, axiom));
+ }
+ else if(AnnotationShorthand.contributor.getAnnotationProperty().equals(property.getIRI())) {
+ // keep and propagate
+ triple.contributors.add(axiom.getAnnotation());
+ }
+ else if(AnnotationShorthand.date.getAnnotationProperty().equals(property.getIRI())) {
+ // keep and propagate
+ triple.contributors.add(axiom.getAnnotation());
+ }
+ else if(AnnotationShorthand.comment.getAnnotationProperty().equals(property.getIRI())) {
+ // keep only
+ }
+ else {
+ // remove and move to evidence individual
+ changes.add(new RemoveAxiom(abox, axiom));
+ triple.evidenceAnnotations.add(axiom.getAnnotation());
+ }
+ }
+ return triple;
+ }
+
+ public static EvidenceTriple createEvidenceTriple(Set annotations) {
+ final EvidenceTriple triple = new EvidenceTriple();
+ for (OWLAnnotation annotation : annotations) {
+ OWLAnnotationProperty property = annotation.getProperty();
+ if (AnnotationShorthand.evidence.getAnnotationProperty().equals(property.getIRI())) {
+ OWLAnnotationValue value = annotation.getValue();
+ value.accept(new OWLAnnotationValueVisitor() {
+
+ @Override
+ public void visit(OWLLiteral literal) {
+ // ignore
+ }
+
+ @Override
+ public void visit(OWLAnonymousIndividual individual) {
+ // ignore
+ }
+
+ @Override
+ public void visit(IRI iri) {
+ triple.ecoIRIs.add(iri);
+ }
+ });
+ }
+ else if(AnnotationShorthand.contributor.getAnnotationProperty().equals(property.getIRI())) {
+ triple.contributors.add(annotation);
+ }
+ else if(AnnotationShorthand.date.getAnnotationProperty().equals(property.getIRI())) {
+ triple.contributors.add(annotation);
+ }
+ else if(AnnotationShorthand.comment.getAnnotationProperty().equals(property.getIRI())) {
+ triple.contributors.add(annotation);
+ }
+ else {
+ triple.evidenceAnnotations.add(annotation);
+ }
+ }
+ return triple;
+ }
+ }
+
+ public void convertLegoModelToAllIndividuals(final OWLOntology abox, final String modelId) {
+ final OWLOntologyManager m = abox.getOWLOntologyManager();
+ final OWLDataFactory f = m.getOWLDataFactory();
+ final List changes = new ArrayList();
+ final Set individuals = abox.getIndividualsInSignature();
+ final Set propertyAssertionAxioms = abox.getAxioms(AxiomType.OBJECT_PROPERTY_ASSERTION);
+
+ // update all relevant axioms pertaining to only one individual
+ for (final OWLNamedIndividual individual : individuals) {
+ Set annotationAssertionAxioms = getAnnotationAssertionAxioms(abox, individual);
+ // convert evidence into individual(s)
+ // split into ECO IRI and annotations
+ EvidenceTriple triple = EvidenceTriple.createEvidenceTriple(annotationAssertionAxioms, abox, changes);
+
+ // create individuals for ECO IRIs and link to existing individual
+ Set evidenceIndividuals = new HashSet();
+ for(IRI ecoIRI : triple.ecoIRIs) {
+ OWLNamedIndividual evidenceIndividual = createEvidenceIndividual(ecoIRI, triple.evidenceAnnotations, modelId, abox, changes);
+ evidenceIndividuals.add(evidenceIndividual.getIRI());
+ OWLAnnotationValue value = evidenceIndividual.getIRI();
+ OWLAnnotation a = f.getOWLAnnotation(
+ f.getOWLAnnotationProperty(AnnotationShorthand.evidence.getAnnotationProperty()),
+ value);
+ changes.add(new AddAxiom(abox, f.getOWLAnnotationAssertionAxiom(individual.getIRI(), a)));
+ }
+
+ // convert svf types into individuals
+ final Set classAssertionAxioms = getClassAssertionAxioms(abox, individual);
+ for(OWLClassAssertionAxiom axiom : classAssertionAxioms) {
+ OWLClassExpression ce = axiom.getClassExpression();
+ if (ce instanceof OWLObjectSomeValuesFrom) {
+ OWLObjectSomeValuesFrom svf = (OWLObjectSomeValuesFrom) ce;
+ OWLClassExpression filler = svf.getFiller();
+ OWLObjectPropertyExpression property = svf.getProperty();
+
+ Pair> pair = CoreMolecularModelManager.createIndividual(modelId, abox, filler, triple.contributors);
+ OWLNamedIndividual newIndividual = pair.getLeft();
+ for(OWLAxiom newAxiom : pair.getRight()) {
+ changes.add(new AddAxiom(abox, newAxiom));
+ }
+ changes.add(new AddAxiom(abox, CoreMolecularModelManager.createFact(f, property, individual, newIndividual, triple.contributors)));
+ changes.add(new RemoveAxiom(abox, axiom));
+ }
+ }
+ }
+
+ // update all (old) axioms for two individuals
+ for(OWLObjectPropertyAssertionAxiom oldAxiom : propertyAssertionAxioms) {
+ Set annotations = oldAxiom.getAnnotations();
+ EvidenceTriple triple = EvidenceTriple.createEvidenceTriple(annotations);
+ if (triple.ecoIRIs.isEmpty() == false) {
+ // clean up axiom annotations
+ changes.add(new RemoveAxiom(abox, oldAxiom));
+ // add annotations for new evidence individuals
+ Set newAnnotations = new HashSet(triple.contributors);
+ for(IRI ecoIRI : triple.ecoIRIs) {
+ OWLNamedIndividual evidenceIndividual = createEvidenceIndividual(ecoIRI, triple.evidenceAnnotations, modelId, abox, changes);
+ newAnnotations.add(f.getOWLAnnotation(
+ f.getOWLAnnotationProperty(AnnotationShorthand.evidence.getAnnotationProperty()),
+ evidenceIndividual.getIRI()));
+ }
+ // create new axiom
+ changes.add(new AddAxiom(abox,
+ f.getOWLObjectPropertyAssertionAxiom(
+ oldAxiom.getProperty(),
+ oldAxiom.getSubject(),
+ oldAxiom.getObject(),
+ newAnnotations)));
+ }
+ }
+
+ if (changes.isEmpty() == false) {
+ m.applyChanges(changes);
+ }
+ }
+
+ static OWLNamedIndividual createEvidenceIndividual(IRI ecoIRI, Set evidenceAnnotations, String modelId, OWLOntology abox, List changes) {
+ OWLDataFactory f = abox.getOWLOntologyManager().getOWLDataFactory();
+ OWLClass c = f.getOWLClass(ecoIRI);
+ Pair> evidenceIndividualPair = CoreMolecularModelManager.createIndividual(modelId, abox, c, null);
+ OWLNamedIndividual individual = evidenceIndividualPair.getLeft();
+ for(OWLAxiom newAxiom : evidenceIndividualPair.getRight()) {
+ changes.add(new AddAxiom(abox, newAxiom));
+ }
+ IRI individualIRI = individual.getIRI();
+ for(OWLAnnotation evidenceAnnotation : evidenceAnnotations) {
+ changes.add(new AddAxiom(abox, f.getOWLAnnotationAssertionAxiom(individualIRI, evidenceAnnotation)));
+ }
+ return individual;
+ }
+
+ private Set getAnnotationAssertionAxioms(OWLOntology abox, OWLNamedIndividual individual) {
+ Set all = abox.getAxioms(AxiomType.ANNOTATION_ASSERTION);
+ Set relevant = new HashSet();
+ IRI individualIRI = individual.getIRI();
+ for (OWLAnnotationAssertionAxiom axiom : all) {
+ OWLAnnotationSubject subject = axiom.getSubject();
+ if (individualIRI.equals(subject)) {
+ relevant.add(axiom);
+ }
+ }
+ return relevant;
+ }
+
+ /**
+ * @param abox
+ * @param individual
+ * @return axioms
+ */
+ private Set getClassAssertionAxioms(OWLOntology abox, OWLNamedIndividual individual) {
+ Set axioms = abox.getAxioms(individual);
+ final Set classAssertionAxioms = new HashSet();
+
+ for (final OWLIndividualAxiom owlIndividualAxiom : axioms) {
+ owlIndividualAxiom.accept(new OWLAxiomVisitorAdapter(){
+
+ @Override
+ public void visit(OWLClassAssertionAxiom axiom) {
+ classAssertionAxioms.add(axiom);
+ }
+ });
+ }
+ return classAssertionAxioms;
+ }
+
+}
diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/legacy/AbstractLegoTranslator.java b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/AbstractLegoTranslator.java
new file mode 100644
index 00000000..e48e042b
--- /dev/null
+++ b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/AbstractLegoTranslator.java
@@ -0,0 +1,425 @@
+package org.geneontology.minerva.legacy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.geneontology.minerva.util.IdStringManager.AnnotationShorthand;
+import org.obolibrary.obo2owl.Owl2Obo;
+import org.semanticweb.owlapi.model.OWLAnnotationProperty;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObjectProperty;
+import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
+import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.reasoner.OWLReasoner;
+
+import owltools.gaf.Bioentity;
+import owltools.gaf.BioentityDocument;
+import owltools.gaf.ExtensionExpression;
+import owltools.gaf.GafDocument;
+import owltools.gaf.GeneAnnotation;
+import owltools.gaf.eco.SimpleEcoMapper;
+import owltools.graph.OWLGraphWrapper;
+import owltools.vocab.OBOUpperVocabulary;
+
+abstract class AbstractLegoTranslator {
+
+ protected final OWLObjectProperty partOf;
+ protected final OWLObjectProperty occursIn;
+ protected final OWLObjectProperty enabledBy;
+
+ protected final OWLAnnotationProperty source;
+ protected final OWLAnnotationProperty contributor;
+ protected final OWLAnnotationProperty date;
+ protected final OWLAnnotationProperty evidence;
+
+ protected final OWLClass mf;
+ protected final Set mfSet;
+
+ protected final OWLClass cc;
+ protected final Set ccSet;
+
+ protected final OWLClass bp;
+ protected final Set bpSet;
+
+ protected final SimpleEcoMapper mapper;
+
+ protected AbstractLegoTranslator(OWLGraphWrapper graph, OWLReasoner reasoner, SimpleEcoMapper mapper) {
+ this.mapper = mapper;
+ OWLDataFactory df = graph.getDataFactory();
+ partOf = OBOUpperVocabulary.BFO_part_of.getObjectProperty(df);
+ occursIn = OBOUpperVocabulary.BFO_occurs_in.getObjectProperty(df);
+
+ mf = OBOUpperVocabulary.GO_molecular_function.getOWLClass(df);
+ cc = graph.getOWLClassByIdentifier("GO:0005575");
+ bp = OBOUpperVocabulary.GO_biological_process.getOWLClass(df);
+
+ enabledBy = OBOUpperVocabulary.GOREL_enabled_by.getObjectProperty(df);
+
+ source = df.getOWLAnnotationProperty(AnnotationShorthand.source.getAnnotationProperty());
+ contributor = df.getOWLAnnotationProperty(AnnotationShorthand.contributor.getAnnotationProperty());
+ date = df.getOWLAnnotationProperty(AnnotationShorthand.date.getAnnotationProperty());
+ evidence = df.getOWLAnnotationProperty(AnnotationShorthand.evidence.getAnnotationProperty());
+
+ bpSet = getAllSubClasses(bp, graph, reasoner, true);
+ mfSet = getAllSubClasses(mf, graph, reasoner, true);
+ ccSet = getAllSubClasses(cc, graph, reasoner, false);
+ }
+
+ protected static Set getAllSubClasses(OWLClass cls, OWLGraphWrapper g, OWLReasoner r, boolean reflexive) {
+ Set allSubClasses = r.getSubClasses(cls, false).getFlattened();
+ Iterator it = allSubClasses.iterator();
+ while (it.hasNext()) {
+ OWLClass current = it.next();
+ if (current.isBuiltIn()) {
+ it.remove();
+ }
+ }
+ if (reflexive) {
+ allSubClasses.add(cls);
+ }
+ return allSubClasses;
+ }
+
+
+ protected static class Entry {
+ T value;
+ Metadata metadata;
+ // TODO multi-species interactions
+ }
+
+ protected static class Metadata {
+ OWLClass evidence = null;
+ String assignedBy = null;
+ String date = null;
+ Set sources = null;
+
+ Metadata copy() {
+ Metadata metadata = new Metadata();
+ metadata.evidence = this.evidence;
+ metadata.assignedBy = this.assignedBy;
+ metadata.date = this.date;
+ metadata.sources = copy(this.sources);
+ return metadata;
+ }
+
+ private static Set copy(Set c) {
+ if (c == null) {
+ return null;
+ }
+ return new HashSet(c);
+ }
+
+ private static Metadata combine(Metadata primary, Metadata secondary) {
+ if (primary.evidence != null) {
+ return primary.copy();
+ }
+ if (secondary.evidence != null) {
+ return secondary.copy();
+ }
+ if (primary.sources != null && !primary.sources.isEmpty()) {
+ return primary.copy();
+ }
+ return secondary.copy();
+ }
+ }
+
+ protected class Summary {
+
+ Set> activities = null;
+ Set> activityExpressions = null;
+ Set> locations = null;
+ Set> processes = null;
+ OWLClass entity = null;
+ String entityType = null;
+ String entityTaxon = null;
+
+ void addMfOrBp(OWLClass cls, Metadata metadata) {
+ if (isMf(cls)) {
+ activities = addAnnotation(cls, metadata , activities);
+ }
+ else if (isBp(cls)) {
+ processes = addAnnotation(cls, metadata, processes);
+ }
+ }
+
+ void addMf(OWLClass cls, Metadata metadata) {
+ if (isMf(cls)) {
+ activities = addAnnotation(cls, metadata , activities);
+ }
+ }
+
+ void addBp(OWLClass cls, Metadata metadata) {
+ if (isBp(cls)) {
+ processes = addAnnotation(cls, metadata, processes);
+ }
+ }
+
+ void addCc(OWLClassExpression ce, Metadata metadata) {
+ if (ce instanceof OWLClass) {
+ OWLClass cls = ce.asOWLClass();
+ locations = addAnnotation(cls, metadata, locations);
+ }
+ }
+
+ private Set> addAnnotation(T cls, Metadata metadata, Set> set) {
+ if (set == null) {
+ set = new HashSet>();
+ }
+ Entry entry = new Entry();
+ entry.value = cls;
+ entry.metadata = metadata.copy();
+ set.add(entry);
+ return set;
+ }
+
+ void addProcesses(Set> processes, Metadata metadata) {
+ if (processes != null) {
+ if (this.processes == null) {
+ this.processes = new HashSet>();
+ }
+ for(Entry process : processes) {
+ Entry newEntry = new Entry();
+ newEntry.value = process.value;
+ newEntry.metadata = Metadata.combine(metadata, process.metadata);
+ this.processes.add(newEntry);
+ }
+ }
+ }
+
+ void addLocations(Set> locations) {
+ if (locations != null) {
+ if (this.locations == null) {
+ this.locations = new HashSet>(locations);
+ }
+ else {
+ this.locations.addAll(locations);
+ }
+ }
+ }
+
+ void addExpression(OWLObjectPropertyExpression p, Collection> entries, OWLDataFactory f) {
+ if (entries != null && !entries.isEmpty()) {
+ for (Entry entry : entries) {
+ OWLObjectSomeValuesFrom svf = f.getOWLObjectSomeValuesFrom(p, entry.value);
+ activityExpressions = addAnnotation(svf, entry.metadata, activityExpressions);
+ }
+ }
+ }
+
+ void addExpression(OWLObjectPropertyExpression p, OWLClass cls, Metadata metadata, OWLDataFactory f) {
+ OWLObjectSomeValuesFrom svf = f.getOWLObjectSomeValuesFrom(p, cls);
+ activityExpressions = addAnnotation(svf, metadata, activityExpressions);
+ }
+ }
+
+ protected boolean isMf(OWLClass cls) {
+ return mfSet.contains(cls);
+ }
+
+ protected boolean isBp(OWLClass cls) {
+ return bpSet.contains(cls);
+ }
+
+ protected boolean isCc(OWLClass cls) {
+ return ccSet.contains(cls);
+ }
+
+ public abstract void translate(OWLOntology modelAbox, GafDocument annotations, BioentityDocument entities, List additionalRefs);
+
+ /**
+ * Get the type of an enabled by entity, e.g. gene, protein
+ *
+ * @param modelGraph
+ * @param entity
+ * @return type
+ */
+ protected String getEntityType(OWLClass entity, OWLGraphWrapper modelGraph) {
+ String id = modelGraph.getIdentifier(entity);
+ if (id.startsWith("UniProtKB")) {
+ return "protein"; // TODO
+ }
+ return "gene";
+ }
+
+ protected String getEntityTaxon(OWLClass entity, OWLNamedIndividual individual, OWLGraphWrapper modelGraph) {
+ return null; // TODO
+ }
+
+ public Pair translate(String id, OWLOntology modelAbox, List additionalReferences) {
+ final GafDocument annotations = new GafDocument(id, null);
+ final BioentityDocument entities = new BioentityDocument(id);
+ translate(modelAbox, annotations, entities, additionalReferences);
+ return Pair.of(annotations, entities);
+ }
+
+ protected GeneAnnotation createAnnotation(Entry e, Bioentity entity, String Aspect, OWLGraphWrapper g, Collection c16) {
+ GeneAnnotation annotation = new GeneAnnotation();
+ annotation.setBioentityObject(entity);
+ annotation.setBioentity(entity.getId());
+ annotation.setAspect(Aspect);
+
+ //annotation.setActsOnTaxonId(taxonRelPair) // TODO?
+
+ if (e.metadata.assignedBy != null) {
+ annotation.setAssignedBy(e.metadata.assignedBy);
+ }
+
+ annotation.setCls(g.getIdentifier(e.value));
+
+ if (e.metadata.evidence != null) {
+ String ecoId = g.getIdentifier(e.metadata.evidence);
+ if (ecoId != null) {
+ String goCode = null;
+ Pair pair = mapper.getGoCode(ecoId);
+ if (pair != null) {
+ goCode = pair.getLeft();
+ }
+ annotation.setEvidence(goCode, ecoId);
+ }
+ }
+ annotation.setLastUpdateDate(e.metadata.date);
+ //annotation.setRelation(relation); // TODO
+ if (e.metadata.sources != null) {
+ annotation.addReferenceIds(e.metadata.sources);
+ }
+
+ if (c16 != null && !c16.isEmpty()) {
+ List expressions = new ArrayList();
+ for (OWLObjectSomeValuesFrom svf : c16) {
+ OWLObjectPropertyExpression property = svf.getProperty();
+ OWLClassExpression filler = svf.getFiller();
+ if (property instanceof OWLObjectProperty && filler instanceof OWLClass) {
+ String rel = getRelId(property, g);
+ String objectId = g.getIdentifier(filler);
+ ExtensionExpression expr = new ExtensionExpression(rel, objectId);
+ expressions.add(expr);
+ }
+ }
+ annotation.setExtensionExpressions(Collections.singletonList(expressions));
+ }
+
+ return annotation;
+ }
+
+ protected String getRelId(OWLObjectPropertyExpression p, OWLGraphWrapper graph) {
+ String relId = null;
+ for(OWLOntology ont : graph.getAllOntologies()) {
+ relId = Owl2Obo.getIdentifierFromObject(p, ont, null);
+ if (relId != null && relId.indexOf(':') < 0) {
+ return relId;
+ }
+ }
+ return relId;
+ }
+
+ protected Bioentity createBioentity(OWLClass entityCls, String entityType, String taxon, OWLGraphWrapper g) {
+ Bioentity bioentity = new Bioentity();
+ BioentityStrings strings = getBioentityStrings(entityCls, entityType, taxon, g);
+ String id = strings.id;
+ bioentity.setId(id);
+ if (strings.db != null) {
+ bioentity.setDb(strings.db);
+ }
+ bioentity.setSymbol(strings.symbol);
+ bioentity.setTypeCls(strings.type);
+ bioentity.setNcbiTaxonId(taxon);
+ // TODO more bioentity content
+ return bioentity;
+ }
+
+ protected static class BioentityStrings {
+ String id;
+ String db;
+ String symbol;
+ String type;
+ }
+
+ protected BioentityStrings getBioentityStrings(OWLClass entityCls, String entityType, String taxon, OWLGraphWrapper g) {
+ BioentityStrings strings = new BioentityStrings();
+ strings.id = g.getIdentifier(entityCls);
+ strings.db = null;
+ String[] split = StringUtils.split(strings.id, ":", 2);
+ if (split.length == 2) {
+ strings.db = split[0];
+ }
+ strings.symbol = g.getLabel(entityCls);
+ strings.type = entityType;
+ return strings;
+ }
+
+ protected void addAnnotations(OWLGraphWrapper modelGraph,
+ Summary summary,
+ GafDocument annotations, BioentityDocument entities)
+ {
+ final OWLDataFactory f = modelGraph.getDataFactory();
+ Bioentity entity = createBioentity(summary.entity, summary.entityType, summary.entityTaxon , modelGraph);
+ entities.addBioentity(entity);
+ annotations.addBioentity(entity);
+
+ if (summary.activities != null) {
+ for (Entry e: summary.activities) {
+ List c16 = new ArrayList();
+ boolean renderActivity = true;
+ if (mf.equals(e.value)) {
+ // special handling for top level molecular functions
+ // only add as annotation, if there is more than one annotation
+ // otherwise they tend to be redundant with the bp or cc annotation
+ int count = 0;
+ if (summary.processes != null) {
+ count += summary.processes.size();
+ }
+ if (summary.locations != null) {
+ count += summary.locations.size();
+ }
+ if (count <= 1 && (summary.activityExpressions == null || summary.activityExpressions.isEmpty())) {
+ renderActivity = false;
+ }
+ }
+ if (renderActivity) {
+ if (summary.processes != null) {
+ for (Entry processEntry : summary.processes) {
+ c16.add(f.getOWLObjectSomeValuesFrom(partOf, processEntry.value));
+ }
+ }
+ if (summary.locations != null) {
+ for (Entry locationEntry : summary.locations) {
+ c16.add(f.getOWLObjectSomeValuesFrom(occursIn, locationEntry.value));
+ }
+ }
+ if (summary.activityExpressions != null) {
+ for(Entry expressionEntry : summary.activityExpressions) {
+ c16.add(expressionEntry.value);
+ }
+ }
+ GeneAnnotation annotation = createAnnotation(e, entity, "F", modelGraph, c16);
+ annotations.addGeneAnnotation(annotation);
+ }
+ }
+ }
+ if (summary.processes != null) {
+ for (Entry e : summary.processes) {
+ GeneAnnotation annotation = createAnnotation(e, entity, "P", modelGraph, null);
+ annotations.addGeneAnnotation(annotation);
+ }
+ }
+ if (summary.locations != null) {
+ for (Entry e : summary.locations) {
+ if (isCc(e.value)) {
+ GeneAnnotation annotation = createAnnotation(e, entity, "C", modelGraph, null);
+ annotations.addGeneAnnotation(annotation);
+ }
+ }
+ }
+ }
+}
diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/legacy/GafExportTool.java b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/GafExportTool.java
new file mode 100644
index 00000000..1e2f6591
--- /dev/null
+++ b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/GafExportTool.java
@@ -0,0 +1,81 @@
+package org.geneontology.minerva.legacy;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.geneontology.minerva.ModelContainer;
+import org.semanticweb.owlapi.model.OWLOntology;
+
+import owltools.gaf.BioentityDocument;
+import owltools.gaf.GafDocument;
+import owltools.gaf.eco.EcoMapperFactory;
+import owltools.gaf.eco.SimpleEcoMapper;
+import owltools.gaf.io.GafWriter;
+import owltools.gaf.io.GpadWriter;
+import owltools.graph.OWLGraphWrapper;
+
+public class GafExportTool {
+
+ private static volatile GafExportTool INSTANCE = null;
+
+ private final SimpleEcoMapper ecoMapper;
+
+ private GafExportTool(SimpleEcoMapper mapper) {
+ this.ecoMapper = mapper;
+ }
+
+ public static synchronized GafExportTool getInstance() throws IOException {
+ if (INSTANCE == null) {
+ INSTANCE = new GafExportTool(EcoMapperFactory.createSimple());
+ }
+ return INSTANCE;
+ }
+
+ /**
+ * Export the model (ABox) in a legacy format, such as GAF or GPAD.
+ *
+ * @param modelId
+ * @param model
+ * @param format format name or null for default
+ * @return modelContent
+ * @throws IOException
+ */
+ public String exportModelLegacy(String modelId, ModelContainer model, String format) throws IOException {
+ final OWLOntology aBox = model.getAboxOntology();
+ LegoToGeneAnnotationTranslator translator = new LegoToGeneAnnotationTranslator(new OWLGraphWrapper(model.getTboxOntology()), model.getReasoner(), ecoMapper);
+ Pair pair = translator.translate(modelId, aBox, null);
+ ByteArrayOutputStream outputStream = null;
+ try {
+ outputStream = new ByteArrayOutputStream();
+ if (format == null || "gaf".equalsIgnoreCase(format)) {
+ // GAF
+ GafWriter writer = new GafWriter();
+ try {
+ writer.setStream(new PrintStream(outputStream));
+ GafDocument gafdoc = pair.getLeft();
+ writer.write(gafdoc);
+ }
+ finally {
+ writer.close();
+ }
+
+ }
+ else if ("gpad".equalsIgnoreCase(format)) {
+ // GPAD version 1.2
+ GpadWriter writer = new GpadWriter(new PrintWriter(outputStream) , 1.2);
+ writer.write(pair.getLeft());
+ }
+ else {
+ throw new IOException("Unknown legacy format: "+format);
+ }
+ return outputStream.toString();
+ }
+ finally {
+ IOUtils.closeQuietly(outputStream);
+ }
+ }
+}
diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/legacy/LegoAllIndividualToGeneAnnotationTranslator.java b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/LegoAllIndividualToGeneAnnotationTranslator.java
new file mode 100644
index 00000000..743e9de6
--- /dev/null
+++ b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/LegoAllIndividualToGeneAnnotationTranslator.java
@@ -0,0 +1,290 @@
+package org.geneontology.minerva.legacy;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.semanticweb.owlapi.model.AxiomType;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLAnnotation;
+import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLAnnotationProperty;
+import org.semanticweb.owlapi.model.OWLAnnotationValue;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLLiteral;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.reasoner.OWLReasoner;
+
+import owltools.gaf.BioentityDocument;
+import owltools.gaf.GafDocument;
+import owltools.gaf.eco.SimpleEcoMapper;
+import owltools.graph.OWLGraphWrapper;
+
+import com.google.common.collect.Sets;
+
+public class LegoAllIndividualToGeneAnnotationTranslator extends AbstractLegoTranslator {
+
+ private OWLGraphWrapper graph;
+
+ public LegoAllIndividualToGeneAnnotationTranslator(OWLGraphWrapper graph, OWLReasoner reasoner, SimpleEcoMapper mapper) {
+ super(graph, reasoner, mapper);
+ this.graph = graph;
+ }
+
+ private boolean isEco(OWLClass cls) {
+ String identifier = graph.getIdentifier(cls);
+ return identifier != null && identifier.startsWith("ECO:");
+ }
+
+ private OWLClass getEco(Set set) {
+ for (OWLClass cls : set) {
+ if (isEco(cls)) {
+ return cls;
+ }
+ }
+ return null;
+ }
+
+ private boolean isTaxon(OWLClass cls) {
+ String identifier = graph.getIdentifier(cls);
+ return identifier != null && identifier.startsWith("NCBITaxon:");
+ }
+
+ private OWLClass getTaxon(Set set) {
+ for (OWLClass cls : set) {
+ if (isTaxon(cls)) {
+ return cls;
+ }
+ }
+ return null;
+ }
+
+ private Set getTypes(OWLNamedIndividual i, OWLOntology modelAbox) {
+ Set axioms = modelAbox.getClassAssertionAxioms(i);
+ Set types = new HashSet();
+ for (OWLClassAssertionAxiom axiom : axioms) {
+ OWLClassExpression ce = axiom.getClassExpression();
+ if (ce instanceof OWLClass) {
+ OWLClass cls = ce.asOWLClass();
+ if (cls.isBuiltIn() == false) {
+ types.add(cls);
+ }
+ }
+ }
+ return types;
+ }
+
+ private Metadata mergeMetadata(Metadata...data) {
+ Metadata result = null;
+ for (Metadata metadata : data) {
+ if (metadata != null) {
+ if (result == null) {
+ result = metadata.copy();
+ }
+ else {
+ if (result.evidence == null && metadata.evidence != null) {
+ Metadata oldResult = result;
+ result = metadata.copy();
+ if (oldResult.sources != null && !oldResult.sources.isEmpty()) {
+ if (result.sources == null) {
+ result.sources = Sets.newHashSet(oldResult.sources);
+ }
+ else {
+ result.sources.addAll(oldResult.sources);
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ public void translate(OWLOntology modelAbox, GafDocument annotations, BioentityDocument entities, List additionalRefs) {
+ final OWLGraphWrapper modelGraph = new OWLGraphWrapper(modelAbox);
+ final OWLDataFactory f = modelGraph.getDataFactory();
+
+ final Set annotationIndividuals = new HashSet();
+ final Map evidenceIndividuals = new HashMap();
+ final Map taxonIndividuals = new HashMap();
+
+ for(OWLNamedIndividual individual : modelAbox.getIndividualsInSignature()) {
+ Set individualTypes = getTypes(individual, modelAbox);
+ OWLClass eco = getEco(individualTypes);
+ OWLClass taxon = getTaxon(individualTypes);
+ if (eco != null) {
+ // is eco
+ Metadata metadata = extractMetadata(individual, modelGraph, null);
+ metadata.evidence = eco;
+ evidenceIndividuals.put(individual.getIRI(), metadata);
+ }
+ else if(taxon != null) {
+ // is taxon (in future, currently not used)
+ taxonIndividuals.put(individual, taxon);
+ }
+ else {
+ // assume annotation
+ annotationIndividuals.add(individual);
+ }
+ }
+
+ final Map allMetadata = new HashMap();
+ for(OWLNamedIndividual individual : annotationIndividuals) {
+ Metadata metadata = extractMetadata(individual, modelGraph, evidenceIndividuals);
+ allMetadata.put(individual, metadata);
+ }
+
+ Set summaries = new HashSet();
+ for (OWLObjectPropertyAssertionAxiom axiom : modelAbox.getAxioms(AxiomType.OBJECT_PROPERTY_ASSERTION)) {
+ final OWLObjectPropertyExpression p = axiom.getProperty();
+ if (enabledBy.equals(p)) {
+
+ // gene/protein/complex
+ final OWLNamedIndividual object = axiom.getObject().asOWLNamedIndividual();
+ Set objectTypes = getTypes(object, modelAbox);
+ for (OWLClass objectType : objectTypes) {
+ final Summary summary = new Summary();
+ summary.entity = objectType;
+ summary.entityTaxon = getEntityTaxon(objectType, object, modelGraph);
+ summary.entityType = getEntityType(objectType, modelGraph);
+ summaries.add(summary);
+
+ final OWLNamedIndividual subject = axiom.getSubject().asOWLNamedIndividual();
+
+ // get associated meta data
+ final Metadata linkMetadata = extractMetadata(axiom.getAnnotations(), modelGraph, evidenceIndividuals);
+ final Metadata objectMetadata = allMetadata.get(object);
+ final Metadata subjectMetadata = allMetadata.get(subject);
+ final Metadata mfMetadata = mergeMetadata(linkMetadata, objectMetadata, subjectMetadata);
+
+ // handle types
+ for(OWLClass cls : getTypes(subject, modelAbox)) {
+ if (isMf(cls)) {
+ summary.addMf(cls, mfMetadata);
+ }
+ else {
+ // TODO how do we record that in a GAF?
+ }
+ }
+
+ // get all OWLObjectPropertyAssertionAxiom for subject
+ Set subjectAxioms = modelAbox.getObjectPropertyAssertionAxioms(subject);
+ for(OWLObjectPropertyAssertionAxiom current : subjectAxioms) {
+ final Metadata currentLinkMetadata = extractMetadata(current.getAnnotations(), modelGraph, evidenceIndividuals);
+ final OWLObjectPropertyExpression currentP = current.getProperty();
+ final OWLNamedIndividual currentObj = current.getObject().asOWLNamedIndividual();
+ final Metadata currentObjMetadata = allMetadata.get(currentObj);
+ if (occursIn.equals(currentP)) {
+ // check for cc for subject (occurs in)
+ final Metadata metadata = mergeMetadata(currentObjMetadata, currentLinkMetadata);
+ for(OWLClass cls : getTypes(currentObj, modelAbox)) {
+ if (isCc(cls)) {
+ summary.addCc(cls, metadata);
+ }
+ else {
+ summary.addExpression(occursIn, cls, metadata, f);
+ }
+ }
+ }
+ else if (partOf.equals(currentP)) {
+ // check for bp for subject (part_of)
+ final Metadata metadata = mergeMetadata(currentObjMetadata, currentLinkMetadata);
+ for(OWLClass cls : getTypes(currentObj, modelAbox)) {
+ if (isBp(cls)) {
+ summary.addBp(cls, metadata);
+ }
+ else {
+ summary.addExpression(currentP, cls, metadata, f);
+ }
+ }
+
+ }else if (enabledBy.equals(currentP)) {
+ // do nothing
+ }
+// else if (taxon.equals(currentP)) {
+// // do nothing
+// }
+ else {
+ Set types = getTypes(currentObj, modelAbox);
+ final Metadata miscMetadata = mergeMetadata(currentObjMetadata, currentLinkMetadata);
+ for (OWLClass cls : types) {
+ summary.addExpression(currentP, cls, miscMetadata, f);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for(Summary summary : summaries) {
+ if (summary.entity != null) {
+ addAnnotations(modelGraph, summary, annotations, entities);
+ }
+ }
+ }
+
+
+ private Metadata extractMetadata(OWLNamedIndividual individual, OWLGraphWrapper modelGraph, Map allEvidences) {
+ Metadata metadata = new Metadata();
+ Set assertionAxioms = modelGraph.getSourceOntology().getAnnotationAssertionAxioms(individual.getIRI());
+ for (OWLAnnotationAssertionAxiom axiom : assertionAxioms) {
+ OWLAnnotationProperty currentProperty = axiom.getProperty();
+ OWLAnnotationValue value = axiom.getValue();
+ extractMetadata(currentProperty, value, metadata, allEvidences);
+ }
+ return metadata;
+ }
+
+ private void extractMetadata(OWLAnnotationProperty p, OWLAnnotationValue v, final Metadata metadata, Map allEvidences)
+ {
+ if (this.evidence.equals(p) && allEvidences != null && metadata.evidence == null) {
+ Metadata evidenceMetadata = allEvidences.get(v);
+ if (evidenceMetadata != null) {
+ metadata.evidence = evidenceMetadata.evidence;
+ metadata.sources = evidenceMetadata.sources;
+ }
+ }
+ else if (this.contributor.equals(p)) {
+ if (v instanceof OWLLiteral) {
+ metadata.assignedBy = ((OWLLiteral) v).getLiteral();
+ }
+ }
+ else if (this.date.equals(p)) {
+ if (v instanceof OWLLiteral) {
+ metadata.date = ((OWLLiteral) v).getLiteral();
+ }
+ }
+ else if (this.source.equals(p)) {
+ if (v instanceof OWLLiteral) {
+ String source = ((OWLLiteral) v).getLiteral();
+ if (metadata.sources == null) {
+ metadata.sources = new HashSet();
+ }
+ metadata.sources.add(source);
+ }
+ }
+
+ }
+
+ private Metadata extractMetadata(Collection annotations, OWLGraphWrapper modelGraph, Map allEvidences) {
+ Metadata metadata = new Metadata();
+ if (annotations != null && !annotations.isEmpty()) {
+ for (OWLAnnotation owlAnnotation : annotations) {
+ OWLAnnotationProperty currentProperty = owlAnnotation.getProperty();
+ OWLAnnotationValue value = owlAnnotation.getValue();
+ extractMetadata(currentProperty, value, metadata, allEvidences);
+ }
+ }
+ return metadata;
+ }
+
+}
diff --git a/minerva-converter/src/main/java/org/geneontology/minerva/legacy/LegoToGeneAnnotationTranslator.java b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/LegoToGeneAnnotationTranslator.java
new file mode 100644
index 00000000..69912460
--- /dev/null
+++ b/minerva-converter/src/main/java/org/geneontology/minerva/legacy/LegoToGeneAnnotationTranslator.java
@@ -0,0 +1,209 @@
+package org.geneontology.minerva.legacy;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLAnnotation;
+import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLAnnotationProperty;
+import org.semanticweb.owlapi.model.OWLAnnotationValue;
+import org.semanticweb.owlapi.model.OWLClass;
+import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLClassExpression;
+import org.semanticweb.owlapi.model.OWLDataFactory;
+import org.semanticweb.owlapi.model.OWLIndividual;
+import org.semanticweb.owlapi.model.OWLLiteral;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLObjectProperty;
+import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
+import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
+import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.reasoner.OWLReasoner;
+
+import owltools.gaf.BioentityDocument;
+import owltools.gaf.GafDocument;
+import owltools.gaf.eco.SimpleEcoMapper;
+import owltools.graph.OWLGraphWrapper;
+import owltools.vocab.OBOUpperVocabulary;
+
+public class LegoToGeneAnnotationTranslator extends AbstractLegoTranslator {
+
+ public LegoToGeneAnnotationTranslator(OWLGraphWrapper graph, OWLReasoner reasoner, SimpleEcoMapper mapper) {
+ super(graph, reasoner, mapper);
+ }
+
+ public void translate(OWLOntology modelAbox, GafDocument annotations, BioentityDocument entities, List additionalRefs) {
+ final OWLGraphWrapper modelGraph = new OWLGraphWrapper(modelAbox);
+ final OWLDataFactory f = modelGraph.getDataFactory();
+ Set individuals = modelAbox.getIndividualsInSignature();
+
+ // create initial summaries
+ Map summaries = new HashMap();
+ for (OWLNamedIndividual individual : individuals) {
+ Summary summary = new Summary();
+ summaries.put(individual, summary);
+
+ Metadata metadata = extractMetadata(individual, modelGraph, additionalRefs);
+
+ Set assertionAxioms = modelAbox.getClassAssertionAxioms(individual);
+ for (OWLClassAssertionAxiom axiom : assertionAxioms) {
+ OWLClassExpression ce = axiom.getClassExpression();
+ if (!ce.isAnonymous()) {
+ if (!ce.isBottomEntity() && !ce.isOWLNothing() && !ce.isOWLThing() && !ce.isTopEntity()) {
+ summary.addMfOrBp(ce.asOWLClass(), metadata);
+ }
+ }
+ else if (ce instanceof OWLObjectSomeValuesFrom) {
+ OWLObjectSomeValuesFrom svf = (OWLObjectSomeValuesFrom) ce;
+ OWLObjectPropertyExpression p = svf.getProperty();
+ OWLClassExpression filler = svf.getFiller();
+ if (occursIn.equals(p)) {
+ summary.addCc(filler, metadata);
+ }
+ else if (enabledBy.equals(p)) {
+ if (filler instanceof OWLClass) {
+ summary.entity = (OWLClass) filler;
+ summary.entityType = getEntityType(summary.entity, modelGraph);
+ summary.entityTaxon = getEntityTaxon(summary.entity, individual, modelGraph);
+ // TODO multi-species
+ }
+ }
+ else {
+ if (filler instanceof OWLClass) {
+ OWLClass cls = (OWLClass) filler;
+ summary.addExpression(p, cls, metadata, f);
+ }
+ }
+ }
+ }
+ }
+
+
+ // extract process and other infos
+ for(OWLNamedIndividual individual : summaries.keySet()) {
+ Summary summary = summaries.get(individual);
+ if (summary.entity != null) {
+ Set axioms = modelAbox.getObjectPropertyAssertionAxioms(individual);
+ for (OWLObjectPropertyAssertionAxiom axiom : axioms) {
+ Metadata metadata = extractMetadata(axiom.getAnnotations(), modelGraph, additionalRefs);
+ OWLIndividual object = axiom.getObject();
+ OWLObjectPropertyExpression property = axiom.getProperty();
+ if (partOf.equals(property)) {
+ Summary objectSummary = summaries.get(object);
+ if (objectSummary != null) {
+ summary.addProcesses(objectSummary.processes, metadata);
+ // only add locations from the process, if there are no ones already present.
+ if (summary.locations == null || summary.locations.isEmpty()) {
+ summary.addLocations(objectSummary.locations);
+ }
+ }
+ }
+ else if (property instanceof OWLObjectProperty) {
+ Summary objectSummary = summaries.get(object);
+ if (objectSummary != null) {
+ // handle as additional information
+ if (objectSummary.activities != null) {
+ summary.addExpression(property, objectSummary.activities, f);
+ }
+ else {
+ summary.addExpression(property, objectSummary.processes, f);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // report
+ for(OWLNamedIndividual individual : summaries.keySet()) {
+ Summary summary = summaries.get(individual);
+ if (summary.entity != null) {
+ addAnnotations(modelGraph, summary, annotations, entities);
+ }
+ }
+ }
+
+
+ private Metadata extractMetadata(OWLNamedIndividual individual, OWLGraphWrapper modelGraph, List additionalRefs) {
+ Metadata metadata = new Metadata();
+ Set assertionAxioms = modelGraph.getSourceOntology().getAnnotationAssertionAxioms(individual.getIRI());
+ for (OWLAnnotationAssertionAxiom axiom : assertionAxioms) {
+ OWLAnnotationProperty currentProperty = axiom.getProperty();
+ OWLAnnotationValue value = axiom.getValue();
+ extractMetadata(currentProperty, value, metadata, modelGraph, additionalRefs);
+ }
+ if (metadata.sources == null && additionalRefs != null) {
+ metadata.sources = new HashSet(additionalRefs);
+ }
+ return metadata;
+ }
+
+ private void extractMetadata(OWLAnnotationProperty p, OWLAnnotationValue v, Metadata metadata,
+ OWLGraphWrapper modelGraph, List additionalRefs)
+ {
+ if (this.evidence.equals(p)) {
+ if (v instanceof IRI) {
+ IRI iri = (IRI) v;
+ metadata.evidence = modelGraph.getOWLClass(iri);
+ }
+ else if (v instanceof OWLLiteral) {
+ String literal = ((OWLLiteral) v).getLiteral();
+ if (StringUtils.startsWith(literal, OBOUpperVocabulary.OBO)) {
+ IRI iri = IRI.create(literal);
+ metadata.evidence = modelGraph.getOWLClass(iri);
+ }
+ else {
+ metadata.evidence = modelGraph.getOWLClassByIdentifier(literal);
+ }
+ }
+ }
+ else if (this.contributor.equals(p)) {
+ if (v instanceof OWLLiteral) {
+ metadata.assignedBy = ((OWLLiteral) v).getLiteral();
+ }
+ }
+ else if (this.date.equals(p)) {
+ if (v instanceof OWLLiteral) {
+ metadata.date = ((OWLLiteral) v).getLiteral();
+ }
+ }
+ else if (this.source.equals(p)) {
+ if (v instanceof OWLLiteral) {
+ String sourceValue = ((OWLLiteral) v).getLiteral();
+ if (metadata.sources == null) {
+ metadata.sources = new HashSet();
+ }
+ metadata.sources.add(sourceValue);
+ }
+ }
+ if (additionalRefs != null) {
+ if (metadata.sources == null) {
+ metadata.sources = new HashSet();
+ }
+ metadata.sources.addAll(additionalRefs);
+ }
+ }
+
+ private Metadata extractMetadata(Collection annotations, OWLGraphWrapper modelGraph, List additionalRefs) {
+ Metadata metadata = new Metadata();
+ if (annotations != null && !annotations.isEmpty()) {
+ for (OWLAnnotation owlAnnotation : annotations) {
+ OWLAnnotationProperty currentProperty = owlAnnotation.getProperty();
+ OWLAnnotationValue value = owlAnnotation.getValue();
+ extractMetadata(currentProperty, value, metadata, modelGraph, additionalRefs);
+ }
+ }
+ if (metadata.sources == null && additionalRefs != null) {
+ metadata.sources = new HashSet(additionalRefs);
+ }
+ return metadata;
+ }
+
+}
diff --git a/minerva-converter/src/test/java/org/geneontology/minerva/format/LegoModelVersionConverterTest.java b/minerva-converter/src/test/java/org/geneontology/minerva/format/LegoModelVersionConverterTest.java
new file mode 100644
index 00000000..b33d2f1c
--- /dev/null
+++ b/minerva-converter/src/test/java/org/geneontology/minerva/format/LegoModelVersionConverterTest.java
@@ -0,0 +1,85 @@
+package org.geneontology.minerva.format;
+
+import static org.junit.Assert.*;
+
+import java.io.ByteArrayOutputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.geneontology.minerva.ModelContainer;
+import org.geneontology.minerva.MolecularModelManager;
+import org.geneontology.minerva.format.LegoModelVersionConverter;
+import org.geneontology.minerva.json.MolecularModelJsonRenderer;
+import org.junit.Test;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLNamedIndividual;
+import org.semanticweb.owlapi.model.OWLOntology;
+import org.semanticweb.owlapi.model.OWLOntologyManager;
+
+import owltools.graph.OWLGraphWrapper;
+import owltools.io.ParserWrapper;
+
+import com.google.common.collect.Sets;
+
+public class LegoModelVersionConverterTest {
+
+ @Test
+ public void testConvertLegoModelToAllIndividuals() throws Exception {
+ ParserWrapper pw = new ParserWrapper();
+ OWLGraphWrapper graph = new OWLGraphWrapper(pw.parse("http://purl.obolibrary.org/obo/go.owl"));
+ MolecularModelManager> m3 = new MolecularModelManager