-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6 from phyloref/rewrote_phyloref_resolution_testing
The current version of the phyloreference testing code had evolved through several different cycles, was badly written, and appeared to not be correctly testing phyloreferences using the expected_phyloreference_named property. I replaced it with cleaner, easier to read code that appears to be testing phyloreferences correctly, and tested these in PR #9 and its use in phyloref/clade-ontology#29.
- Loading branch information
Showing
6 changed files
with
198 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Change log for JPhyloref | ||
|
||
Based on the suggestion at https://keepachangelog.com/en/1.0.0/. | ||
|
||
## [Unreleased] | ||
|
||
## 0.1 - 2018-06-20 | ||
- Initial release, with support for testing phyloreferences expressed in OWL | ||
and stored in RDF/XML. | ||
|
||
[Unreleased]: https://github.com/phyloref/jphyloref/compare/v0.1...HEAD |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,24 @@ | ||
package org.phyloref.jphyloref.commands; | ||
|
||
import org.phyloref.jphyloref.helpers.PhylorefHelper; | ||
import org.phyloref.jphyloref.helpers.OWLHelper; | ||
|
||
import java.io.File; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.LinkedList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.Set; | ||
import java.util.stream.Collectors; | ||
|
||
import org.apache.commons.cli.CommandLine; | ||
import org.apache.commons.cli.Options; | ||
import org.phyloref.jphyloref.helpers.OWLHelper; | ||
import org.phyloref.jphyloref.helpers.PhylorefHelper; | ||
import org.semanticweb.owlapi.apibinding.OWLManager; | ||
import org.semanticweb.owlapi.model.OWLAnnotationProperty; | ||
import org.semanticweb.owlapi.model.OWLAxiom; | ||
import org.semanticweb.owlapi.model.OWLClass; | ||
import org.semanticweb.owlapi.model.OWLDataFactory; | ||
import org.semanticweb.owlapi.model.OWLDataProperty; | ||
import org.semanticweb.owlapi.model.OWLLiteral; | ||
import org.semanticweb.owlapi.model.OWLNamedIndividual; | ||
import org.semanticweb.owlapi.model.OWLObjectProperty; | ||
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression; | ||
import org.semanticweb.owlapi.model.OWLOntology; | ||
import org.semanticweb.owlapi.model.OWLOntologyCreationException; | ||
import org.semanticweb.owlapi.model.OWLOntologyManager; | ||
|
@@ -39,25 +33,25 @@ | |
import org.tap4j.producer.TapProducerFactory; | ||
import org.tap4j.util.DirectiveValues; | ||
import org.tap4j.util.StatusValues; | ||
|
||
import uk.ac.manchester.cs.jfact.JFactReasoner; | ||
import uk.ac.manchester.cs.jfact.kernel.options.JFactReasonerConfiguration; | ||
|
||
/** | ||
* Test whether the phyloreferences in the provided ontology resolve correctly. | ||
* This currently supports RDF/XML input only, but we will eventually modify | ||
* this to support PHYX files directly. | ||
* | ||
* At the moment, this works on OWL ontologies, but there's really no reason we | ||
* couldn't test the labeled.json file directly! Maybe at a later date? | ||
* | ||
* I can't resist using the Test Anything Protocol here, which has nice | ||
* libraries in both Python and Java. | ||
* I use the Test Anything Protocol here, which has nice libraries in both | ||
* Python and Java. | ||
* | ||
* @author Gaurav Vaidya <[email protected]> | ||
* | ||
*/ | ||
public class TestCommand implements Command { | ||
/** | ||
* This command is named "test". It should be | ||
* involved "java -jar jphyloref.jar test ..." | ||
* This command is named Test. It should be | ||
* invoked as "java -jar jphyloref.jar test ..." | ||
*/ | ||
|
||
@Override | ||
|
@@ -66,6 +60,8 @@ public String getName() { | |
} | ||
|
||
/** | ||
* A description of the Test command. | ||
* | ||
* @return A description of this command. | ||
*/ | ||
@Override | ||
|
@@ -74,7 +70,8 @@ public String getDescription() { | |
} | ||
|
||
/** | ||
* Add command-line options specific to this command. | ||
* Add command-line options specific to this command. There is only one: | ||
* -i or --input can be used to set the RDF/XML file to read. | ||
* | ||
* @param opts The command-line options to modify for this command. | ||
*/ | ||
|
@@ -146,7 +143,7 @@ public void execute(CommandLine cmdLine) throws RuntimeException { | |
// Get some properties ready before-hand so we don't have to reload | ||
// them on every loop. | ||
OWLAnnotationProperty labelAnnotationProperty = dataFactory.getOWLAnnotationProperty(OWLRDFVocabulary.RDFS_LABEL.getIRI()); | ||
OWLDataProperty expectedPhyloreferenceNameProperty = dataFactory.getOWLDataProperty(PhylorefHelper.IRI_NAME_OF_EXPECTED_PHYLOREF); | ||
OWLDataProperty expectedPhyloreferenceNamedProperty = dataFactory.getOWLDataProperty(PhylorefHelper.IRI_NAME_OF_EXPECTED_PHYLOREF); | ||
OWLObjectProperty unmatchedSpecifierProperty = dataFactory.getOWLObjectProperty(PhylorefHelper.IRI_PHYLOREF_UNMATCHED_SPECIFIER); | ||
// OWLDataProperty specifierDefinitionProperty = dataFactory.getOWLDataProperty(PhylorefHelper.IRI_CLADE_DEFINITION); | ||
|
||
|
@@ -178,7 +175,7 @@ public void execute(CommandLine cmdLine) throws RuntimeException { | |
phylorefLabel = phyloref.getIRI().toString(); | ||
result.setDescription("Phyloreference '" + phylorefLabel + "'"); | ||
|
||
// Which nodes did this phyloreference resolved to? | ||
// Which nodes did this phyloreference resolve to? | ||
OWLClass phylorefAsClass = manager.getOWLDataFactory().getOWLClass(phyloref.getIRI()); | ||
Set<OWLNamedIndividual> nodes = reasoner.getInstances(phylorefAsClass, false).getFlattened(); | ||
|
||
|
@@ -188,59 +185,53 @@ public void execute(CommandLine cmdLine) throws RuntimeException { | |
result.addComment(new Comment("No nodes matched.")); | ||
testFailed = true; | ||
} else { | ||
// Make a list of every expected phyloreference for input node. | ||
Map<OWLNamedIndividual, Set<OWLLiteral>> expectedPhyloreferencesByNode = new HashMap<>(); | ||
|
||
// Look for nodes where either its label or its expected phyloreference label | ||
// is equal to the phyloreference we are currently processing. | ||
Set<String> nodeLabelsWithExpectedPhylorefs = new HashSet<>(); | ||
Set<String> nodeLabelsWithoutExpectedPhylorefs = new HashSet<>(); | ||
|
||
for(OWLNamedIndividual node: nodes) { | ||
// What are the expected phyloreferences associated with these nodes? | ||
expectedPhyloreferencesByNode.put( | ||
node, | ||
node.getDataPropertyValues(expectedPhyloreferenceNameProperty, ontology) | ||
); | ||
// Get a list of all expected phyloreference labels from the OWL file. | ||
Set<String> expectedPhylorefsNamed = node.getDataPropertyValues(expectedPhyloreferenceNamedProperty, ontology) | ||
.stream() | ||
.map(literal -> literal.getLiteral()) // We ignore languages for now. | ||
.collect(Collectors.toSet()); | ||
|
||
// Add the label of the node as well. | ||
Set<String> nodeLabels = OWLHelper.getLabelsInEnglish(node, ontology); | ||
expectedPhylorefsNamed.addAll(nodeLabels); | ||
|
||
// Build a new node label that describes this node. | ||
String nodeLabel = new StringBuilder() | ||
.append("[") | ||
.append(String.join(", ", expectedPhylorefsNamed)) | ||
.append("]") | ||
.toString(); | ||
|
||
// Does this node have an expected phyloreference identical to the phyloref being tested? | ||
if(expectedPhylorefsNamed.contains(phylorefLabel)) { | ||
nodeLabelsWithExpectedPhylorefs.add(nodeLabel); | ||
} else { | ||
nodeLabelsWithoutExpectedPhylorefs.add(nodeLabel); | ||
} | ||
} | ||
|
||
// Flatten expected phyloreference names from each Node into a | ||
// single set of unique expected phyloreference names. | ||
Set<OWLLiteral> distinctExpectedPhylorefNames = expectedPhyloreferencesByNode.values() | ||
.stream().flatMap(n -> n.stream()) | ||
.collect(Collectors.toSet()); | ||
|
||
// How many distinct expected phyloref names do we have? | ||
if(distinctExpectedPhylorefNames.isEmpty()) { | ||
result.addComment(new Comment("None of the " + nodes.size() + " resolved nodes are expected to resolve to phyloreferences.")); | ||
// What happened? | ||
if(!nodeLabelsWithExpectedPhylorefs.isEmpty() && !nodeLabelsWithoutExpectedPhylorefs.isEmpty()) { | ||
// We found nodes that expected this phyloref, as well as nodes that did not -- success! | ||
result.addComment(new Comment("The following nodes were matched and expected this phyloreference: " + String.join("; ", nodeLabelsWithExpectedPhylorefs))); | ||
result.addComment(new Comment("Also, the following nodes were matched but did not expect this phyloreference: " + String.join("; ", nodeLabelsWithoutExpectedPhylorefs))); | ||
} else if(!nodeLabelsWithExpectedPhylorefs.isEmpty()) { | ||
// We only found nodes that expected this phyloref -- success! | ||
result.addComment(new Comment("The following nodes were matched and expected this phyloreference: " + String.join("; ", nodeLabelsWithExpectedPhylorefs))); | ||
} else if(!nodeLabelsWithoutExpectedPhylorefs.isEmpty()) { | ||
// We only have nodes that did not expect this phyloref -- failure! | ||
result.addComment(new Comment("The following nodes were matched but did not expect this phyloreference: " + String.join("; ", nodeLabelsWithoutExpectedPhylorefs))); | ||
testFailed = true; | ||
|
||
} else if(distinctExpectedPhylorefNames.size() > 1) { | ||
// This is okay IF at least one of the nodes is expected to resolve to this phyloreference. | ||
List<String> otherLabels = new LinkedList<>(); | ||
|
||
int matchCount = 0; | ||
for(OWLLiteral label: distinctExpectedPhylorefNames) { | ||
if(label.getLiteral().equals(phylorefLabel)) matchCount++; | ||
else otherLabels.add(label.getLiteral()); | ||
} | ||
|
||
String otherLabelsStr = otherLabels.stream().collect(Collectors.joining("; ")); | ||
|
||
if(matchCount > 0) { | ||
result.addComment(new Comment("Phyloreference resolved to " + matchCount + " nodes with the expected phyloreference label '" + phylorefLabel + "'; other nodes expected phyloreferences: " + otherLabelsStr)); | ||
} else { | ||
result.addComment(new Comment("Phyloreference did not resolve to the expected phyloreference label '" + phylorefLabel + "', but did resolve to multiple expected phyloreferences: " + otherLabelsStr)); | ||
testFailed = true; | ||
} | ||
|
||
} else { | ||
// We have exactly one expected phyloref name -- but is it the right one? | ||
OWLLiteral onlyOne = distinctExpectedPhylorefNames.iterator().next(); | ||
String label = onlyOne.getLiteral(); | ||
|
||
if(label.equals(phylorefLabel)) { | ||
result.addComment(new Comment("Resolved node label '" + label + "' identical to expected phyloreference label '" + phylorefLabel + "'")); | ||
} else { | ||
result.addComment(new Comment("Resolved node label '" + label + "' differs from expected phyloreference label '" + phylorefLabel + "'")); | ||
testFailed = true; | ||
} | ||
} | ||
// No nodes matched. This should have been caught earlier, but just in case. | ||
throw new RuntimeException("No nodes were matched, which should have been caught earlier. Programmer error!"); | ||
} | ||
} | ||
|
||
// Look for all unmatched specifiers reported for this phyloreference | ||
|
Oops, something went wrong.