Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

matching between ontology classes (not instances) #41

Merged
merged 1 commit into from Jan 12, 2017
Jump to file or symbol
Failed to load files and symbols.
+350 −0
Split
@@ -0,0 +1,93 @@
+package org.monarchinitiative.owlsim.compute.classmatch;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.inject.Inject;
+
+import org.monarchinitiative.owlsim.kb.BMKnowledgeBase;
+import org.monarchinitiative.owlsim.kb.LabelMapper;
+
+import com.googlecode.javaewah.EWAHCompressedBitmap;
+
+/**
+ * Finds matches between classes in the KB
+ *
+ * @author cjm
+ *
+ */
+public class ClassMatcher {
+
+ BMKnowledgeBase kb;
+
+
+ @Inject
+ public ClassMatcher(BMKnowledgeBase kb) {
+ super();
+ this.kb = kb;
+ }
+
+ /**
+ * Find best match for every class in ont1, where the best
+ * match is in ont2
+ *
+ * @param qOnt
+ * @param tOnt
+ * @return
+ */
+ public List<SimpleClassMatch> matchOntologies(String qOnt, String tOnt) {
+ Set<String> qids = getClassIdsByOntology(qOnt);
+ Set<String> tids = getClassIdsByOntology(tOnt);
+ return matchClassSets(qids, tids);
+ }
+
+ public List<SimpleClassMatch> matchClassSets(Set<String> qids,
+ Set<String> tids) {
+ ArrayList<SimpleClassMatch> matches = new ArrayList<>();
+ for (String q : qids) {
+ matches.add(getBestMatch(q, tids));
+ }
+ return matches;
+ }
+
+ private SimpleClassMatch getBestMatch(String q, Set<String> tids) {
+ EWAHCompressedBitmap qbm = kb.getSuperClassesBM(q);
+ double bestEqScore = 0.0;
+ String best = null;
+ for (String t : tids) {
+ EWAHCompressedBitmap tbm = kb.getSuperClassesBM(t);
+ int numInQueryAndInTarget = qbm.andCardinality(tbm);
+ int numInQueryOrInTarget = qbm.orCardinality(tbm);
+ double eqScore = numInQueryAndInTarget / (double) numInQueryOrInTarget;
+ if (eqScore > bestEqScore) {
+ bestEqScore = eqScore;
+ best = t;
+ }
+ }
+
+ EWAHCompressedBitmap tbm = kb.getSuperClassesBM(best);
+ int numInQueryAndInTarget = qbm.andCardinality(tbm);
+ double subClassScore = numInQueryAndInTarget / (double) qbm.cardinality();
+ double superClassScore = numInQueryAndInTarget / (double) tbm.cardinality();
+
+ LabelMapper lm = kb.getLabelMapper();
+ return new SimpleClassMatch(q, best,
+ lm.getArbitraryLabel(q),
+ lm.getArbitraryLabel(best),
+ bestEqScore,
+ subClassScore,
+ superClassScore);
+ }
+
+ public Set<String> getClassIdsByOntology(String ont) {
+ return kb.getClassIdsInSignature().stream().filter(x -> isIn(x, ont)).collect(Collectors.toSet());
+ }
+
+ public boolean isIn(String id, String ont) {
+ // TODO - use curie util
+ return id.startsWith(ont+":") || id.contains("/"+ont+"_");
+ }
+
+}
@@ -0,0 +1,124 @@
+package org.monarchinitiative.owlsim.compute.classmatch;
+
+public class SimpleClassMatch {
+
+ private String queryClassId;
+ private String matchClassId;
+ private String queryClassLabel;
+ private String matchClassLabel;
+
+ private double eqScore;
+ private double subClassScore;
+ private double superClassScore;
+ public SimpleClassMatch(String queryClassId, String matchClassId,
+ String queryClassLabel, String matchClassLabel, double eqScore,
+ double subClassScore, double superClassScore) {
+ super();
+ this.queryClassId = queryClassId;
+ this.matchClassId = matchClassId;
+ this.queryClassLabel = queryClassLabel;
+ this.matchClassLabel = matchClassLabel;
+ this.eqScore = eqScore;
+ this.subClassScore = subClassScore;
+ this.superClassScore = superClassScore;
+ }
+ /**
+ * @return the queryClassId
+ */
+ public String getQueryClassId() {
+ return queryClassId;
+ }
+ /**
+ * @param queryClassId the queryClassId to set
+ */
+ public void setQueryClassId(String queryClassId) {
+ this.queryClassId = queryClassId;
+ }
+ /**
+ * @return the matchClassId
+ */
+ public String getMatchClassId() {
+ return matchClassId;
+ }
+ /**
+ * @param matchClassId the matchClassId to set
+ */
+ public void setMatchClassId(String matchClassId) {
+ this.matchClassId = matchClassId;
+ }
+ /**
+ * @return the queryClassLabel
+ */
+ public String getQueryClassLabel() {
+ return queryClassLabel;
+ }
+ /**
+ * @param queryClassLabel the queryClassLabel to set
+ */
+ public void setQueryClassLabel(String queryClassLabel) {
+ this.queryClassLabel = queryClassLabel;
+ }
+ /**
+ * @return the matchClassLabel
+ */
+ public String getMatchClassLabel() {
+ return matchClassLabel;
+ }
+ /**
+ * @param matchClassLabel the matchClassLabel to set
+ */
+ public void setMatchClassLabel(String matchClassLabel) {
+ this.matchClassLabel = matchClassLabel;
+ }
+ /**
+ * @return the eqScore
+ */
+ public double getEqScore() {
+ return eqScore;
+ }
+ /**
+ * @param eqScore the eqScore to set
+ */
+ public void setEqScore(double eqScore) {
+ this.eqScore = eqScore;
+ }
+ /**
+ * @return the subClassScore
+ */
+ public double getSubClassScore() {
+ return subClassScore;
+ }
+ /**
+ * @param subClassScore the subClassScore to set
+ */
+ public void setSubClassScore(double subClassScore) {
+ this.subClassScore = subClassScore;
+ }
+ /**
+ * @return the superClassScore
+ */
+ public double getSuperClassScore() {
+ return superClassScore;
+ }
+ /**
+ * @param superClassScore the superClassScore to set
+ */
+ public void setSuperClassScore(double superClassScore) {
+ this.superClassScore = superClassScore;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "SimpleClassMatch [queryClassId=" + queryClassId
+ + ", matchClassId=" + matchClassId + ", queryClassLabel="
+ + queryClassLabel + ", matchClassLabel=" + matchClassLabel
+ + ", eqScore=" + eqScore + ", subClassScore=" + subClassScore
+ + ", superClassScore=" + superClassScore + "]";
+ }
+
+
+
+
+}
@@ -0,0 +1,8 @@
+/**
+ *
+ */
+/**
+ * @author cjm
+ *
+ */
+package org.monarchinitiative.owlsim.compute.classmatch;
@@ -0,0 +1,59 @@
+package org.monarchinitiative.owlsim.compute.classmatch;
+
+import static org.junit.Assert.*;
+
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.junit.Test;
+import org.monarchinitiative.owlsim.compute.mica.AbstractMICAStoreTest;
+import org.monarchinitiative.owlsim.compute.mica.MICAStore;
+import org.monarchinitiative.owlsim.compute.mica.impl.MICAStoreImpl;
+import org.monarchinitiative.owlsim.compute.mica.impl.NoRootException;
+import org.monarchinitiative.owlsim.compute.stats.KBStatsCalculator;
+import org.monarchinitiative.owlsim.io.OWLLoader;
+import org.monarchinitiative.owlsim.kb.BMKnowledgeBase;
+import org.monarchinitiative.owlsim.kb.LabelMapper;
+import org.semanticweb.owlapi.model.IRI;
+import org.semanticweb.owlapi.model.OWLOntologyCreationException;
+
+import com.google.monitoring.runtime.instrumentation.common.com.google.common.io.Resources;
+
+public class ClassMatcherTest {
+
+ protected BMKnowledgeBase kb;
+ protected ClassMatcher classMatcher;
+ private Logger LOG = Logger.getLogger(ClassMatcherTest.class);
+
+ protected void load(String fn, String... ontfns) throws OWLOntologyCreationException, URISyntaxException, NoRootException {
+ OWLLoader loader = new OWLLoader();
+ LOG.info("Loading: "+fn);
+ loader.load(IRI.create(Resources.getResource(fn)));
+ for (String ontfn : ontfns) {
+ URL res = getClass().getResource(ontfn);
+ LOG.info("RES="+res);
+ loader.loadOntologies(res.getFile());
+ }
+ kb = loader.createKnowledgeBaseInterface();
+ classMatcher = new ClassMatcher(kb);
+ }
+
+ @Test
+ public void selfTest() throws OWLOntologyCreationException, URISyntaxException, NoRootException {
+ load("mp-subset.ttl");
+ LabelMapper lm = kb.getLabelMapper();
+
+ List<SimpleClassMatch> matches = classMatcher.matchOntologies("MP", "MP");
+
+ int numNonSelfMatches = 0;
+ for (SimpleClassMatch m : matches) {
+ if (!m.getQueryClassId().equals(m.getMatchClassId())) {
+ numNonSelfMatches++;
+ }
+ }
+ assertEquals(0, numNonSelfMatches);
+ }
+
+}
@@ -0,0 +1,66 @@
+package org.monarchinitiative.owlsim.services.resources;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.monarchinitiative.owlsim.compute.classmatch.ClassMatcher;
+import org.monarchinitiative.owlsim.compute.classmatch.SimpleClassMatch;
+import org.monarchinitiative.owlsim.compute.cpt.IncoherentStateException;
+import org.monarchinitiative.owlsim.compute.matcher.NegationAwareProfileMatcher;
+import org.monarchinitiative.owlsim.compute.matcher.ProfileMatcher;
+import org.monarchinitiative.owlsim.kb.filter.AnonIndividualFilter;
+import org.monarchinitiative.owlsim.kb.filter.TypeFilter;
+import org.monarchinitiative.owlsim.kb.filter.UnknownFilterException;
+import org.monarchinitiative.owlsim.model.match.MatchSet;
+import org.monarchinitiative.owlsim.model.match.ProfileQuery;
+import org.monarchinitiative.owlsim.model.match.ProfileQueryFactory;
+import org.monarchinitiative.owlsim.services.exceptions.NonNegatedMatcherException;
+import org.monarchinitiative.owlsim.services.exceptions.UnknownMatcherException;
+
+import com.codahale.metrics.annotation.Timed;
+import com.wordnik.swagger.annotations.Api;
+import com.wordnik.swagger.annotations.ApiOperation;
+import com.wordnik.swagger.annotations.ApiParam;
+
+import io.dropwizard.jersey.caching.CacheControl;
+
+@Path("/ontomatch")
+@Api(value = "/ontomatch", description = "ontology match services")
+@Produces({MediaType.APPLICATION_JSON})
+public class OntologyMatchResource {
+
+ @Inject
+ ClassMatcher classMatcher;
+
+ @GET
+ @Path("/{queryOntology}/{targetOntology}")
+ @Timed
+ @CacheControl(maxAge = 2, maxAgeUnit = TimeUnit.HOURS)
+ @ApiOperation(value = "Match", response = MatchSet.class,
+ notes = "Additional notes on the match resource.")
+ public List<SimpleClassMatch> getMatches(
+ @ApiParam(value = "base ontology, e.g. MP",
+ required = true) @PathParam("queryOntology") String queryOntology,
+ @ApiParam(value = "ontology to be matched, e.g. HP",
+ required = true) @PathParam("targetOntology") String targetOntology)
+ throws UnknownFilterException, IncoherentStateException {
+ List<SimpleClassMatch> matches =
+ classMatcher.matchOntologies(queryOntology, targetOntology);
+ return matches;
+ }
+
+ // TODO - API for comparing two entities
+
+}