Skip to content
New issue

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

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#72] added service for single entity #73

Merged
merged 3 commits into from
Mar 25, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.monarchinitiative.owlsim.kb.BMKnowledgeBase;
import org.monarchinitiative.owlsim.kb.LabelMapper;

import com.google.common.collect.Sets;
import com.googlecode.javaewah.EWAHCompressedBitmap;

/**
Expand Down Expand Up @@ -37,6 +38,18 @@ public List<SimpleClassMatch> matchOntologies(String qOnt, String tOnt) {
return matchClassSets(qids, tids);
}

/**
* Find best match for one entity in a whole ontology
*
* @param entity
* @param tOnt
* @return list of matches
*/
public List<SimpleClassMatch> matchEntity(String entity, String tOnt) {
Set<String> tids = kb.getClassIdsByOntology(tOnt);
return matchClassSets(Sets.newHashSet(entity), tids);
}

public List<SimpleClassMatch> matchClassSets(Set<String> qids, Set<String> tids) {
ArrayList<SimpleClassMatch> matches = new ArrayList<>();
for (String q : qids) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,62 @@
import java.util.List;
import java.util.stream.Collectors;

import static org.junit.Assert.assertEquals;
import javax.swing.plaf.synth.SynthSplitPaneUI;

import static org.junit.Assert.*;

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.ontologies(res.getFile());
// }
// kb = loader.createKnowledgeBaseInterface();
kb = OwlKnowledgeBase.loader()
.loadOntology(filePath(fn))
.loadOntologies(Arrays.stream(ontfns).map(ontfn -> filePath(ontfn)).collect(Collectors.toList()))
.createKnowledgeBase();
classMatcher = new ClassMatcher(kb);
}

private String filePath(String filename) {
return Paths.get("src/test/resources/", filename).toString();
}

@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);
}
protected BMKnowledgeBase kb;
private Logger LOG = Logger.getLogger(ClassMatcherTest.class);

protected ClassMatcher 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.ontologies(res.getFile());
// }
// kb = loader.createKnowledgeBaseInterface();
kb = OwlKnowledgeBase.loader().loadOntology(filePath(fn))
.loadOntologies(Arrays.stream(ontfns).map(ontfn -> filePath(ontfn)).collect(Collectors.toList()))
.createKnowledgeBase();
return new ClassMatcher(kb);
}

private String filePath(String filename) {
return Paths.get("src/test/resources/", filename).toString();
}

@Test
public void selfTest() throws OWLOntologyCreationException, URISyntaxException, NoRootException {
ClassMatcher classMatcher = 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);
}

@Test
public void entityMatchTest() throws OWLOntologyCreationException, URISyntaxException, NoRootException {
ClassMatcher classMatcher = load("mp-subset.ttl");

String testEntity = "http://purl.obolibrary.org/obo/MP_0001951";

List<SimpleClassMatch> matches = classMatcher.matchEntity(testEntity, "MP");

assertFalse(matches.isEmpty());
assertEquals(testEntity, matches.get(0).getMatchClassId());
}

}
Original file line number Diff line number Diff line change
@@ -1,48 +1,39 @@
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 org.prefixcommons.CurieUtil;

import com.codahale.metrics.annotation.Timed;

import io.dropwizard.jersey.caching.CacheControl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.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;

@Inject
CurieUtil curieUtil;

@GET
@Path("/{queryOntology}/{targetOntology}")
Expand All @@ -61,6 +52,28 @@ public List<SimpleClassMatch> getOntoMatches(
return matches;
}


// TODO - API for comparing two entities

@GET
@Path("/{entity}/{ontology}")
@Timed
@CacheControl(maxAge = 2, maxAgeUnit = TimeUnit.HOURS)
@ApiOperation(value = "Match", response = MatchSet.class,
notes = "Additional notes on the match resource.")
public List<SimpleClassMatch> getEntityMatches(
@ApiParam(value = "entity, e.g. MP:0001951",
required = true) @PathParam("entity") String entity,
@ApiParam(value = "ontology to be matched, e.g. HP",
required = true) @PathParam("ontology") String ontology)
throws UnknownFilterException, IncoherentStateException {

// TODO it's weird to resolve the curie here
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you're passing the entity into the ClassMatcher via the matchEntity() method so you have the curieUtil accessible from you in there and don't need to do it here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean passing the CurieUtil as a parameter of matchEntity()?

I'm wondering if the ClassMatcher should have a CurieUtil in the constructor, what do you think?

Copy link
Contributor

@julesjacobsen julesjacobsen Mar 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, no sorry - I'm mistaken. The curieUtil is used internally within the BMKnowledgebase, but is not accessible from it. Providing the ClassMatcher with the curieUtil and bmKnowledgeBase in the constructor would solve this. Then you can move

String resolveEntity = curieUtil.getIri(entity).orElse(entity); 

into the ClassMatcher.

I just wonder to what extent we need to hide the CurieUtil inside the BMKnowledgeBase - presumably we're always going to use the OWLAPI and the CurieUtil in the BMKnowledgeBase? If that's the case and these are going to be required externally to query the BMKnowledgeBase, then it should expose them so they can be used, or provide methods like:

public String resolveIri(String entity)
    return curieUtil.getIri(entity).orElse(entity); 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep I was also leaning towards that solution, I'll make that change in my PR!

Thanks!

Copy link
Contributor

@julesjacobsen julesjacobsen Mar 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant to add the resolveIri() method to the BMKnowledgeBase interface, in case I wasn't clear - which I wasn't!

String resolveEntity = curieUtil.getIri(entity).orElse(entity);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a common pattern using the CurieUtil - might be worth providing a toIriString() method?


List<SimpleClassMatch> matches =
classMatcher.matchEntity(resolveEntity, ontology);
return matches;
}

}