diff --git a/build.sbt b/build.sbt index 1db06f43..a5423a92 100644 --- a/build.sbt +++ b/build.sbt @@ -8,7 +8,7 @@ organization := "org.renci" name := "cam-kp-api" -version := "0.3-pre1" +version := "0.3-pre4" licenses := Seq("MIT license" -> url("https://opensource.org/licenses/MIT")) diff --git a/src/it/resources/examples/BCL2L1-decreases-activity-abundance-chemical.json b/src/it/resources/examples/BCL2L1-decreases-activity-abundance-chemical.json new file mode 100644 index 00000000..5baa65de --- /dev/null +++ b/src/it/resources/examples/BCL2L1-decreases-activity-abundance-chemical.json @@ -0,0 +1,47 @@ +{ + "description": "Example creative mode query (https://github.com/NCATSTranslator/TranslatorArchitecture/issues/80) using NCBIGene:598 (BCL2L1)", + "message": { + "query_graph": { + "nodes": { + "gene": { + "categories": [ + "biolink:Gene" + ], + "ids": [ + "NCBIGene:598" + ] + }, + "chemical": { + "categories": [ + "biolink:ChemicalEntity" + ] + } + }, + "edges": { + "t_edge": { + "object": "gene", + "subject": "chemical", + "predicates": [ + "biolink:affects" + ], + "knowledge_type": "inferred", + "qualifier_constraints": [ + { + "qualifier_set": [ + { + "qualifier_type_id": "biolink:object_aspect_qualifier", + "qualifier_value": "activity_or_abundance" + }, + { + "qualifier_type_id": "biolink:object_direction_qualifier", + "qualifier_value": "decreased" + } + ] + } + ] + } + } + } + }, +"minExpectedResults": 6 +} \ No newline at end of file diff --git a/src/it/resources/examples/PRCD-increases-chemical.json b/src/it/resources/examples/PRCD-increases-chemical.json new file mode 100644 index 00000000..f0034ba3 --- /dev/null +++ b/src/it/resources/examples/PRCD-increases-chemical.json @@ -0,0 +1,47 @@ +{ + "description": "PRCD increases chemical", + "message": { + "query_graph": { + "nodes": { + "gene": { + "categories": [ + "biolink:Gene" + ], + "ids": [ + "NCBIGene:768206" + ] + }, + "chemical": { + "categories": [ + "biolink:ChemicalEntity" + ] + } + }, + "edges": { + "t_edge": { + "object": "gene", + "subject": "chemical", + "predicates": [ + "biolink:affects" + ], + "knowledge_type": "inferred", + "qualifier_constraints": [ + { + "qualifier_set": [ + { + "qualifier_type_id": "biolink:object_aspect_qualifier", + "qualifier_value": "activity_or_abundance" + }, + { + "qualifier_type_id": "biolink:object_direction_qualifier", + "qualifier_value": "increased" + } + ] + } + ] + } + } + } + }, + "minExpectedResults": 1000 +} \ No newline at end of file diff --git a/src/it/resources/examples/STING1-increases-activity-abundance-chemical.json b/src/it/resources/examples/STING1-increases-activity-abundance-chemical.json new file mode 100644 index 00000000..da0f0535 --- /dev/null +++ b/src/it/resources/examples/STING1-increases-activity-abundance-chemical.json @@ -0,0 +1,47 @@ +{ + "description": "Example creative mode query (https://github.com/NCATSTranslator/TranslatorArchitecture/issues/79) using NCBIGene:340061 (STING1)", + "message": { + "query_graph": { + "nodes": { + "gene": { + "categories": [ + "biolink:Gene" + ], + "ids": [ + "NCBIGene:340061" + ] + }, + "chemical": { + "categories": [ + "biolink:ChemicalEntity" + ] + } + }, + "edges": { + "t_edge": { + "object": "gene", + "subject": "chemical", + "predicates": [ + "biolink:affects" + ], + "knowledge_type": "inferred", + "qualifier_constraints": [ + { + "qualifier_set": [ + { + "qualifier_type_id": "biolink:object_aspect_qualifier", + "qualifier_value": "activity_or_abundance" + }, + { + "qualifier_type_id": "biolink:object_direction_qualifier", + "qualifier_value": "increased" + } + ] + } + ] + } + } + } + } + "minExpectedResults": 6 +} \ No newline at end of file diff --git a/src/it/resources/examples/genes-upstream-of-GPR35.json b/src/it/resources/examples/genes-upstream-of-GPR35.json index 2d53d30c..70250497 100644 --- a/src/it/resources/examples/genes-upstream-of-GPR35.json +++ b/src/it/resources/examples/genes-upstream-of-GPR35.json @@ -19,7 +19,17 @@ "e0": { "subject": "n0", "object": "n1", - "predicates": ["biolink:affects_activity_of"] + "predicates": ["biolink:affects"], + "qualifier_constraints": [ + { + "qualifier_set": [ + { + "qualifier_type_id": "biolink:object_aspect_qualifier", + "qualifier_value": "activity" + } + ] + } + ] }, "e1": { "subject": "n1", diff --git a/src/it/resources/examples/simple.json b/src/it/resources/examples/simple.json index afd520c7..4051e15f 100644 --- a/src/it/resources/examples/simple.json +++ b/src/it/resources/examples/simple.json @@ -21,5 +21,5 @@ } }, "minExpectedResults": 160, - "maxExpectedResults": 160 + "maxExpectedResults": 1000 } \ No newline at end of file diff --git a/src/it/resources/examples/swagger-example.json b/src/it/resources/examples/swagger-example.json index 5ece3dde..be0d58d9 100644 --- a/src/it/resources/examples/swagger-example.json +++ b/src/it/resources/examples/swagger-example.json @@ -17,7 +17,17 @@ "edges": { "e0": { "predicates": [ - "biolink:positively_regulates" + "biolink:regulates" + ], + "qualifier_constraints": [ + { + "qualifier_set": [ + { + "qualifier_type_id": "biolink:object_direction_qualifier", + "qualifier_value": "upregulated" + } + ] + } ], "subject": "n0", "object": "n1" diff --git a/src/it/scala/org/renci/cam/it/ImplicitsTest.scala b/src/it/scala/org/renci/cam/it/ImplicitsTest.scala index fc7e337e..2802338f 100644 --- a/src/it/scala/org/renci/cam/it/ImplicitsTest.scala +++ b/src/it/scala/org/renci/cam/it/ImplicitsTest.scala @@ -4,7 +4,7 @@ import com.typesafe.scalalogging.LazyLogging import io.circe.generic.auto._ import io.circe.parser._ import io.circe.syntax._ -import io.circe.{Decoder, Encoder, KeyDecoder, KeyEncoder} +import io.circe.{KeyDecoder, KeyEncoder} import org.renci.cam.Biolink.BiolinkData import org.renci.cam.domain._ import org.renci.cam.{AppConfig, Biolink, HttpClient, Implicits} @@ -39,15 +39,23 @@ object ImplicitsTest extends DefaultRunnableSpec with LazyLogging { testM("test Implicits.predicateOrPredicateListDecoder") { for { biolinkData <- Biolink.biolinkData - } yield { - val dataAsList = """["biolink:participates_in","biolink:related_to"]""" - val data = """"biolink:related_to"""" - import biolinkData.implicits._ - val ret = decode[List[BiolinkPredicate]](data) - val retWithListData = decode[List[BiolinkPredicate]](dataAsList) - assert(ret.toOption.get)(contains(BiolinkPredicate("related_to"))) && assert(retWithListData.toOption.get)( - contains(BiolinkPredicate("related_to"))) - } + data = """"biolink:related_to"""" + dataAsJson = { + import biolinkData.implicits._ + decode[BiolinkPredicate](data) + } + + dataAsList = """["biolink:participates_in","biolink:related_to"]""" + dataAsListAsJson = { + import biolinkData.implicits._ + decode[List[BiolinkPredicate]](dataAsList) + } + } yield assert(dataAsJson)(Assertion.isRight(Assertion.equalTo(BiolinkPredicate("related_to")))) && + assert(dataAsListAsJson)( + Assertion.isRight( + Assertion.contains(BiolinkPredicate("participates_in")) && + Assertion.contains(BiolinkPredicate("related_to")) + )) } ) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 3a15d95c..893da615 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -1,10 +1,11 @@ { - version = "0.3-pre1" + version = "0.3-pre4" host = 0.0.0.0 port = 8080 port = ${?PORT} trapi-version = "1.3.0" trapi-version = ${?TRAPI_VERSION} + biolink-version = "v3.2.3" location = "http://localhost:8080" location = ${?LOCATION} sparql-endpoint = "https://cam-kp-sparql.apps.renci.org/sparql" diff --git a/src/main/resources/biolink/README.md b/src/main/resources/biolink/README.md new file mode 100644 index 00000000..95bdeb5c --- /dev/null +++ b/src/main/resources/biolink/README.md @@ -0,0 +1,38 @@ +# Biolink mappings + +CAM-KP needs Biolink information in both the triplestore backend as well as the +frontend. This is frustrating -- if only one of them needed to know about the +Biolink model, that would greatly simplify what we need to do here. + +We previously generated `predicates.csv` and `mkg-nodes.csv` from the +[CAM Pipeline](https://github.com/ExposuresProvider/cam-pipeline) and incorporated +them in here (via the parent directory). This was relatively easy to do when +Biolink predicates could be mapped directly to relations in the triplestore, but +since Biolink 3 includes predicates modified with qualifiers, this mapping is more +complicated. + +This directory takes all of our predicate mapping logic and puts it into one place: +the [`predicates.json`](./predicates.json) file in this directory is intended to provide +the definitive set of mappings between Biolink predicate/qualifier combinations and +triplestore relations. A single relation may be mapped to several predicate/qualifier +combinations and vice versa. + +Two pieces of code interact with this file: +1. `org.renci.cam.util.GenerateBiolinkPredicateMappings` is a standalone program that + can be used to regenerate this file. It currently uses the + [Biolink predicate_mapping.yaml](https://github.com/biolink/biolink-model/blob/master/predicate_mapping.yaml), + mapping information from the triplestore and a list of manual mappings added during + development, but in the future it may be expanded to include additional files. +2. `org.renci.cam.domain.PredicateMappings` is a module in the code that provides a + programmatic interface to the contents of the `predicates.json` file, and provides + methods to map from Biolink predicate/qualifier combinations to relations. + +The `predicates.json` file can be regenerated by updating the +Biolink version in application.conf and then running: + +```shell +$ SPARQL_ENDPOINT=https://cam-kp-sparql-dev.apps.renci.org/sparql sbt "runMain org.renci.cam.util.GenerateBiolinkPredicateMappings" +``` + +The latest `predicates.json` file should be checked into the GitHub repository so that +changes to it can be tracked. \ No newline at end of file diff --git a/src/main/resources/biolink/predicates.json b/src/main/resources/biolink/predicates.json new file mode 100644 index 00000000..90e2a161 --- /dev/null +++ b/src/main/resources/biolink/predicates.json @@ -0,0 +1,5082 @@ +[ + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004008", + "label" : [ + "has primary output" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002497", + "label" : [ + "end stage" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "immediately_preceded_by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.org/dc/terms/contributor", + "label" : [ + "contributor" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002019", + "label" : [ + "has ligand" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of" + }, + "shorthand" : "acts_upstream_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004034", + "label" : [ + "acts upstream of, positive effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000050", + "label" : [ + "part_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#created_by", + "label" : [ + "created_by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002162", + "label" : [ + "in taxon" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002496", + "label" : [ + "existence starts during or after" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002608", + "label" : [ + "process has causal agent" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004034", + "label" : [ + "acts upstream of, positive effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002215", + "label" : [ + "capable_of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002216", + "label" : [ + "capable of part of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000425", + "label" : [ + "expand assertion to" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002174", + "label" : [ + "dubious_for_taxon" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002296", + "label" : [ + "results in development of" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasOBONamespace", + "label" : [ + "has_obo_namespace" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/positively_regulates" + }, + "shorthand" : "positively_regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004032", + "label" : [ + "acts upstream of or within, positive effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002597", + "label" : [ + "capable of negatively regulating" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/ECO_9000002", + "label" : [ + "has GO evidence code" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000015", + "label" : [ + "location_notes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002338", + "label" : [ + "has target start location" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002423", + "label" : [ + "logical macro assertion on an annotation property" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0011002", + "label" : [ + "regulates activity of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of" + }, + "shorthand" : "acts_upstream_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004035", + "label" : [ + "acts upstream of, negative effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000202", + "label" : [ + "fma_set_term" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0017001", + "label" : [ + "device utilizes material" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004035", + "label" : [ + "acts upstream of, negative effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002163", + "label" : [ + "spatially disjoint from" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_output" + }, + "shorthand" : "has_output" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004008", + "label" : [ + "has primary output" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#inSubset", + "label" : [ + "in_subset" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002412", + "label" : [ + "immediately causally upstream of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002215", + "label" : [ + "capable of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_output" + }, + "shorthand" : "has_output" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002299", + "label" : [ + "results in maturation of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004046", + "label" : [ + "causally upstream of or within, negative effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002581", + "label" : [ + "is a defining property chain axiom" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_input" + }, + "shorthand" : "has_input" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002590", + "label" : [ + "results in disassembly of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002333", + "label" : [ + "enabled by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002431", + "label" : [ + "involved in or involved in regulation of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/overlaps" + }, + "shorthand" : "overlaps" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000050", + "label" : [ + "part of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "starts_at_end_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002454", + "label" : [ + "has host" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "starts_at_end_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002175", + "label" : [ + "present in taxon" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasRelatedSynonym", + "label" : [ + "has related synonym" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002093", + "label" : [ + "ends during" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002174", + "label" : [ + "dubious for taxon" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002501", + "label" : [ + "causal relation between processes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://translator.renci.org/ubergraph-axioms.ofn#acts_upstream_of_o_enabled_by", + "label" : [ + "acts_upstream_of_o_enabled_by" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasExactSynonym", + "label" : [ + "has_exact_synonym" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012006", + "label" : [ + "is small molecule inhibitor of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002298", + "label" : [ + "results in morphogenesis of" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#creation_date", + "label" : [ + "creation_date" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000010", + "label" : [ + "structure_notes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002295", + "label" : [ + "results in developmental progression of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000232", + "label" : [ + "curator notes" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0040042", + "label" : [ + "is homeomorphic for" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012003", + "label" : [ + "acts on population of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002211", + "label" : [ + "regulates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002590", + "label" : [ + "results in disassembly of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.org/dc/elements/1.1/contributor", + "label" : [ + "contributor" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/preceded_by" + }, + "shorthand" : "preceded_by" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "starts_at_end_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002409", + "label" : [ + "indirectly negatively regulates" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/emapa#has_part", + "label" : [ + "has_part" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_output" + }, + "shorthand" : "has_output" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002298", + "label" : [ + "results in morphogenesis of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002221", + "label" : [ + "surrounds" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002086", + "label" : [ + "ends after" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002264", + "label" : [ + "acts upstream of or within" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002344", + "label" : [ + "results in transport to from or in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004032", + "label" : [ + "acts upstream of or within, positive effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002436", + "label" : [ + "molecularly interacts with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_input" + }, + "shorthand" : "has_input" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002233", + "label" : [ + "has input" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002492", + "label" : [ + "existence ends during" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002092", + "label" : [ + "happens during" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002175", + "label" : [ + "present_in_taxon" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000008", + "label" : [ + "taxon_notes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002131", + "label" : [ + "overlaps" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/overlaps" + }, + "shorthand" : "overlaps" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0001019", + "label" : [ + "contains" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/coexists_with" + }, + "shorthand" : "coexists_with" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002220", + "label" : [ + "adjacent to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/process_regulates_process" + }, + "shorthand" : "process_regulates_process" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002211", + "label" : [ + "regulates" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasNarrowSynonym", + "label" : [ + "has_narrow_synonym" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002334", + "label" : [ + "regulated by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002223", + "label" : [ + "starts" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/enabled_by" + }, + "shorthand" : "enabled_by" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002333", + "label" : [ + "enabled by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002475", + "label" : [ + "has no connections with" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000004", + "label" : [ + "provenance_notes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002432", + "label" : [ + "is active in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000056", + "label" : [ + "participates in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002331", + "label" : [ + "involved in" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002487", + "label" : [ + "relation between physical entity and a process or stage" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_direction_qualifier", + "qualifier_value" : "downregulated" + } + ] + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002449", + "label" : [ + "directly negatively regulates activity of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002500", + "label" : [ + "causal agent in process" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002629", + "label" : [ + "directly positively regulates" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002173", + "label" : [ + "ambiguous_for_taxon" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002586", + "label" : [ + "results in breakdown of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/causes" + }, + "shorthand" : "causes" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002315", + "label" : [ + "results in acquisition of features of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/preceded_by" + }, + "shorthand" : "preceded_by" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "immediately preceded by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/produced_by" + }, + "shorthand" : "produced_by" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0003001", + "label" : [ + "produced by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0001025", + "label" : [ + "located in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "immediately preceded by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000112", + "label" : [ + "example of usage" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012001", + "label" : [ + "has small molecule activator" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002092", + "label" : [ + "happens during" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000056", + "label" : [ + "participates in" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000116", + "label" : [ + "editor note" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/description" + }, + "shorthand" : "description" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000115", + "label" : [ + "definition" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/process_regulates_process" + }, + "shorthand" : "process_regulates_process" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002211", + "label" : [ + "regulates (processual)" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000107", + "label" : [ + "vertebra number" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000424", + "label" : [ + "expand expression to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002411", + "label" : [ + "causally upstream of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000014", + "label" : [ + "actions_notes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002592", + "label" : [ + "results in organization of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004007", + "label" : [ + "has primary input or output" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/GOREL_0001006", + "label" : [ + "acts_on_population_of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/opposite_of" + }, + "shorthand" : "opposite_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002604", + "label" : [ + "is_opposite_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002491", + "label" : [ + "existence starts and ends during" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002502", + "label" : [ + "depends on" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://translator.renci.org/ubergraph-axioms.ofn#acts_upstream_of_o_enabled_by", + "label" : [ + "acts_upstream_of_o_enabled_by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002296", + "label" : [ + "results in development of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/occurs_in" + }, + "shorthand" : "occurs_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002231", + "label" : [ + "has start location" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004009", + "label" : [ + "has primary input" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002588", + "label" : [ + "results in assembly of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002354", + "label" : [ + "formed as result of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/part_of" + }, + "shorthand" : "part_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000050", + "label" : [ + "part_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.org/dc/elements/1.1/description", + "label" : [ + "description" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0008506", + "label" : [ + "ecologically co-occurs with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/caused_by" + }, + "shorthand" : "caused_by" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002608", + "label" : [ + "process has causal agent" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002229", + "label" : [ + "ends" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_input" + }, + "shorthand" : "has_input" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004009", + "label" : [ + "has primary input" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002327", + "label" : [ + "enables" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/consumes" + }, + "shorthand" : "consumes" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004009", + "label" : [ + "has primary input" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000119", + "label" : [ + "definition source" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/interacts_with" + }, + "shorthand" : "interacts_with" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002436", + "label" : [ + "molecularly interacts with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/contributes_to" + }, + "shorthand" : "contributes_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002326", + "label" : [ + "contributes to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of_positive_effect" + }, + "shorthand" : "acts_upstream_of_positive_effect" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004034", + "label" : [ + "acts upstream of, positive effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of_or_within_negative_effect" + }, + "shorthand" : "acts_upstream_of_or_within_negative_effect" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004033", + "label" : [ + "acts upstream of or within, negative effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_output" + }, + "shorthand" : "has_output" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002297", + "label" : [ + "results in formation of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/preceded_by" + }, + "shorthand" : "preceded_by" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "immediately_preceded_by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000051", + "label" : [ + "has_part" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/overlaps" + }, + "shorthand" : "overlaps" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002131", + "label" : [ + "overlaps" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002327", + "label" : [ + "enables" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002598", + "label" : [ + "capable of positively regulating" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000052", + "label" : [ + "characteristic of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002406", + "label" : [ + "obsolete directly activates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002497", + "label" : [ + "end stage" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/mondo#excluded_subClassOf", + "label" : [ + "excluded subClassOf" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000009", + "label" : [ + "function_notes" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0100001", + "label" : [ + "term replaced by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002565", + "label" : [ + "results in movement of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/overlaps" + }, + "shorthand" : "overlaps" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000051", + "label" : [ + "has part" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0003000", + "label" : [ + "produces" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002578", + "label" : [ + "directly regulates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of_or_within" + }, + "shorthand" : "acts_upstream_of_or_within" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004032", + "label" : [ + "acts upstream of or within, positive effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002205", + "label" : [ + "has gene product" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002264", + "label" : [ + "acts upstream of or within" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002479", + "label" : [ + "has part that occurs in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/precedes" + }, + "shorthand" : "precedes" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002411", + "label" : [ + "causally upstream of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002432", + "label" : [ + "is active in" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000085", + "label" : [ + "has function" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_aspect_qualifier", + "qualifier_value" : "activity_or_abundance" + }, + { + "qualifier_type_id" : "biolink:object_direction_qualifier", + "qualifier_value" : "decreased" + } + ] + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002449", + "label" : [ + "directly negatively regulates activity of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002348", + "label" : [ + "results in commitment to" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002575", + "label" : [ + "is direct form of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012003", + "label" : [ + "acts on population of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/OMO_0002000", + "label" : [ + "defined by construct" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002488", + "label" : [ + "existence starts during" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/enables" + }, + "shorthand" : "enables" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002327", + "label" : [ + "enables" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.w3.org/2000/01/rdf-schema#seeAlso", + "label" : [ + "see also" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000111", + "label" : [ + "rhombomere number" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of" + }, + "shorthand" : "acts_upstream_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002263", + "label" : [ + "acts upstream of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/produces" + }, + "shorthand" : "produces" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0003000", + "label" : [ + "produces" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000104", + "label" : [ + "ray number" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002427", + "label" : [ + "causally downstream of or within" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/preceded_by" + }, + "shorthand" : "preceded_by" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000062", + "label" : [ + "preceded by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002234", + "label" : [ + "has output" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002233", + "label" : [ + "has input" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002315", + "label" : [ + "results in acquisition of features of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004032", + "label" : [ + "acts upstream of or within, positive effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/molecularly_interacts_with" + }, + "shorthand" : "molecularly_interacts_with" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002436", + "label" : [ + "molecularly interacts with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002326", + "label" : [ + "contributes to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_part" + }, + "shorthand" : "has_part" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000051", + "label" : [ + "has_part" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/actively_involves" + }, + "shorthand" : "actively_involves" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002331", + "label" : [ + "involved in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004008", + "label" : [ + "has primary output" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002614", + "label" : [ + "is evidence with support from" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000057", + "label" : [ + "has_participant" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012000", + "label" : [ + "has small molecule regulator" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002604", + "label" : [ + "is opposite of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002496", + "label" : [ + "start stage" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002161", + "label" : [ + "never_in_taxon" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasSynonymType", + "label" : [ + "has_synonym_type" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004033", + "label" : [ + "acts upstream of or within, negative effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002410", + "label" : [ + "causally related to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002448", + "label" : [ + "directly regulates activity of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/part_of" + }, + "shorthand" : "part_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000050", + "label" : [ + "part of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002579", + "label" : [ + "is indirect form of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000012", + "label" : [ + "external_ontology_notes" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002171", + "label" : [ + "mutually spatially disjoint with" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.org/dc/elements/1.1/source", + "label" : [ + "derived from resource" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.org/dc/elements/1.1/creator", + "label" : [ + "creator" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/positively_regulates" + }, + "shorthand" : "positively_regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002629", + "label" : [ + "directly positively regulates" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002429", + "label" : [ + "involved in positive regulation of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002434", + "label" : [ + "interacts with" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasBroadSynonym", + "label" : [ + "has_broad_synonym" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000066", + "label" : [ + "occurs in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_output" + }, + "shorthand" : "has_output" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002588", + "label" : [ + "results in assembly of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000062", + "label" : [ + "preceded_by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/opposite_of" + }, + "shorthand" : "opposite_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002604", + "label" : [ + "is opposite of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002447", + "label" : [ + "phosphorylates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "immediately preceded by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002590", + "label" : [ + "results in disassembly of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002211", + "label" : [ + "regulates (processual)" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002333", + "label" : [ + "enabled by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002085", + "label" : [ + "encompasses" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002490", + "label" : [ + "existence overlaps" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0001015", + "label" : [ + "location of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002298", + "label" : [ + "results in morphogenesis of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000101", + "label" : [ + "preceding element is" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_output" + }, + "shorthand" : "has_output" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002296", + "label" : [ + "results in development of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012004", + "label" : [ + "is small molecule regulator of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_output" + }, + "shorthand" : "has_output" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002234", + "label" : [ + "has output" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/in_taxon" + }, + "shorthand" : "in_taxon" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002160", + "label" : [ + "only in taxon" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002216", + "label" : [ + "capable of part of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/precedes" + }, + "shorthand" : "precedes" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000063", + "label" : [ + "precedes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_gene_product" + }, + "shorthand" : "has_gene_product" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002205", + "label" : [ + "has gene product" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/actively_involved_in" + }, + "shorthand" : "actively_involved_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002331", + "label" : [ + "involved in" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002407", + "label" : [ + "indirectly positively regulates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000056", + "label" : [ + "participates_in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002230", + "label" : [ + "ends with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000052", + "label" : [ + "inheres in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/precedes" + }, + "shorthand" : "precedes" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002412", + "label" : [ + "immediately causally upstream of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002088", + "label" : [ + "during which starts" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0003001", + "label" : [ + "produced by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002411", + "label" : [ + "causally upstream of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002414", + "label" : [ + "transitively provides input for" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#consider", + "label" : [ + "consider" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_direction_qualifier", + "qualifier_value" : "downregulated" + } + ] + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002305", + "label" : [ + "causally upstream of, negative effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_aspect_qualifier", + "qualifier_value" : "activity_or_abundance" + }, + { + "qualifier_type_id" : "biolink:object_direction_qualifier", + "qualifier_value" : "increased" + } + ] + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002450", + "label" : [ + "directly positively regulates activity of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004009", + "label" : [ + "has primary input" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/physically_interacts_with" + }, + "shorthand" : "physically_interacts_with" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002436", + "label" : [ + "molecularly interacts with" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004047", + "label" : [ + "causally upstream of or within, positive effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000011", + "label" : [ + "development_notes" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004036", + "label" : [ + "nominally disjoint with" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#date", + "label" : [ + "date" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002331", + "label" : [ + "involved in" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002304", + "label" : [ + "causally upstream of, positive effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/entity_regulates_entity" + }, + "shorthand" : "entity_regulates_entity" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002448", + "label" : [ + "directly regulates activity of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002325", + "label" : [ + "colocalizes with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000050", + "label" : [ + "part of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002089", + "label" : [ + "starts before" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002349", + "label" : [ + "results in determination of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/preceded_by" + }, + "shorthand" : "preceded_by" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000062", + "label" : [ + "preceded_by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002011", + "label" : [ + "regulates transport of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/precedes" + }, + "shorthand" : "precedes" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002090", + "label" : [ + "immediately precedes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002356", + "label" : [ + "results in specification of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002565", + "label" : [ + "results in movement of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002012", + "label" : [ + "occurrent part of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000002", + "label" : [ + "axiom_lost_from_external_ontology" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_direction_qualifier", + "qualifier_value" : "downregulated" + } + ] + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002212", + "label" : [ + "negatively regulates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_direction_qualifier", + "qualifier_value" : "upregulated" + } + ] + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002213", + "label" : [ + "positively regulates" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000003", + "label" : [ + "homology_notes" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasRelatedSynonym", + "label" : [ + "has_related_synonym" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002418", + "label" : [ + "causally upstream of or within" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012002", + "label" : [ + "has small molecule inhibitor" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002506", + "label" : [ + "causal relation between entities" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002087", + "label" : [ + "immediately_preceded_by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002582", + "label" : [ + "is a defining property chain axiom where second argument is reflexive" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000233", + "label" : [ + "term tracker item" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of_negative_effect" + }, + "shorthand" : "acts_upstream_of_negative_effect" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004035", + "label" : [ + "acts upstream of, negative effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000234", + "label" : [ + "ontology term requester" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002324", + "label" : [ + "developmentally related to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002211", + "label" : [ + "regulates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002604", + "label" : [ + "is_opposite_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002222", + "label" : [ + "temporally related to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002488", + "label" : [ + "existence starts during" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_part" + }, + "shorthand" : "has_part" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0001019", + "label" : [ + "contains" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002313", + "label" : [ + "transports or maintains localization of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002224", + "label" : [ + "starts with" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002337", + "label" : [ + "related via localization to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/active_in" + }, + "shorthand" : "active_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002432", + "label" : [ + "is active in" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000007", + "label" : [ + "has_relational_adjective" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/actively_involved_in" + }, + "shorthand" : "actively_involved_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002215", + "label" : [ + "capable_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasExactSynonym", + "label" : [ + "has exact synonym" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002595", + "label" : [ + "causal relation between material entity and a process" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002230", + "label" : [ + "ends with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/overlaps" + }, + "shorthand" : "overlaps" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000051", + "label" : [ + "has_part" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002353", + "label" : [ + "output of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002412", + "label" : [ + "immediately causally upstream of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.org/dc/terms/license", + "label" : [ + "license" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/emapa#located_in", + "label" : [ + "located_in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/actively_involved_in" + }, + "shorthand" : "actively_involved_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002500", + "label" : [ + "causal agent in process" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002448", + "label" : [ + "directly regulates activity of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004049", + "label" : [ + "is positive form of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002405", + "label" : [ + "immediately causally downstream of" + ] + } + }, + { + "predicate" : { + "iri" : "http://xmlns.com/foaf/0.1/depicted_by", + "label" : [ + "depicted by" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#id", + "label" : [ + "id" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002497", + "label" : [ + "existence ends during or before" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002497", + "label" : [ + "existence ends during or before" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000056", + "label" : [ + "participates_in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002215", + "label" : [ + "capable_of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000063", + "label" : [ + "precedes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of_or_within_positive_effect" + }, + "shorthand" : "acts_upstream_of_or_within_positive_effect" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002264", + "label" : [ + "acts upstream of or within" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002329", + "label" : [ + "part of structure that is capable of" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#shorthand", + "label" : [ + "shorthand" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasNarrowSynonym", + "label" : [ + "has narrow synonym" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002496", + "label" : [ + "existence starts during or after" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002305", + "label" : [ + "causally upstream of, negative effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_part" + }, + "shorthand" : "has_part" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000051", + "label" : [ + "has part" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002024", + "label" : [ + "directly positively regulated by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_direction_qualifier", + "qualifier_value" : "upregulated" + } + ] + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002450", + "label" : [ + "directly positively regulates activity of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012009", + "label" : [ + "constitutively upstream of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/contributes_to" + }, + "shorthand" : "contributes_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002315", + "label" : [ + "results in acquisition of features of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002328", + "label" : [ + "functionally related to" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012010", + "label" : [ + "removes input for" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_aspect_qualifier", + "qualifier_value" : "activity" + } + ] + }, + "predicate" : { + "iri" : "http://translator.renci.org/ubergraph-axioms.ofn#acts_upstream_of_o_enabled_by", + "label" : [ + "acts_upstream_of_o_enabled_by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000108", + "label" : [ + "somite number" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000100", + "label" : [ + "is count of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "biolinkQualifiers" : { + "qualifier_set" : [ + { + "qualifier_type_id" : "biolink:object_aspect_qualifier", + "qualifier_value" : "transport" + } + ] + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002313", + "label" : [ + "transports or maintains localization of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002352", + "label" : [ + "input of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002211", + "label" : [ + "regulates (processual)" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of" + }, + "shorthand" : "acts_upstream_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002264", + "label" : [ + "acts upstream of or within" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000005", + "label" : [ + "external_comment" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002233", + "label" : [ + "has input" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000105", + "label" : [ + "phalanx number" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002400", + "label" : [ + "has direct input" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/capable_of" + }, + "shorthand" : "capable_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002215", + "label" : [ + "capable of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002588", + "label" : [ + "results in assembly of" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#is_inferred", + "label" : [ + "is_inferred" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002091", + "label" : [ + "starts during" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002224", + "label" : [ + "starts with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000057", + "label" : [ + "has_participant" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002339", + "label" : [ + "has target end location" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002160", + "label" : [ + "only in taxon" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/IAO_0000117", + "label" : [ + "term editor" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002475", + "label" : [ + "has_no_connections_with" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000057", + "label" : [ + "has participant at some time" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0001019", + "label" : [ + "contains" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000106", + "label" : [ + "rib number" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002161", + "label" : [ + "never in taxon" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002009", + "label" : [ + "cell expresses" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002323", + "label" : [ + "mereotopologically related to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002223", + "label" : [ + "starts" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000063", + "label" : [ + "precedes" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0001018", + "label" : [ + "contained in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002211", + "label" : [ + "regulates (processual)" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004007", + "label" : [ + "has primary input or output" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002093", + "label" : [ + "ends during" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002173", + "label" : [ + "ambiguous for taxon" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasAlternativeId", + "label" : [ + "has_alternative_id" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002320", + "label" : [ + "evolutionarily related to" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002404", + "label" : [ + "causally downstream of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/location_of" + }, + "shorthand" : "location_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0001015", + "label" : [ + "location of" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#SubsetProperty", + "label" : [ + "subset_property" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002220", + "label" : [ + "adjacent to" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002299", + "label" : [ + "results in maturation of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000001", + "label" : [ + "external_definition" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000057", + "label" : [ + "has participant" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002023", + "label" : [ + "directly negatively regulated by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002413", + "label" : [ + "provides input for" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002566", + "label" : [ + "causally influences" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002171", + "label" : [ + "mutually_spatially_disjoint_with" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#SynonymTypeProperty", + "label" : [ + "synonym_type_property" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002335", + "label" : [ + "negatively regulated by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002313", + "label" : [ + "transports or maintains localization of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002492", + "label" : [ + "existence ends during" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004034", + "label" : [ + "acts upstream of, positive effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002299", + "label" : [ + "results in maturation of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000112", + "label" : [ + "tooth number" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012005", + "label" : [ + "is small molecule activator of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002084", + "label" : [ + "during which ends" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002559", + "label" : [ + "causally influenced by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002022", + "label" : [ + "directly regulated by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012011", + "label" : [ + "indirectly causally upstream of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000201", + "label" : [ + "source atlas" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002584", + "label" : [ + "has part structure that is capable of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0040036", + "label" : [ + "results in changes to anatomical or cellular structure" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002430", + "label" : [ + "involved in negative regulation of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002219", + "label" : [ + "surrounded by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002232", + "label" : [ + "has end location" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/negatively_regulates" + }, + "shorthand" : "negatively_regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002630", + "label" : [ + "directly negatively regulates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/capable_of" + }, + "shorthand" : "capable_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002500", + "label" : [ + "causal agent in process" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000006", + "label" : [ + "implements_design_pattern" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/GOREL_0001006", + "label" : [ + "acts_on_population_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002428", + "label" : [ + "involved in regulation of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/capable_of" + }, + "shorthand" : "capable_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002215", + "label" : [ + "capable_of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/occurs_in" + }, + "shorthand" : "occurs_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000066", + "label" : [ + "occurs in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002211", + "label" : [ + "regulates" + ] + } + }, + { + "predicate" : { + "iri" : "http://xmlns.com/foaf/0.1/depicted_by", + "label" : [ + "depicted_by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004035", + "label" : [ + "acts upstream of, negative effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002379", + "label" : [ + "spatially coextensive with" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasScope", + "label" : [ + "has_scope" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002408", + "label" : [ + "obsolete directly inhibits" + ] + } + }, + { + "predicate" : { + "iri" : "http://xmlns.com/foaf/0.1/page", + "label" : [ + "page" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/overlaps" + }, + "shorthand" : "overlaps" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000050", + "label" : [ + "part_of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002596", + "label" : [ + "capable of regulating" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.w3.org/2000/01/rdf-schema#seeAlso", + "label" : [ + "seeAlso" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/hp#is_observable_through", + "label" : [ + "is_observable_through" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/interacts_with" + }, + "shorthand" : "interacts_with" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002434", + "label" : [ + "interacts with" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/coexists_with" + }, + "shorthand" : "coexists_with" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002219", + "label" : [ + "surrounded by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002297", + "label" : [ + "results in formation of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002229", + "label" : [ + "ends" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002090", + "label" : [ + "immediately precedes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002297", + "label" : [ + "results in formation of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004031", + "label" : [ + "enables subfunction" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002336", + "label" : [ + "positively regulated by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000103", + "label" : [ + "pharyngeal arch number" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/regulates" + }, + "shorthand" : "regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002630", + "label" : [ + "directly negatively regulates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000051", + "label" : [ + "has part" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000062", + "label" : [ + "preceded by" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000067", + "label" : [ + "contains process" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/coexists_with" + }, + "shorthand" : "coexists_with" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002221", + "label" : [ + "surrounds" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002090", + "label" : [ + "immediately precedes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of" + }, + "shorthand" : "acts_upstream_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004033", + "label" : [ + "acts upstream of or within, negative effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.org/dc/elements/1.1/title", + "label" : [ + "title" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000062", + "label" : [ + "preceded by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/temporally_related_to" + }, + "shorthand" : "temporally_related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002496", + "label" : [ + "start stage" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/UBPROP_0000013", + "label" : [ + "terminology_notes" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002234", + "label" : [ + "has output" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002263", + "label" : [ + "acts upstream of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/located_in" + }, + "shorthand" : "located_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0001025", + "label" : [ + "located in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002231", + "label" : [ + "has start location" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/acts_upstream_of" + }, + "shorthand" : "acts_upstream_of" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004032", + "label" : [ + "acts upstream of or within, positive effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0012012", + "label" : [ + "indirectly regulates" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002263", + "label" : [ + "acts upstream of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/affects" + }, + "shorthand" : "affects" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002592", + "label" : [ + "results in organization of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/actively_involved_in" + }, + "shorthand" : "actively_involved_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002215", + "label" : [ + "capable of" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.org/dc/terms/date", + "label" : [ + "date" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/participates_in" + }, + "shorthand" : "participates_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002500", + "label" : [ + "causal agent in process" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/actively_involved_in" + }, + "shorthand" : "actively_involved_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002432", + "label" : [ + "is active in" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/BFO_0000062", + "label" : [ + "preceded_by" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/occurs_in" + }, + "shorthand" : "occurs_in" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002232", + "label" : [ + "has end location" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/positively_regulates" + }, + "shorthand" : "positively_regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004034", + "label" : [ + "acts upstream of, positive effect" + ] + } + }, + { + "predicate" : { + "iri" : "http://www.geneontology.org/formats/oboInOwl#hasDbXref", + "label" : [ + "database_cross_reference" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/negatively_regulates" + }, + "shorthand" : "negatively_regulates" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004035", + "label" : [ + "acts upstream of, negative effect" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/related_to" + }, + "shorthand" : "related_to" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0002215", + "label" : [ + "capable of" + ] + } + }, + { + "biolinkPredicate" : { + "iri" : { + "value" : "https://w3id.org/biolink/vocab/has_participant" + }, + "shorthand" : "has_participant" + }, + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0000057", + "label" : [ + "has participant" + ] + } + }, + { + "predicate" : { + "iri" : "http://purl.obolibrary.org/obo/RO_0004050", + "label" : [ + "is negative form of" + ] + } + } +] \ No newline at end of file diff --git a/src/main/scala/org/renci/cam/AppConfig.scala b/src/main/scala/org/renci/cam/AppConfig.scala index ef3e1e2d..9635df72 100644 --- a/src/main/scala/org/renci/cam/AppConfig.scala +++ b/src/main/scala/org/renci/cam/AppConfig.scala @@ -9,6 +9,7 @@ final case class AppConfig(host: String, location: String, sparqlEndpoint: Uri, trapiVersion: String, + biolinkVersion: String, maturity: String, version: String) diff --git a/src/main/scala/org/renci/cam/LookupService.scala b/src/main/scala/org/renci/cam/LookupService.scala index 04147063..b4b2070e 100644 --- a/src/main/scala/org/renci/cam/LookupService.scala +++ b/src/main/scala/org/renci/cam/LookupService.scala @@ -11,7 +11,7 @@ import org.renci.cam.HttpClient.HttpClient import org.renci.cam.Server.EndpointEnv import org.renci.cam.Server.LocalTapirJsonCirce.jsonBody import org.renci.cam.Util.IterableSPARQLOps -import org.renci.cam.domain.{BiolinkClass, BiolinkPredicate, IRI} +import org.renci.cam.domain.{BiolinkClass, BiolinkPredicate, IRI, PredicateMappings, QualifiedBiolinkPredicate} import sttp.tapir.Endpoint import sttp.tapir.generic.auto._ import sttp.tapir.server.http4s.ztapir.ZHttp4sServerInterpreter @@ -95,7 +95,7 @@ object LookupService extends LazyLogging { case class Relation( subj: Set[LabeledIRI], preds: Set[LabeledIRI], - biolinkPredicates: Map[String, Set[LabeledIRI]], + qualifiedBiolinkPredicates: Map[String, Set[QualifiedBiolinkPredicate]], obj: Set[LabeledIRI], objRelations: Seq[Relation], g: Set[String] @@ -120,7 +120,7 @@ object LookupService extends LazyLogging { case class Result( queryId: String, normalizedIds: List[LabeledIRI], - biolinkPredicates: Map[String, Set[LabeledIRI]], + qualifiedBiolinkPredicates: Set[QualifiedBiolinkPredicate], relations: Seq[Relation], subjectTriples: Seq[ResultTriple], objectTriples: Seq[ResultTriple] @@ -161,7 +161,7 @@ object LookupService extends LazyLogging { ?s ${QueryService.SesameDirectType} ?subj . ?subj ${QueryService.RDFSSubClassOf} ?subjClass . VALUES ?subjClass { ${subjectIRIs.asValues} } . - + ?o ${QueryService.SesameDirectType} ?obj . ?obj ${QueryService.RDFSSubClassOf} ${QueryService.BiolinkNamedThing.iri} . @@ -175,13 +175,12 @@ object LookupService extends LazyLogging { }""" relationsResults <- SPARQLQueryExecutor.runSelectQuery(relationsQuery.toQuery) preds = relationsResults.map(_.getResource("p").getURI).map(IRI(_)) - biolinkRelationMap <- QueryService.mapRelationsToLabelAndBiolink(preds.toSet) // We want to group these by object, so we don't return a gazillion predicates for each result. objectMap = relationsResults.groupBy(_.getResource("obj").getURI) relations = objectMap.map { case (obj, results) => - val predResults = results.map { res => + val predResults = results.flatMap { res => val predIRI = res.getResource("p").getURI val pred = res.getLiteral("pLabel") match { @@ -189,14 +188,8 @@ object LookupService extends LazyLogging { case lit => LabeledIRI(predIRI, Set(lit.getString)) } - val biolinkRes = biolinkRelationMap.get(IRI(predIRI)) - val biolink = biolinkRes match { - case None => Set[LabeledIRI]() - case Some((None, iri)) => Set(LabeledIRI(iri.value, Set())) - case Some((Some(label), iri)) => Set(LabeledIRI(iri.value, Set(label))) - } - - (pred, biolink) + val biolinkQualifiedPreds = PredicateMappings.getBiolinkQualifiedPredicates(IRI(predIRI)) + biolinkQualifiedPreds.map(bp => (pred, bp.biolinkPredicate, bp.qualifierList)) } val objLabeled = results @@ -221,10 +214,13 @@ object LookupService extends LazyLogging { ) .toSet + val qualifiedBiolinkPredicates = + predResults.map(kv => (kv._1.iri, QualifiedBiolinkPredicate(kv._2, kv._3))).groupMapReduce(_._1)(p => Set(p._2))(_ ++ _) + Relation( subjLabeled, predResults.map(_._1).toSet, - predResults.map(kv => (kv._1.iri, kv._2)).toMap, + qualifiedBiolinkPredicates, objLabeled, Seq[Relation](), // TODO: recurse! results.map(_.getResource("g").getURI).toSet @@ -336,13 +332,11 @@ object LookupService extends LazyLogging { // Get every relation from this subject. relations <- getRelations(qualifiedIds.map(_.iri).toSet) - biolinkPredicates: Map[String, Set[LabeledIRI]] = relations.flatMap(_.biolinkPredicates).foldLeft(Map[String, Set[LabeledIRI]]()) { - case (map, entry) => map.updated(entry._1, map.getOrElse(entry._1, Set()) ++ entry._2) - } + biolinkPredicates = relations.flatMap(_.qualifiedBiolinkPredicates.values).flatten } yield Result( queryId, qualifiedIds.toList, - biolinkPredicates, + biolinkPredicates.toSet, relations.toSeq, subjectTriples.map(fromQuerySolution), objectTriples.map(fromQuerySolution) diff --git a/src/main/scala/org/renci/cam/QueryService.scala b/src/main/scala/org/renci/cam/QueryService.scala index f2a7745e..cd8becfc 100644 --- a/src/main/scala/org/renci/cam/QueryService.scala +++ b/src/main/scala/org/renci/cam/QueryService.scala @@ -6,13 +6,14 @@ import io.circe.syntax._ import org.apache.jena.query.QuerySolution import org.apache.jena.rdf.model.Resource import org.phenoscape.sparql.SPARQLInterpolation._ -import org.renci.cam.Biolink.{biolinkData, BiolinkData} +import org.renci.cam.Biolink.{BiolinkData, biolinkData} import org.renci.cam.HttpClient.HttpClient import org.renci.cam.SPARQLQueryExecutor.SPARQLCache import org.renci.cam.Util.IterableSPARQLOps -import org.renci.cam.domain.{TRAPIAttribute, _} -import zio.config.{getConfig, ZConfig} -import zio.{config => _, Has, RIO, Task, UIO, ZIO} +import org.renci.cam.domain.PredicateMappings.{getBiolinkQualifiedPredicates, mapQueryEdgePredicates} +import org.renci.cam.domain._ +import zio.config.{ZConfig, getConfig} +import zio.{Has, RIO, Task, UIO, ZIO, config => _} import java.math.BigInteger import java.nio.charset.StandardCharsets @@ -21,6 +22,8 @@ import scala.jdk.CollectionConverters._ object QueryService extends LazyLogging { + val INNER_LIMIT_MULTIPLIER = 100 + val ProvWasDerivedFrom: IRI = IRI("http://www.w3.org/ns/prov#wasDerivedFrom") val RDFSSubClassOf: IRI = IRI("http://www.w3.org/2000/01/rdf-schema#subClassOf") @@ -44,6 +47,7 @@ object QueryService extends LazyLogging { val SlotMapping: IRI = IRI("http://cam.renci.org/biolink_slot") val BiolinkNamedThing: BiolinkClass = BiolinkClass("NamedThing", IRI(s"${BiolinkTerm.namespace}NamedThing")) + val BiolinkRelatedTo: BiolinkPredicate = BiolinkPredicate("related_to") /* Hints used to optimize the query (see https://github.com/blazegraph/database/wiki/QueryHints for details). */ @@ -188,8 +192,7 @@ object QueryService extends LazyLogging { * @see * org.renci.cam.QueryService#getTRAPIEdges */ - def generateTRAPIEdges(results: List[Result], relationsToLabelAndBiolinkPredicate: Map[IRI, (Option[String], IRI)]) - : RIO[ZConfig[AppConfig] with ZConfig[BiolinkData], Map[String, TRAPIEdge]] = + def generateTRAPIEdges(results: List[Result]): RIO[ZConfig[AppConfig] with ZConfig[BiolinkData], Map[String, TRAPIEdge]] = for { // Get some data we need to generate the TRAPI edges. biolinkData <- biolinkData @@ -207,50 +210,52 @@ object QueryService extends LazyLogging { .orElseFail(new Exception("could not get biolink:InformationResource")) // Generate the edges. - edges = results.flatMap(result => - for { - key <- result.edges.keys - - // Generate the pieces of this TRAPIEdge. - iri = result.edges(key) - labelAndBiolinkPredicate = relationsToLabelAndBiolinkPredicate.get(iri) - biolinkPredicateIRI = labelAndBiolinkPredicate.map(_._2) - biolinkPred = biolinkData.predicates.find(a => biolinkPredicateIRI.forall(_.equals(a.iri))) - queryEdge = result.queryGraph.edges(key) - subjectIRI = result.nodes(queryEdge.subject) - objectIRI = result.nodes(queryEdge.`object`) - derivedFroms = result.derivedFrom - - // Generate the attributes for this edge. - aggregatorKSAttribute = TRAPIAttribute(Some("infores:cam-kp"), - aggregatorKS.iri, - None, - List("infores:cam-kp"), - Some(infoResBiolinkClass.iri), - Some(appConfig.location), - None, - None) - originalKnowledgeSources = derivedFroms.map { - case df @ ctd if ctd.value.contains("ctdbase.org") => (df, "infores:ctd") - case df => (df, "infores:go-cam") - } - originalKSAttributes = originalKnowledgeSources.map { case (derivedFrom, inforesKS) => - TRAPIAttribute(Some("infores:cam-kp"), - originalKS.iri, - None, - List(inforesKS), - Some(infoResBiolinkClass.iri), - Some(derivedFrom.value), - None, - None) - } - attributes = aggregatorKSAttribute +: originalKSAttributes.toList + edges = results + .flatMap(result => + for { + key <- result.edges.keys + + // Generate the pieces of this TRAPIEdge. + relationIRI = result.edges(key) + queryEdge = result.queryGraph.edges(key) + subjectIRI = result.nodes(queryEdge.subject) + objectIRI = result.nodes(queryEdge.`object`) + derivedFroms = result.derivedFrom + + // Generate the attributes for this edge. + aggregatorKSAttribute = TRAPIAttribute(Some("infores:cam-kp"), + aggregatorKS.iri, + None, + List("infores:cam-kp"), + Some(infoResBiolinkClass.iri), + Some(appConfig.location), + None, + None) + originalKnowledgeSources = derivedFroms.map { + case df @ ctd if ctd.value.contains("ctdbase.org") => (df, "infores:ctd") + case df => (df, "infores:go-cam") + } + originalKSAttributes = originalKnowledgeSources.map { case (derivedFrom, inforesKS) => + TRAPIAttribute(Some("infores:cam-kp"), + originalKS.iri, + None, + List(inforesKS), + Some(infoResBiolinkClass.iri), + Some(derivedFrom.value), + None, + None) + } + attributes = aggregatorKSAttribute +: originalKSAttributes.toList - // Generate the TRAPIEdge and its edge key. - trapiEdge = TRAPIEdge(biolinkPred, subjectIRI, objectIRI, Some(attributes)) - // edgeKey = getTRAPIEdgeKey(queryEdge.subject, biolinkPred, queryEdge.`object`) - edgeKey = result.getEdgeKey(key) - } yield (edgeKey, trapiEdge)) + // Generate the TRAPIEdge and its edge key. + biolinkPreds = getBiolinkQualifiedPredicates(relationIRI) + trapiEdges = biolinkPreds.zipWithIndex.map { case (qualifiedPred, index) => + (result.getEdgeKey(key) + "_pred_" + index, + TRAPIEdge(Some(qualifiedPred.biolinkPredicate), subjectIRI, objectIRI, Some(attributes), qualifiedPred.asQualifierList)) + } + // edgeKey = getTRAPIEdgeKey(queryEdge.subject, biolinkPred, queryEdge.`object`) + } yield trapiEdges) + .flatten } yield edges.toMap /** Generate TRAPI results from a list of Results. @@ -263,33 +268,70 @@ object QueryService extends LazyLogging { * @return * An UIO that generates the list of TRAPI Results. */ - def generateTRAPIResults(results: List[Result]): List[TRAPIResult] = + def generateTRAPIResults(results: List[Result], edges: Map[String, TRAPIEdge]): List[TRAPIResult] = for { result <- results nodeBindings = result.nodes - .groupMap(_._1)(p => - TRAPINodeBinding( - id = p._2, - query_id = result.queryGraph.nodes.get(p._1) match { - // If no nodes IDs were provided, query_id MUST be null or absent. - case None => None - case Some(TRAPIQueryNode(None, _, _, _)) => None - case Some(TRAPIQueryNode(Some(List()), _, _, _)) => - None - case Some(TRAPIQueryNode(Some(ids), _, _, _)) => - result.originalNodes.get(p._1) match { - // According to the TRAPI 1.3 spec, we SHOULD NOT provide a query_id if it is the - // same as the id. - case Some(p._2) => None - case x => x - } + .groupMap(_._1) { p => + val node_id = p._1 + val node_iri = p._2 + + logger.info(f"Searching through nodes: ${result.queryGraph.nodes}") + logger.info(f"And then translating using: ${result.originalNodes}") + + val nb = TRAPINodeBinding( + id = node_iri, + query_id = { + logger.info( + f"Looking for node binding for ${node_id} (${node_iri}) using query graph node ${result.queryGraph.nodes.get(node_id)}") + + val query_id = result.queryGraph.nodes.get(node_id) match { + // If no nodes IDs were provided, query_id MUST be null or absent. + case None => None + case Some(TRAPIQueryNode(None, _, _, _)) => None + case Some(TRAPIQueryNode(Some(List()), _, _, _)) => + None + case Some(TRAPIQueryNode(Some(ids), _, _, _)) => + logger.info(f"Translating from ${node_iri} to ${ids} with original nodes: ${result.originalNodes.get(node_id)}") + + val query_id = result.originalNodes.get(node_id) match { + // According to the TRAPI 1.3 spec, we SHOULD NOT provide a query_id if it is the + // same as the id. + case Some(ni) if ni == node_iri => None + case x => x + } + + logger.info(f"Query ID is ${query_id}") + + query_id + } + query_id } - )) + ) + + logger.info(f"TRAPINodeBinding generated for result ${result.index}: ${nb}") + + nb + } .map(p => (p._1, p._2.toList)) - edgeBindings = result.edges.keys - .map(key => (key, List(TRAPIEdgeBinding(result.getEdgeKey(key))))) - .toMap + + edgeBindings = result.edges.keys.map { key => + // This is a pretty dumb way to do this, but it should be error-proof. + val fullEdgeId = result.getEdgeKey(key) + val allPreds = edges.keySet.flatMap { p => + val rMatchPreds = """^(.*)_pred_(\d+)$""".r + p match { + case rMatchPreds(edgeId, _) if edgeId == fullEdgeId => Some(p) + case _ => None + } + } + + if (allPreds.isEmpty) + (key, List(TRAPIEdgeBinding(fullEdgeId))) + else + (key, allPreds.map(pred => TRAPIEdgeBinding(pred)).toList) + }.toMap } yield TRAPIResult(node_bindings = nodeBindings, edge_bindings = edgeBindings) /** Query the triplestore with a TRAPIQuery and return a TRAPIMessage with the result. @@ -309,6 +351,13 @@ object QueryService extends LazyLogging { _.constraints.getOrElse(List())) ++ submittedQueryGraph.edges.values.flatMap(_.attribute_constraints.getOrElse(List())) val allQualifierConstraints = submittedQueryGraph.edges.values.flatMap(_.qualifier_constraints.getOrElse(List())) + // Try mapping all predicates. If any fail, we should produce appropriate errors. + // TODO: we shouldn't just discard these mappings! We should use them. + val unmappedEdges = submittedQueryGraph.edges.flatMap { case (key, edge) => + val mappedPreds = mapQueryEdgePredicates(edge.predicates, edge.qualifier_constraints) + if (mappedPreds.isEmpty) Seq((key, edge)) else Seq() + } + if (allAttributeConstraints.nonEmpty) { ZIO.succeed( TRAPIResponse( @@ -327,22 +376,28 @@ object QueryService extends LazyLogging { ) ) ) - } else if (allQualifierConstraints.nonEmpty) { - // Are there any qualifier constraints? If so, we can't match them, so we should return an empty list of results. + } else if (unmappedEdges.nonEmpty) { + // Generate a list of all the edges that couldn't be mapped. + val errorList = unmappedEdges.map { case (key, edge) => + val warning = s"Edge ${key} could not be mapped to a predicate, and so cannot be matched: ${edge}" + logger.warn(warning) + + LogEntry( + Some(java.time.Instant.now().toString), + Some("ERROR"), + Some("UnsupportedEdge"), + Some(warning) + ) + } + + // Are there any unmapped edges? If so, we should return them as errors. ZIO.succeed( TRAPIResponse( emptyTRAPIMessage, - Some("Success"), + Some("ERROR"), None, Some( - List( - LogEntry( - Some(java.time.Instant.now().toString), - Some("WARNING"), - Some("UnsupportedQualifierConstraint"), - Some(s"The following qualifier constraints are not supported: ${allQualifierConstraints}") - ) - ) + errorList.toList ) ) ) @@ -354,16 +409,12 @@ object QueryService extends LazyLogging { // Prepare the query graph for processing. queryGraph = enforceQueryEdgeTypes(submittedQueryGraph, biolinkData.predicates) - - // Generate the relationsToLabelAndBiolinkPredicate. - allPredicatesInQuery = queryGraph.edges.values.flatMap(_.predicates.getOrElse(Nil)).to(Set) - predicatesToRelations <- mapQueryBiolinkPredicatesToRelations(allPredicatesInQuery) - allRelationsInQuery = predicatesToRelations.values.flatten.to(Set) - relationsToLabelAndBiolinkPredicate <- mapRelationsToLabelAndBiolink(allRelationsInQuery) + _ = logger.debug(s"Transformed the submitted query graph: ${submittedQueryGraph}") + _ = logger.debug(s"Submitted query graph transformed to: ${queryGraph}") // Generate query solutions. - _ = logger.debug(s"findInitialQuerySolutions($queryGraph, $predicatesToRelations, $limit)") - initialQuerySolutions <- findInitialQuerySolutions(queryGraph, predicatesToRelations, limit) + _ = logger.debug(s"findInitialQuerySolutions($queryGraph, $limit)") + initialQuerySolutions <- findInitialQuerySolutions(queryGraph, limit) results = initialQuerySolutions.zipWithIndex.map { case (qs, index) => Result.fromQuerySolution(qs, index, queryGraph) } @@ -372,9 +423,9 @@ object QueryService extends LazyLogging { // From the results, generate the TRAPI nodes, edges and results. nodes <- generateTRAPINodes(results) _ = logger.debug(s"Nodes: $nodes") - edges <- generateTRAPIEdges(results, relationsToLabelAndBiolinkPredicate) + edges <- generateTRAPIEdges(results) _ = logger.debug(s"Edges: $edges") - trapiResults = generateTRAPIResults(results) + trapiResults = generateTRAPIResults(results, edges) _ = logger.debug(s"Results: $trapiResults") } yield TRAPIResponse( TRAPIMessage(Some(queryGraph), Some(TRAPIKnowledgeGraph(nodes, edges)), Some(trapiResults.distinct)), @@ -384,6 +435,7 @@ object QueryService extends LazyLogging { ) } + /* def oldRun(limit: Int, includeExtraEdges: Boolean, submittedQueryGraph: TRAPIQueryGraph) : RIO[ZConfig[AppConfig] with HttpClient with Has[BiolinkData] with Has[SPARQLCache], TRAPIMessage] = for { @@ -395,7 +447,7 @@ object QueryService extends LazyLogging { allRelationsInQuery = predicatesToRelations.values.flatten.to(Set) relationsToLabelAndBiolinkPredicate: Map[IRI, (Option[String], IRI)] <- mapRelationsToLabelAndBiolink(allRelationsInQuery) _ = logger.warn(s"findInitialQuerySolutions($queryGraph, $predicatesToRelations, $limit)") - initialQuerySolutions <- findInitialQuerySolutions(queryGraph, predicatesToRelations, limit) + initialQuerySolutions <- findInitialQuerySolutions(queryGraph, limit) _ = logger.warn(s"Initial query solutions: ${initialQuerySolutions.length} (limit: $limit): $initialQuerySolutions") _ = logger.warn(s"extractCoreTriples($initialQuerySolutions, $queryGraph)") solutionTriples = extractCoreTriples(initialQuerySolutions, queryGraph) @@ -441,6 +493,7 @@ object QueryService extends LazyLogging { _ = logger.warn(s"results: $results (length: ${results.length}, limit: $limit)") _ = logger.warn(s"results distinct: ${results.distinct} (length: ${results.distinct.length}, limit: $limit)") } yield TRAPIMessage(Some(queryGraph), Some(TRAPIKnowledgeGraph(initialKGNodes, initialKGEdges)), Some(results.distinct)) + */ /** Construct and execute a SPARQL query based on the provided query graph in the triplestore. * @@ -456,15 +509,17 @@ object QueryService extends LazyLogging { * org.renci.cam.QueryService#Result for a more human-readable version of the query solution. */ def findInitialQuerySolutions(queryGraph: TRAPIQueryGraph, - predicatesToRelations: Map[BiolinkPredicate, Set[IRI]], limit: Int): ZIO[ZConfig[AppConfig] with HttpClient, Throwable, List[QuerySolution]] = { + val queryEdgeSparql = queryGraph.edges.map { case (queryEdgeID, queryEdge) => - val relationsForEdge = queryEdge.predicates.getOrElse(Nil).flatMap(predicatesToRelations.getOrElse(_, Set.empty)).to(Set) - val predicatesQueryText = relationsForEdge.asSPARQLList val edgeIDVar = Var(queryEdgeID) val edgeSourceVar = Var(queryEdge.subject) val edgeTargetVar = Var(queryEdge.`object`) - val predicatesValuesClause = sparql""" FILTER( $edgeIDVar IN ( $predicatesQueryText ) )""" + val predicatesValuesClause = { + // To calculate this, we need to map every predicate using the predicate mapping information. + val mappedPredicates = mapQueryEdgePredicates(queryEdge.predicates, queryEdge.qualifier_constraints) + sparql""" FILTER( $edgeIDVar IN ( ${mappedPredicates.asSPARQLList} ) )""" + } val subjectNode = queryGraph.nodes(queryEdge.subject) val subjectNodeValuesClauses = getNodeValuesClauses(subjectNode.ids, subjectNode.categories, edgeSourceVar) val objectNode = queryGraph.nodes(queryEdge.`object`) @@ -483,6 +538,8 @@ object QueryService extends LazyLogging { val nodesToDirectTypes = getNodesToDirectTypes(queryGraph.nodes) val edgePatterns = queryEdgeSparql.fold(sparql"")(_ + _) val limitSparql = if (limit > 0) sparql" LIMIT $limit" else sparql"" + val innerLimit = INNER_LIMIT_MULTIPLIER * limit + val innerLimitSparql = if (limit > 0) sparql" LIMIT $innerLimit" else sparql"" val queryString = sparql"""SELECT DISTINCT $typeProjections (GROUP_CONCAT(DISTINCT ?g; SEPARATOR='|') AS ?graphs) @@ -494,7 +551,7 @@ object QueryService extends LazyLogging { SELECT $nodeProjections ?g WHERE { $edgePatterns - } + } ${innerLimitSparql} } $BigDataQueryHintPrior $BigDataQueryHintRunFirst true . } @@ -574,8 +631,8 @@ object QueryService extends LazyLogging { def enforceQueryEdgeTypes(queryGraph: TRAPIQueryGraph, biolinkPredicates: List[BiolinkPredicate]): TRAPIQueryGraph = { val improvedEdgeMap = queryGraph.edges.map { case (edgeID, edge) => val newPredicates = edge.predicates match { - case None => Some(List(BiolinkPredicate("related_to"))) - case Some(Nil) => Some(List(BiolinkPredicate("related_to"))) + case None => Some(List(BiolinkRelatedTo)) + case Some(Nil) => Some(List(BiolinkRelatedTo)) case predicates => predicates } val filteredPredicates = newPredicates.map(_.filter(pred => biolinkPredicates.contains(pred))) @@ -819,40 +876,4 @@ object QueryService extends LazyLogging { nodeMap } - // TODO: - // - Change this to cached queries (see mapQueryBiolinkPredicatesToRelations for example) - def mapRelationsToLabelAndBiolink(relations: Set[IRI]): RIO[ZConfig[AppConfig] with HttpClient, Map[IRI, (Option[String], IRI)]] = { - final case class RelationInfo(relation: IRI, biolinkSlot: IRI, label: Option[String]) - val queryText = sparql""" - SELECT DISTINCT ?relation ?biolinkSlot ?label - WHERE { - VALUES ?relation { ${relations.asValues} } - ?relation $SlotMapping ?biolinkSlot . - ?biolinkSlot a $BiolinkMLSlotDefinition . - OPTIONAL { ?relation $RDFSLabel ?label . } - FILTER NOT EXISTS { - ?relation $SlotMapping ?other . - ?other $BiolinkMLIsA+/$BiolinkMLMixins* ?biolinkSlot . - } - }""" - SPARQLQueryExecutor.runSelectQueryAs[RelationInfo](queryText.toQuery).map { res => - res.groupMap(_.relation)(info => (info.label, info.biolinkSlot)).map { case (relationIRI, infos) => relationIRI -> infos.head } - } - } - - def mapQueryBiolinkPredicatesToRelations( - predicates: Set[BiolinkPredicate]): RIO[ZConfig[AppConfig] with HttpClient with Has[SPARQLCache], Map[BiolinkPredicate, Set[IRI]]] = { - final case class Predicate(biolinkPredicate: BiolinkPredicate, predicate: IRI) - val queryText = sparql""" - SELECT DISTINCT ?biolinkPredicate ?predicate WHERE { - VALUES ?biolinkPredicate { ${predicates.asValues} } - ?predicate $SlotMapping ?biolinkPredicate . - FILTER EXISTS { ?s ?predicate ?o } - $BigDataQueryHintQuery $BigDataQueryHintFilterExists "SubQueryLimitOne" - }""" - for { - predicates <- SPARQLQueryExecutor.runSelectQueryWithCacheAs[Predicate](queryText.toQuery) - } yield predicates.to(Set).groupMap(_.biolinkPredicate)(_.predicate) - } - } diff --git a/src/main/scala/org/renci/cam/domain/PredicateMappings.scala b/src/main/scala/org/renci/cam/domain/PredicateMappings.scala new file mode 100644 index 00000000..c0bdcc56 --- /dev/null +++ b/src/main/scala/org/renci/cam/domain/PredicateMappings.scala @@ -0,0 +1,211 @@ +package org.renci.cam.domain + +import io.circe.generic.auto._ +import org.phenoscape.sparql.SPARQLInterpolation.SPARQLStringContext +import org.renci.cam.HttpClient.HttpClient +import org.renci.cam.LookupService.LabeledIRI +import org.renci.cam.SPARQLQueryExecutor.SPARQLCache +import org.renci.cam.util.GenerateBiolinkPredicateMappings.logger +import org.renci.cam.{AppConfig, QueryService, SPARQLQueryExecutor} +import zio.blocking.{blocking, Blocking} +import zio.config.{getConfig, ZConfig} +import zio.stream.ZStream +import zio.{Has, RIO, Task, ZIO} + +import java.io.{File, FileInputStream} +import scala.io.Source + +object PredicateMappings { + + case class PredicateMapping( + predicate: LabeledIRI, + biolinkPredicate: Option[BiolinkPredicate], + biolinkQualifiers: Option[TRAPIQualifierConstraint] + ) + + /** Retrieve the list of predicates from the triplestore, along with Biolink mappings where available. + * + * @return + * A sequence of PredicateMappings from the triplestore. + */ + def getPredicatesFromSPARQL: RIO[ZConfig[AppConfig] with HttpClient with Has[SPARQLCache], Seq[PredicateMapping]] = { + val predicateQuery = + sparql"""SELECT DISTINCT ?pred ?pred_label ?biolink_slot WHERE { + OPTIONAL { ?pred ${QueryService.RDFSLabel} ?pred_label } . + OPTIONAL { ?pred ${QueryService.SlotMapping} ?biolink_slot } + + { + SELECT DISTINCT ?pred WHERE { ?s ?pred ?o } + } + }""".toQuery + + for { + result <- SPARQLQueryExecutor.runSelectQuery(predicateQuery) + preds <- ZStream + .fromIterable(result) + .map( + { qs => + val predURI = qs.getResource("pred").getURI + val predLabel = qs.getLiteral("pred_label").getString + val biolinkSlot = qs.getResource("biolink_slot") + + if (biolinkSlot == null) { + logger.warn(f"No Biolink mapping known for predicate ${predURI} (${predLabel})") + PredicateMapping( + LabeledIRI(predURI, Set(predLabel)), + None, + None + ) + } else { + val biolinkURI = biolinkSlot.getURI + val shorthand = biolinkURI.replaceFirst(raw"^https://w3id.org/biolink/vocab/", "") + + PredicateMapping( + LabeledIRI(predURI, Set(predLabel)), + Some(BiolinkPredicate(shorthand, IRI(biolinkURI))), + None + ) + } + } + ) + .runCollect + } yield preds + } + + /* PREDICATE MAPPING. + + For Biolink v3, the TRAPI developers created a file of predicate mappings. We use that to expand the predicates + currently in the + + For future versions, we will either continue to rely on that file, maintain our own copy of those mappings, + or replace this with some other mechanism for predicate mapping. + */ + + /** A case class for predicate mappings. */ + case class PredicateMappingRow( + `mapped predicate`: String, + `object aspect qualifier`: Option[String], + `object direction qualifier`: Option[String], + predicate: String, + `qualified predicate`: Option[String], + `exact matches`: Option[Set[String]] + ) { + def biolinkPredicate: BiolinkPredicate = BiolinkPredicate(predicate.replace(' ', '_')) + + def biolinkMappedPredicate: BiolinkPredicate = BiolinkPredicate(`mapped predicate`.replace(' ', '_')) + + def qualifiers: Seq[TRAPIQualifier] = (`object aspect qualifier` match { + case Some(aspect: String) => + List(TRAPIQualifier(qualifier_type_id = "biolink:object_aspect_qualifier", qualifier_value = aspect.replace(' ', '_'))) + case _ => List() + }) ++ (`object direction qualifier` match { + case Some(direction: String) => + List(TRAPIQualifier(qualifier_type_id = "biolink:object_direction_qualifier", qualifier_value = direction.replace(' ', '_'))) + case _ => List() + }) ++ (`qualified predicate` match { + case Some(qualified_predicate: String) => + List( + TRAPIQualifier(qualifier_type_id = "biolink:qualified_predicate", + qualifier_value = BiolinkPredicate(qualified_predicate.replace(' ', '_')).withBiolinkPrefix) + ) + case _ => List() + }) + + def qualifierConstraint: TRAPIQualifierConstraint = TRAPIQualifierConstraint(qualifier_set = qualifiers.toList) + + def qualifierConstraintList = List(qualifierConstraint) + } + + case class PredicateMappings( + `predicate mappings`: List[PredicateMappingRow] + ) + + /** To initialize this object, we need to download and parse the predicate_mapping.yaml file from the Biolink model, which needs to be + * downloaded to the package resources (src/main/resources) from + * https://github.com/biolink/biolink-model/blob/${biolinkVersion}/predicate_mapping.yaml (the raw version is available from + * https://raw.githubusercontent.com/biolink/biolink-model/v3.2.1/predicate_mapping.yaml) + */ + val getPredicateMappingsFromGitHub: RIO[ZConfig[AppConfig] with Blocking, List[PredicateMappingRow]] = + for { + appConfig <- getConfig[AppConfig] + predicateMappingText <- blocking( + Task.effect( + Source + .fromURL(s"https://raw.githubusercontent.com/biolink/biolink-model/${appConfig.biolinkVersion}/predicate_mapping.yaml") + .getLines() + .mkString("\n") + ) + ) + predicateMappingsYaml <- ZIO.fromEither(io.circe.yaml.parser.parse(predicateMappingText)) + predicateMappings <- ZIO.fromEither(predicateMappingsYaml.as[PredicateMappings]) + } yield predicateMappings.`predicate mappings` + + /** Compares two qualifier lists. */ + def compareQualifierConstraints(ql1: List[TRAPIQualifier], ql2: List[TRAPIQualifier]): Boolean = { + + val set1 = ql1.map(q => (q.qualifier_value, q.qualifier_type_id)).toSet + val set2 = ql2.map(q => (q.qualifier_value, q.qualifier_type_id)).toSet + + (set1 == set2) + } + + /** Load the predicates data so we can use it subsequently. */ + // TODO: there's some hacky code here for handling the case where biolink/predicates.json doesn't exist. It should + // generally always exist, since it's included in the repository. But we should still test this so it's better. + // TODO: Source.fromResource() is probably better here. + val predicateMappingsStream = + if (PredicateMappings.getClass.getResourceAsStream("/biolink/predicates.json") != null) + PredicateMappings.getClass.getResourceAsStream("/biolink/predicates.json") + else + new FileInputStream(new File("src/main/resources/biolink/predicates.json")) + + val predicatesDataAsString = + Source + .fromInputStream(predicateMappingsStream) + .getLines() + .mkString("\n") + + val predicatesData = + if (predicateMappingsStream == null) Seq() + else io.circe.parser.parse(predicatesDataAsString).toTry.get.as[Seq[PredicateMapping]].toTry.get + + def mapQueryEdgePredicates(predicates: Option[List[BiolinkPredicate]], + qualifier_constraints: Option[List[TRAPIQualifierConstraint]]): Set[IRI] = { + // predicatesData consists of unique mappings between relations and (biolinkPredicate, biolinkQualifier) pairs. + val biolinkPredicates = predicates.toList.flatten.toSet + val qualifierConstraint = qualifier_constraints.toList.flatten.flatMap(_.qualifier_set) + + logger.debug(s"Searching for ${predicates} with ${qualifier_constraints} in ${predicatesData}") + + val relations = predicatesData.filter { + case pred @ PredicateMapping(_, Some(biolinkPredicate), qualifierOpt) => + logger.debug( + f"Check if ${biolinkPredicates} contains ${biolinkPredicate} from ${pred}: ${biolinkPredicates.contains(biolinkPredicate)}") + if (!biolinkPredicates.contains(biolinkPredicate)) false + else { + // qualifierOpt should match qualifierConstraint, whether empty or not. + qualifierOpt match { + case None => qualifierConstraint.isEmpty + case Some(constraint) => compareQualifierConstraints(qualifierConstraint, constraint.qualifier_set) + } + } + case _ => false + } + + relations.map(pred => IRI(pred.predicate.iri)).toSet + } + + def getBiolinkQualifiedPredicates(relationIRI: IRI): Seq[QualifiedBiolinkPredicate] = + predicatesData.flatMap { + case PredicateMapping(relation, Some(biolinkPredicate), qualifierOpt) => + if (relation.iri != relationIRI.value) None + else + qualifierOpt match { + case None => Some(QualifiedBiolinkPredicate(biolinkPredicate, List())) + case Some(constraint) if constraint.qualifier_set.isEmpty => Some(QualifiedBiolinkPredicate(biolinkPredicate, List())) + case Some(constraint) => Some(QualifiedBiolinkPredicate(biolinkPredicate, constraint.qualifier_set)) + } + case _ => None + } + +} diff --git a/src/main/scala/org/renci/cam/domain/package.scala b/src/main/scala/org/renci/cam/domain/package.scala index eff4e5f9..3659a449 100644 --- a/src/main/scala/org/renci/cam/domain/package.scala +++ b/src/main/scala/org/renci/cam/domain/package.scala @@ -138,6 +138,26 @@ package object domain { attribute_constraints: Option[List[TRAPIAttributeConstraint]] = None, qualifier_constraints: Option[List[TRAPIQualifierConstraint]] = None) + /** A case class representing a combination of a BiolinkPredicate and the qualifiers that qualify it. + * + * At some point we might need to add attributes to this, but not at the moment. + * + * @param biolinkPredicate + * A Biolink predicate + * @param qualifierList + * A list of qualifiers that qualify them. + */ + final case class QualifiedBiolinkPredicate(biolinkPredicate: BiolinkPredicate, qualifierList: List[TRAPIQualifier] = List.empty) { + + val asQualifierList: Option[List[TRAPIQualifier]] = if (qualifierList.isEmpty) None else Some(qualifierList) + + val asQualifierConstraint: Option[List[TRAPIQualifierConstraint]] = + if (qualifierList.isEmpty) None + else + Some(List(TRAPIQualifierConstraint(qualifierList))) + + } + final case class TRAPIAttributeConstraint(id: IRI, name: String, not: Option[Boolean], diff --git a/src/main/scala/org/renci/cam/util/GenerateBiolinkPredicateMappings.scala b/src/main/scala/org/renci/cam/util/GenerateBiolinkPredicateMappings.scala new file mode 100644 index 00000000..92e4ce9d --- /dev/null +++ b/src/main/scala/org/renci/cam/util/GenerateBiolinkPredicateMappings.scala @@ -0,0 +1,143 @@ +package org.renci.cam.util + +import com.typesafe.scalalogging.{LazyLogging, Logger} +import io.circe.generic.auto._ +import io.circe.syntax._ +import org.renci.cam.LookupService.LabeledIRI +import org.renci.cam.domain.{BiolinkPredicate, TRAPIQualifier, TRAPIQualifierConstraint} +import org.renci.cam.domain.PredicateMappings.{getPredicateMappingsFromGitHub, getPredicatesFromSPARQL, PredicateMapping, PredicateMappingRow} +import org.renci.cam.{AppConfig, HttpClient, SPARQLQueryExecutor} +import zio._ +import zio.config.ZConfig +import zio.config.typesafe.TypesafeConfig + +import java.nio.file.{Files, Paths} + +/** This class can generate Biolink predicate mappings in the src/main/resources/biolink directory, based on two input sources: + * 1. It queries the triplestore to download the list of all predicates in use in the triplestore, along with Biolink mappings where + * available. + * + * 2. It downloads the predicate mapping file from a specific Biolink model version, and uses that to map single predicates to + * predicate+qualifier combinations. + * + * It generates a single JSON document that can be used to handle all our predicate mapping needs: + * 1. Map a Biolink predicate with zero or more qualifiers to a set of triplestore predicates. + * + * 2. Map a triplestore predicate to a Biolink predicate with zero or more qualifiers. + * + * It also generates warnings for predicates not mapped. + */ +object GenerateBiolinkPredicateMappings extends zio.App with LazyLogging { + override lazy val logger: Logger = Logger(GenerateBiolinkPredicateMappings.getClass.getSimpleName); + + /* Manual annotations. */ + val manualPredicateMappings = Seq( + PredicateMapping( + predicate = LabeledIRI("http://purl.obolibrary.org/obo/RO_0002450", Set("directly positively regulates activity of")), + biolinkPredicate = Some(BiolinkPredicate("affects")), + biolinkQualifiers = Some( + TRAPIQualifierConstraint( + List( + TRAPIQualifier("biolink:object_aspect_qualifier", "activity_or_abundance"), + TRAPIQualifier("biolink:object_direction_qualifier", "increased") + )) + ) + ), + PredicateMapping( + predicate = LabeledIRI("http://purl.obolibrary.org/obo/RO_0002449", Set("directly negatively regulates activity of")), + biolinkPredicate = Some(BiolinkPredicate("affects")), + biolinkQualifiers = Some( + TRAPIQualifierConstraint( + List( + TRAPIQualifier("biolink:object_aspect_qualifier", "activity_or_abundance"), + TRAPIQualifier("biolink:object_direction_qualifier", "decreased") + )) + ) + ), + PredicateMapping( + predicate = LabeledIRI("http://purl.obolibrary.org/obo/RO_0002305", Set("causally upstream of, negative effect")), + biolinkPredicate = Some(BiolinkPredicate("regulates")), + biolinkQualifiers = Some( + TRAPIQualifierConstraint( + List( + TRAPIQualifier("biolink:object_direction_qualifier", "downregulated") + )) + ) + ) + ) + + /** Where should we save the predicates.json files? */ + val PredicateJsonFilePath = Paths.get("src/main/resources/biolink/predicates.json") + + override def run(args: List[String]): URIO[zio.ZEnv, ExitCode] = { + def transformPredicateWithMappedPredicateInfo(pred: PredicateMapping, mp: PredicateMappingRow): PredicateMapping = { + val predReplaced = PredicateMapping( + pred.predicate, + Some(mp.biolinkPredicate), + Some(mp.qualifierConstraint) + ) + + logger.error(f"Replacing ${pred} with ${predReplaced} with information from ${mp}") + + predReplaced + } + + val program = for { + preds <- getPredicatesFromSPARQL + mappedPredicates <- getPredicateMappingsFromGitHub + predsMappedByExactMatch = preds.map { pred => + val foundByExactMatch = mappedPredicates.find( + { mp => + val exactMatches = mp.`exact matches`.toList.flatten.toSet + + // These are in CURIEs. Normally I would write some very complicated code to un-CURIE-fy it, but + // instead... + exactMatches + .map(_.replaceFirst(raw"^RO:", "http://purl.obolibrary.org/obo/RO_")) + .contains(pred.predicate.iri) + } + ) + + foundByExactMatch match { + case None => pred + case Some(mp) => transformPredicateWithMappedPredicateInfo(pred, mp) + } + } + qualifiedPreds: Seq[PredicateMapping] = predsMappedByExactMatch.map { + /* For each predicate, we need to check to see if this is a "mapped predicate". If so, we transform it + into a qualified predicate as per the predicate mapping. + */ + case pred @ PredicateMapping(_, Some(biolinkPredicate: BiolinkPredicate), _) => + // In some cases, we might be able to find the mappings by Biolink predicate. + val foundByBiolinkPredicate = mappedPredicates.find(mp => mp.biolinkMappedPredicate == biolinkPredicate) + + foundByBiolinkPredicate match { + case None => pred + case Some(mp) => transformPredicateWithMappedPredicateInfo(pred, mp) + } + + // If we haven't matched it, don't transform it. + case pred => pred + } + uniquePreds: Set[PredicateMapping] = (manualPredicateMappings ++ qualifiedPreds).toSet + predsOutput = uniquePreds.asJson.deepDropNullValues.spaces2SortKeys + } yield { + logger.info(f"Found ${preds.size} predicates:") + preds.foreach(pred => logger.info(f" - ${pred}")) + + logger.info(f"Found ${mappedPredicates.size} predicate mappings:") + mappedPredicates.foreach(predMap => logger.info(f" - ${predMap}")) + + logger.info(f"Transformed to ${qualifiedPreds.size} predicates:") + qualifiedPreds.foreach(pred => logger.info(f" - ${pred}")) + + Files.writeString(PredicateJsonFilePath, predsOutput) + logger.info(f"Wrote predicate output (${predsOutput.size}) to ${PredicateJsonFilePath}") + } + + val configLayer: Layer[Throwable, ZConfig[AppConfig]] = TypesafeConfig.fromDefaultLoader(AppConfig.config) + val runLayer = HttpClient.makeHttpClientLayer ++ configLayer >+> SPARQLQueryExecutor.makeCache.toLayer + program.provideCustomLayer(runLayer).exitCode + } + +} diff --git a/src/test/resources/lookup-service-test/ids.txt b/src/test/resources/lookup-service-test/ids.txt index aef72ba4..9258daaa 100644 --- a/src/test/resources/lookup-service-test/ids.txt +++ b/src/test/resources/lookup-service-test/ids.txt @@ -1,7 +1,5 @@ CHEBI:17685 PUBCHEM.COMPOUND:157225 -CHEBI:22563 -CHEBI:26369 CHEBI:35660 CHEBI:35703 MONDO:0001208 @@ -31,21 +29,4 @@ HP:0025491 HP:0011105 HP:0003111 HP:0011032 -UniProtKB:O75795 -UniProtKB:P07900 -UniProtKB:P08684 -UniProtKB:P13569 -UniProtKB:P16662 -UniProtKB:P19224 -UniProtKB:P22310 -UniProtKB:P24462 -UniProtKB:P51589 -UniProtKB:P54855 -UniProtKB:P56856 -UniProtKB:P82251 -UniProtKB:Q07837 -UniProtKB:Q16651 -UniProtKB:Q9HB55 -UniProtKB:Q9HBW0 -UniProtKB:Q9NPD5 -UniProtKB:Q9NZQ3 \ No newline at end of file +UniProtKB:P24462 \ No newline at end of file diff --git a/src/test/scala/org/renci/cam/test/Biolink3Test.scala b/src/test/scala/org/renci/cam/test/Biolink3Test.scala new file mode 100644 index 00000000..57b2dbbb --- /dev/null +++ b/src/test/scala/org/renci/cam/test/Biolink3Test.scala @@ -0,0 +1,372 @@ +package org.renci.cam.test + +import com.typesafe.scalalogging.LazyLogging +import org.renci.cam._ +import org.renci.cam.domain._ +import zio._ +import zio.config.ZConfig +import zio.config.typesafe.TypesafeConfig +import zio.stream.ZStream +import zio.test.Assertion._ +import zio.test._ + +/** This test suite tests that CAM-KP can handle Biolink 3 queries. Biolink 3 shifted from having single predicates to qualified predicates. + * The examples in this file are based on the example queries provided in the GitHub issues listed in the references and inline comments + * below. + * + * References: + * - https://github.com/biolink/biolink-model/blob/ac69bb2dc94d62d50f5cfab3fa07414b0ca092b1/Migration_3.0_Guide.md + * - https://github.com/biolink/biolink-model/blob/ac69bb2dc94d62d50f5cfab3fa07414b0ca092b1/predicate_mapping.yaml + * - https://github.com/NCATSTranslator/TranslatorArchitecture/issues/79 + * - https://github.com/NCATSTranslator/TranslatorArchitecture/issues/80 + * - https://github.com/NCATSTranslator/TranslatorArchitecture/issues/81 + * - https://github.com/NCATSTranslator/TranslatorArchitecture/issues/82 + */ + +object Biolink3Test extends DefaultRunnableSpec with LazyLogging { + + val biolink3conversions = { + case class ConversionTest( + biolinkPredicates: Option[List[BiolinkPredicate]], + trapiQualifierConstraints: Option[List[TRAPIQualifierConstraint]], + predicates: Set[IRI] + ) + + val biolink3conversions: Seq[ConversionTest] = Seq( + // related_to should include all possible predicates. + ConversionTest( + Some(List(BiolinkPredicate("related_to"))), + None, + Set( + IRI("http://purl.obolibrary.org/obo/RO_0002565"), + IRI("http://purl.obolibrary.org/obo/RO_0000057"), + IRI("http://purl.obolibrary.org/obo/RO_0002224"), + IRI("http://purl.obolibrary.org/obo/RO_0002087"), + IRI("http://purl.obolibrary.org/obo/RO_0002500"), + IRI("http://purl.obolibrary.org/obo/RO_0004007"), + IRI("http://purl.obolibrary.org/obo/RO_0002131"), + IRI("http://purl.obolibrary.org/obo/RO_0002436"), + IRI("http://purl.obolibrary.org/obo/RO_0002160"), + IRI("http://purl.obolibrary.org/obo/RO_0001025"), + IRI("http://purl.obolibrary.org/obo/RO_0002093"), + IRI("http://purl.obolibrary.org/obo/RO_0002356"), + IRI("http://purl.obolibrary.org/obo/RO_0002216"), + IRI("http://purl.obolibrary.org/obo/BFO_0000063"), + IRI("http://purl.obolibrary.org/obo/RO_0002432"), + IRI("http://purl.obolibrary.org/obo/BFO_0000051"), + IRI("http://purl.obolibrary.org/obo/RO_0002349"), + IRI("http://purl.obolibrary.org/obo/RO_0002488"), + IRI("http://purl.obolibrary.org/obo/RO_0004034"), + IRI("http://purl.obolibrary.org/obo/RO_0002497"), + IRI("http://purl.obolibrary.org/obo/RO_0004033"), + IRI("http://purl.obolibrary.org/obo/RO_0001015"), + IRI("http://purl.obolibrary.org/obo/RO_0002434"), + IRI("http://purl.obolibrary.org/obo/RO_0002263"), + IRI("http://purl.obolibrary.org/obo/RO_0002496"), + IRI("http://purl.obolibrary.org/obo/RO_0002331"), + IRI("http://purl.obolibrary.org/obo/RO_0002608"), + IRI("http://purl.obolibrary.org/obo/RO_0002333"), + IRI("http://purl.obolibrary.org/obo/RO_0002298"), + IRI("http://purl.obolibrary.org/obo/RO_0000056"), + IRI("http://purl.obolibrary.org/obo/RO_0002229"), + IRI("http://purl.obolibrary.org/obo/RO_0004032"), +// IRI("http://translator.renci.org/ubergraph-axioms.ofn#acts_upstream_of_o_enabled_by"), -- this maps to a qualified term, weirdly enough. + IRI("http://purl.obolibrary.org/obo/RO_0000052"), + IRI("http://purl.obolibrary.org/obo/BFO_0000066"), + IRI("http://purl.obolibrary.org/obo/RO_0002348"), + IRI("http://purl.obolibrary.org/obo/RO_0002588"), + IRI("http://purl.obolibrary.org/obo/BFO_0000062"), + IRI("http://purl.obolibrary.org/obo/RO_0002211"), + IRI("http://purl.obolibrary.org/obo/RO_0002205"), + IRI("http://purl.obolibrary.org/obo/RO_0002604"), + IRI("http://purl.obolibrary.org/obo/RO_0003001"), + IRI("http://purl.obolibrary.org/obo/RO_0002448"), + IRI("http://purl.obolibrary.org/obo/RO_0002344"), + IRI("http://purl.obolibrary.org/obo/RO_0002232"), + IRI("http://purl.obolibrary.org/obo/RO_0002338"), + IRI("http://purl.obolibrary.org/obo/RO_0002592"), + IRI("http://purl.obolibrary.org/obo/RO_0002315"), + IRI("http://purl.obolibrary.org/obo/RO_0002234"), + IRI("http://purl.obolibrary.org/obo/RO_0002327"), + IRI("http://purl.obolibrary.org/obo/RO_0002492"), + IRI("http://purl.obolibrary.org/obo/RO_0002090"), + IRI("http://purl.obolibrary.org/obo/RO_0002412"), + IRI("http://purl.obolibrary.org/obo/RO_0002296"), + IRI("http://purl.obolibrary.org/obo/GOREL_0001006"), + IRI("http://purl.obolibrary.org/obo/RO_0002230"), + IRI("http://purl.obolibrary.org/obo/RO_0002299"), + IRI("http://purl.obolibrary.org/obo/RO_0002264"), + IRI("http://purl.obolibrary.org/obo/RO_0002092"), + IRI("http://purl.obolibrary.org/obo/RO_0002084"), + IRI("http://purl.obolibrary.org/obo/RO_0002297"), + IRI("http://purl.obolibrary.org/obo/RO_0003000"), + IRI("http://purl.obolibrary.org/obo/RO_0004009"), + IRI("http://purl.obolibrary.org/obo/RO_0002223"), + IRI("http://purl.obolibrary.org/obo/RO_0002219"), + IRI("http://purl.obolibrary.org/obo/RO_0002339"), + IRI("http://purl.obolibrary.org/obo/RO_0002221"), + // IRI("http://purl.obolibrary.org/obo/RO_0002313"), -- maps to a qualified predicate + IRI("http://purl.obolibrary.org/obo/RO_0004008"), + IRI("http://purl.obolibrary.org/obo/RO_0002326"), + IRI("http://purl.obolibrary.org/obo/BFO_0000050"), + IRI("http://purl.obolibrary.org/obo/RO_0002220"), + IRI("http://purl.obolibrary.org/obo/RO_0001019"), + IRI("http://purl.obolibrary.org/obo/RO_0002215"), + IRI("http://purl.obolibrary.org/obo/RO_0002231"), + IRI("http://purl.obolibrary.org/obo/RO_0012003"), + IRI("http://purl.obolibrary.org/obo/RO_0002411"), + IRI("http://purl.obolibrary.org/obo/RO_0004035"), + IRI("http://purl.obolibrary.org/obo/RO_0002590"), + IRI("http://purl.obolibrary.org/obo/RO_0002328"), + IRI("http://purl.obolibrary.org/obo/RO_0002233") + ) + ), + + // biomarker_for isn't present in our triplestore, so it should return an empty set. + ConversionTest(Some(List(BiolinkPredicate("biomarker_for"))), None, Set()), + + // "increases expression of" should be mapped to http://purl.obolibrary.org/obo/RO_0003003, since this is what + // predicate_mapping.yaml tells us. + ConversionTest( + Some(List(BiolinkPredicate("affects"))), + Some( + List( + TRAPIQualifierConstraint( + qualifier_set = List( + TRAPIQualifier("biolink:object_aspect_qualifier", "activity_or_abundance"), + TRAPIQualifier("biolink:object_direction_qualifier", "decreased") + ) + ) + ) + ), + Set(IRI("http://purl.obolibrary.org/obo/RO_0002449")) + ) + ) + + suite("biolink3conversions")( + suiteM("Test whether we can map predicates to relations") { + ZStream + .fromIterable(biolink3conversions) + .map { ct: ConversionTest => + test(s"Testing ${ct.biolinkPredicates} with ${ct.trapiQualifierConstraints} to ${ct.predicates}") { + assert(PredicateMappings.mapQueryEdgePredicates(ct.biolinkPredicates, ct.trapiQualifierConstraints))( + Assertion.hasSubset(ct.predicates)) + } + } + .runCollect + }, + suiteM("Make sure we can map relations to predicates") { + + ZStream + .fromIterable(biolink3conversions) + .flatMap { ct: ConversionTest => + val biolinkPreds = ct.biolinkPredicates.toList.flatten.toSet + + ZStream + .fromIterable(ct.predicates) + .map( + { pred => + test(s"Testing ${pred} to ${ct.biolinkPredicates} with ${ct.trapiQualifierConstraints}") { + val preds = PredicateMappings.getBiolinkQualifiedPredicates(pred) + + val qualifiersActual = preds.filter(p => biolinkPreds.contains(p.biolinkPredicate)).flatMap(_.qualifierList).toSet + val qualifiersExpected = ct.trapiQualifierConstraints.getOrElse(List()).flatMap(_.qualifier_set).toSet + + assert(preds.map(_.biolinkPredicate).toSet)(Assertion.hasSubset(ct.biolinkPredicates.getOrElse(List()).toSet)) && + assert(qualifiersActual)(Assertion.equalTo(qualifiersExpected)) + } + } + ) + } + .runCollect + } + ) + } + + def generateQualifiedEdge(obj: String, + subj: String, + preds: Option[List[BiolinkPredicate]], + knowledge_type: Option[String], + qualifier_aspect: Option[String], + qualified_direction: Option[String]) = { + val qualifier_constraints: List[TRAPIQualifier] = (qualifier_aspect match { + case Some(aspect: String) => List(TRAPIQualifier(qualifier_type_id = "biolink:object_aspect_qualifier", qualifier_value = aspect)) + case _ => List() + }) ++ (qualified_direction match { + case Some(direction: String) => + List(TRAPIQualifier(qualifier_type_id = "biolink:object_direction_qualifier", qualifier_value = direction)) + case _ => List() + }) + + TRAPIQueryEdge( + `object` = obj, + subject = subj, + predicates = preds, + knowledge_type = knowledge_type, + qualifier_constraints = (qualifier_constraints match { + case Seq() => None + case list: List[TRAPIQualifier] => Some(List(TRAPIQualifierConstraint(qualifier_set = list))) + }) + ) + } + + val queries = Map( + /* Example Biolink 3 query from https://github.com/NCATSTranslator/TranslatorArchitecture/issues/79 + * using http://identifiers.org/ncbigene/2859 ("G protein-coupled receptor 35"), which produces the + * protein http://identifiers.org/uniprot/Q9HC97. + * + * We know via /lookup that we know that this protein participates in http://purl.obolibrary.org/obo/GO_0007204 + * ("positive regulation of cytosolic calcium ion concentration"), so we would expect calcium ions to appear here. + * + * We don't have NCBIGene:2859, but we do have NCBIGene:340061 ("stimulator of interferon response cGAMP interactor 1") + */ + "STING1-increases-chemical" -> TRAPIQueryGraph( + nodes = Map( + "gene" -> TRAPIQueryNode( + ids = Some(List(IRI("http://identifiers.org/ncbigene/340061"))), + categories = Some(List(BiolinkClass("Gene"))), + None, + None + ), + "chemical" -> TRAPIQueryNode(None, Some(List(BiolinkClass("ChemicalEntity"))), None, None) + ), + edges = Map( + "t_edge" -> generateQualifiedEdge( + "gene", + "chemical", + Some(List(BiolinkPredicate("affects"))), + knowledge_type = Some("inferred"), + qualifier_aspect = Some("activity_or_abundance"), + qualified_direction = Some("increased") + ) + ) + ), + + /* + * Example Biolink 3 query from https://github.com/NCATSTranslator/TranslatorArchitecture/issues/80 + * using http://identifiers.org/ncbigene/2859 ("G protein-coupled receptor 35"), which produces the + * protein http://identifiers.org/uniprot/Q9HC97. + * + * We know via /lookup that we know that this protein participates in http://purl.obolibrary.org/obo/GO_0007204 + * ("positive regulation of cytosolic calcium ion concentration"), so we would expect calcium ions to appear here. + * + * We don't have NCBIGene:2859, but we do have NCBIGene:598 ("BCL2 like 1") + */ + "BCL2L1-decreases-chemical" -> TRAPIQueryGraph( + nodes = Map( + "gene" -> TRAPIQueryNode( + ids = Some(List(IRI("http://identifiers.org/ncbigene/598"))), + categories = Some(List(BiolinkClass("Gene"))), + None, + None + ), + "chemical" -> TRAPIQueryNode(None, Some(List(BiolinkClass("ChemicalEntity"))), None, None) + ), + edges = Map( + "t_edge" -> generateQualifiedEdge( + "gene", + "chemical", + Some(List(BiolinkPredicate("affects"))), + knowledge_type = Some("inferred"), + qualifier_aspect = Some("activity_or_abundance"), + qualified_direction = Some("decreased") + ) + ) + ), + + /* + * Example Biolink 3 query from https://github.com/NCATSTranslator/TranslatorArchitecture/issues/81 + * using valproic acid (PUBCHEM.COMPOUND:88111 = CHEBI:39867). + * + * Okay, we don't seem to have this information, but we do have it for CHEBI:51143 ("nitrogen molecular entity"), + * so let's include that instead. + * + */ + "pyruvate-increases-chemical" -> TRAPIQueryGraph( + nodes = Map( + "gene" -> TRAPIQueryNode(None, Some(List(BiolinkClass("Gene"))), None, None), + "chemical" -> TRAPIQueryNode(ids = Some(List(IRI("http://purl.obolibrary.org/obo/CHEBI_51143"))), + categories = Some(List(BiolinkClass("ChemicalEntity"))), + None, + None) + ), + edges = Map( + "t_edge" -> generateQualifiedEdge( + "gene", + "chemical", + Some(List(BiolinkPredicate("affects"))), + knowledge_type = Some("inferred"), + qualifier_aspect = Some("activity_or_abundance"), + qualified_direction = Some("increased") + ) + ) + ), + + /* + * Example Biolink 3 query from https://github.com/NCATSTranslator/TranslatorArchitecture/issues/82 + * using valproic acid (PUBCHEM.COMPOUND:88111 = CHEBI:39867). + * + * (Another one we could use is pyruvate (http://purl.obolibrary.org/obo/CHEBI_15361). + * + * Okay, we don't seem to have this information, but we do have it for CHEBI:51143 ("nitrogen molecular entity"), + * so let's include that instead. + */ + "valproic-acid-decreases-chemical" -> TRAPIQueryGraph( + nodes = Map( + "gene" -> TRAPIQueryNode(None, Some(List(BiolinkClass("Gene"))), None, None), + "chemical" -> TRAPIQueryNode(ids = Some(List(IRI("http://purl.obolibrary.org/obo/CHEBI_51143"))), + categories = Some(List(BiolinkClass("ChemicalEntity"))), + None, + None) + ), + edges = Map( + "t_edge" -> generateQualifiedEdge( + "gene", + "chemical", + Some(List(BiolinkPredicate("affects"))), + knowledge_type = Some("inferred"), + qualifier_aspect = Some("activity_or_abundance"), + qualified_direction = Some("decreased") + ) + ) + ) + ) + + /** The new Biolink3 code has an error in it -- the knowledge graph edge names don't match with the result edge names. To test for that, + * we'll make sure that all the queries we make here have no knowledge graph edge results that are not also present in the results. + */ + def checkKnowledgeGraphIDs(message: TRAPIMessage): TestResult = { + val kgEdgeIds: Set[String] = message.knowledge_graph.map(_.edges.keySet).toSet.flatten + val resultEdgeIds: Set[String] = message.results.map(_.flatMap(_.edge_bindings.values.flatMap(_.map(_.id)))).toList.flatten.toSet + + assert(kgEdgeIds)(Assertion.equalTo(resultEdgeIds)) + } + + val biolink3exampleQueries = suiteM("biolink3exampleQueries") { + ZStream + .fromIterable(queries) + .map { case (testName, queryGraph) => + testM(f"Test example Biolink 3 query ${testName}") { + for { + response <- QueryService + .run(100, queryGraph) + _ = logger.info(s"Response: ${response}") + } yield ( + assert(response.status)(Assertion.isSome(Assertion.equalTo("Success"))) && + assert(response.message.results)(Assertion.isSome(Assertion.isNonEmpty)) && + checkKnowledgeGraphIDs(response.message) + ) + } + } + .runCollect + } + + val configLayer: Layer[Throwable, ZConfig[AppConfig]] = TypesafeConfig.fromDefaultLoader(AppConfig.config) + val testLayer = HttpClient.makeHttpClientLayer ++ Biolink.makeUtilitiesLayer ++ configLayer >+> SPARQLQueryExecutor.makeCache.toLayer + + def spec = suite("Biolink 3 example queries")( + biolink3conversions, + biolink3exampleQueries + ).provideCustomLayer(testLayer.mapError(TestFailure.die)) + +} diff --git a/src/test/scala/org/renci/cam/test/LimitTest.scala b/src/test/scala/org/renci/cam/test/LimitTest.scala index a24ed763..15843280 100644 --- a/src/test/scala/org/renci/cam/test/LimitTest.scala +++ b/src/test/scala/org/renci/cam/test/LimitTest.scala @@ -18,10 +18,10 @@ object LimitTest extends DefaultRunnableSpec with LazyLogging { * from 1..50 return the correct number of expected results. */ val testQueryWithExpectedResults = { - // Expected results as of 2022-may-18 for the test query - val queryGraphExpectedResults = 30 + // Expected results as of 2023-mar-17 for the test query + val queryGraphExpectedResults = 1583 // The limits to test -- this should be set up to go neatly within - val limitsToTest = Seq(1, 2, 3, 4, 5, 10, 20, 30, 40, 50) + val limitsToTest = Seq(1, 2, 3, 4, 5, 10, 20, 30, 60, 90, 150, 300, 500, 700, 1000, 1200, 1500, 1583) // The test query: pyruvate related_to $[NamedThing] val testQueryGraph = TRAPIQueryGraph( Map( diff --git a/src/test/scala/org/renci/cam/test/LookupServiceTest.scala b/src/test/scala/org/renci/cam/test/LookupServiceTest.scala index b2a1e774..61071da7 100644 --- a/src/test/scala/org/renci/cam/test/LookupServiceTest.scala +++ b/src/test/scala/org/renci/cam/test/LookupServiceTest.scala @@ -13,8 +13,10 @@ import zio.blocking.effectBlockingIO import zio.cache.Cache import zio.config.ZConfig import zio.config.typesafe.TypesafeConfig +import zio.duration.durationInt import zio.interop.catz.concurrentInstance import zio.stream.ZStream +import zio.test.environment.Live import zio.test.{assert, _} import zio.{Layer, Task, ZIO, ZLayer, ZManaged} @@ -24,6 +26,9 @@ import java.io.{File, FileWriter, PrintWriter} */ object LookupServiceTest extends DefaultRunnableSpec with LazyLogging { + /** The time limit for an individual lookup query (in testIdentifier()). */ + val LOOKUP_TIME_LIMIT = 60.second + /** Node normalization endpoint. Defaults to the production NodeNorm, but can be overriden by setting the NODE_NORM_URL environmental * variable. */ @@ -49,7 +54,7 @@ object LookupServiceTest extends DefaultRunnableSpec with LazyLogging { assert(result.subjectTriples)(Assertion.isNonEmpty) && assert(result.objectTriples)(Assertion.isNonEmpty) && assert(result.relations)(Assertion.isNonEmpty) && - assert(result.biolinkPredicates)(Assertion.isNonEmpty) + assert(result.qualifiedBiolinkPredicates)(Assertion.isNonEmpty) } } @@ -64,7 +69,7 @@ object LookupServiceTest extends DefaultRunnableSpec with LazyLogging { * @return * A ZSpec that will test the single identifier being queried. */ - def testIdentifier(id: String): ZSpec[EndpointEnv, Throwable] = + def testIdentifier(id: String): ZSpec[Live with EndpointEnv, Throwable] = testM(s"Test whether we can retrieve results for identifier ${id}") { val idFilenameSafe = id.replaceAll("\\W", "_") val outputFile = new File(s"./src/test/resources/lookup-service-test/${idFilenameSafe}.json") @@ -79,8 +84,9 @@ object LookupServiceTest extends DefaultRunnableSpec with LazyLogging { response <- server(Request(GET, uri)) content <- EntityDecoder.decodeText(response) resultOrErrorJson <- ZIO.fromEither(io.circe.parser.parse(content)) + _ = logger.debug(s"Raw JSON results for identifier ${id}: ${resultOrErrorJson.deepDropNullValues.spaces2SortKeys}") result <- ZIO.fromEither(resultOrErrorJson.as[LookupService.Result]) - _ = logger.debug(s"Results for identifier ${id}: ${result.asJson.deepDropNullValues.spaces2SortKeys}") + // _ = logger.debug(s"Results for identifier ${id}: ${result.asJson.deepDropNullValues.spaces2SortKeys}") fileWritten <- effectBlockingIO(new PrintWriter(new FileWriter(outputFile))) .bracketAuto { pw => pw.println(result.asJson.deepDropNullValues.spaces2SortKeys) @@ -95,7 +101,7 @@ object LookupServiceTest extends DefaultRunnableSpec with LazyLogging { // assert(result.relations)(Assertion.isNonEmpty) && // assert(result.biolinkPredicates)(Assertion.isNonEmpty) && assert(fileWritten)(Assertion.isTrue) - } + } @@ TestAspect.timeout(LOOKUP_TIME_LIMIT) /* Generate tests for all the identifiers in the lookupServiceIdFile. */ @@ -103,7 +109,7 @@ object LookupServiceTest extends DefaultRunnableSpec with LazyLogging { val lookupServiceIdFile = new File("./src/test/resources/lookup-service-test/ids.txt") /** A spec made up of tests for every identifier in the lookupServiceIdFile. */ - val testIdentifiersInFile: Spec[EndpointEnv, TestFailure[Throwable], TestSuccess] = + val testIdentifiersInFile: Spec[Live with EndpointEnv, TestFailure[Throwable], TestSuccess] = suiteM(s"Test identifiers in ${lookupServiceIdFile}") { ZStream .fromIteratorManaged( diff --git a/src/test/scala/org/renci/cam/test/QueryServiceTest.scala b/src/test/scala/org/renci/cam/test/QueryServiceTest.scala index d870040d..bbb71378 100644 --- a/src/test/scala/org/renci/cam/test/QueryServiceTest.scala +++ b/src/test/scala/org/renci/cam/test/QueryServiceTest.scala @@ -71,9 +71,7 @@ object QueryServiceTest extends DefaultRunnableSpec with LazyLogging { } yield assert(nodeBindings.keys)( contains("n0") && contains("n1") ) && assertTrue( - nodeBindings - .get("n0") - .get + nodeBindings("n0") .map(a => a.id) .contains(IRI("http://purl.obolibrary.org/obo/go/extensions/reacto.owl#REACTO_R-HSA-166103"))) } @@ -459,7 +457,10 @@ object QueryServiceTest extends DefaultRunnableSpec with LazyLogging { e0: TRAPIQueryEdge = TRAPIQueryEdge( subject = "n0", `object` = "n1", - predicates = Some(List(BiolinkPredicate("positively_regulates"))) + predicates = Some(List(BiolinkPredicate("regulates"))), + qualifier_constraints = Some( + List(TRAPIQualifierConstraint( + List(TRAPIQualifier("biolink:object_direction_qualifier", "downregulated"))))) )) = TRAPIQueryGraph(Map("n0" -> n0, "n1" -> n1), Map("e0" -> e0)) @@ -467,21 +468,23 @@ object QueryServiceTest extends DefaultRunnableSpec with LazyLogging { testM("Ensure that query_id is absent for nodes without ids") { for { response <- QueryService - .run(1000, createTestTRAPIQueryGraph(TRAPIQueryNode(None, Some(List(BiolinkClass("BiologicalProcessOrActivity"))), None))) + .run(100, createTestTRAPIQueryGraph(TRAPIQueryNode(None, Some(List(BiolinkClass("BiologicalProcessOrActivity"))), None))) // _ = logger.warn(s"Response: ${response}") nodeBindings = response.message.results.get.flatMap(_.node_bindings.getOrElse("n0", List())) queryIds = nodeBindings.map(_.query_id) - } yield assert(response.message.results)(Assertion.isSome(Assertion.hasSize(Assertion.equalTo(1000)))) && + } yield assert(response.message.results)(Assertion.isSome(Assertion.hasSize(Assertion.equalTo(100)))) && assert(queryIds)(Assertion.forall(Assertion.isNone)) }, testM( "Ensure that query_id is present only when the identifier is ambiguous for a process (GO:0033549, MAP kinase phosphatase activity)") { - val iriToQuery = IRI("http://purl.obolibrary.org/obo/GO_0033549") + val iriToQuery = IRI("http://purl.obolibrary.org/obo/GO_0017017") + val query = createTestTRAPIQueryGraph(TRAPIQueryNode(Some(List(iriToQuery)), None)) for { response <- QueryService - .run(1000, createTestTRAPIQueryGraph(TRAPIQueryNode(Some(List(iriToQuery)), None))) - // _ = logger.warn(s"Response: ${response}") + .run(100, query) + _ = logger.warn(s"Response query_id is present only when the identifier is ambiguous query: ${query}") + _ = logger.warn(s"Response query_id is present only when the identifier is ambiguous response: ${response}") nodeBindings = response.message.results.get.flatMap(_.node_bindings.getOrElse("n0", List())) queryIds = nodeBindings.map(_.query_id) queryIdsUnambiguous = nodeBindings.filter(_.id == iriToQuery).map(_.query_id) @@ -500,7 +503,7 @@ object QueryServiceTest extends DefaultRunnableSpec with LazyLogging { for { response <- QueryService .run( - 1000, + 100, createTestTRAPIQueryGraph( TRAPIQueryNode(Some(List(cytoplasm)), None), TRAPIQueryNode(None, categories = Some(List(BiolinkClass("BiologicalProcessOrActivity"))), None), @@ -513,6 +516,7 @@ object QueryServiceTest extends DefaultRunnableSpec with LazyLogging { ) // _ = logger.warn(s"Response: ${response}") node0Bindings = response.message.results.get.flatMap(_.node_bindings.getOrElse("n0", List())) + // _ = logger.warn(s"Node bindings for n0 in GO:0005737, cytoplasm query: ${node0Bindings}") queryIds = node0Bindings.map(_.query_id) queryIdsUnambiguous = node0Bindings.filter(_.id == cytoplasm).map(_.query_id) queryIdsAmbiguous = node0Bindings.filter(_.id != cytoplasm).map(_.query_id) @@ -526,29 +530,31 @@ object QueryServiceTest extends DefaultRunnableSpec with LazyLogging { assert(node0Bindings)(Assertion.contains(TRAPINodeBinding(id = germplasm, query_id = Some(cytoplasm)))) }, testM("Ensure that two different identifiers can be provided for the same node, to be disambiguated by query_id") { - val glucose = IRI("http://purl.obolibrary.org/obo/CHEBI_17234") + val glucose = IRI("http://purl.obolibrary.org/obo/CHEBI_17925") val rna = IRI("http://purl.obolibrary.org/obo/CHEBI_33697") + val query = createTestTRAPIQueryGraph( + TRAPIQueryNode(Some(List(glucose, rna)), None), + TRAPIQueryNode(None, categories = Some(List(BiolinkClass("BiologicalProcessOrActivity"))), None), + TRAPIQueryEdge( + subject = "n1", + `object` = "n0", + predicates = Some(List(BiolinkPredicate("has_participant"))) + ) + ) + logger.debug(f"Glucose/RNA query: ${query}") for { response <- QueryService .run( - 1000, - createTestTRAPIQueryGraph( - TRAPIQueryNode(Some(List(glucose, rna)), None), - TRAPIQueryNode(None, categories = Some(List(BiolinkClass("BiologicalProcessOrActivity"))), None), - TRAPIQueryEdge( - subject = "n1", - `object` = "n0", - predicates = Some(List(BiolinkPredicate("has_participant"))) - ) - ) + 10, + query ) // _ = logger.warn(s"Response: ${response}") node0Bindings = response.message.results.get.flatMap(_.node_bindings.getOrElse("n0", List())) queryIdsUnambiguous = node0Bindings.filter(b => b.id == glucose || b.id == rna).map(_.query_id) idsAmbiguousGlucose = node0Bindings.filter(_.query_id.contains(glucose)).map(_.id) idsAmbiguousRNA = node0Bindings.filter(_.query_id.contains(rna)).map(_.id) - } yield assert(response.message.results)(Assertion.isSome(Assertion.hasSize(Assertion.isGreaterThanEqualTo(50)))) && + } yield assert(response.message.results)(Assertion.isSome(Assertion.hasSize(Assertion.isGreaterThanEqualTo(10)))) && // All unambiguous IDs -- glucose and RNA -- should have empty query_ids. assert(queryIdsUnambiguous)(Assertion.isNonEmpty) && assert(queryIdsUnambiguous)(Assertion.forall(Assertion.isNone)) && diff --git a/src/test/scala/org/renci/cam/test/TRAPITest.scala b/src/test/scala/org/renci/cam/test/TRAPITest.scala index 2217daa8..6a195b11 100644 --- a/src/test/scala/org/renci/cam/test/TRAPITest.scala +++ b/src/test/scala/org/renci/cam/test/TRAPITest.scala @@ -11,7 +11,7 @@ import org.renci.cam.Biolink.biolinkData import org.renci.cam.HttpClient.HttpClient import org.renci.cam.Server.EndpointEnv import org.renci.cam._ -import org.renci.cam.domain.{BiolinkClass, BiolinkPredicate, IRI, LogEntry, TRAPIAttribute, TRAPIResponse} +import org.renci.cam.domain.{LogEntry, TRAPIAttribute, TRAPIResponse} import zio.cache.Cache import zio.config.ZConfig import zio.config.typesafe.TypesafeConfig @@ -121,7 +121,7 @@ object TRAPITest extends DefaultRunnableSpec with LazyLogging { "qualifier_value": "abundance" }, { "qualifier_type_id": "biolink:subject_direction_qualifier", - "qualifier_value": "decreased" + "qualifier_value": "exactly-the-same" }] }] } @@ -157,13 +157,19 @@ object TRAPITest extends DefaultRunnableSpec with LazyLogging { logs = trapiResponse.logs logWarningOfQualifierConstraints = logs.getOrElse(List()).filter { // We've made this up ourselves. - case LogEntry(_, Some("WARNING"), Some("UnsupportedQualifierConstraint"), _) => true - case _ => false + case LogEntry( + _, + Some("ERROR"), + Some("UnsupportedEdge"), + Some( + "Edge e0 could not be mapped to a predicate, and so cannot be matched: TRAPIQueryEdge(Some(List(BiolinkPredicate(part_of,IRI(https://w3id.org/biolink/vocab/part_of)))),n0,n1,None,None,Some(List(TRAPIQualifierConstraint(List(TRAPIQualifier(biolink:subject_aspect_qualifier,abundance), TRAPIQualifier(biolink:subject_direction_qualifier,exactly-the-same))))))")) => + true + case _ => false } } yield assert(response.status)(Assertion.hasField("isSuccess", _.isSuccess, Assertion.isTrue)) && assert(content)(Assertion.isNonEmptyString) && - // Should return an overall status of Success - assert(trapiResponse.status)(Assertion.isSome(Assertion.equalTo("Success"))) && + // Should return an overall status of Error (because an edge couldn't be interpreted) + assert(trapiResponse.status)(Assertion.isSome(Assertion.equalTo("ERROR"))) && // ... and in the logs assert(logs)(Assertion.isSome(Assertion.isNonEmpty)) && assert(logWarningOfQualifierConstraints)(Assertion.isNonEmpty) &&