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

Update from master #446

Merged
merged 14 commits into from
Jul 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 6 additions & 6 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ daemonUser in Linux := "phenoscape" // user which will execute the application

daemonGroup in Linux := "phenoscape" // group which will execute the application

scalaVersion := "2.12.13"
scalaVersion := "2.13.6"

scalacOptions := Seq("-unchecked", "-deprecation", "-feature", "-encoding", "utf8")

Expand All @@ -35,16 +35,16 @@ libraryDependencies ++= {
"com.typesafe.akka" %% "akka-stream" % "2.6.12",
"com.typesafe.akka" %% "akka-actor" % "2.6.12",
"com.typesafe.akka" %% "akka-slf4j" % "2.6.12",
"com.typesafe.akka" %% "akka-http" % "10.1.14",
"com.typesafe.akka" %% "akka-http-caching" % "10.1.14",
"com.typesafe.akka" %% "akka-http-spray-json" % "10.1.14",
"com.typesafe.akka" %% "akka-http" % "10.2.4",
"com.typesafe.akka" %% "akka-http-caching" % "10.2.4",
"com.typesafe.akka" %% "akka-http-spray-json" % "10.2.4",
"ch.megard" %% "akka-http-cors" % "1.0.0",
"com.lightbend.akka" %% "akka-stream-alpakka-xml" % "2.0.2",
"io.spray" %% "spray-json" % "1.3.6",
"net.sourceforge.owlapi" % "owlapi-distribution" % "4.5.18",
"org.phenoscape" %% "owlet" % "1.8.1" exclude("org.slf4j", "slf4j-log4j12"), // exclude("log4j", "log4j"),
"org.phenoscape" %% "scowl" % "1.3.4",
"org.phenoscape" %% "kb-owl-tools" % "1.5.1" exclude("org.slf4j", "slf4j-log4j12"), // exclude("log4j", "log4j"),
"org.phenoscape" %% "kb-owl-tools" % "1.13.0" exclude("org.slf4j", "slf4j-log4j12"), // exclude("log4j", "log4j"),
"org.phenoscape" %% "phenoscape-kb-ingest" % "1.6.2",
"org.phenoscape" % "phenex" % "1.17.2" exclude("org.slf4j", "slf4j-log4j12") exclude("net.sourceforge.owlapi", "owlapi-apibinding"),
"commons-io" % "commons-io" % "2.8.0", // exclude("log4j", "log4j"),
Expand All @@ -55,7 +55,7 @@ libraryDependencies ++= {
"org.codehaus.groovy" % "groovy-all" % "3.0.5",
"org.phenoscape" %% "sparql-utils" % "1.3.1",
"org.phenoscape" %% "sparql-utils-owlapi" % "1.3.1",
"com.lihaoyi" %% "utest" % "0.7.7" % Test
"com.lihaoyi" %% "utest" % "0.7.9" % Test
)
}

Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.4.7
sbt.version=1.5.3
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
addSbtPlugin("io.spray" % "sbt-revolver" % "0.9.1")

addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.8.0")
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.8.1")

addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.0")
2 changes: 1 addition & 1 deletion src/main/scala/org/phenoscape/kb/Gene.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import org.phenoscape.kb.KBVocab.{rdfsLabel, rdfsSubClassOf, _}
import org.phenoscape.kb.Main.system.dispatcher
import org.phenoscape.kb.JSONResultItem.JSONResultItemsMarshaller
import org.phenoscape.kb.queries.GeneAffectingPhenotype
import org.phenoscape.owl.Vocab._
import org.phenoscape.owl.{NamedRestrictionGenerator, Vocab}
import org.phenoscape.owlet.OwletManchesterSyntaxDataType.SerializableClassExpression
import org.phenoscape.owlet.SPARQLComposer._
Expand All @@ -27,6 +26,7 @@ import spray.json._
import org.phenoscape.sparql.SPARQLInterpolation.{QueryText, _}
import org.phenoscape.sparql.SPARQLInterpolationOWL._
import org.phenoscape.kb.util.SPARQLInterpolatorOWLAPI._
import org.phenoscape.owl.Vocab.{AnnotatedPhenotype, GeneExpression, associated_with_gene, associated_with_taxon, dcSource, has_part, in_taxon, inheres_in, occurs_in, part_of, rdfType, towards}

import scala.collection.JavaConverters._
import scala.concurrent.Future
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package org.phenoscape.kb
import java.net.URI
import java.text.SimpleDateFormat
import java.util.Calendar

import org.apache.jena.query.{Query, QuerySolution}
import org.apache.jena.rdf.model.{Property, ResourceFactory}
import org.apache.jena.sparql.core.Var
Expand All @@ -19,7 +18,6 @@ import org.phenoscape.kb.Main.system.dispatcher
import org.phenoscape.model.MultipleState.MODE
import org.phenoscape.model.{Character, DataSet, MultipleState, State, Taxon => MatrixTaxon}
import org.phenoscape.owl.NamedRestrictionGenerator
import org.phenoscape.owl.Vocab._
import org.phenoscape.owlet.OwletManchesterSyntaxDataType.SerializableClassExpression
import org.phenoscape.owlet.SPARQLComposer._
import org.phenoscape.scowl._
Expand All @@ -29,6 +27,7 @@ import org.phenoscape.sparql.SPARQLInterpolation._
import org.phenoscape.sparql.SPARQLInterpolationOWL._
import org.phenoscape.kb.util.SPARQLInterpolatorOWLAPI._
import org.phenoscape.kb.KBVocab.KBMainGraph
import org.phenoscape.owl.Vocab.{ABSENCE_OF, IMPLIES_PRESENCE_OF, dcDescription, describes_phenotype, exhibits_state, has_absence_of, has_character, has_presence_of, may_have_state_value, part_of}
import scalaz.NonEmptyList

import scala.collection.JavaConverters._
Expand Down
8 changes: 4 additions & 4 deletions src/main/scala/org/phenoscape/kb/Study.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.phenoscape.kb

import java.util.UUID

import akka.http.scaladsl.marshalling.{Marshaller, ToEntityMarshaller}
import akka.http.scaladsl.model.MediaTypes

Expand All @@ -21,7 +20,6 @@ import org.phenoscape.kb.Facets.Facet
import org.phenoscape.kb.Main.system.dispatcher
import org.phenoscape.kb.queries.QueryUtil.{PhenotypicQuality, QualitySpec}
import org.phenoscape.kb.queries.StudiesRelevantToPhenotype
import org.phenoscape.owl.Vocab._
import org.phenoscape.owlet.SPARQLComposer._
import org.phenoscape.scowl._
import org.semanticweb.owlapi.apibinding.OWLManager
Expand All @@ -32,7 +30,8 @@ import spray.json.DefaultJsonProtocol._
import org.phenoscape.sparql.SPARQLInterpolation._
import org.phenoscape.sparql.SPARQLInterpolationOWL._
import org.phenoscape.sparql.FromQuerySolutionOWL._
import org.phenoscape.kb.KBVocab.KBMainGraph
import org.phenoscape.kb.KBVocab.{KBMainGraph, rdfsLabel}
import org.phenoscape.owl.Vocab.{ANATOMICAL_ENTITY, CHORDATA, CharacterStateDataMatrix, belongs_to_TU, belongs_to_character, dcDescription, describes_phenotype, has_TU, has_character, has_external_reference, has_state, list_index, may_have_state_value, rdfType, state_symbol}

import scala.language.higherKinds

Expand Down Expand Up @@ -317,7 +316,8 @@ object Study {
} yield character.asResource.getURI -> stateGroup.toSet)
.toSet[(String, Set[String])]
.groupBy(_._1)
.mapValues(_.map(_._2))
.view
.mapValues(_.map(_._2)).to(Map)
val allIndividualStatesAsSets = neededStateGroups.values.flatten.flatten.map(Set(_))
val stateGroupIDs = (for {
(character, stateGroups) <- neededStateGroups
Expand Down
62 changes: 36 additions & 26 deletions src/main/scala/org/phenoscape/kb/Term.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ object Term {
limit: Int = 100): Future[Seq[MatchedTerm[DefinedMinimalTerm]]] = {
def resultFromQuerySolution(qs: QuerySolution): DefinedMinimalTerm =
DefinedMinimalTerm(MinimalTerm.fromQuerySolution(qs),
Option(qs.getResource("ont")).map(o => IRI.create(o.getURI)))
Option(qs.getResource("ont")).map(o => IRI.create(o.getURI)))

App
.executeSPARQLQueryString(
Expand Down Expand Up @@ -95,8 +95,8 @@ object Term {
def computeLabelForAnonymousTerm(iri: IRI): Future[MinimalTerm] =
iri.toString match {
case expression
if expression.startsWith(ExpressionUtil.namedExpressionPrefix) || expression.startsWith(
ExpressionUtil.namedSubClassPrefix) =>
if expression.startsWith(ExpressionUtil.namedExpressionPrefix) || expression.startsWith(
ExpressionUtil.namedSubClassPrefix) =>
labelForNamedExpression(iri)
case negation if negation.startsWith("http://phenoscape.org/not/") =>
computedLabel(IRI.create(negation.replaceFirst(Pattern.quote("http://phenoscape.org/not/"), ""))).map { term =>
Expand Down Expand Up @@ -133,18 +133,20 @@ object Term {
def withIRI(iri: IRI): Future[Option[Term]] = {
def termResult(result: QuerySolution) =
(Option(result.getLiteral("label")).map(_.getLexicalForm),
Option(result.getLiteral("definition")).map(_.getLexicalForm).getOrElse(""),
Option(result.getResource("ontology")).map(_.getURI))
Option(result.getLiteral("definition")).map(_.getLexicalForm).getOrElse(""),
Option(result.getResource("ontology")).map(_.getURI))

val termFuture = App.executeSPARQLQuery(buildTermQuery(iri), termResult).map(_.headOption)
val synonymsFuture = termSynonyms(iri)
val relsFuture = termRelationships(iri)
val classificationFuture = classification(iri, None)
for {
termOpt <- termFuture
synonyms <- synonymsFuture
relationships <- relsFuture
classification <- classificationFuture
} yield termOpt.map { case (label, definition, ontology) =>
Term(iri, label, definition, ontology, synonyms, relationships)
Term(iri, label, definition, ontology, synonyms, classification, relationships)
}
}

Expand Down Expand Up @@ -188,8 +190,8 @@ object Term {
def shouldHide(term: MinimalTerm) = {
val termID = term.iri.toString
termID.startsWith("http://example.org") ||
termID == "http://www.w3.org/2002/07/owl#Nothing" ||
termID == "http://www.w3.org/2002/07/owl#Thing"
termID == "http://www.w3.org/2002/07/owl#Nothing" ||
termID == "http://www.w3.org/2002/07/owl#Thing"
}

val superclassesFuture = querySuperClasses(iri, source)
Expand All @@ -202,9 +204,9 @@ object Term {
subclasses <- subclassesFuture
equivalents <- equivalentsFuture
} yield Classification(term,
superclasses.filterNot(shouldHide).toSet,
subclasses.filterNot(shouldHide).toSet,
equivalents.filterNot(shouldHide).toSet)
superclasses.filterNot(shouldHide).toSet,
subclasses.filterNot(shouldHide).toSet,
equivalents.filterNot(shouldHide).toSet)
}

def querySuperClasses(iri: IRI, source: Option[IRI]): Future[Seq[MinimalTerm]] = {
Expand Down Expand Up @@ -268,7 +270,7 @@ object Term {
val query = select_distinct('term, 'term_label) from "http://kb.phenoscape.org/" where (bgp(
(t('term, rdfsLabel, 'term_label) ::
definedByTriple): _*),
union)
union)
App.executeSPARQLQuery(query, MinimalTerm.fromQuerySolution)
}

Expand Down Expand Up @@ -342,16 +344,16 @@ object Term {
val superClassesQuery = select_distinct('super) from "http://kb.phenoscape.org/" where (bgp(
(t('super, rdfType, owlClass) ::
definedByTriple ++
iris.map(superClassTriple).toList): _*))
iris.map(superClassTriple).toList): _*))
val superSuperClassesQuery = select_distinct('supersuper) from "http://kb.phenoscape.org/" where (
bgp(
(t('super, rdfType, owlClass) ::
t('supersuper, rdfType, owlClass) ::
t('super, new P_OneOrMore1(new P_Link(rdfsSubClassOf)), 'supersuper) ::
definedByTriple ++
iris.map(superClassTriple).toList): _*
iris.map(superClassTriple).toList): _*
)
)
)
val superClassesFuture = App.executeSPARQLQuery(superClassesQuery, _.getResource("super").getURI)
val superSuperClassesFuture = App.executeSPARQLQuery(superSuperClassesQuery, _.getResource("supersuper").getURI)
for {
Expand All @@ -371,16 +373,16 @@ object Term {
def buildTermQuery(iri: IRI): Query =
select_distinct('label, 'definition, 'ontology) from "http://kb.phenoscape.org/" where (optional(
bgp(t(iri, rdfsLabel, 'label))),
optional(bgp(t(iri, definition, 'definition))),
optional(bgp(t(iri, rdfsIsDefinedBy, 'ontology))))
optional(bgp(t(iri, definition, 'definition))),
optional(bgp(t(iri, rdfsIsDefinedBy, 'ontology))))

def termRelationships(iri: IRI): Future[Seq[TermRelationship]] =
App.executeSPARQLQuery(
buildRelationsQuery(iri),
(result) =>
TermRelationship(
MinimalTerm(IRI.create(result.getResource("relation").getURI),
Some(result.getLiteral("relation_name").getString)),
Some(result.getLiteral("relation_name").getString)),
MinimalTerm(IRI.create(result.getResource("filler").getURI), Some(result.getLiteral("filler_name").getString))
)
)
Expand Down Expand Up @@ -413,8 +415,8 @@ object Term {
t('restriction, owlSomeValuesFrom, 'filler),
t('filler, rdfsLabel, 'filler_label)
),
new ElementFilter(new E_IsIRI(new ExprVar('relation))),
new ElementFilter(new E_IsIRI(new ExprVar('filler))))
new ElementFilter(new E_IsIRI(new ExprVar('relation))),
new ElementFilter(new E_IsIRI(new ExprVar('filler))))
// We need to handle multiple labels in the DB for properties (and possibly classes)
query.getProject.add(Var.alloc("filler_name"), query.allocAggregate(new AggMin(new ExprVar('filler_label))))
query.getProject.add(Var.alloc("relation_name"), query.allocAggregate(new AggMin(new ExprVar('relation_label))))
Expand Down Expand Up @@ -485,8 +487,8 @@ object Term {
t('term, rdfsIsDefinedBy, definedBy),
t('term, rdfType, owlClass)
),
new ElementFilter(new E_IsIRI(new ExprVar('term))),
new ElementFilter(new E_NotExists(triplesBlock(bgp(t('term, owlDeprecated, "true" ^^ XSDDatatype.XSDboolean))))))
new ElementFilter(new E_IsIRI(new ExprVar('term))),
new ElementFilter(new E_NotExists(triplesBlock(bgp(t('term, owlDeprecated, "true" ^^ XSDDatatype.XSDboolean))))))
query.addOrderBy('rank, Query.ORDER_ASCENDING)
if (limit > 0) query.setLimit(limit)
query
Expand Down Expand Up @@ -563,8 +565,9 @@ final case class Term(iri: IRI,
definition: String,
sourceOntology: Option[String],
synonyms: Seq[(IRI, String)],
classification: Classification,
relationships: Seq[TermRelationship])
extends LabeledTerm
extends LabeledTerm
with JSONResultItem {

def toJSON: JsObject =
Expand All @@ -576,6 +579,7 @@ final case class Term(iri: IRI,
"synonyms" -> synonyms.map { case (iri, value) =>
JsObject("property" -> iri.toString.toJson, "value" -> value.toJson).toJson
}.toJson,
"classification" -> classification.jsonWithoutTerm,
"relationships" -> relationships.map(_.toJSON).toJson
).toJson.asJsObject

Expand All @@ -594,7 +598,7 @@ object MinimalTerm {

def fromQuerySolution(result: QuerySolution): MinimalTerm =
MinimalTerm(IRI.create(result.getResource("term").getURI),
Option(result.getLiteral("term_label")).map(_.getLexicalForm))
Option(result.getLiteral("term_label")).map(_.getLexicalForm))

val tsvMarshaller: ToEntityMarshaller[MinimalTerm] =
Marshaller.stringMarshaller(MediaTypes.`text/tab-separated-values`).compose(_.toTSV)
Expand Down Expand Up @@ -663,15 +667,15 @@ class LabelMapProvider(labels: Map[IRI, String]) extends ShortFormProvider {

def getShortForm(entity: OWLEntity): String = labels.getOrElse(entity.getIRI, entity.getIRI.toString)

def dispose(): Unit = Unit
def dispose(): Unit = ()

}

final case class Classification(term: MinimalTerm,
superclasses: Set[MinimalTerm],
subclasses: Set[MinimalTerm],
equivalents: Set[MinimalTerm])
extends JSONResultItem {
extends JSONResultItem {

def toJSON: JsObject =
JsObject(
Expand All @@ -683,6 +687,12 @@ final case class Classification(term: MinimalTerm,
)
)

def jsonWithoutTerm: JsObject = Map(
"subClassOf" -> superclasses.toSeq.sortBy(_.label.map(_.toLowerCase)).map(_.toJSON).toJson,
"superClassOf" -> subclasses.toSeq.sortBy(_.label.map(_.toLowerCase)).map(_.toJSON).toJson,
"equivalentTo" -> equivalents.toSeq.sortBy(_.label.map(_.toLowerCase)).map(_.toJSON).toJson
).toJson.asJsObject

}

final case class TermRelationship(property: MinimalTerm, value: MinimalTerm) extends JSONResultItem {
Expand Down