<<sparql-settings>>
<<cypher-settings>>
SELECT DISTINCT
?p
# ?pp
# ?po
WHERE {
?dataset a sparc:Dataset .
?dataset ?p ?o .
# ?p ?pp ?po .
} ORDER BY ?p
SELECT DISTINCT
?d
?label
?approach
WHERE {
VALUES ?match { "electrophysiology" }
?d a sparc:Dataset ;
rdfs:label ?l ;
TEMP:hasExperimentalApproach ?approach .
FILTER (str(?approach) = str(?match))
BIND(substr(str(?l), 0, 40) AS ?label)
# TODO lift and pull filetypes
}
SELECT DISTINCT
?dataset
?ut
(substr(str(?l), 0, 40) as ?label)
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:contentsWereUpdatedAtTime ?ut .
?dataset rdfs:label ?l .
} ORDER BY DESC(?ut)
import rdflib
from pyontutils.core import OntResIri
from pyontutils.namespaces import sparc, TEMP, dc, rdfs
ori = OntResIri('https://cassava.ucsd.edu/sparc/preview/exports/curation-export.ttl')
g = ori.graph
gns = g.namespace_manager
def fmt(s, u):
return f'[[{u}][{s.n3(gns)}]]'
species = set([fmt(do, urih) for s, p, o in g
if isinstance(o, rdflib.Literal) and
('human' in o.lower() or 'homo' in o.lower()) and
p == sparc.animalSubjectIsOfSpecies
for do in g[s:TEMP.hasDerivedInformationAsParticipant]
for urih in g[do:TEMP.hasUriHuman]])
hlabel = set([fmt(s, urih) for s, p, o in g
if isinstance(o, rdflib.Literal) and
('human' in o.lower() or 'homo' in o.lower()) and
p == rdfs.label
for urih in g[s:TEMP.hasUriHuman]])
htitle = set([fmt(s, urih) for s, p, o in g
if isinstance(o, rdflib.Literal) and
('human' in o.lower() or 'homo' in o.lower()) and
p == dc.title
for urih in g[s:TEMP.hasUriHuman]])
htd = set([fmt(s, urih) for s, p, o in g
if isinstance(o, rdflib.Literal) and
('human' in o.lower() or 'homo' in o.lower()) and
(p == dc.title or p == dc.description)
for urih in g[s:TEMP.hasUriHuman]])
counts = dict(species=len(human),
label=len(hlabel),
title=len(htitle),
title_and_desc=len(htd))
[print(_ + r' \\') for _ in ['species n= ' + str(counts['species'])] +
sorted(species) +
['label n= ' + str(counts['label'])] +
sorted(hlabel) +
['title n= ' + str(counts['title'])] +
sorted(htitle) +
['td n= ' + str(counts['title_and_desc'])] +
sorted(htd)]
Originally from sparcur.reports.SparqlQueries
.
SELECT DISTINCT
?dataset
?about
WHERE {
?type rdfs:subClassOf* sparc:Resource .
?dataset rdf:type ?type .
?dataset isAbout: ?about .
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?subj
WHERE {
?startsubj a sparc:Subject .
?startsubj TEMP:hasDerivedInformationAsParticipant ?dataset .
?subj a sparc:Subject .
?subj TEMP:hasDerivedInformationAsParticipant ?dataset .
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?group
?subj
WHERE {
?startsubj TEMP:hasDerivedInformationAsParticipant ?dataset .
?subj TEMP:hasDerivedInformationAsParticipant ?dataset .
?subj TEMP:hasAssignedGroup ?group .
} LIMIT ?limit
SELECT DISTINCT
?dataset
WHERE {
?startdataset TEMP:collectionTitle ?string .
?dataset TEMP:collectionTitle ?string .
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?species
WHERE {
?dataset TEMP:isAboutParticipant ?subject .
?subject sparc:animalSubjectIsOfSpecies ?species .
FILTER ( CONTAINS(str(?species), "human")
|| CONTAINS(str(?species), "homo sapiens")
|| ?species = NCBITaxon:9606 )
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?subject
?subject_meta
?sample
?sample_meta
?species
WHERE {
?dataset TEMP:isAboutParticipant ?subject .
?subject sparc:animalSubjectIsOfSpecies ?species .
?subject ?sup ?subject_meta .
FILTER ( CONTAINS(str(?species), "human") || CONTAINS(str(?species), "homo sapiens") || ?species = NCBITaxon:9606 )
?sample TEMP:wasDerivedFromSubject ?subject .
?sample ?sap ?sample_meta .
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?date
WHERE {
?dataset TEMP:milestoneCompletionDate ?date .
}
ORDER BY ASC(?date)
LIMIT ?limit
Can we see the multi-institutional nature of SPARC collaborations?
SELECT DISTINCT
?award
?affiliation
(str(?affil_l) as ?al)
WHERE {
?dataset TEMP:hasAwardNumber ?award .
?contributor TEMP:contributorTo ?dataset .
?contributor TEMP:hasAffiliation ?affiliation .
?affiliation rdfs:label ?affil_l .
# FILTER isUri(?affiliation)
}
ORDER BY ASC(?award) ASC(?al)
LIMIT ?limit
select distinct
?published_uri
?isDescBy
#?dataset
#?connectivity
where {
?dataset a sparc:Dataset .
?dataset TEMP:hasExperimentalApproach ?connectivity .
?dataset TEMP:hasUriPublished ?published_uri .
filter contains(str(?connectivity), "connectivity")
optional { ?dataset TEMP:isDescribedBy ?isDescBy }
} order by ?published_id
How to interpret this report.
The rows are ordered by
- whether there is a dataset directly associated with the protocol id
- whether the protocol has a human readable uri.
- by the number of protcur annotations that have been made on the protocol
If there are zero protcur annotations it usually means that only the minimal protocol curation workflow was completed. If there the number of protocol annotations is null it means that no annotations of any kind have been made on that protocol. This can only happen for protocols that come from the dataset description file.
If the dataset is null and there are annotations it usually means that the protocol is transitively related to a dataset. There are annotations on the protocols that link them directly to the dataset in question but we are not currently pulling them into the knowledge graph. It also means that the protocol url in question was not listed in the dataset description file but may have been listed in another protocol or in a collection of protocols.
If hasUri
is false and dataset is not null then it usually means that the protocol has been
deleted or that something else has gone wrong. If dataset is null and hasUri
is null it just means
that the protocol is present only in protcur.ttl
and the additional identifiers have not been
processed.
select distinct
?protocol
?n
(sample(?dataset) AS ?datasetx)
?doi_protocol
(sample(bound(?urih_protocol)) as ?hasUri)
(sample(bound(?some_child)) as ?hasComplexAnnos)
where {
?protocol a sparc:Protocol .
optional { ?protocol TEMP:hasNumberOfProtcurAnnotations ?n }
optional {
#?dataset TEMP:hasProtocol ?protocol
{ ?protocol TEMP:priorInformationalConstraintOnProcessThatGenerated ?dataset } union { ?dataset TEMP:hasProtocol ?protocol }
}
optional { ?protocol TEMP:hasDoi ?doi_protocol }
optional { ?protocol TEMP:hasUriHuman ?urih_protocol }
optional { ?protocol ?some_predicate ?annotation .
?annotation TEMP:protcurChildren ?some_child }
}
group by ?protocol ?n ?doi_protocol ?hasUri
order by desc(bound(?datasetx)) asc(?hasUri) desc(?n)
XXX FIXME producing complete nonsense right now
SELECT
(COUNT(DISTINCT ?protocol) AS ?count)
#DISTINCT ?protocol
WHERE { ?protocol a sparc:Protocol . }
#order by str(?protocol)
SELECT (COUNT(*) as ?count) {
<<sparql-protocols-at-least-one-protc>>
}}
SELECT (COUNT(*) as ?count) {
<<sparql-protocols-pio-api-at-least-one-protc>>
}
<<sparql-protocols-at-least-one-protc>>
FILTER CONTAINS(str(?protocol), "protocols.io/api")
#FILTER CONTAINS(str(?protocol), "protocols.io")
}
grep -oE 'TEMP:protocol[^\ ]+' protcur.ttl | sort -u
select distinct
?protocol ?anno_count
where {
values ?some_predicate {
TEMP:protocolEmploysTechnique
TEMP:protocolInvolvesAction
TEMP:protocolInvolvesAspect
TEMP:protocolInvolvesBlackBox
TEMP:protocolInvolvesParameter
TEMP:protocolInvolvesInvariant
# these two are noisy because they also include tags converted from sparc:
TEMP:protocolInvolvesBlackBoxComponent
TEMP:protocolInvolvesInput
}
?protocol a sparc:Protocol ;
?some_predicate ?annotation ; # this line an the filter should wind up with the same number TODO add a test to check
TEMP:hasNumberOfProtcurAnnotations ?anno_count .
FILTER (?anno_count > 0 )
SELECT (COUNT(*) as ?count) {
<<sparql-complex-protocols>>
}}
SELECT (COUNT(*) as ?count) {
<<sparql-complex-protocols-published>>
}
<<sparql-complex-protocols>>
?protocol TEMP:hasDoi ?doi .
}
select distinct
?protocol ?anno_count
where {
?annotation TEMP:protcurChildren ?some_child .
?protocol a sparc:Protocol ;
?some_predicate ?annotation ;
TEMP:hasNumberOfProtcurAnnotations ?anno_count .
WHERE {
?startsubj TEMP:hasDerivedInformationAsParticipant ?dataset .
?subj TEMP:hasDerivedInformationAsParticipant ?dataset .
?subj TEMP:hasAssignedGroup ?group .
}
SELECT DISTINCT
?dataset
?group
?subj
<<experimental-groups-core>>
ORDER BY ASC(?dataset) ASC(?group) LIMIT ?limit
SELECT DISTINCT
?group
?subj
<<experimental-groups-core>>
ORDER BY ASC(?group) LIMIT ?limit
SELECT DISTINCT
?dataset
?technique
# ?protocol
# ?technique_p
WHERE {
{ ?dataset a sparc:Dataset .
?dataset TEMP:protocolEmploysTechnique ?technique .
# ?technique rdfs:label ?tl
}
UNION
{ #?dataset TEMP:hasProtocol ?protocol .
{ ?protocol TEMP:priorInformationalConstraintOnProcessThatGenerated ?dataset } union { ?dataset TEMP:hasProtocol ?protocol }
?protocol TEMP:protocolEmploysTechnique ?technique .
# ?technique rdfs:label ?tl
}
}
LIMIT ?limit
Originally from sparcur.reports.SparqlQueries
.
SELECT DISTINCT
?protocol
?technique
WHERE {
?protocol rdf:type sparc:Protocol .
?protocol TEMP:protocolEmploysTechnique ?technique .
}
LIMIT ?limit
SELECT DISTINCT
?protocol
?aspect
WHERE {
?protocol rdf:type sparc:Protocol .
?protocol TEMP:protocolInvolvesAspect ?ast .
?ast rdf:type protcur:aspect .
?ast TEMP:hasValue ?aspect .
}
LIMIT ?limit
SELECT DISTINCT
?protocol
?ast_in
?input
WHERE {
?protocol rdf:type sparc:Protocol .
?protocol TEMP:protocolInvolvesInput ?ast_in .
?ast_in rdf:type protcur:input .
?ast_in TEMP:hasValue ?input .
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?protocol
(str(?label_drug) as ?l_drug)
?value_lt
WHERE {
VALUES ?t {protcur:invariant protcur:parameter} .
?ast_inv a ?t .
?ast_inv TEMP:hasValue ?bnode .
?bnode rdf:value ?value_lt .
#?bnode TEMP:hasUnit unit:milligram%20%2F%20kilogram . # seems like the %20 etc. break curies?
?bnode TEMP:hasUnit <http://uri.interlex.org/tgbugs/uris/readable/aspect/unit/milligram%20%2F%20kilogram> .
FILTER (?value_lt < ?limit)
?ast_drug a protcur:input .
?ast_drug TEMP:hasValue ?drug .
?drug rdfs:label ?label_drug .
?ast_drug TEMP:protcurChildren+ ?ast_child .
?ast_child TEMP:hasValue ?bnode .
?protocol a sparc:Protocol .
?protocol TEMP:protocolInvolvesInput ?ast_drug .
?protocol TEMP:protocolInvolvesInput ?ast_in_sp .
?ast_in_sp rdf:type protcur:input .
?ast_in_sp TEMP:hasValue ?species .
OPTIONAL {
# ?dataset TEMP:hasProtocol ?protocol
{ ?protocol TEMP:priorInformationalConstraintOnProcessThatGenerated ?dataset } union { ?dataset TEMP:hasProtocol ?protocol }
}
}
ORDER BY ?label_input ?value_lt
select distinct
?pro
?ana
?l
?u
?v
where {
?pro TEMP:protocolInvolvesInput ?anno .
?anno TEMP:hasValue ?ana .
?anno TEMP:protcurChildren ?ad .
?ad TEMP:hasValue ?asp .
?ad TEMP:protcurChildren ?ai .
?ai TEMP:hasValue ?bn .
?bn TEMP:hasUnit ?u .
?bn rdf:value ?v .
?ana rdfs:label ?l .
?ana ?p ?b .
?b owl:onProperty RO:0000087 .
?b owl:someValuesFrom ?o .
?o rdfs:subClassOf* ?role .
values ?asp {asp:dose asp:percent-volume} .
values ?role {CHEBI:38867 CHEBI:35480} .
} order by ?l
select distinct
?val_asp
(count(?val_asp) as ?ac)
where {
?ast_asp a protcur:aspect ;
TEMP:hasValue ?val_asp .
} GROUP BY ?val_asp ORDER BY desc(?ac)
select distinct
?val_inp
?lbl_inp
(count(?val_inp) as ?ic)
where {
?ast_inp a protcur:input ;
TEMP:hasValue ?val_inp .
OPTIONAL { ?val_inp rdfs:label ?lbl_inp }
} GROUP BY ?val_inp ?lbl_inp ORDER BY desc(?ic) asc(str(?val_inp))
few have additional parameterize
select distinct
?ast_in
where {
?ast_in TEMP:hasValue sparc:Sample ;
TEMP:protcurChildren ?ast_n .
}
select distinct
?ast_in
?next_type
?next_value
?nv_value
?nv_unit
?nv_rv
?nn_type
?nn_value
?nnn_value
?nnn_unit
?nnn_rv
where {
?ast_in TEMP:hasValue sparc:Sample ;
TEMP:protcurChildren ?ast_n .
?ast_n a ?next_type ;
TEMPRAW:hasValue ?nv_rv ;
TEMP:hasValue ?next_value .
optional {
?next_value rdf:value ?nv_value .
?next_value TEMP:hasUnit ?nv_unit .
}
optional {
?ast_n TEMP:protcurChildren+ ?ast_nn .
?ast_nn a ?nn_type ;
TEMPRAW:hasValue ?nnn_rv ;
TEMP:hasValue ?nn_value .
optional {
?nn_value rdf:value ?nnn_value .
?nn_value TEMP:hasUnit ?nnn_unit .
#?nn_value TEMPRAW:hasValue ?nnn_rv .
#?nn_value rdf:value ?nnn_value ;
#ilxtr:hasUnit ?nnn_unit .
#?ast_nn TEMP:protcurChildren+ ?ast_nnn .
#?ast_nnn a ?nnn_type ;
#TEMP:hasValue ?nnn_value .
}
}
} LIMIT ?limit
the inputs that have dilation aspects associated are not normalized really need RRIDs for this part of the graph
select distinct
#?val_inp
?rv_inp
#(count(distinct ?rv_inp) as ?crv)
where {
?ast_inp
TEMPRAW:hasValue ?rv_inp ;
# TEMP:hasValue ?val_inp ;
TEMP:protcurChildren ?ast_asp .
?ast_asp TEMP:hasValue asp:dilution .
} order by asc(str(?rv_inp))
select distinct
#?val_inp
?rv_inp
#(count(distinct ?rv_inp) as ?crv)
?ast_value
?unit
?value
?rbunit
?rbvalue
?reunit
?revalue
#?p
#?o
where {
?ast_inp
TEMPRAW:hasValue ?rv_inp ;
# TEMP:hasValue ?val_inp ;
TEMP:protcurChildren ?ast_asp .
?ast_asp TEMP:hasValue asp:age ; TEMP:protcurChildren ?ast_invpar .
?ast_invpar TEMP:hasValue ?ast_value .
?ast_value ?p ?o .
optional {
?ast_value TEMP:rangeStart ?rb . ?rb rdf:value ?rbvalue ; TEMP:hasUnit ?rbunit .
?ast_value TEMP:rangeStop ?re . ?re rdf:value ?revalue ; TEMP:hasUnit ?reunit .
}
optional {
?ast_value rdf:value ?value .
?ast_value TEMP:hasUnit ?unit .
}
} order by asc(str(?rv_inp))
select distinct
#?protocol
?tech
(count(?tech) as ?ct)
where {
?protocol a sparc:Protocol ;
TEMP:protocolEmploysTechnique ?tech .
} group by ?tech order by desc(?ct)
here is the actual list of techniques that we have, however it definitely needs a further normalization pass than what we have here, very close to exverbs in terms of how it has been used as a catchall, and also because the annotations were targeting text with the expectation that we would normalize later and haven’t
select distinct
?trs
(count(?trs) as ?ct)
where {
?protocol a sparc:Protocol ;
TEMPRAW:protocolEmploysTechnique ?tech_raw .
bind (lcase(str(?tech_raw)) as ?trs)
} group by ?trs order by desc(?ct)
as technique
select distinct
?protocol
#?trs
#(count(?trs) as ?ct)
where {
?protocol a sparc:Protocol ;
TEMPRAW:protocolEmploysTechnique ?tech_raw .
bind (lcase(str(?tech_raw)) as ?trs)
filter regex(?trs, "microsc")
}
#group by ?trs
order by desc(?ct)
datasets with protocols missing microscopy where there is no protocol associated with that dataset that does include microscopy
select distinct
?dataset
?protocol
?na
where
{
filter (bound(?protocol))
filter (!bound(?somepred))
{
<<sparql-microscopy-check>>
}
MINUS { # to get minus to work it needs to share a variable with the core query
?dataset a sparc:Dataset ;
TEMP:hasExperimentalApproach ?approach .
{ ?protocol2 TEMP:priorInformationalConstraintOnProcessThatGenerated ?dataset } union { ?dataset TEMP:hasProtocol ?protocol2 }
?protocol2 TEMP:hasNumberOfProtcurAnnotations ?na2 .
filter (?na2 > 0)
?protocol2 a sparc:Protocol ;
?somepred2 ?somestr2 .
bind (lcase(str(?somestr2)) as ?lcs2)
filter (?somepred2 != <https://uilx.org/tgbugs/u/sparc/spn/approach>)
filter regex(?lcs2, "microsc")
}
}
order by desc(?na)
clearly we have an issue the number of datasets with protocols that do not have anything about microscopy … isn’t quit what this does, but it close
select distinct
?dataset
?protocol
?na
?somepred
?lcs
where {
?dataset a sparc:Dataset ;
TEMP:hasExperimentalApproach ?approach .
filter (str(?approach) = "microscopy")
optional {
{ ?protocol TEMP:priorInformationalConstraintOnProcessThatGenerated ?dataset } union { ?dataset TEMP:hasProtocol ?protocol }
?protocol TEMP:hasNumberOfProtcurAnnotations ?na . # must be in protcur.ttl basically
filter (?na > 0 )
optional {
?protocol a sparc:Protocol ;
?somepred ?somestr .
bind (lcase(str(?somestr)) as ?lcs)
filter (?somepred != <https://uilx.org/tgbugs/u/sparc/spn/approach>)
filter regex(?lcs, "microsc")
}
}
} order by ?dataset ?protocol ?somepred ?lcs
# TODO order datasets based on how many rows they have in this table?
select distinct
?species
(count(distinct ?ast_in_sp) as ?cs)
where {
?protocol a sparc:Protocol ; ?sigh ?ast_asp ; TEMP:protocolInvolvesInput ?ast_in_sp .
?ast_in_sp rdf:type protcur:input ; TEMP:hasValue ?species .
#filter contains(str(iri(?species)), "NCBITaxon")
?species rdfs:subClassOf* NCBITaxon:1 .
} group by ?species
another not-so-great attempt
select distinct
?s0
?s1
where {
?region (rdfs:subClassOf|owl:someValuesFrom)+ UBERON:0000010 .
?s0 rdfs:subClassOf ?bn0 .
?bn0 a owl:Restriction ;
owl:onProperty partOf: ;
owl:someValuesFrom ?region_p0 .
filter (?region = ?s0)
filter (?region = ?region_p0)
#?s1 rdfs:subClassOf ?bn1 .
#?bn1 a owl:Restriction ;
# owl:onProperty partOf: ;
# owl:someValuesFrom ?region_p1 .
#?s2 rdfs:subClassOf ?bn2 .
#?bn2 a owl:Restriction ;
# owl:onProperty partOf: ;
# owl:someValuesFrom ?region_p2 .
#
#?s3 rdfs:subClassOf ?bn3 .
#?bn3 a owl:Restriction ;
# owl:onProperty partOf: ;
# owl:someValuesFrom ?region_p3 .
#
#?s4 rdfs:subClassOf ?bn4 .
#?bn4 a owl:Restriction ;
# owl:onProperty partOf: ;
# owl:someValuesFrom ?region_p4 .
#values ?region_pn { UBERON:0000010 } .
#filter (?s0 = ?region_pn)
#?s rdfs:subClassOf ?bn0; owl:someValuesFrom UBERON:0000010 .
#?bn1 owl:someValuesFrom
} limit 10
one approach to the part of query which doesn’t filter properly :/
select distinct
?region
(str(?rl) as ?label)
where {
?region rdfs:subClassOf+ UBERON:0001062 ; # with this it is 67 secons ???
(rdfs:subClassOf|owl:someValuesFrom)+ UBERON:0000010 ; # 41 - 45 seconds :/
rdfs:label ?rl ;
rdfs:subClassOf ?rest .
?rest a owl:Restriction ; owl:onProperty partOf: ; owl:someValuesFrom ?region2 .
# ?region rdfs:subClassOf ?rest ; rdfs:label ?rl .
# ?rest a owl:Restriction ; owl:onProperty partOf: ; owl:someValuesFrom ?region2 .
#
# ?region2 rdfs:subClassOf+ UBERON:0001062 .
# ?region2 (rdfs:subClassOf|owl:someValuesFrom)+ UBERON:0000010 .
#?region2 UBERON:0000010 .
#?region2 (rdfs:subClassOf|owl:someValuesFrom)* UBERON:0000010 .
#{ }
} limit 100
this one can be a little bit different
show me the species and objective magnification for datasets with protocols that involve magnification and that involve part of the peripheral nervous system the nodose ganglion nerves or ganglia
as written this query is annoyingly slow the original partOf:
based query was extremely slow
SELECT DISTINCT
?dataset
?protocol
?id_species
?species
?id_region
?region
?value
?unit
WHERE {
?protocol a sparc:Protocol ;
TEMP:protocolInvolvesAspect ?ast_asp ;
TEMP:protocolInvolvesInput ?ast_species ;
?_ ?ast_region .
?ast_asp a protcur:aspect ;
TEMP:hasValue asp:magnification ;
TEMP:protcurChildren [ TEMP:hasValue [ rdf:value ?value ;
TEMP:hasUnit ?unit ] ] .
?ast_species rdf:type protcur:input ;
TEMP:hasValue ?id_species .
?id_species rdfs:subClassOf+ NCBITaxon:33208 ; # metazoa
rdfs:label ?sl .
BIND (str(?sl) AS ?species)
?ast_region TEMP:protcurChildren* ?ast_reg ;
TEMP:hasValue ?id_region .
?id_region rdfs:subClassOf+ ?nerves_and_ganglia ;
rdfs:label ?rl .
BIND (str(?rl) AS ?region)
VALUES ?nerves_and_ganglia {
UBERON:0000122 # neuron projection bundle
UBERON:0000045 # ganglion
}
OPTIONAL {
{ ?dataset TEMP:hasProtocol ?protocol } UNION
{ ?protocol
TEMP:priorInformationalConstraintOnProcessThatGenerated
?dataset }}
}
ORDER BY ?region ?dataset ?protocol
dataset | protocol | id_species | species | id_region | region | value | unit |
---|---|---|---|---|---|---|---|
dataset:d484110a-e6e3-4574-aab2-418703c978e2 | pio.api:22831 | NCBITaxon:10116 | Rattus norvegicus | UBERON:0005363 | inferior vagus X ganglion | 40 | unit:fold |
dataset:d484110a-e6e3-4574-aab2-418703c978e2 | pio.api:22831 | NCBITaxon:10116 | Rattus norvegicus | UBERON:0005363 | inferior vagus X ganglion | 63 | unit:fold |
dataset:e4bfb720-a367-42ab-92dd-31fd7eefb82e | pio.api:22831 | NCBITaxon:10116 | Rattus norvegicus | UBERON:0005363 | inferior vagus X ganglion | 40 | unit:fold |
dataset:e4bfb720-a367-42ab-92dd-31fd7eefb82e | pio.api:22831 | NCBITaxon:10116 | Rattus norvegicus | UBERON:0005363 | inferior vagus X ganglion | 63 | unit:fold |
dataset:6fa2666c-aa3d-4e27-a405-7848fc061b04 | pio.api:19131 | NCBITaxon:10116 | Rattus norvegicus | UBERON:0001759 | vagus nerve | 20 | unit:fold |
dataset:ff6eb067-62d4-4bfb-b4b2-15ad65db0999 | pio.api:19143 | NCBITaxon:10090 | Mus musculus | UBERON:0001759 | vagus nerve | 20 | unit:fold |
blood pressure might work maybe?
select distinct
?protocol
#?val_inp
?ast_asp
?in_type
?rv_inp
#(count(distinct ?rv_inp) as ?crv)
?c_type
?raw_invpar
?ast_val_invpar
where {
?protocol TEMP:protocolInvolvesAspect ?ast_asp .
?ast_asp TEMP:hasValue asp:pressure .
optional {
?ast_inp a ?in_type ;
TEMPRAW:hasValue ?rv_inp ;
# TEMP:hasValue ?val_inp ;
TEMP:protcurChildren ?ast_asp .
}
optional {
?ast_asp TEMP:protcurChildren ?c . ?c a ?c_type .
}
values ?invpar {protcur:invariant protcur:parameter} .
optional {
?ast_asp TEMP:protcurChildren ?ast_invpar .
?ast_invpar a ?invpar ;
TEMPRAW:hasValue ?raw_invpar ;
TEMP:hasValue ?ast_val_invpar .
}
} order by ?protocol asc(str(?rv_inp))
pio.html:18655 deleted ??? pio.html:18786 also del ??? pio.html:22863
SELECT DISTINCT
?dataset
?completeness
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:completenessOfDataset ?completeness .
}
LIMIT ?limit
SELECT DISTINCT
?title
?dataset
WHERE {
?startdataset TEMP:collectionTitle ?title .
?dataset TEMP:collectionTitle ?title .
}
ORDER BY ASC(?title)
LIMIT ?limit
Show me all of the experimental subjects that a dataset contains information about.
SELECT DISTINCT
?dataset
?subject
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:isAboutParticipant ?subject .
?subject a sparc:Subject .
}
LIMIT ?limit
Show me the total number of subjects in the knowledge graph.
SELECT DISTINCT
(COUNT(DISTINCT ?subject) as ?count_subject)
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:isAboutParticipant ?subject .
?subject a sparc:Subject .
}
Show me a regularized set of metadata for all subjects that includes the following.
- Identifier
- Group
- Species
- Strain
- Sex
- Age Category
- Age
- Mass
SELECT DISTINCT
?local_id
?assigned_group
?l_species
?strain
?l_sex
?age_category
?age_value
?age_unit
?mass_value
?mass_unit
WHERE {
?subject a sparc:Subject .
?subject TEMP:localId ?local_id .
?subject sparc:animalSubjectIsOfSpecies ?species . OPTIONAL { ?species rdfs:label ?l_species . }
OPTIONAL { ?subject sparc:animalSubjectIsOfStrain ?strain . } # ?strain rdfs:label ?l_strain .
OPTIONAL { ?subject TEMP:hasBiologicalSex ?sex . ?sex rdfs:label ?l_sex . }
OPTIONAL { ?subject TEMP:hasAgeCategory ?age_category . }
OPTIONAL { ?subject TEMP:hasAssignedGroup ?assigned_group . }
# OPTIONAL { ?subject TEMP:participantInPerformanceOf ?protocol . }
OPTIONAL {
# mass
?subject sparc:animalSubjectHasWeight ?bn_mass .
?bn_mass a sparc:Measurement .
?bn_mass TEMP:hasUnit ?mass_unit .
?bn_mass rdf:value ?mass_value .
}
OPTIONAL {
# age
?subject TEMP:hasAge ?bn_age .
?bn_age a sparc:Measurement .
?bn_age TEMP:hasUnit ?age_unit .
?bn_age rdf:value ?age_value .
}
# VALUES ?l_s {?species ?sex} # doesn't work, if it did it would duplicate rows
# ?l_s rdfs:label ?label
} LIMIT ?limit
SELECT DISTINCT
(COUNT(DISTINCT ?subject) as ?count_subject)
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:isAboutParticipant ?subject .
?subject a sparc:Subject .
}
Show me all of the experimental samples that a dataset contains information about.
SELECT DISTINCT
?dataset
?sample
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:isAboutParticipant ?sample .
?sample a sparc:Sample .
}
LIMIT ?limit
Show me the total number of samples in the knowledge graph.
SELECT DISTINCT
(COUNT(DISTINCT ?sample) as ?count_sample)
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:isAboutParticipant ?sample .
?sample a sparc:Sample .
}
SELECT DISTINCT
?p
WHERE {
?sample a sparc:Sample .
?sample ?p ?o .
}
Show me a regularized set of metadata for all subjects that includes the following.
- Identifier
- Group
- Anatomical entity
SELECT DISTINCT
?subject_lid
?local_id
?assigned_group
(str(?anat_ent_src) as ?aess)
WHERE {
?sample a sparc:Sample .
?sample TEMP:localId ?local_id .
?sample TEMP:wasDerivedFromSubject ?subject .
?subject TEMP:localId ?subject_lid .
?subject a sparc:Subject .
OPTIONAL { ?sample TEMP:hasAssignedGroup ?assigned_group . }
OPTIONAL { ?sample TEMPRAW:wasExtractedFromAnatomicalRegion ?anat_ent_src . }
# OPTIONAL { ?sample TEMP:hasAge ?abe . }
# OPTIONAL { ?sample TEMP:participantInPerformanceOf ?protocol . }
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?protocol
#?ae
(str(?aes) as ?entity)
WHERE {
?dataset a sparc:Dataset .
#?dataset TEMP:hasProtocol ?protocol .
{ ?protocol TEMP:priorInformationalConstraintOnProcessThatGenerated ?dataset } union { ?dataset TEMP:hasProtocol ?protocol }
?protocol TEMPRAW:involvesAnatomicalRegion ?aes .
# ?ae rdfs:label ?l_ae .
}
ORDER BY ASC(?entity)
LIMIT ?limit
SELECT DISTINCT
?dataset
# ?ae
(str(?l_ae) as ?entity)
WHERE {
?dataset a sparc:Dataset .
?dataset isAbout: ?ae . # TODO not 100% on the modelling here
?ae rdfs:label ?l_ae .
?ae rdfs:subClassOf* UBERON:0001062 . # have to load uberon for this
}
ORDER BY ASC(?l_ae)
LIMIT ?limit
SELECT DISTINCT
?dataset
(str(?ae) as ?aes)
# ?slid
WHERE {
?sample TEMP:hasDerivedInformationAsParticipant ?dataset .
?sample TEMPRAW:wasExtractedFromAnatomicalRegion ?ae .
?sample a sparc:Sample .
# ?sample TEMP:localId ?slid .
?dataset a sparc:Dataset .
}
ORDER BY
DESC(?ae)
# ASC(?slid)
LIMIT ?limit
SELECT (COUNT(*) as ?count) {
<<sparql-protocols-pio-api>>
}
SELECT DISTINCT
?protocol
WHERE {
?protocol a sparc:Protocol .
FILTER CONTAINS(str(?protocol), "protocols.io/api")
#FILTER CONTAINS(str(?protocol), "protocols.io")
}
SELECT DISTINCT
?protocol
?p
?o
WHERE {
?protocol a sparc:Protocol .
?protocol ?p ?o
FILTER CONTAINS(str(?protocol), "protocols.io")
} LIMIT ?limit
NOTE In order for these to work with subClassOf UBERON
uberon must be loaded.
SELECT DISTINCT
?protocol
?bb_value
(str(?l_bb) as ?ls)
WHERE {
?protocol a sparc:Protocol .
?protocol TEMP:protocolInvolvesBlackBox ?ast_bb .
?ast_bb rdf:type protcur:black-box . # TODO need to refine on organ an ingest the new alignment
?ast_bb TEMP:hasValue ?bb_value .
?bb_value rdfs:subClassOf+ UBERON:0001062 .
?bb_value rdfs:label ?l_bb .
} LIMIT ?limit
SELECT DISTINCT
?protocol
?bbc_value
(str(?l_bbc) as ?bbl)
WHERE {
?protocol a sparc:Protocol .
?protocol TEMP:protocolInvolvesBlackBoxComponent ?ast_bbc .
?ast_bbc rdf:type protcur:black-box-component . # TODO need to refine on organ an ingest the new alignment
?ast_bbc TEMP:hasValue ?bbc_value .
?bbc_value rdfs:subClassOf+ UBERON:0001062 .
?bbc_value rdfs:label ?l_bbc .
} ORDER BY ?bbl LIMIT ?limit
grep -oE 'a\ protcur:[^\ ]+' protcur.ttl | sort -u | cut -d' ' -f2
select (count(*) as ?count) {
<<sparql-annotations-protc>>
}}
select (count(*) as ?count) {
<<sparql-annotations-pio-api-protc>>
}
<<sparql-annotations-protc>>
?protocol a sparc:Protocol .
?protocol ?p ?banno .
?banno TEMP:protcurChildren* ?anno .
FILTER CONTAINS(str(?protocol), "protocols.io/api")
#FILTER CONTAINS(str(?protocol), "protocols.io")
}
select distinct ?anno where {
# TODO subPropertyOf
#values ?anno_predicate {} # this is a bad way to do this
# ?s ?anno_predicate ?anno
values ?anno_type {
protcur:aspect
protcur:black-box
protcur:black-box-component
protcur:executor-verb
protcur:input
protcur:invariant
protcur:output
protcur:parameter
}
?anno a ?anno_type .
In order to use these you need to load the latest version of uberon into blazegraph.
SELECT DISTINCT ?sc (str(?l) as ?label) WHERE {
# BIND("brain" AS ?label) # Well would you look at that!
VALUES (?root) { ( UBERON:0001062 ) }
?sc rdfs:subClassOf+ ?root .
?sc rdfs:label ?l .
} ORDER BY ASC(?label) LIMIT ?limit
select ?p ?o where {
VALUES (?s) { ( UBERON:0001062 ) }
?s ?p ?o .
}
A SODA development use case. Find me datasets that have top level manifests with no errors.
SELECT DISTINCT
?dataset
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:hasPart+ ?file .
?file a sparc:File .
?file a sparc:Manifest .
?file TEMP:hasParent ?dataset . # this is the tricky bit, because we conflate the identifier for dataset and the folder
?file TEMP:hasErrors 0 .
}
LIMIT ?limit
SELECT DISTINCT
(COUNT(DISTINCT ?person) as ?cp)
WHERE {
?person a sparc:Person .
}
LIMIT ?limit
Count the number of contributors that have ORCiDs.
SELECT DISTINCT
(COUNT(DISTINCT ?person) as ?cp)
#?fn
#?ln
WHERE {
?person a sparc:Person .
?person sparc:firstName ?fn .
?person sparc:lastName ?ln .
FILTER CONTAINS(str(?person), "orcid.org")
}
LIMIT ?limit
NOTE These are not yet in the ttl file, the queries written here will not work yet.
In all likelihood we are not going to include the names of each of the individual files in the standard ttl export. We may put it in a named graph and then update the journal, possibly only for released datasets. The use cases for having individual files in the graph is not at all clear, we might have individual folders, or run it in the other direction where a subject could list the folders that contain data about it. Trying to keep the graph in sync with Blackfynn would be quite a pain, essentially we would store/append every single file that ever appears and then mark the deleted ones as deleted or something.
SELECT DISTINCT
?dataset
?file_type
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:containsFileWithType ?file_type . # TODO not 100% on the modelling here
}
LIMIT ?limit
In the path-metadata
folder of curation-export
.
grep -rh 'mimetype":' | sort | uniq -c | sort -h
This doesn’t get coverage for file extensions so in addition we run the following.
grep -rh 'basename":.\+\.\([a-z]\+\)' | grep -o '\.[a-z]\+"' | sort | uniq -c | sort -h
SELECT DISTINCT
?dataset
?raw
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:containsFolderForRawData ?raw . # TODO not 100% on the modelling here
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?derived
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:containsFolderForDerivedData ?derived . # TODO not 100% on the modelling here
}
LIMIT ?limit
SELECT DISTINCT
?dataset
?code
WHERE {
?dataset a sparc:Dataset .
?dataset TEMP:containsFolderForCode ?code . # TODO not 100% on the modelling here
}
LIMIT ?limit
This modeling is extremely preliminary.
SELECT DISTINCT
?dataset
?dataset_sim
WHERE {
?dataset a sparc:Dataset .
?dataset_sim a sparc:Dataset . # TODO not 100% on this
# the dataset holds the simulation, and is also what references the other datasets
# whether we need an explicit type for simulation datasets is not clear, I suspect
# that we do not, since datasets are just data, the aboutness or typeness probably
# should come from the fact that the dataset specifies or houses a simulation ...
# ?dataset_sim a sparc:SimulationDataset . # also not good
# ?dataset_sim TEMP:isSubstrateForSomeComputationalSimulation true . # FIXME this is bad bad bad
VALUES ?p {TEMP:derivesParametersFrom TEMP:derivesValidationDataFrom ilxtr:hasInformationInput} .
?dataset_sim ?p ?dataset .
}
LIMIT ?limit
first pass requires that the subject_id be identical
SELECT (COUNT(*) as ?count) {
<<pds-v2>>
}
SELECT DISTINCT ?s ?dataset (str(?id) as ?local_id) ?award ?species
WHERE {
?s a sparc:Subject;
TEMP:localId ?id;
TEMP:hasDerivedInformationAsParticipant ?dataset ;
sparc:animalSubjectIsOfSpecies ?species .
?dataset a sparc:Dataset ;
TEMP:hasAwardNumber ?award .
{ SELECT DISTINCT ?id
WHERE {
?s a sparc:Subject ;
TEMP:localId ?id ;
TEMP:hasDerivedInformationAsParticipant ?dataset .
} GROUP BY ?id HAVING (count(?id) > 1) }
}
ORDER BY ?id
# :results table
# RUN:block
SELECT distinct ?s1 ?s2 ?id ?dataset1 ?dataset2 ?species1 ?species2 ?award1 ?award2
WHERE {
# Give me all subjects with duplicate IDs with unique datasets
{ SELECT ?id
WHERE {
?s1 a owl:NamedIndividual ;
TEMP:localId ?id ;
TEMP:hasDerivedInformationAsParticipant ?datasetx .
?s2 a owl:NamedIndividual ;
TEMP:localId ?id ;
TEMP:hasDerivedInformationAsParticipant ?datasety .
filter(?datasetx != ?datasety)
} GROUP BY ?id having (count(?id) > 1)}
# filter out the cases where there can't be a match because species doesn't match
?s1 TEMP:localId ?id ;
sparc:animalSubjectIsOfSpecies ?species1;
TEMP:hasDerivedInformationAsParticipant ?dataset1 .
?s2 TEMP:localId ?id ;
sparc:animalSubjectIsOfSpecies ?species2;
TEMP:hasDerivedInformationAsParticipant ?dataset2 .
filter(?s1 != ?s2)
filter(STR(IRI(?s1)) < STR(IRI(?s2))) # this is a hack to filter out duplicate triples
# filter to find non-matching awards
# using contact person doesn't make sense as they are 1:1 with award right now
?dataset1 a owl:NamedIndividual ;
TEMP:hasAwardNumber ?award1 .
?dataset2 a owl:NamedIndividual ;
TEMP:hasAwardNumber ?award2 .
} order by ?id limit ?limit
Python code to simplify neru
and supporting functions to extract terminal regions.
from pyontutils.config import auth
from nifstd_tools.simplify import apinat_deblob, sub, pred, obj, ematch
from nifstd_tools.simplify import axon, dend, bag, top, ie, ies, iot, iots, ext, fasIn, endIn, layerIn, onts
ext = onts # XXX schema change
def query(neupop_id):
import requests
url = ('https://scicrunch.org/api/1/sparc-scigraph/scigraph/dynamic/'
f'demos/apinat/neru-7/{neupop_id}?limit=9999999&key={auth.get("scigraph-api-key")}')
resp = requests.get(url, headers={'Accept': 'application/json'})
blob = resp.json()
return blob
def find_terminals(blob, type):
return [es for es in blob['edges']
if
pred(es, iots) and
obj(es, type) and
ematch(blob,
(lambda e, m:
sub(e, m) and
pred(e, top) and
obj(e, bag)),
sub(es))]
def find_region(blob, edge):
collect = []
def select(e, m, collect=collect):
if sub(e, m):
#print(e)
if pred(e, layerIn) or pred(e, fasIn) or pred(e, endIn):
return ematch(blob, select, obj(e))
elif pred(e, onts):
region = obj(e)
collect.extend([b for b in blob['nodes'] if b['id'] == region])
return region
ematch(blob, select, sub(edge))
return collect
def find_region_layer(blob, edge, bindex):
_nonelayer = False
collect = []
layers = []
layers_iots = []
donel = set()
doner = set()
def select_term(e, m, layers=layers):
if sub(e, m):
pprint(e)
if (pred(e, onts)
or pred(e, iot)
or pred(e, iots)):
layer = obj(e)
if layer not in donel:
donel.add(layer)
if pred(e, iot) or pred(e, iots):
layers_iots.append(bindex[layer])
else:
layers.append(bindex[layer])
return layer
def select(e, m, collect=collect):
if sub(e, m):
if pred(e, layerIn):
# we're at a layer
ematch(blob, select_term, sub(e))
return ematch(blob, select, obj(e))
elif (pred(e, fasIn)
or pred(e, endIn)):
return ematch(blob, select, obj(e))
elif pred(e, onts):
region = obj(e)
if region not in doner:
doner.add(region)
collect.append(bindex[region])
return region
ematch(blob, select, sub(edge))
if collect and not layers and not layers_iots:
layers = [None]
_nonelayer = True
elif layers_iots and not layers:
layers = layers_iots
if not layers and (_nonelayer or layers_iots):
layers = [None]
if len(collect) != len(layers):
raise ValueError(f'len not matched {len(collect)} {len(layers)}')
return list(zip(collect, layers))
def find_terminal_regions(blob, type):
return [region for es in find_terminals(blob, type) for region in find_region(blob, es)]
def find_terminal_region_layers(blob, type, bindex):
return [(region, layer) for es in find_terminals(blob, type)
for region, layer in find_region_layer(blob, es, bindex)]
def main(blob=None, blob_string=None, neupop_id=None, remove_converge=remove):
# do not call this function unless it is from an org babel block, there are free variables
if blob is None and blob_string is not None:
import json
blob = json.loads(blob_string)
neupop_id = neupop_id if neupop_id else 'ilxtr:neuron-type-keast-6'
if blob is None:
blob = query(neupop_id)
blob, edges, somas, externals, ordering_edges = v = apinat_deblob(
blob, remove_converge=remove_converge)
test_call = False # change to True to test the #+call: expression
if test_call:
pprint(v)
return v
pprint(blob)
Find the ontology identifiers for terminal regions.
<<python-process-neru>>
from pprint import pprint
blob, *_ = main(blob_string=result)
bindex = {n['id']:n for n in blob['nodes']}
# find terminal regions
axon_terminal_regions = find_terminal_regions(blob, axon)
dend_terminal_regions = find_terminal_regions(blob, dend)
#pprint(axon_terminal_regions)
#pprint(dend_terminal_regions)
axon_terminal_rl = find_terminal_region_layers(blob, axon, bindex)
dend_terminal_rl = find_terminal_region_layers(blob, dend, bindex)
pprint([(r['id'], (l if l is None else l['id'])) for r, l in axon_terminal_rl])
pprint([(r['id'], (l if l is None else l['id'])) for r, l in dend_terminal_rl])
This code produces the basic connectivity of a neuron population.
The result is a list of pairs, the pairs are the subject and object
of the triple subject (or apinatomy:next apinatomy:next*) object
.
Thus they represent the full connectivity of the population.
The contents of each element of the pair tuples with three elements.
- The id for the neuronal process involved in the connection.
- The ontology id for the layer in which the neuronal process is located. This may be None if no layer is specified in the model.
- The ontology id for the region in which the neuronal process is located.
In the example presented here for keast neuron 5 the final entries all have the same start and end location because they are the soma, and the roots of the axon and the dendrite.
intIn = 'apinatomy:internalIn'
def isLayer(blob, s):
return ematch(blob, (lambda e, m: sub(e, m) and pred(e, layerIn)), s)
def reclr(blob, start_link):
# recurse up the hierarchy until fasIn endIn intIn terminates
#print('starting reclr')
collect = []
layer = []
col = True
def select_ext(e, m, collect=collect):
nonlocal col
nonlocal layer
if sub(e, m):
if pred(e, 'apinatomy:cloneOf'): # should be zapped during simplify
return ematch(blob, select_ext, obj(e))
if pred(e, onts) or pred(e, iot) or pred(e, iots):
#print('select_ext', e)
external = obj(e)
#print('se', col, layer)
if col:
if layer:
if len(layer) > 1:
l, *layer = layer
else:
l = layer.pop()
else:
l = None
r = [b for b in blob['nodes'] if b['id'] == external][0]['id'] # if this is empty we are in big trouble
collect.append((l, r))
else:
l = [b for b in blob['nodes'] if b['id'] == external][0]['id']
layer.append(l)
#print(layer)
return external
def select(e, m):
nonlocal col
if sub(e, m):
#print(e)
if pred(e, layerIn) or pred(e, fasIn) or pred(e, endIn) or pred(e, intIn):
#print('select', e)
col = not isLayer(blob, obj(e))
#print('s', col)
ematch(blob, select_ext, obj(e))
ematch(blob, select, obj(e))
ematch(blob, select, start_link)
return collect
def lay_reg(blob, start):
direct = [obj(t) for t in
ematch(blob, (lambda e, m: sub(e, m)
and (pred(e, intIn) or # XXX why isn't this getting pulled in correctly for somas? answer: missing somas in starts? surely not, ARGH a lyph internalIn a layer # FIXME this is the interneuron case FIXME axon terminal in same region case even if leaves region
pred(e, endIn) or
pred(e, fasIn))),
start)]
layers = [obj(t) for d in direct for t in
ematch(blob, (lambda e, m: sub(e, m)
and isLayer(blob, m)
and (pred(e, iot) or
pred(e, iots) or
pred(e, onts))),
d)]
lregs = []
if layers:
ldir = [obj(t) for d in direct for t in
ematch(blob, (lambda e, m: sub(e, m)
and pred(e, layerIn)),
d)]
lregs = [obj(t) for d in ldir for t in
ematch(blob, (lambda e, m: sub(e, m)
and not isLayer(blob, m)
and (pred(e, iot) or
pred(e, iots) or # XXX ie seems to have no hits now
pred(e, onts))),
d)]
regions = [obj(t) for d in direct for t in
ematch(blob, (lambda e, m: sub(e, m)
and not isLayer(blob, m)
and (pred(e, iot) or
pred(e, iots) or
pred(e, onts))),
d)]
#if start == 'kblad:snl16':
#print(start, direct, layers, regions)
# FIXME TODO nested regions and layers
lrs = reclr(blob, start) # FIXME doesn't pair regions and layers
# FIXME SIGH SIGH SIGH start can be either part of a next >_<
#print(lrs)
assert not (lregs and regions), (lregs, regions) # not both
regions = lregs if lregs else regions
#out = start, layers[0] if layers else None, regions[0] if regions else None, tuple([l for l in lrs])
out = start, tuple(lrs)
if out:
return out
def render_blob(blob):
starts = [obj(e) for e in blob['edges'] if pred(e, 'apinatomy:lyphs')]
nxt = 'apinatomy:next'
nxts = 'apinatomy:next*'
nexts = [(sub(t), obj(t)) for start in starts for t in
ematch(blob, (lambda e, m: pred(e, nxt) or pred(e, nxts)), None)]
#pprint(nexts)
connected_pairs = sorted(set([tuple([lay_reg(blob, e) for e in p]) for p in nexts]))
#pprint(connected_pairs)
return connected_pairs
blob, *_ = main(blob_string=result)
render_blob(blob)
from pprint import pprint
from pyontutils.scigraph import Cypher, Vocabulary
from pyontutils.scigraph_codegen import moduleDirect
from pyontutils.config import auth
scigraphd = moduleDirect(auth.get('scigraph-api'), 'scigraphd')
<<python-process-neru>>
<<py-conn-pairs>>
sgv = Vocabulary()
sgd = scigraphd.Dynamic(cache=True, verbose=True, do_error=True)
sgc = scigraphd.Cypher(cache=True, verbose=True)
q_neru_6 = """
<<cypher-neru-6>>
"""
q_neru_7 = """
<<cypher-neru-7>>
"""
q_cnap = """
<<cy-neru-all-pop>>
"""
def neupop_blob(neupop_id):
# XXX requires a patch to Cypher and CypherBase to support arbitrary kwargs
blob = sgc.execute(query=q_neru_7, limit=None, neupop_id=neupop_id, output='application/json')
return blob
def sigh():
blobs = [neupop_blob(f"ilxtr:neuron-type-keast-{npid}") for npid in range(1, 21)]
debs = [main(blob=blob)[0] for blob in blobs]
simples = [render_blob(deb) for deb in debs]
#[pprint(simple) for simple in simples[:1]]
def fbid(id):
if id:
result = sgv.findById(id)
if result['labels']:
return result['labels'][0]
def fbids(ids):
return [(id, fbid(id)) for id in ids]
def rendlab(pairs):
for pair in pairs:
yield tuple((start, *(tuple(fbids(hp)) for hp in housings)) for start, housings in pair)
#for (*tstart, sid, sasdf), (*tend, eid, easdf) in pairs:
#yield ((*tstart, sid, fbid(sid), fbids(sasdf)) if sid else (*tstart, sid, fbids(sasdf)),
#(*tend, eid, fbid(eid), fbids(easdf)) if eid else (*tend, eid, fbids(easdf)))
from copy import deepcopy
blobs = [neupop_blob(f"ilxtr:neuron-type-keast-{npid}") for npid in range(1, 21)]
debs = [main(blob=deepcopy(blob))[0] for blob in blobs]
simples = [render_blob(deb) for deb in debs]
sigh = [s for n, si in enumerate(simples) for s in ((f'--------- {n + 1}','---------'), *sorted(rendlab(si)))]
#sigh
#pprint(blobs[0])
#pprint(debs[0])
#pprint(simples[0])
#sigh[:200]
sigh
from neurondm import orders
from neurondm.models.nlp import add_partial_orders
from pyontutils.core import OntId, OntGraph
from pyontutils.utils import log
from pyontutils.config import auth
from pyontutils.namespaces import ilxtr
def apinat_to_raw_adj(blob):
dblob, *_ = apinat_deblob(blob)
cpairs = render_blob(dblob)
cpairs_bad = [c for c in cpairs if not (c[0][1] and c[1][1])]
if cpairs_bad:
log.error(f'cpairs_bad: {cpairs_bad}')
cpairs_ok = [c for c in cpairs if c[0][1] and c[1][1]]
raw_adj = [((r1, l1), (r2, l2)) for # region first since neurondm.orders.rl.__init__(self, region, layer=None)
((link1, ((l1, r1), *housing1)), (link2, ((l2, r2), *housing2))) # FIXME housing ...
# FIXME no projections case ... do we link to self for soma? XXX yes, we link back to self
in cpairs_ok]
raw_adj = sorted(set(raw_adj), key=lambda tt: tuple(('' if t[0] is None else t[0], '' if t[1] is None else t[1]) for t in tt))
if len(raw_adj) > 1: # non degenerate case
raw_adj = [(a, b) for a, b in raw_adj if a != b] # soma cycles if there are other connections
return raw_adj
def all_nst(ids, blobs):
pos = {}
for id, blob in zip(ids, blobs):
#print(id)
raw_adj = apinat_to_raw_adj(blob)
nst = raw_adj_to_nst(raw_adj)
if nst:
pos[OntId(id).u] = nst
return pos
def raw_adj_to_nst(raw_adj):
# apparently dupes ARE an issue on the input for some reason and produce
# really wild results and aren't culled by set ??? or rather there are
# issues with the stability of the rl sort which translate to unstable
# representations in the ttl, so that will need to get sorted out
def key(tt):
return tuple(tuple('' if e is None else e for e in t) for t in tt)
ss_adj = sorted(set(raw_adj), key=key)
# dupes aren't an issue but removing them produces a slight performance improvement
adj = sorted(set(tuple(orders.rl(*(a if a is None else OntId(a).u for a in rl)) for rl in rls) for rls in ss_adj))
nst = orders.adj_to_nst(adj)
return nst
def get_apinat_blobs():
d = sgc.execute(query=q_cnap, limit=99999, output='application/json')
ids = [n['id'] for n in d['nodes']]
for id in ids:
blob = sgd.demos_apinat_neru_7_neupop_id(neupop_id=id) # FIXME slow, TODO parallize
anst = all_nst(ids, blobs)
olr = auth.get_path('ontology-local-repo')
og = OntGraph().parse(olr / 'ttl/generated/neurons/apinat-simple-sheet.ttl')
g = OntGraph()
g.namespace_manager.populate_from(og)
add_partial_orders(g, anst)
g.write(olr / 'ttl/generated/neurons/apinat-partial-orders.ttl')
debug, looks like there are nasty issues with duplicate nodes on the input here to rl which is not good, like rl equality test is not working (this was indeed the case)
# wat = anst[OntId('ilxtr:neuron-type-aacar-6').u]
#issue = 3 # 'ilxtr:neuron-type-splen-2'
#issue = ids.index('ilxtr:neuron-type-aacar-6')
#issue = ids.index('ilxtr:neuron-type-aacar-7v')
issue = ids.index('ilxtr:neuron-type-keast-11')
#issue = 101 # 'ilxtr:neuron-type-pancr-2'
iblob = blobs[issue]
idb, *_ = apinat_deblob(iblob)
oof = render_blob(idb)
owie = ids[issue]
# oh boy, somas are missing housing entirely in some cases
#ematch(iblob, sub, 'aacar:ac-atrial-epi-term-6_lnk_1')
#ematch(iblob, obj, 'aacar:ac-atrial-epi-term-6_lnk_1')
# lol forgot to deblob
#ematch(iblob, sub, 'aacar:ac-sn-sgt3_6_lnk_2')
#ematch(iblob, obj, 'aacar:ac-sn-sgt3_6_lnk_2')
ouch = apinat_to_raw_adj(iblob)
souch = sorted(set(ouch))
hrm = raw_adj_to_nst(ouch)
wat1 = sorted(set(tuple(orders.rl(*(a if a is None else OntId(a).curie for a in rl)) for rl in rls) for rls in ouch))
wat2 = sorted(set(tuple(orders.rl(*(a if a is None else OntId(a).curie for a in rl)) for rl in rls) for rls in souch))
sigh1 = wat1 == wat2 # utoh
wat3 = sorted(set(tuple(orders.rl(*(a if a is None else OntId(a).curie for a in rl)) for rl in rls) for rls in sorted(set(ouch))))
wat4 = sorted(set(tuple(orders.rl(*(a if a is None else OntId(a).curie for a in rl)) for rl in rls) for rls in sorted(set(souch))))
sigh2 = wat3 == wat4 # ok
qq = orders.adj_to_nst(wat3) # XXX no, this is what is broken
# well that is concerning
select distinct ?s ?p where {
?s ?p ilxtr:NeuronCUT . }
// MATCH path = (a)-[t]-(:Class) RETURN a
//MATCH path = ()-[:apinatomy:conveyingLyph]-() RETURN path
// MATCH path = ()-[:TEMPRAW:protocolInvolvesInputInstance]-() RETURN path
<<py-neupop-helper>>
from collections import defaultdict
def get_label(region):
return id_label[region]
def get_labels(regions):
return [get_label(region) for region in regions]
d = sgc.execute(query=q_cnap, limit=99999, output='application/json')
ids = [n['id'] for n in d['nodes']]
blobs = [neupop_blob(id) for id in ids]
id_label = {n['id']:n['lbl'] if 'lbl' in n and n['lbl'] else n['id'] for blob in blobs for n in blob['nodes']}
_ext_all = sorted(set([obj(e) for b in blobs for e in b['edges'] if pred(e, 'apinatomy:ontologyTerms')]))
ext_pop = {i:set([obj(e) for e in blob['edges'] if pred(e, 'apinatomy:ontologyTerms')]) for i, blob in zip(ids, blobs)}
# TODO popuation, region, process type, terminal
pop_by_reg_ads_trm = []
pop_by_reg = defaultdict(list)
for i, regs in ext_pop.items():
for reg in regs:
pop_by_reg[reg].append(i)
def key_allc(region):
count = 0
for i, id in enumerate(ids):
if region in ext_pop[id]:
count += 1
return count
_ext_allc = sorted(_ext_all, key=key_allc)
def key_pop(pop):
return -len(ext_pop[pop])
ids_ord = sorted(ids, key=key_pop)
def key_all(region):
first = None
count = 0
regs = []
iths = []
for i, id in enumerate(ids_ord):
if region in ext_pop[id]:
regs.append(region)
iths.append(i)
#count += 1 # wow =+ 1 no error wat
#if first is None:
#first = i
return iths[0], *[-i for i in iths[1:]]
ext_all = sorted(_ext_all, key=key_all)
n_region = len(ext_all)
n_pop = len(ext_pop)
header = [['neupop', *ext_all]] # TODO -> label
xl = get_labels(header[0][1:])
rows = header + [[id, *[region in ext_pop[id] for region in ext_all]] for id in ids_ord]
def jac(a, b):
anb, aub = zip(*[(ar and br, ar or br) for ar, br in zip(a, b)])
sanb, saub = sum(anb) , sum(aub)
if not sanb and not saub:
return sanb # 0
elif not sanb:
return saub
elif not saub:
return sanb
else:
return sanb / saub
def sumjac(rows, norm=False):
# actually want distance from .5 ?
mat = jac_mat(rows, switch=True)
#pprint(mat)
return [(sum(r[:-1]) * sum(rows[r[-1] + 1][1:]) if norm else 1, r[-1]) for i, r in enumerate(mat)]
def sumjac_norm(rows):
return sumjac(rows, norm=True)
def jac_mat(rows, switch=False, reverse=False):
asdf = []
for i, (_, *rowa) in enumerate(rows[1:]):
jacr = []
for j, (_, *rowb) in enumerate(rows[1:]):
jci = jac(rowa, rowb)
if switch:
jacr.append(jci)
else:
jacr.append((jci, j))
if switch:
jacr.append(i)
asdf.append(jacr)
else:
minimized = [i for j, i in sorted(jacr)][1:] # 1: to skip self
minimized.append(i)
asdf.append(minimized)
return asdf
def jmc(rows):
return jac_mat(rows, switch=True)
def jmcr(rows): # XXX broken
return jac_mat(rows, switch=True, reverse=True)
def jac_sigh(rows):
sigh = jmc(rows)
return [(np.std(s[:-1]), np.mean(s[:-1]), s[-1]) for s in sigh]
def jac_sigh(rows):
sigh = jmc(rows)
#return [(np.std(s[:-1]), np.mean(s[:-1]), s[-1]) for s in sigh]
return [(*[((x - .5) ** 2) ** .5 for x in s[:-1]], s[-1]) for s in sigh]
def resort(rows, sortf, reverse=False):
asdf_ord = sorted(sortf(rows), reverse=not reverse) # don't think too hard about it
ind_rank = {j:i for i, (*_, j) in enumerate(asdf_ord)}
def srt(row):
ind = rows.index(row)
if ind == 0:
return 0
else:
return ind_rank[ind - 1]
return sorted(rows, key=srt)
def sumthm(rows):
return [[-sum(row[1:]), i] for i, row in enumerate(rows[1:])]
def sumth(rows):
return [[sum(row[1:]), i] for i, row in enumerate(rows[1:])]
def blank(rows):
return [[*row[1:], i] for i, row in enumerate(rows[1:])]
def sumoth(rows):
crank = [sum(col) for col in list(zip(*rows[1:]))[1:]]
return [[*
#[crank[j] if c and crank[j] == max([crank[x] for x, v in enumerate(row[1:]) if v]) else 0
[crank[j] if c else 0
for j, c in enumerate(row[1:])], i] for i, row in enumerate(rows[1:])]
def sumothm(rows):
crank = [sum(col) for col in list(zip(*rows[1:]))[1:]]
return [[*
#[crank[j] if c and crank[j] == max([crank[x] for x, v in enumerate(row[1:]) if v]) else 0
[-crank[j] if c else 0
for j, c in enumerate(row[1:])], i] for i, row in enumerate(rows[1:])]
def maxp(rows):
crank = [sum(col) for col in list(zip(*rows[1:]))[1:]]
return [[
sorted([crank[j] if c else 0 for j, c in enumerate(row[1:])])[0],
*[-_ for _ in sorted([crank[j] if c else 0 for j, c in enumerate(row[1:])])[1:]]
, i]
for i, row in enumerate(rows[1:])]
def jacb(rows):
a = [row[1:] for row in rows[1:]]
aT = list(zip(*a))
# FIXME symmetry
rd = [[jac(r1, r2) for r2 in a] for r1 in a]
cd = [[jac(c1, c2) for c2 in aT] for c1 in aT]
#pprint(rd)
#pprint(cd)
# output is a 4d matrix, from rc -> to rc
dist = np.zeros((len(rd), len(cd), len(rd), len(cd)))
for i, row_dists in enumerate(rd):
for k, row_dist in enumerate(row_dists):
for j, col_dists in enumerate(cd):
for l, col_dist in enumerate(col_dists):
dist[i, j, k, l] = (row_dist ** 2 + col_dist ** 2) ** .5
#pprint(dist)
return dist
rows = resort(rows, sumth)
rows = list(zip(*resort(list(zip(*rows)), blank, reverse=True)))
rows = resort(rows, jmc)
if False:
import seaborn
seaborn.set(rc={'figure.figsize':(50, 50)})
#seaborn.set(rc={'figure.figsize':(5, 5)})
axes = seaborn.heatmap(
[r[1:] for r in rows[1:]],
xticklabels=xl,
yticklabels=[r[0] for r in rows[1:]],
cbar=False,
square=True,
)
# axes.get_figure().savefig('heatmap-pop-reg-test.svg')
import csv
csv_path = 'heatmap-pop-reg.csv'
with open(csv_path, 'wt') as f:
csv.writer(f).writerows(rows)
undifferentiated NPO representation that matches the heatmap above
run the blocks in the section above first
#len(blobs)
#pprint(id_label)
#pprint(blobs[0])
sorted([[a, *sorted(b)] for a, b in ext_pop.items()])
from neurondm import Neuron, Phenotype, EntailedPhenotype, Config
from pyontutils.namespaces import ilxtr, owl, skos, rdfs
config = Config('apinatomy-locations')
neurons = [Neuron(Phenotype(id), *(EntailedPhenotype(loc, ilxtr.hasLocationPhenotype) for loc in sorted(locs)), id_=id) for id, locs in ext_pop.items()]
config.write()
to_mod = [(s, skos.altLabel, o) for s, p, o in config._written_graph if p == rdfs.label]
to_remove = [t for t in config._written_graph if t[1] in (owl.equivalentClass, ilxtr.genLabel, ilxtr.localLabel, ilxtr.simpleLabel, ilxtr.simpleLocalLabel, rdfs.label, skos.prefLabel)]
[config._written_graph.remove(t) for t in to_remove]
[config._written_graph.add(t) for t in to_mod]
config._written_graph.write()
config.write_python()
<<py-nbr-1>>
<<py-nbr-2>>
<<py-nbr-3>>
These can be tested against the execute endpoint as well (if the SciGraph server is running the patch to align the behavior).
// :results drawer
// :var hello="there"
match
(o:Ontology{iri: "http://uri.interlex.org/sparc/ontologies/ilx_0793177"})
<-[:isDefinedBy]-(t)
// this shit is fucked ... those labels should be in sparc community terms because it is being loaded ... nah just the known FMA -> ILX change and use case issue
return t
// (o:Ontology{iri: "https://cassava.ucsd.edu/sparc/ontologies/published/N:organization:618e8dd9-f8d2-4dc4-9abb-c6aaab2e78a0"})
id | label |
---|
Switch over to apinat:inheritedOntologyTerms
.
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
, (neugrp)
-[:apinatomy:links]->(link)
-[c:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer) // real lyphs convey things, layers do not
-[d:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
WITH neugrp, link, lyph, a, c, d
OPTIONAL MATCH layer_ext = (lyph)
<-[d*1]-(layer)-[:apinatomy:cloneOf*0..1]->()-[:apinatomy:inheritedOntologyTerms]->()
WITH neugrp, link, lyph, a, c, d, layer_ext
OPTIONAL MATCH more = (lyph)
-[:apinatomy:layerIn|apinatomy:endsIn|apinatomy:fasciculatesIn|apinatomy:internalIn|apinatomy:cloneOf*1..]->()
-[:apinatomy:ontologyTerms|apinatomy:inheritedOntologyTerms]->()
WITH neugrp, link, lyph, a, c, d, layer_ext, more // there is a difference here because the previous match does not require lyphs to have external ids
MATCH (lyph)
-[e:apinatomy:ontologyTerms]->(region)
, p2 = (link)
-[:apinatomy:conveyingLyph]->(cl)
-[:apinatomy:topology]->()
, (cl)
-[x:apinatomy:inheritedOntologyTerms*0..1]->()
// use apinatomy:next to extract ordering information
, (link)
-[f:apinatomy:next|apinatomy:nextChainStartLevels*0..]->()
-[g:apinatomy:target*0..1]->()
-[h:apinatomy:rootOf*0..1]->()
-[i:apinatomy:levels*0..1]->()
<-[:apinatomy:links]-(neugrp)
// publications
WITH neugrp, a, c, d, e, f, g,h,i, p2, x, layer_ext, more
OPTIONAL MATCH path = (neugrp)
-[:apinatomy:references]->(pub)
-[:type]->(:Class{iri: "https://apinatomy.org/uris/elements/Reference"}) // cannot be curied, dynamic endpoints will not expand it
RETURN a, null as b, c, d, e, f, g,h,i, path, p2, x, layer_ext, more
UNION
// this part usually only returns the soma housing lyph
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
-[b:apinatomy:lyphs]->(lyph)
-[c:apinatomy:internalIn]->()
-[d:apinatomy:ontologyTerms*0..1]->(region)
, p2 = (lyph)
-[:apinatomy:conveys]->(soma_link)
-[:apinatomy:source|apinatomy:target]->(soma_node)
-[:apinatomy:sourceOf]->(chain_link)
, (chain_link)
-[:apinatomy:levelIn]->(chain)
, (soma_node)
-[:apinatomy:rootOf]->(chain)
WITH lyph, a, b, c, d, p2
OPTIONAL MATCH more = (lyph)
-[:apinatomy:layerIn|apinatomy:endsIn|apinatomy:fasciculatesIn|apinatomy:internalIn|apinatomy:cloneOf*1..]->()
-[:apinatomy:ontologyTerms|apinatomy:inheritedOntologyTerms]->()
RETURN a, b, c, d, null AS e, null AS f, null AS g, null AS h, null AS i, null AS path, p2, null as x, null as layer_ext, more
The only difference between 5 and 6 is that 6 also traverses apinat:nextChainStartLevels
<<cypher-neru-5/6-common-1>>
-[f:apinatomy:next|apinatomy:nextChainStartLevels*0..]->()
<<cypher-neru-5/6-common-2>>
<<cypher-neru-5/6-common-1>>
-[f:apinatomy:next*0..]->()
<<cypher-neru-5/6-common-2>>
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
, (neugrp)
-[:apinatomy:links]->(link)
-[c:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer) // real lyphs convey things, layers do not
-[d:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
WITH neugrp, link, lyph, a, c, d
OPTIONAL MATCH layer_ext = (lyph)
<-[d*1]-(layer)-[:apinatomy:cloneOf*0..1]->()-[:apinatomy:inheritedExternal]->()
WITH neugrp, link, lyph, a, c, d, layer_ext
OPTIONAL MATCH more = (lyph)
-[:apinatomy:layerIn|apinatomy:endsIn|apinatomy:fasciculatesIn|apinatomy:internalIn|apinatomy:cloneOf*1..]->()
-[:apinatomy:ontologyTerms|apinatomy:inheritedExternal]->()
WITH neugrp, link, lyph, a, c, d, layer_ext, more // there is a difference here because the previous match does not require lyphs to have external ids
MATCH (lyph)
-[e:apinatomy:ontologyTerms]->(region)
, p2 = (link)
-[:apinatomy:conveyingLyph]->(cl)
-[:apinatomy:topology]->()
, (cl)
-[x:apinatomy:inheritedExternal*0..1]->()
// use apinatomy:next to extract ordering information
, (link)
-[g:apinatomy:target*0..1]->()
-[h:apinatomy:rootOf*0..1]->()
-[i:apinatomy:levels*0..1]->()
<-[:apinatomy:links]-(neugrp)
// publications
WITH neugrp, a, c, d, e, f, g,h,i, p2, x, layer_ext, more
OPTIONAL MATCH path = (neugrp)
-[:apinatomy:references]->(pub)
-[:type]->(:Class{iri: "https://apinatomy.org/uris/elements/Reference"}) // cannot be curied, dynamic endpoints will not expand it
RETURN a, null as b, c, d, e, f, g,h,i, path, p2, x, layer_ext, more
UNION
// this part usually only returns the soma housing lyph
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
-[b:apinatomy:lyphs]->(lyph)
-[c:apinatomy:internalIn]->()
-[d:apinatomy:ontologyTerms*0..1]->(region)
, p2 = (lyph)
-[:apinatomy:conveys]->(soma_link)
-[:apinatomy:source|apinatomy:target]->(soma_node)
-[:apinatomy:sourceOf]->(chain_link)
, (chain_link)
-[:apinatomy:levelIn]->(chain)
, (soma_node)
-[:apinatomy:rootOf]->(chain)
WITH lyph, a, b, c, d, p2
OPTIONAL MATCH more = (lyph)
-[:apinatomy:layerIn|apinatomy:endsIn|apinatomy:fasciculatesIn|apinatomy:internalIn|apinatomy:cloneOf*1..]->()
-[:apinatomy:ontologyTerms|apinatomy:inheritedExternal]->()
RETURN a, b, c, d, null AS e, null AS f, null AS g, null AS h, null AS i, null AS path, p2, null as x, null as layer_ext, more
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
, (neugrp)
-[:apinatomy:links]->(link)
-[c:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer) // real lyphs convey things, layers do not
-[d:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
WITH neugrp, link, lyph, a, c, d
OPTIONAL MATCH layer_ext = (lyph)
<-[d*1]-(layer)-[:apinatomy:cloneOf]->()-[:apinatomy:inheritedOntologyTerms]->()
WITH neugrp, link, lyph, a, c, d, layer_ext // there is a difference here because the previous match does not require lyphs to have external ids
MATCH (lyph)
-[e:apinatomy:ontologyTerms]->(region)
, p2 = (link)
-[:apinatomy:conveyingLyph]->(cl)
-[:apinatomy:topology]->()
, (cl)
-[x:apinatomy:inheritedOntologyTerms*0..1]->()
// use apinatomy:next to extract ordering information
, (link)
-[f:apinatomy:next*0..]->()
-[g:apinatomy:target*0..1]->()
-[h:apinatomy:rootOf*0..1]->()
-[i:apinatomy:levels*0..1]->()
<-[:apinatomy:links]-(neugrp)
// publications
WITH neugrp, a, c, d, e, f, g,h,i, p2, x, layer_ext
OPTIONAL MATCH path = (neugrp)
-[:apinatomy:references]->(pub)
-[:type]->(:Class{iri: "https://apinatomy.org/uris/elements/Publication"}) // cannot be curied, dynamic endpoints will not expand it
RETURN a, null as b, c, d, e, f, g,h,i, path, p2, x, layer_ext
UNION
// this part usually only returns the soma housing lyph
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
-[b:apinatomy:lyphs]->(lyph)
-[c:apinatomy:internalIn]->()
-[d:apinatomy:ontologyTerms*0..1]->(region)
, p2 = (lyph)
-[:apinatomy:conveys]->(soma_link)
-[:apinatomy:source|apinatomy:target]->(soma_node)
-[:apinatomy:sourceOf]->(chain_link)
, (chain_link)
-[:apinatomy:levelIn]->(chain)
, (soma_node)
-[:apinatomy:rootOf]->(chain)
RETURN a, b, c, d, null AS e, null AS f, null AS g, null AS h, null AS i, null AS path, p2, null as x, null as layer_ext
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
// publications
WITH neugrp, a
OPTIONAL MATCH path = (neugrp)
-[:apinatomy:references]->(pub)
-[:type]->(:Class{iri: "https://apinatomy.org/uris/elements/Publication"}) // cannot be curied, dynamic endpoints will not expand it
WITH neugrp, a, path
MATCH (neugrp)
-[b:apinatomy:links]->(link)
-[c:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer) // real lyphs convey things, layers do not
-[d:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
WITH neugrp, link, lyph, a, b, c, d, path // MATCH vs , not all things that match as lyphs have externals
MATCH (lyph)
-[e:apinatomy:ontologyTerms]->(region)
// use apinatomy:next to extract ordering information
WITH neugrp, link, a, b, c, d, e, path
MATCH p2 = (link)
-[:apinatomy:conveyingLyph]->(cl)
-[:apinatomy:topology]->()
WITH neugrp, link, a, b, c, d, e, path, p2, cl
MATCH (cl)
-[x:apinatomy:inheritedOntologyTerms*0..1]->()
WITH neugrp, link, a, b, c, d, e, path, p2, x
MATCH (link)
-[f:apinatomy:next*0..]->()
//-[f:apinatomy:next|apinatomy:nextChainStartLevels*0..]->()
// FIXME these should be collapsing into a single relationship
-[g:apinatomy:target*0..1]->()
-[h:apinatomy:rootOf*0..1]->()
-[i:apinatomy:levels*0..1]->()
<-[:apinatomy:links]-(neugrp)
RETURN a, b, c, d, e, f, g,h,i, path, p2, x
UNION
// this part usually only returns the soma housing lyph
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
-[b:apinatomy:lyphs]->(lyph)
-[c:apinatomy:internalIn]->()
-[d:apinatomy:ontologyTerms*0..1]->(region)
// this variant shows the dead end lyphs that correspond to the fasciculatesIn links above
//-[c:apinatomy:internalIn*0..1]->()
//-[d:apinatomy:ontologyTerms*0..1]->(region)
RETURN a, b, c, d, null AS e, null AS f, null AS g, null AS h, null AS i, null AS path, null as p2, null as x
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
// publications
WITH neugrp, a
OPTIONAL MATCH path = (neugrp)
-[:apinatomy:references]->(pub)
-[:type]->(:Class{iri: "https://apinatomy.org/uris/elements/Publication"}) // cannot be curied, dynamic endpoints will not expand it
WITH neugrp, a, path
MATCH (neugrp)
-[b:apinatomy:links]->(link)
-[c:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer) // real lyphs convey things, layers do not
-[d:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
WITH neugrp, link, lyph, a, b, c, d, path
MATCH (lyph)
-[e:apinatomy:ontologyTerms]->(region)
// use apinatomy:next to extract ordering information
WITH neugrp, link, a, b, c, d, e, path
MATCH (link)
-[f:apinatomy:next*0..]->()
//-[f:apinatomy:next|apinatomy:nextChainStartLevels*0..]->()
// FIXME these should be collapsing into a single relationship
-[g:apinatomy:target*0..1]->()
-[h:apinatomy:rootOf*0..1]->()
-[i:apinatomy:levels*0..1]->()
<-[:apinatomy:links]-(neugrp)
RETURN a, b, c, d, e, f, g,h,i, path
UNION
// this part usually only returns the soma housing lyph
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
-[b:apinatomy:lyphs]->(lyph)
-[c:apinatomy:internalIn]->(e) // e is a hack to get columns to match
-[d:apinatomy:ontologyTerms*0..1]->(region)
// this variant shows the dead end lyphs that correspond to the fasciculatesIn links above
//-[c:apinatomy:internalIn*0..1]->(e)
//-[d:apinatomy:ontologyTerms*0..1]->(region)
RETURN a, b, c, d, null AS e, null AS f, null AS g, null AS h, null AS i, null AS path
MATCH path = (neupop:Class{iri: $neupop_id})
-[:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"})
-[:apinatomy:links]->()
-[:apinatomy:next*0..]->()
// -[:apinatomy:nextChainStartLevels*0..]-()
//-[:apinatomy:prevChainEndLevels*0..]-()
-[:apinatomy:levelIn*0..]->()
RETURN path
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
// publications
WITH neugrp, a
OPTIONAL MATCH path = (neugrp)
-[:apinatomy:references]->(pub)
-[:type]->(:Class{iri: "https://apinatomy.org/uris/elements/Publication"}) // cannot be curied, dynamic endpoints will not expand it
WITH neugrp, a, path
MATCH (neugrp)
-[b:apinatomy:links]->(link)
-[c:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer) // real lyphs convey things, layers do not
-[d:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
WITH lyph, a, b, c, d, path
MATCH (lyph)
-[e:apinatomy:ontologyTerms]->(region)
RETURN a, b, c, d, e, path
UNION
// this part usually only returns the soma housing lyph
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
-[b:apinatomy:lyphs]->(lyph)
-[c:apinatomy:internalIn]->(e) // e is a hack to get columns to match
-[d:apinatomy:ontologyTerms*0..1]->(region)
// this variant shows the dead end lyphs that correspond to the fasciculatesIn links above
//-[c:apinatomy:internalIn*0..1]->(e)
//-[d:apinatomy:ontologyTerms*0..1]->(region)
return a, b, c, d, null AS e, null AS path
OPTIONAL MATCH (start:Ontology)
<-[:isDefinedBy]-(graph:NamedIndividual)
-[:type]->({iri: "https://apinatomy.org/uris/elements/Graph"})
, (start)
<-[:isDefinedBy]-(external:Class)
-[:subClassOf*]->(:Class {iri: "http://uri.interlex.org/tgbugs/uris/readable/NeuronEBM"})
return external
List all neuron populations that appear in some ApiNATOMY model.
MATCH (start:Ontology)
<-[:isDefinedBy]-(external:Class)
-[:subClassOf*]->(:Class {iri: "http://uri.interlex.org/tgbugs/uris/readable/NeuronEBM"}) // FIXME
, (start:Ontology)
<-[:apinat:hasGraph]-(graph:Class {iri: ""})
RETURN external
Given an ApiNATOMY model id return the identifiers for the neuron populations that are present in the model.
MATCH (start:Ontology {iri: $model_id})
<-[:isDefinedBy]-(external:Class)
-[:subClassOf*]->(:Class {iri: "http://uri.interlex.org/tgbugs/uris/readable/NeuronEBM"}) // FIXME
RETURN external
Given an ApiNATOMY model id return the identifiers for the neuron populations that are present in the model and the identifiers for references that provide supporting evidence. Publications and populations can be distingished by checking whether their meta type field is NamedIndividual or Class.
MATCH (start:Ontology {iri: $model_id})
<-[:isDefinedBy]-(external:Class)
-[:subClassOf*]->(:Class {iri: "http://uri.interlex.org/tgbugs/uris/readable/NeuronEBM"}) // FIXME
,
(external)
-[e:type]->()
RETURN e
UNION
OPTIONAL MATCH (start:Ontology {iri: $model_id})
<-[:isDefinedBy]-(graph:NamedIndividual)
-[:type]->({iri: "https://apinatomy.org/uris/elements/Graph"}) // elements don't have a superclass right now
,
(graph)
-[:apinatomy:references]->(pub)
-[e:type]->(:Class{iri: "https://apinatomy.org/uris/elements/Reference"})
RETURN e
region contains some process part of some neuron population
MATCH (region)
-[:apinatomy:annotates]->(lyph)
<-[:apinatomy:lyphs]-
(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"})
RETURN region
MATCH (neupop:Class{iri: $neupop_id})
-[:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"})
-[:apinatomy:lyphs]->(end_lyph)
-[t:apinatomy:topology]->(top)
WHERE top.iri IN ["https://apinatomy.org/uris/readable/BAG", "https://apinatomy.org/uris/readable/BAG2"]
WITH neugrp, end_lyph, t
MATCH (type) // FIXME we need more information in the models
<-[x:apinatomy:inheritedOntologyTerms*0..1]-(end_lyph)
-[a:apinatomy:conveys]->(link)
-[b:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer) // real lyphs convey things, layers do not
-[c:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
WITH neugrp, lyph, a,b,c,t,x
MATCH (lyph)
-[e:apinatomy:ontologyTerms]->(region)
RETURN e, a,b,c,t,x
Given an anatomical region return a list of neuron types that project to that region.
<<cypher-neru-terminal-type>>
Given an anatomical region return a list of neuron types with axons that are located in that region.
<<cypher-neru-process-type>>
RETURN e, neupop, neugrp
Given an anatomical region return a list of neuron types that have dendrite terminals in that region.
<<cypher-neru-terminal-type>>
Given an anatomical region return a list of neuron types with dendrites that are located in that region.
<<cypher-neru-process-type>>
RETURN e, neupop, neugrp
Given an anatomical region return a list of neuron types with processes that are located in that region.
MATCH
(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"})
-[:apinatomy:links]->(link)
-[:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer)
-[:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:ontologyTerms*0..1]->(region:Class{iri: $region_id})
WITH neugrp
OPTIONAL MATCH (neupop:Class)
-[e:apinatomy:annotates*0..1]->(neugrp)
// somas
MATCH
(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"})
-[:apinatomy:lyphs]->(lyph)
-[:apinatomy:internalIn]->()
-[:apinatomy:ontologyTerms*0..1]->(region:Class{iri: $region_id})
WITH neugrp
OPTIONAL MATCH (neupop:Class)
-[e:apinatomy:annotates*0..1]->(neugrp)
TODO Need to expand region_id
using the Uberon partonomy to answer more generic queries.
// dendrites and axons
<<cypher-neru-processes-base>>
RETURN e, neupop, neugrp
UNION
<<cypher-neru-processes-somas>>
RETURN e, neupop, neugrp
<<cypher-neru-processes-base>>
RETURN neupop
UNION
<<cypher-neru-processes-somas>>
RETURN neupop
Helper blocks for more specialized queries.
Filter by process type_id
, where type_id
could be the ontology
identifier for axon or dendrite. The type_id
has to match the
conventions used in ApiNATOMY models.
<<cypher-neru-processes-base>>
WITH e, neupop, neugrp, link
MATCH (link)
-[:apinatomy:conveyingLyph]->(cl)
-[:apinatomy:inheritedOntologyTerms]->(:Class {iri: $type_id})
Filter processes based on their topology. For example, this is used to select processes with bag topology that correspond to axon and dendrite terminals.
<<cypher-neru-process-type>>
WITH e, neupop, neugrp, cl
MATCH (cl)
-[:apinatomy:topology]-(top)
WHERE top.iri IN ["https://apinatomy.org/uris/readable/BAG", "https://apinatomy.org/uris/readable/BAG2"]
RETURN e, neupop, neugrp
Get the parts list for an organ including nerves and blood vessels
// depth of 6 captures everything, 5 is too shallow, 40 is WAY too deep
MATCH path = (start:Class{iri: "${id}"})
<-[:subClassOf|ilxtr:includedForSPARCUnder|fma:regional_part_of|fma:constitutional_part_of|fma:related_part_of*0..6]-(part)
<-[:fma:arterial_supply_of|fma:nerve_supply_of|fma:venous_drainage_of|fma:continuous_with*0..1]-(sup)
<-[:subClassOf|fma:constitutional_part_of|fma:branch|fma:tributary|fma:branch_of*0..1]-(a_bit_more)
RETURN path
UNION // for this query UNION seems to be MUCH faster than using WITH
MATCH path = (start:Class{iri: "${id}"})
// this one does not need to be inverted ? except for the INCOMING flag
<-[:fma:arterial_supply_of|fma:venous_drainage_of]-(vessel)
<-[:fma:branch|fma:tributary]-(more_vessel)
<-[:fma:branch|fma:tributary|fma:regional_part]-(even_more_vessel)
RETURN path
MATCH path = (artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species)
WHERE artifact.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path
MATCH path = (artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species:Class{iri: "${species-id}"})
WHERE artifact.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path
MATCH path = (root)
-[:ilxtr:isDefinedBy]->(a)<-[:subClassOf*0..2]
-(artifact:Class{iri: "${artifact-id}"})
RETURN path
MATCH path = (label)
-[:subClassOf]->(root)
-[:ilxtr:isDefinedBy]->(a)<-[:subClassOf*0..2]
-(artifact:Class{iri: "${artifact-id}"})
WHERE label.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path
MATCH (label)-[:subClassOf]->(root:Class{iri: "${root-id}"})
, path = (label)-[relation*0..1]-(maybe)
WHERE NONE (r in relation WHERE type(r) IN ["isDefinedBy", "subClassOf", "filler"])
AND NOT (label.iri =~ ".*_:.*") AND NOT (maybe.iri =~ ".*_:.*")
AND label.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path
MATCH path = (artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species)
WHERE artifact.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path
UNION
MATCH path = (root)
-[:ilxtr:isDefinedBy]->(artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species)
RETURN path
MATCH path = (artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species:Class{iri: "${species-id}"})
WHERE artifact.iri <> "http://www.w3.org/2002/07/owl#Nothing"
return path
UNION
MATCH path = (root)
-[:ilxtr:isDefinedBy]->(artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species:Class{iri: "${species-id}"})
RETURN path
MATCH
(region:Class{iri: "${region-id}"})
<-[:ilxtr:isDefinedInRegion]-
(parent)
-[:ilxtr:isDefinedInTaxon]->
(species:Class{iri: "${species-id}"})
WITH parent
MATCH path = (artifact)
-[:subClassOf*0..2]->(parent)
WHERE artifact.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path
UNION
MATCH
(region:Class{iri: "${region-id}"})
<-[:ilxtr:isDefinedInRegion]-
(parent)
-[:ilxtr:isDefinedInTaxon]->
(species:Class{iri: "${species-id}"})
WITH parent
MATCH path = (root)
-[:ilxtr:isDefinedBy]->(artifact)
-[:subClassOf*0..2]->(parent)
RETURN path
MATCH (fma:Class{iri: "${fma-id}"})
WITH "FMA:" + toString(fma.`http://purl.org/sig/ont/fma/FMAID`) AS curie
MATCH (region)
-[:subClassOf*]->(start:Class{iri: "http://purl.obolibrary.org/obo/UBERON_0001062"})
WHERE any(x IN
region.`http://www.geneontology.org/formats/oboInOwl#hasDbXref`
WHERE x =~ curie)
WITH region
MATCH
(region)
<-[:ilxtr:isDefinedInRegion]-
(parent)
-[:ilxtr:isDefinedInTaxon]->
(species:Class{iri: "${species-id}"})
WITH parent
MATCH path = (artifact)
-[:subClassOf*0..2]->(parent)
WHERE artifact.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path
UNION
MATCH (fma:Class{iri: "${fma-id}"})
WITH "FMA:" + toString(fma.`http://purl.org/sig/ont/fma/FMAID`) AS curie
MATCH (region)
-[:subClassOf*]->(start:Class{iri: "http://purl.obolibrary.org/obo/UBERON_0001062"})
WHERE any(x IN
region.`http://www.geneontology.org/formats/oboInOwl#hasDbXref`
WHERE x =~ curie)
WITH region
MATCH
(region)
<-[:ilxtr:isDefinedInRegion]-
(parent)
-[:ilxtr:isDefinedInTaxon]->
(species:Class{iri: "${species-id}"})
WITH parent
MATCH path = (root)
-[:ilxtr:isDefinedBy]->(artifact)
-[:subClassOf*0..2]->(parent)
RETURN path
MATCH path = (artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species)
WHERE artifact.iri <> "http://www.w3.org/2002/07/owl#Nothing"
return path
UNION
MATCH path = (maybe)
-[relation*0..1]-(label)
-[:subClassOf]->(root)
-[:ilxtr:isDefinedBy]->(artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species)
WHERE NONE (r in relation WHERE type(r) IN ["isDefinedBy", "subClassOf", "filler"])
AND NOT (label.iri =~ ".*_:.*") AND NOT (maybe.iri =~ ".*_:.*")
AND label.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path
MATCH (n)
WHERE n.iri IN [
"http://purl.org/sig/ont/fma/fma7195", // lung
"http://purl.org/sig/ont/fma/fma7088", // heart
"http://purl.org/sig/ont/fma/fma7197", // liver
"http://purl.org/sig/ont/fma/fma7198", // pancreas
"http://purl.org/sig/ont/fma/fma7203", // kidney
"http://purl.org/sig/ont/fma/fma7148", // stomach
"http://purl.org/sig/ont/fma/fma7196", // spleen
"http://purl.org/sig/ont/fma/fma14543", // colon
"http://purl.org/sig/ont/fma/fma7201", // large intestine
"http://purl.org/sig/ont/fma/fma7200", // small intestine
"http://purl.org/sig/ont/fma/fma7199", // intestine
"http://purl.org/sig/ont/fma/fma15900", // urinary bladder
"http://purl.org/sig/ont/fma/fma45659", // lower urinary tract
"http://purl.org/sig/ont/fma/fma7157", // nervous system
"http://purl.org/sig/ont/fma/fma9903", // peripheral nervous system
"http://purl.org/sig/ont/fma/fma9906", // sympathetic nervous system
"http://purl.org/sig/ont/fma/fma7647", // spinal cord
"http://purl.org/sig/ont/fma/fma50801", // brain
"http://purl.org/sig/ont/fma/fma5889", // autonomic ganglion
"http://purl.org/sig/ont/fma/fma19667", // urethra
"http://purl.org/sig/ont/fma/fma7131", // esophagus
"http://uri.interlex.org/base/ilx_0793921" // REVA root
]
RETURN n
MATCH (n)
WHERE n.iri IN [
"http://purl.obolibrary.org/obo/NCBITaxon_9378", // Suncus murinus
"http://purl.obolibrary.org/obo/NCBITaxon_9606", // Homo sapiens
"http://purl.obolibrary.org/obo/NCBITaxon_9685", // Felis catus
"http://purl.obolibrary.org/obo/NCBITaxon_9823", // Sus scrofa
"http://purl.obolibrary.org/obo/NCBITaxon_10090", // Mus musculus
"http://purl.obolibrary.org/obo/NCBITaxon_10116" // Rattus norvegicus
]
RETURN n
MATCH
(t)-[:isDefinedBy]->(graph:Ontology{iri: "http://uri.interlex.org/sparc/ontologies/community-terms"})
RETURN t
Return phenotypes that inhere in some part of an anatomical entity.
MATCH (anatomical_entity:Class{iri: $id})
<-[part_of:subClassOf|BFO:0000050|RO:0002433*0..40]-(subclass_part_ctmo)
<-[inheres_in:RO:0000052|RO:0002314!]-(intersection_of_quality_and_anatomy) // inheres in (anon intersection of)
<-[has_process_part:BFO:0000051]-() // has part (process)
<-[:subClassOf*0..]-(phenotype) // phenotype and all subclasses
WHERE
// filter out partOf/hasPart cases that induce circularity
ALL(e IN part_of WHERE NOT EXISTS(e.owlType) OR e.owlType = "subClassOf" OR e.owlType = "operand")
RETURN phenotype
Return anatomical entities associated with a given phenotype.
this is super slow and scigraph does not support value arrays for queries right now so will have to work through how to implement that
MATCH (anatomical_entity:Class)
<-[part_of:BFO:0000050|RO:0002433*0..4]-
(subclass_part_ctmo)
<-[inheres_in:RO:0000052|RO:0002314!]-(intersection_of_quality_and_anatomy) // inheres in (anon intersection of)
<-[has_process_part:BFO:0000051]-() // has part (process)
<-[:subClassOf*0..]-(phenotype:Class{iri: $id}) // phenotype and all subclasses
WHERE phenotype.iri IN $id
RETURN part_of
MATCH (anatomical_entity:Class{iri: $id})
<-[part_of:subClassOf*0..40]-(subclass_part_ctmo)
<-[inheres_in:RO:0000052|RO:0002314!]-(intersection_of_quality_and_anatomy) // inheres in (anon intersection of)
<-[has_process_part:BFO:0000051]-(direct_phen) // has part (process)
WHERE
// filter out partOf/hasPart cases that induce circularity
ALL(e IN part_of WHERE NOT EXISTS(e.owlType) OR e.owlType = "subClassOf" OR e.owlType = "operand")
// RETURN count(distinct direct_phen)
// RETURN count(distinct subclass_part_ctmo)
RETURN subclass_part_ctmo
distinct direct phenotypes 3638
+-----------------------------+ | count(distinct direct_phen) | +-----------------------------+ | 3658 | +-----------------------------+
+------------------------------------+ | count(distinct subclass_part_ctmo) | +------------------------------------+ | 1056 | +------------------------------------+
XXX need cypher normal json results so we can use count
MATCH (c)-[:subClassOf*0..]->(b:Class{iri: $start}) RETURN c
MATCH (start:Class{iri: '${start_id}'})
WITH start
MATCH (end:Class{iri: '${end_id}'})
WITH start, end
MATCH path = shortestPath((start)-[:${relationship}*..${max_depth}]->(end))
RETURN path
MATCH (blank)-
[entrytype:ilxtr:hasSomaLocatedIn|ilxtr:hasAxonLocatedIn|ilxtr:hasDendriteLocatedIn|ilxtr:hasPresynapticTerminalsIn]
->(location:Class{iri: '${start_id}'})
WITH location, entrytype, blank
MATCH (phenotype)<-[predicate]-(blank)<-[:equivalentClass]-(neuron)
WHERE NOT (phenotype.iri =~ ".*_:.*")
// RETURN phenotype, (phenotype)-[predicate]-(neuron) as e
// WITH location, predicate, phenotype, neuron
RETURN location, entrytype, neuron, predicate, phenotype
MATCH (blank)-
[entrytype:ilxtr:hasSomaLocatedIn|ilxtr:hasAxonLocatedIn|ilxtr:hasDendriteLocatedIn|ilxtr:hasPresynapticTerminalsIn]
->(location:Class{iri: '${start_id}'})
WITH entrytype, blank
MATCH (phenotype)<-[:${target_predicate}]-(blank)
// WHERE NOT (phenotype.iri =~ ".*_:.*")
RETURN phenotype
MATCH path1 = (start:Class{iri: "${start-id}"})
-[:apinatomy:annotates]->(start_housing)
-[:apinatomy:subtypes*0..1]->()
-[:apinatomy:clones*0..1]->(layer_or_end)
-[:apinatomy:layers*0..1]->()
-[:apinatomy:bundles]->(linkStart)
-[:apinatomy:prevChainEndLevels|apinatomy:prev|apinatomy:source*1..]->(link)
-[:apinatomy:targetOf|apinatomy:sourceOf]->(linkSoma) // axon or dendrite root
-[:apinatomy:conveyingLyph]->()
-[:apinatomy:supertype*0..1]->(soma:NamedIndividual)
-[:apinatomy:ontologyTerms]->(c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
WITH path1, link
OPTIONAL MATCH path2 = (link)
-[:apinatomy:fasciculatesIn|apinatomy:endsIn]->(layer_or_end)
-[:apinatomy:layerIn*0..1]->(end)
-[:apinatomy:ontologyTerms]->(external)
RETURN path1, path2
MATCH path1 = (start:Class{iri: '${start-id}'})
-[:apinatomy:annotates]->(start_housing)
-[:apinatomy:bundlesChains]->(chain)
-[:apinatomy:root]->(root)
-[:apinatomy:internalIn]->(layer_or_end) # this hits a cycle back to start_housing
-[:apinatomy:cloneOf*0..1]->()
-[:apinatomy:supertype*0..1]->()
-[:apinatomy:ontologyTerms]->(layer_or_end_external)
WITH path1, root, layer_or_end AS layer
OPTIONAL MATCH path2 = (layer)
-[:apinatomy:layerIn]->(end_housing)
-[:apinatomy:ontologyTerms]->(end_housing_external)
WITH path1, path2, root
MATCH path3 = (root) // in the layer case this hits an additional lyph
<-[:apinatomy:target|apinatomy:source]-(link)
<-[:apinatomy:conveys]-(soma)
<-[:apinatomy:annotates]-(soma_NLX)
RETURN path1, path2, path3
MATCH (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual)
RETURN soma
MATCH path = (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual) // soma lyph
-[:apinatomy:conveys]->(somaLink) // link connecting soma to axon and dendrite
-[:apinatomy:target|apinatomy:source]->(root) // axon or dendrite root
-[:apinatomy:controlNodes|apinatomy:rootOf*1..2]->(chain) // axon or dendrite tree
-[:apinatomy:housingLyphs]->(housing) // list of lyphs housing the trees
-[:apinatomy:ontologyTerms*0..1]->(external) // external ids for the housing lyphs
WHERE soma.`https://apinatomy.org/uris/readable/generated` IS NULL
RETURN path
MATCH path1 = (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual) // soma lyph
-[:apinatomy:conveys]->(somaLink) // link connecting soma to axon and dendrite
-[:apinatomy:target|apinatomy:source]->(root) // axon or dendrite root
-[:apinatomy:internalIn]->(layer_or_end)
-[:apinatomy:cloneOf*0..1]->()
-[:apinatomy:supertype*0..1]->()
-[:apinatomy:ontologyTerms]->(layer_or_end_external:Class{iri: '${start-id}'})
WHERE soma.`https://apinatomy.org/uris/readable/generated` IS NULL
WITH path1, root
MATCH path2 = (root)
-[:apinatomy:controlNodes|apinatomy:rootOf*1..2]->(chain) // axon or dendrite tree
-[:apinatomy:housingLyphs]->(housing) // list of lyphs housing the trees
-[:apinatomy:ontologyTerms*0..1]->(external) // external ids for the housing lyphs
RETURN path1, path2
UNION
MATCH path1 = (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual) // soma lyph
-[:apinatomy:conveys]->(somaLink) // link connecting soma to axon and dendrite
-[:apinatomy:target|apinatomy:source]->(root) // axon or dendrite root
-[:apinatomy:internalIn]->(layer)
-[:apinatomy:cloneOf*0..1]->()
-[:apinatomy:supertype*0..1]->()
-[:apinatomy:layerIn]->(end_housing)
-[:apinatomy:ontologyTerms]->(end_housing_external:Class{iri: '${start-id}'})
WHERE soma.`https://apinatomy.org/uris/readable/generated` IS NULL
WITH path1, root
MATCH path2 = (root)
-[:apinatomy:rootOf]->(chain) // axon or dendrite tree
-[:apinatomy:housingLyphs]->(housing) // list of lyphs housing the trees
-[:apinatomy:ontologyTerms*0..1]->(external) // external ids for the housing lyphs
RETURN path1, path2
MATCH path1 = (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual) // soma lyph
-[:apinatomy:conveys]->(linkSoma) // link connecting soma to axon and dendrite
-[:apinatomy:target|apinatomy:source]->(nodeRoot) // axon or dendrite root
-[:apinatomy:sourceOf|apinatomy:nextChainStartLevels|apinatomy:next*1..]->(link) // sourceOf is first and only once
-[:apinatomy:fasciculatesIn|apinatomy:endsIn]->(layer_or_end)
-[:apinatomy:cloneOf*0..1]->()
-[:apinatomy:supertype*0..1]->()
-[:apinatomy:ontologyTerms]->(external)
WHERE soma.`https://apinatomy.org/uris/readable/generated` IS NULL
WITH path1, nodeRoot, layer_or_end AS layer
OPTIONAL MATCH path2 = (layer) // if we were in a layer, get the containing lyph as well
-[:apinatomy:layerIn]->(end_housing)
-[:apinatomy:ontologyTerms]->(end_housing_external)
WITH path1, path2, nodeRoot
MATCH path3 = (nodeRoot) // extract chain for axon vs dendrite
-[:apinatomy:rootOf]->(chain)
RETURN path1, path2, path3
A sparql version of the query (work in progress).
SELECT DISTINCT
?c
?soma
?linkSoma
?nodeRoot
?link
?layer_or_end
?cloned
?supertype
?external_st
?external_loe
?external_end_housing
WHERE
{
VALUES ?c { NLX:154731 }
?c rdf:type owl:Class .
?c apinatomy:annotates ?soma .
?soma rdf:type owl:NamedIndividual .
?soma apinatomy:conveys ?linkSoma .
?linkSoma apinatomy:target | apinatomy:source ?nodeRoot .
?nodeRoot apinatomy:rootOf ?chain .
?nodeRoot apinatomy:sourceOf | apinatomy:nextChainStartLevels | apinatomy:next+ ?link .
?link apinatomy:fasciculatesIn | apinatomy:endsIn ?layer_or_end .
optional { ?layer_or_end apinatomy:cloneOf* ?cloned . } # optional
optional { ?cloned apinatomy:supertype* ?supertype . } # optional
?supertype apinatomy:ontologyTerms ?external_st .
?layer_or_end apinatomy:ontologyTerms ?external_loe .
optional { ?layer_or_end apinatomy:layerIn ?end_housing . } # optional
optional { ?end_housing apinatomy:ontologyTerms ?external_end_housing . } # optional
}
limit ?limit
MATCH path1 = (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual) // soma lyph
-[:apinatomy:conveys]->(linkSoma) // link connecting soma to axon and dendrite
-[:apinatomy:target|apinatomy:source]->(nodeRoot) // axon or dendrite root
-[:apinatomy:internalIn]->(layer_or_end)
-[:apinatomy:cloneOf*0..1]->()
-[:apinatomy:supertype*0..1]->()
-[:apinatomy:layerIn*0..1]->(layerSoma) // don't need to see both layer and housing for soma
-[:apinatomy:ontologyTerms]->(externalEndSoma:Class{iri: '${start-id}'})
WHERE soma.`https://apinatomy.org/uris/readable/generated` IS NULL
WITH path1, nodeRoot
MATCH path3 = (chain)
<-[:apinatomy:rootOf]-(nodeRoot)
-[:apinatomy:sourceOf|apinatomy:nextChainStartLevels|apinatomy:next*1..]->(link)
-[:apinatomy:fasciculatesIn|apinatomy:endsIn]->(layer_or_end)
-[:apinatomy:cloneOf*0..1]->()
-[:apinatomy:supertype*0..1]->()
-[:apinatomy:ontologyTerms]->(external)
WITH path1, path3, nodeRoot, layer_or_end AS layer
OPTIONAL MATCH path2 = (layer) // if we were in a layer, get the containing lyph as well
-[:apinatomy:layerIn]->(end_housing)
-[:apinatomy:ontologyTerms]->(end_housing_external)
RETURN path1, path2, path3
MATCH path1 = (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual) // soma lyph
-[:apinatomy:conveys]->(linkSoma) // link connecting soma to axon and dendrite
-[:apinatomy:target|apinatomy:source]->(nodeRoot) // axon or dendrite root
-[:apinatomy:sourceOf|apinatomy:nextChainStartLevels|apinatomy:next*1..]->(link) // sourceOf is first and only once
-[:apinatomy:fasciculatesIn|apinatomy:endsIn]->(layer_or_end)
-[:apinatomy:cloneOf*0..1]->()
-[:apinatomy:supertype*0..1]->()
-[:apinatomy:ontologyTerms]->(external:Class{iri: '${process-id}'})
WHERE soma.`https://apinatomy.org/uris/readable/generated` IS NULL
WITH path1, nodeRoot, layer_or_end AS layer
OPTIONAL MATCH path2 = (layer) // if we were in a layer, get the containing lyph as well
-[:apinatomy:layerIn]->(end_housing)
-[:apinatomy:ontologyTerms]->(end_housing_external)
WITH path1, path2, nodeRoot
MATCH path3 = (nodeRoot) // extract chain for axon vs dendrite
-[:apinatomy:rootOf]->(chain)
RETURN path1, path2, path3
UNION
MATCH path1 = (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual) // soma lyph
-[:apinatomy:conveys]->(linkSoma) // link connecting soma to axon and dendrite
-[:apinatomy:target|apinatomy:source]->(nodeRoot) // axon or dendrite root
-[:apinatomy:sourceOf|apinatomy:nextChainStartLevels|apinatomy:next*1..]->(link) // sourceOf is first and only once
-[:apinatomy:fasciculatesIn|apinatomy:endsIn]->(layer_or_end)
-[:apinatomy:cloneOf*0..1]->()
-[:apinatomy:supertype*0..1]->()
-[:apinatomy:ontologyTerms]->(external)
WHERE soma.`https://apinatomy.org/uris/readable/generated` IS NULL
WITH path1, nodeRoot, layer_or_end AS layer
MATCH path2 = (layer) // if we were in a layer, get the containing lyph as well
-[:apinatomy:layerIn]->(end_housing)
-[:apinatomy:ontologyTerms]->(end_housing_external:Class{iri: '${process-id}'})
WITH path1, path2, nodeRoot
MATCH path3 = (nodeRoot) // extract chain for axon vs dendrite
-[:apinatomy:rootOf]->(chain)
RETURN path1, path2, path3
Example template.
cypherResources:
- path:
operations: &name-ops
- summary: <<nonl(desc-name())>>
parameters:
- name: some-id
description: does something
paramType:
query: &name |
<<block-name>>
cypherResources:
- path: /dynamic/prod/sparc/phenotypeAnatomy/{id}
operations: &phenotypeAnatomy-ops
- summary: <<nonl(desc-phenotype-anatomy())>>
parameters:
- name: id
description: HPO id of the phenotype to search from
paramType: path
query: &phenotypeAnatomy |
<<cyres-phenotype-anatomy>>
- path: /dynamic/test/sparc/phenotypeAnatomy/{id}
operations: *phenotypeAnatomy-ops
query: *phenotypeAnatomy
- path: /dynamic/prod/sparc/anatomyPhenotypes/{id}
operations: &anatomyPhenotypes-ops
- summary: <<nonl(desc-anatomy-phenotypes())>>
parameters:
- name: id
description: uberon id of the anatomical entity to search from
paramType: path
query: &anatomyPhenotypes |
<<cyres-anatomy-phenotypes>>
- path: /dynamic/test/sparc/anatomyPhenotypes/{id}
operations: *anatomyPhenotypes-ops
query: *anatomyPhenotypes
- path: /dynamic/prod/sparc/organParts/{id}
operations: &organParts-ops
- summary: <<nonl(desc-organ-parts())>>
parameters:
- name: id
description: ontology id of the organ
paramType: path
query: &organParts |
<<cyres-organ-parts>>
- path: /dynamic/test/sparc/organParts/{id}
operations: *organParts-ops
query: *organParts
- path: /dynamic/prod/sparc/parcellationArtifacts
operations:
- summary: Get the graph of all parcellation artifacts for all species
query: |
<<cyres-parcellation-artifacts>>
- path: /dynamic/prod/sparc/parcellationArtifacts/{species-id}
operations:
- summary: Get the graph of all parcellation artifacts for a single species
parameters:
- name: species-id
description: ontology id of the species
paramType: path
query: |
<<cyres-parcellation-artifacts-species-id>>
- path: /dynamic/prod/sparc/artifactRoots/{artifact-id}
operations:
- summary: Get the graph of all parcellation label roots for a single artifact WARNING this can return no results
parameters:
- name: artifact-id
description: ontology id of the parcellation artifact
paramType: path
query: |
<<cyres-artifact-roots-artifact-id>>
- path: /dynamic/prod/sparc/artifactLabels/{artifact-id}
operations:
- summary: Get the graph of all parcellation labels for a single artifact WARNING this can return no results
parameters:
- name: artifact-id
description: ontology id of the parcellation artifact
paramType: path
query: |
<<cyres-artifact-labels-artifact-id>>
- path: /dynamic/prod/sparc/rootLabels/{root-id}
operations: &rootLabes-ops
- summary: Get the list of all parcellation labels for a single label root
parameters:
- name: root-id
description: ontology id of the parcellation label root
paramType: path
query: &rootLabels |
<<cyres-root-labels-root-id>>
- path: /dynamic/test/sparc/rootLabels/{root-id}
operations: *rootLabes-ops
query: *rootLabels
- path: /dynamic/prod/sparc/parcellationRoots
operations:
- summary: Get the graph of all parcellation label roots for all species
query: |
<<cyres-parcellation-roots>>
- path: /dynamic/prod/sparc/parcellationRoots/{species-id}
operations:
- summary: Get the graph of all parcellation label roots for a single species
parameters:
- name: species-id
description: ontology id of the species
paramType: path
query: |
<<cyres-parcellation-roots-species-id>>
- path: /dynamic/prod/sparc/parcellationRoots/{species-id}/{region-id}
operations:
- summary: Get the graph of all parcellation label roots for a single species and anatomical region
parameters:
- name: species-id
description: ontology id of the species
paramType: path
- name: region-id
description: ontology id of the anatomical region
paramType: path
query: |
<<cyres-parcellation-roots-species-id-region-id>>
- path: /dynamic/prod/sparc/parcellationRootsFMA/{species-id}/{fma-id}
operations: &parcellationRootsFMA-ops
- summary: Get the graph of all parcellation label roots for a single species and anatomical region
parameters:
- name: species-id
description: ontology id of the species
paramType: path
- name: fma-id
description: ontology id of the anatomical region
paramType: path
query: &parcellationRootsFMA |
<<cyres-parcellation-roots-fma-species-id-region-id>>
- path: /dynamic/test/sparc/parcellationRootsFMA/{species-id}/{fma-id}
operations: *parcellationRootsFMA-ops
query: *parcellationRootsFMA
- path: /dynamic/prod/sparc/parcellationGraph
operations:
- summary: Get the graph of all parcellation labels for all species
query: |
<<cyres-parcellation-graph>>
- path: /dynamic/prod/sparc/organList
operations: &organList-ops
- summary: Get the list of all FMA organ identifiers relevant to SPARC
query: &organList |
<<cyres-organ-list>>
- path: /dynamic/test/sparc/organList
operations: *organList-ops
query: *organList
- path: /dynamic/prod/sparc/speciesList
operations: &speciesList-ops
- summary: Get the list of all NCBITaxon species identifiers relevant to SPARC
query: &speciesList |
<<cyres-species-list>>
- path: /dynamic/test/sparc/speciesList
operations: *speciesList-ops
query: *speciesList
- path: /dynamic/shortestSimple
query: |
<<cyres-shortest-simple>>
operations:
- summary: Get the shortest path between two IDs
parameters:
- name: start_id
description: The starting node (ex UBERON:0005751)
paramType: query
- name: end_id
description: The ending node (ex UBERON:0001255)
paramType: query
- name: max_depth
description: the maximum depth to traverse
paramType: query
- name: relationship
description: The property to traverse (ex subClassOf or subClassOf|partOf|isA)
paramType: query
required: false
- path: /dynamic/neurons/connectivity
query: |
<<cyres-neurons-connectivity>>
operations:
- summary: Get connected anatomical regions by neuron type
parameters:
- name: start_id
description: The starting location (eg UBERON:0001759)
paramType: query
- path: /dynamic/neurons/connectedRegions
query: |
<<cyres-neurons-connected-regions>>
operations:
- summary: Get connected anatomical regions by starting location and target relationship
parameters:
- name: start_id
description: The starting location (eg UBERON:0001759)
paramType: query
- name: target_predicate
description: The predicate for the type of connectivity (eg ilxtr:hasPresynapticTerminalsIn)
paramType: query
required: false
- path: /dynamic/demos/apinat/bundles/{start-id}
operations:
- summary: Return the paths to somas from an anatomical region (aka connected-somas)
parameters:
- name: start-id
description: ontology id of the starting point
paramType: path
query: |
<<cyres-apinat-bundles-start-id>>
- path: /dynamic/demos/apinat/old-bundles/{start-id}
operations:
- summary: Return the paths to somas from an anatomical region (aka connected-somas)
parameters:
- name: start-id
description: ontology id of the starting point
paramType: path
query: |
<<cyres-apinat-old-bundles-start-id>>
- path: /dynamic/demos/apinat/somas
operations:
- summary: List all the somas for a given graph (TODO on the given graph)
query: |
<<cyres-apinat-somas>>
- path: /dynamic/demos/apinat/housing-lyphs
operations:
- summary: List all the housing lyphs (neuronal processes) for all starting points.
query: |
<<cyres-apinat-housing-lyphs>>
- path: /dynamic/demos/apinat/housing-lyphs/{start-id}
operations:
- summary: List all the housing lyphs for a starting point.
parameters:
- name: start-id
description: ontology id of the starting point
paramType: path
query: |
<<cyres-apinat-housing-lyphs-start-id>>
- path: /dynamic/demos/apinat/soma-processes
operations:
- summary: List all the neuronal processes for all somas.
query: |
<<cyres-apinat-soma-processes>>
- path: /dynamic/demos/apinat/soma-processes/{start-id}
operations:
- summary: List all the neuronal processes for somas located in start-id.
parameters:
- name: start-id
description: ontology id of the starting point
paramType: path
query: |
<<cyres-apinat-soma-processes-start-id>>
- path: /dynamic/demos/apinat/weird-soma-processes/{process-id}
operations:
- summary: List all the neuronal processes for somas where some processes is in process-id.
parameters:
- name: process-id
description: ontology id of the starting point
paramType: path
query: |
<<cyres-apinat-weird-soma-processes-process-id>>
- path: /dynamic/demos/apinat/neru-1/{neupop-id}
operations: &neru-ops
- summary: Return the housing regions and publications for neurulated groups.
parameters:
- name: neupop-id
description: neuron population identifier
paramType: path
query: |
<<cypher-neru-1>>
- path: /dynamic/demos/apinat/neru-2/{neupop_id}
operations: *neru-ops
query: |
<<cypher-neru-2>>
- path: /dynamic/demos/apinat/neru-3/{neupop_id}
operations: *neru-ops
query: |
<<cypher-neru-3>>
- path: /dynamic/demos/apinat/neru-4/{neupop_id}
operations: *neru-ops
query: |
<<cypher-neru-4>>
- path: /dynamic/demos/apinat/neru-5/{neupop_id}
operations: *neru-ops
query: |
<<cypher-neru-5>>
- path: /dynamic/demos/apinat/neru-6/{neupop_id}
operations: *neru-ops
query: |
<<cypher-neru-6>>
- path: /dynamic/demos/apinat/neru-7/{neupop_id}
operations: *neru-ops
query: |
<<cypher-neru-7>>
- path: /dynamic/demos/apinat/graphList
operations:
- summary: <<nonl(desc-cypher-apinat-graphs())>>
query: |
<<cypher-apinat-graphs>>
- path: /dynamic/demos/apinat/modelList
operations:
- summary: <<nonl(desc-cypher-apinat-models())>>
query: |
<<cypher-apinat-models>>
- path: /dynamic/demos/apinat/modelPopulationsReferences/{model_id}
operations:
- summary: <<nonl(desc-cypher-apinat-model-pops-and-refs())>>
parameters:
- name: model_id
description: the identifier for an ApiNATOMY model
paramType: path
query: |
<<cypher-apinat-model-pops-and-refs>>
- path: /dynamic/prod/npo/hasTaxon/{id}
operations:
- summary: <<nonl(desc-npo-taxon())>>
parameters:
- name: id
description: the identifier of a neuron type
paramType: path
query: |
<<npo-taxon>>
Return any taxon associated with a neuron type.
MATCH (neupop:Class{iri: $id})
-[dimension:ilxtr:hasInstanceInSpecies!]->(taxon)
WHERE NOT EXISTS(dimension.owlType) OR dimension.owlType = "subClassOf" OR dimension.owlType = "operand"
RETURN taxon
MATCH (neupop)
-[dimension:ilxtr:hasPhenotype!]->(phenotype)
WHERE NOT EXISTS(dimension.owlType) OR dimension.owlType = "subClassOf" OR dimension.owlType = "operand"
RETURN phenotype
select distinct ?p (count(distinct ?neuron) as ?count) where {
?p rdfs:subPropertyOf* ilxtr:hasPhenotype .
?neuron (rdfs:subClassOf|(owl:equivalentClass/owl:intersectionOf/(rdf:rest|rdf:first)*)) [ owl:onProperty ?p ] .
?neuron rdfs:subClassOf* ?sckan_neuron .
values ?sckan_neuron { ilxtr:NeuronSparcNlp ilxtr:NeuronApinatSimple }
} group by ?p order by desc(?count)
TODO in order for this to work we have to be able to collapse the graph or customize the return value so we get dimension ae pairs
MATCH (neupop)
-[dimension:ilxtr:hasLocationPhenotype!]->(phenotype)
-[:property]->(prop:ObjectProperty{iri: "BFO:0000050"})
,
(phenotype)-[:filler]->(ae)
WHERE NOT EXISTS(dimension.owlType) OR dimension.owlType = "subClassOf" OR dimension.owlType = "operand"
RETURN ae
Extract the adjacency list directly.
select distinct
?s
?region_1 ?layer_1
?region_2 ?layer_2
where {
# common
?s ilxtr:neuronPartialOrder ?o .
?o (rdf:rest|rdf:first)* ?r1 .
?r1 (rdf:rest|rdf:first)* ?r2 .
{ # region region
?region_1 a owl:Class .
?region_2 a owl:Class .
?r1 rdf:first ?region_1 .
?r2 rdf:first ?region_2 .
filter (?mediator = ?r1) # draw only from the same partial order
?mediator rdf:first ?region_1 . # car
?mediator rdf:rest+/rdf:first/rdf:first ?region_2 . # caadr
}
union
{ # region layer region
?region_1 a owl:Class .
?layer_1 a owl:Class .
?region_2 a owl:Class .
?r1 rdf:first [ ?region_1 ?layer_1 ] .
?r2 rdf:first ?region_2 .
filter (?mediator = ?r1) # draw only from the same partial order
?mediator rdf:first [ ?region_1 ?layer_1 ] . # car
?mediator rdf:rest+/rdf:first/rdf:first ?region_2 . # caadr
}
union
{ # region region layer
?region_1 a owl:Class .
?region_2 a owl:Class .
?layer_2 a owl:Class .
?r1 rdf:first ?region_1 .
?r2 rdf:first [ ?region_2 ?layer_2 ] .
filter (?mediator = ?r1) # draw only from the same partial order
?mediator rdf:first ?region_1 . # car
?mediator rdf:rest+/rdf:first/rdf:first [ ?region_2 ?layer_2 ] . # caadr
}
union
{ # region layer region layer
?region_1 a owl:Class .
?layer_1 a owl:Class .
?region_2 a owl:Class .
?layer_2 a owl:Class .
?r1 rdf:first [ ?region_1 ?layer_1 ] .
?r2 rdf:first [ ?region_2 ?layer_2 ] .
filter (?mediator = ?r1) # draw only from the same partial order
?mediator rdf:first [ ?region_1 ?layer_1 ] . # car
?mediator rdf:rest+/rdf:first/rdf:first [ ?region_2 ?layer_2 ] . # caadr
}
} order by ?s ?region_1 ?layer_1 ?region_2 ?layer_2 limit 900
Can’t use cypher atm because owlapi doesn’t know what to do with nested lists. The same issue forced us to use pyontutils/rdflib to merge npo.ttl.
match path = //(Class:{iri: "mmset2:1"})
(s)-[:ilxtr:neuronPartialOrder]->(blank)
-[:rdf:rest|rdf:first*0..100]->(hrm)
return blank, hrm
Potential solution is to reserialize the nested list to output with something other than rdf:first and rdf:rest so that owlapi will parse it as blanknodes and allow it to load. The following seems to work and owlapi will preserve the nesting.
@prefix : <file:///ERROR/EMPTY/PREFIX/BANNED/> .
:asdf a owl:Class ;
rdfs:label "AAAAAAAAAAAAAAAAAAAAAAA" ;
:neuronPartialOrder
[ :first :a ;
:rest [
:first :b ;
:rest [
:first :c
] ] ] .
SPARQL works with a bit of a dance to ensure that each individual pair is extracted. To reconstruct the nested list tree structure start from nil and cons up iirc.
select distinct
?s
?r
?v
where
{
VALUES ?s { mmset1:1 }
?s ilxtr:neuronPartialOrder ?o .
?o (rdf:rest|rdf:first)* ?r .
?r rdf:rest|rdf:first ?v .
} order by ?s ?r ?v limit 900
import io
import csv
import requests
from urllib.parse import quote as url_quote
blazegraph_endpoint = 'http://localhost:9999/blazegraph/sparql'
def procq(res):
_, (str_count,) = res
return int(str_count)
def query(query, *, endpoint=blazegraph_endpoint, **kwargs):
qq = url_quote(query, safe='')
url = f'{endpoint}?query={qq}'
headers = {'Accept': 'text/csv'}
resp = requests.get(url, headers=headers)
return list(csv.reader(io.StringIO(resp.text)))
q = """
<<sparql-npo-query-raw-partial-order>>
"""
out = query(q)
mms1_1 = [o for o in out if o[0].endswith('mmset1/1')]
ends = []
for _, f, r in mms1_1: # TODO actually finish this
if r.endswith('#nil'):
ends.append(f)
return mms1_1
All ontology terms currently used by the whole body reference connectivity model.
MATCH (term:Class)-[:isDefinedBy]-(ont:Ontology{iri: "https://apinatomy.org/uris/models/wbrcm"})
RETURN term
from pyontutils.utils import Async, deferred
q = """
<<cyres-wbrcm-classes>>
"""
res = sgc.execute(q, limit=99999, output='application/json')
ilxn = [n for n in res['nodes'] if n['id'].startswith('ILX:')]
out = Async()(deferred(IlxTerm)(i['id']) for i in ilxn)
sus = [o for o in out if 'ilxtr:hasExistingId' in o.predicates and
not isinstance(o.predicates['ilxtr:hasExistingId'], tuple)]
csvstr = '\n'.join([','.join((s.iri, s.label)) for s in sus])
with open('/tmp/sus-wbrcm-ilx-terms-2023-02-01.csv', 'wt') as f:
f.write(csvstr)
Expected number of somas and neupops.
model-id | neupops | somas |
---|---|---|
ard-arm-cardiac | 12 | 41 |
bolser-lewis | 29 | 29 |
bronchomotor | 6 | 19 |
keast-bladder | 20 | 34 |
sawg-distal-colon | 17 | 23 |
sawg-stomach | 14 | 14 |
somas >= neupops
The number of somas for distinct populations in a given model.
the number of neuron populations as defined by the neurulator that have an ontology identifier
model-id | diag abbrev | external | somas | axons | axon term | dend | dend term |
---|---|---|---|---|---|---|---|
bolser-lewis | SCG | 17 | |||||
keast-bladder | |||||||
bronchomotor | |||||||
ard-arm-cardiac | |||||||
sawg-distal-colon | |||||||
sawg-stomach |
use NPO as a top down constraint on the locations of somas etc.
could do this by population or generically
soma-processes can also be checked using NPO but not needed for simple cases
model-id | neupop | diag abbrev | external |
---|---|---|---|
bolser-lewis | q | PN | |
bolser-lewis | q | C4 | |
bolser-lewis | q | PHRNIC | |
bolser-lewis | q | DIAPHRAGM |
bundles NPO here as well
model-id | diag abbrev | external | neupop |
---|---|---|---|
bolser-lewis | VAGUS | 9 total |
select distinct
?external
(str(?el) as ?label)
#?p
?model
#?region
#?link
#?neru
# ?seed
(replace(str(?neru), "^.+-([A-Za-z0-9]+)$", "$1") as ?neuron_number)
#?dyn
?neupop
where {
values ?external { UBERON:0006457 UBERON:0001894 UBERON:0005453 UBERON:0018683 }
?external a owl:Class ;
apinatomy:annotates ?region ;
rdfs:label ?el .
?region a elements:Lyph .
?model a elements:Graph ;
apinatomy:lyphs ?region .
?link ( apinatomy:fasciculatesIn | apinatomy:endsIn | apinatomy:layerIn | apinatomy:internalIn )+ ?region .
?neru apinatomy:links ?link ;
apinatomy:description ?dyn ;
a elements:Group .
filter contains(str(?dyn), "dynamic")
optional { ?neru apinatomy:ontologyTerms ?neupop . }
optional { ?seed apinatomy:seedIn ?neru . } # seedIn sort of works but misses cases where a dynamic group was created with a seed
}
order by str(?external) str(?model) xsd:integer(?neuron_number)
Expected.
external | diag abbrev | model-id | neupop |
---|---|---|---|
UBERON:0006457 | T1 | bolser-lewis | 1 2 3 6 7 |
UBERON:0006457 | T1 | keast-bladder | 20 |
UBERON:0001894 | DIENC | bolser-lewis | 1 26 |
UBERON:0001894 | Diencephalon | keast-bladder | 13 14 15 16 17 18 |
UBERON:0005453 | IMG | keast-bladder | 3 6 7 11 |
UBERON:0005453 | IMG | sawg-distal-colon | B D F G H Q |
UBERON:0018683 | LumSplN | keast-bladder | 6 7 11 |
UBERON:0018683 | LumSplN | sawg-distal-colon | B |
OWL DL query
hasLocationPhenotype some ('part of' some 'vagus nerve')
hasLocationPhenotype some ('part of' some 'vagus nerve nucleus')
hasLocationPhenotype some ('part of' some 'vagus nerve' or 'part of' some 'vagus nerve nucleus')
// filter out things that project to the vagus nerve not that start in the vagus nerve or something like that
(neupop)-[:ilxtr:hasLocationPhenotype]->(:Class{iri: UBERON:0001759})
(neupop)-[:ilxtr:hasAxonPresynapticElementIn]->(axon_locations)
(neupop)-[:ilxtr:hasSensorySubcellularElementIn]->(dendrite_locations)
Images of nerus that have some process in the IMG, from keast-bladder
and sawg-distal-colon
.
TODO point people to the query that returns a list of all neuron populations and all populations + papers per model
5 is going to be the easiest
RETURN region
Expected.
external | label |
---|---|
UBERON:0016508 | pelvic ganglion |
Input
UBERON:0005453 | inferior mesenteric ganglion |
Expect
ilxtr:neuron-type-keast-3 |
ilxtr:neuron-type-keast-6 |
ilxtr:neuron-type-keast-7 |
ilxtr:neuron-type-keast-11 |
ilxtr:neuron-type-sdcol-b |
ilxtr:neuron-type-sdcol-d |
ilxtr:neuron-type-sdcol-f |
ilxtr:neuron-type-sdcol-g |
ilxtr:neuron-type-sdcol-h |
ilxtr:neuron-type-sdcol-q |
simple sckan queries over blazegraph https://github.com/smtifahim/Loading-Simple-SCKAN/tree/main/sckan-to-simple-sckan
insert { ?s ?np ?o }
<<simple-sckan-load-1-where>>
#select (count(*) as ?c) {
select distinct ?s ?o
where
{
#?s nposimtest:hasSomaLocatedIn ?o
?s nposimtest:hasDendriteLocatedIn ?o
} order by ?s ?o
#}
PREFIX nposimtest: <http://uri.interlex.org/tgbugs/uris/readable/npo-simple-test-1/>
SELECT (COUNT(*) as ?count) {
<<simple-sckan-load-1>>
}
#PREFIX nposimtest: <http://uri.interlex.org/tgbugs/uris/readable/npo-simple-test-1/>
select
distinct ?s ?np ?o
<<simple-sckan-load-1-where>>
order by ?s ?np ?o
limit 5000
where
{
{
values (?p ?np) {
(ilxtr:hasAxonPresynapticElementIn nposimtest:hasAxonPresynapticElementIn)
(ilxtr:hasSomaLocatedIn nposimtest:hasSomaLocatedIn)
#(ilxtr:hasSomaLocatedIn nposimtest:hasAxonLocatedIn) # add inferred axon locations (decided to exclude)
(ilxtr:hasAxonLocatedIn nposimtest:hasAxonLocatedIn)
(ilxtr:hasDendriteLocatedIn nposimtest:hasDendriteLocatedIn)
(ilxtr:hasAxonSensorySubcellularElementIn nposimtest:hasAxonSensorySubcellularElementIn)
#(ilxtr:hasAxonPresynapticElementIn ilxtr:hasAxonTerminalLocation)
#(ilxtr:hasSomaLocatedIn ilxtr:hasSomaLocation)
#(ilxtr:hasAxonLocatedIn ilxtr:hasAxonLocation)
#(ilxtr:hasDendriteLocatedIn ilxtr:hasDendriteLocation)
#(ilxtr:hasAxonSensorySubcellularElementIn ilxtr:hasAxonSensoryLocation)
}
?s owl:equivalentClass [
rdf:type owl:Class ;
owl:intersectionOf ?bn0
] .
?bn0 rdf:rest*/rdf:first ilxtr:NeuronApinatSimple .
?bn0 rdf:rest*/rdf:first [
rdf:type owl:Restriction ;
owl:onProperty ?p ;
owl:someValuesFrom [
a owl:Restriction ;
owl:onProperty partOf: ;
owl:someValuesFrom ?o
] ]
}
union
{
values (?p ?np) {
(ilxtr:hasForwardConnectionPhenotype nposimtest:hasForwardConnectionPhenotype)
(ilxtr:hasFunctionalCircuitRolePhenotype nposimtest:hasFunctionalCircuitRolePhenotype)
}
?s owl:equivalentClass [
rdf:type owl:Class ;
owl:intersectionOf ?bn0
] .
?bn0 rdf:rest*/rdf:first ilxtr:NeuronApinatSimple .
?bn0 rdf:rest*/rdf:first [
rdf:type owl:Restriction ;
owl:onProperty ?p ;
owl:someValuesFrom ?o ]
}}
If you are running a local instance of blazegraph go to the update tab. For example at http://localhost:9999/blazegraph/#update.
Under the Type
dropdown select RDF Data
and under the Format
dropdown select Turtle
. Download simple-sckan-properties.ttl
linked below to a convenient location and then select it to upload.
The switch the type to SPARQL Update
and run the insert statements
below (the corresponding queries are below).
If on production requires port forwarding from aws-stardog LocalForward 9889 localhost:9999
.
Direct execution doesn’t seem to be working right now via ob-sparql
.
INSERT {?neuron_type ?npo_simple_prop ?object}
<<simple-sckan-load-2-where>>
INSERT { ?sub_region ilxtr:isPartOf ?super_region }
<<simple-sckan-uberon-where>>
WHERE
{
VALUES (?npo_prop ?npo_simple_prop)
{
# mapping properties for locational phenotypes
(ilxtr:hasAxonPresynapticElementIn ilxtr:hasAxonTerminalLocation)
(ilxtr:hasSomaLocatedIn ilxtr:hasSomaLocation)
(ilxtr:hasSomaLocatedInLayer ilxtr:hasSomaLocation)
(ilxtr:hasAxonLocatedIn ilxtr:hasAxonLocation)
(ilxtr:hasDendriteLocatedIn ilxtr:hasDendriteLocation)
(ilxtr:hasAxonSensorySubcellularElementIn ilxtr:hasAxonSensoryLocation)
# treat all locational phenotype properties above as hasConnectedLocation in NPO-Simple/Simple SCKAN
(ilxtr:hasAxonPresynapticElementIn ilxtr:hasConnectedLocation)
(ilxtr:hasSomaLocatedInLayer ilxtr:hasConnectedLocation)
(ilxtr:hasSomaLocatedIn ilxtr:hasConnectedLocation)
(ilxtr:hasAxonLocatedIn ilxtr:hasConnectedLocation)
(ilxtr:hasDendriteLocatedIn ilxtr:hasConnectedLocation)
(ilxtr:hasAxonSensorySubcellularElementIn ilxtr:hasConnectedLocation)
# mapping properties for other phenotypes
(ilxtr:hasForwardConnectionPhenotype ilxtr:hasForwardConnection)
(ilxtr:hasFunctionalCircuitRolePhenotype ilxtr:hasFunctionalCircuitRole)
(ilxtr:hasAnatomicalSystemPhenotype ilxtr:hasNeuronalPhenotype) #changed from ilxtr:hasPhenotype to ilxtr:hasAnatomicalSystemPhenotype
(ilxtr:hasProjectionPhenotype ilxtr:hasProjection)
(ilxtr:hasCircuitRolePhenotype ilxtr:hasCircuitRole)
(ilxtr:hasInstanceInTaxon ilxtr:isObservedInSpecies)
(ilxtr:hasBiologicalSex ilxtr:hasPhenotypicSex)
}
# For the neuron types with locational phenotypes specified withing the intersections of the equivalent axioms.
{
?neuron_type a owl:Class;
(owl:equivalentClass | rdfs:subClassOf)
[
rdf:type owl:Class ;
owl:intersectionOf ?bn0
] .
?bn0 rdf:rest*/rdf:first [
rdf:type owl:Restriction ;
owl:onProperty ?npo_prop ;
owl:someValuesFrom [
a owl:Restriction ;
owl:onProperty partOf: ;
owl:someValuesFrom ?object
]
] .
}
UNION # For the neuron types with locational phenotype axioms as super classes e.g., http://uri.neuinfo.org/nif/nifstd/nlx_cell_20081201
{
?neuron_type a owl:Class;
(rdfs:subClassOf)
[
rdf:type owl:Restriction ;
owl:onProperty ?npo_prop ;
owl:someValuesFrom [rdf:type owl:Restriction ;
owl:onProperty partOf: ;
owl:someValuesFrom ?object
]
] .
}
UNION # For neuron types with other phenotypes specified within the intersections of the eqivalent axioms.
{
?neuron_type a owl:Class;
(owl:equivalentClass | rdfs:subClassOf)
[
rdf:type owl:Class ;
owl:intersectionOf ?bn0
] .
?bn0 rdf:rest*/rdf:first [
rdf:type owl:Restriction ;
owl:onProperty ?npo_prop ;
owl:someValuesFrom ?object
]
}
UNION # For neuron types with other phenotypes axioms specified as superclasses.
{
?neuron_type a owl:Class;
(rdfs:subClassOf)
[
rdf:type owl:Restriction ;
owl:onProperty ?npo_prop ;
owl:someValuesFrom ?object
]
}
FILTER (!isBLANK(?object))
}
# Select DISTINCT ?sub_region ?sub_region_label ?super_region ?super_region_label
WHERE
{
# Filter (?super_region_label = 'pancreas')
?super_region rdfs:subClassOf+ <http://purl.obolibrary.org/obo/UBERON_0001062>. #subclass of 'anatomical entity'
?sub_region rdfs:subClassOf+ <http://purl.obolibrary.org/obo/UBERON_0001062>.
?sub_region rdfs:subClassOf+ [rdf:type owl:Restriction ;
owl:onProperty partOf: ;
owl:someValuesFrom ?super_region].
# ?sub_region ilxtr:isPartOf+ ?super_region.
?sub_region rdfs:label ?sub_region_label.
?super_region rdfs:label ?super_region_label.
Filter (!REGEX(str(?sub_region), "CL_")) #exclude CL classes
Filter (!REGEX(str(?super_region), "CL_")) #exclude CL classes
# FILTER (?sub_region != ?super_region)
}
sigh Subqueries in SPARQL
#PREFIX partOf: <http://purl.obolibrary.org/obo/BFO_0000050>
#PREFIX owl: <http://www.w3.org/2002/07/owl#>
#PREFIX TEMP: <http://uri.interlex.org/temp/uris/>
#PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
insert
{ ?region TEMP:partOf ?region2 }
where {
?region rdfs:subClassOf ?rest .
?rest a owl:Restriction ; owl:onProperty partOf: ; owl:someValuesFrom ?region2 .
}
select
?region
(str(?rl) as ?label)
where {
#?region (rdfs:subClassOf|TEMP:partOf)* UBERON:0001016 .
#?region (rdfs:subClassOf|TEMP:partOf)* UBERON:0000010 . # FIXME peripheral nervous system partonomy is utterly broken ???
#?region TEMP:partOf+ UBERON:0000010 .
optional {
?region rdfs:label ?rl .
}
} limit 99
select
?region
#TEMP:partOf
?region2
where {
?region rdfs:subClassOf ?rest .
?rest a owl:Restriction ; owl:onProperty partOf: ; owl:someValuesFrom ?region2 .
} limit 10
Other queries run against various representations of the data.
jq -c '.datasets | length'
jq -c '[paths | select(.[-1] == "path_metadata")] | length'
function path-metadata-coverage () {
local PATH_EXPORT_JSON=$1
local COUNT_T=$(<<&jq-count-datasets()>> "${PATH_EXPORT_JSON}")
local COUNT_PM=$(<<&jq-count-path-metadata()>> "${PATH_EXPORT_JSON}")
awk -v t=${COUNT_T} -v pm=${COUNT_PM} 'BEGIN { print ( pm / t ) }'
}
General metadata and housekeeping queries.
SELECT ?s WHERE { ?s a owl:Ontology }
MATCH (o:Ontology) RETURN o
select distinct ?p ?l where { ?s ?p ?o . optional { ?p rdfs:label ?l . } } order by ?p
select ?s ?p ?o where {
values ?p { prov:startedAtTime prov:wasGeneratedBy dc:date owl:versionInfo TEMP:TimestampExportStart }
?s ?p ?o . } order by desc(str(?o))
Useful version information is not present in all ontology files at the moment.
SELECT ?p ?o WHERE {
build:prov ?p ?o .
}
MATCH
(p)-[i:build:id]-(),
(p)-[e]-()
RETURN i, e
select ?s ?tes ?vi where {
?s TEMP:TimestampExportStart ?tes ;
owl:versionInfo ?vi .
}
select distinct ?o where {
<https://cassava.ucsd.edu/sparc/ontologies/protcur.ttl> owl:versionInfo ?o
}
MATCH ({iri: "https://apinatomy.org/uris/elements/Graph"})<-[:type]-(g)<-[e:apinatomy:hasGraph]-(o:Ontology) RETURN g, e, o
# py-safe-block
from pyontutils.core import OntGraph
g = OntGraph().parse(data=input, format='ttl')
#return [[g.namespace_manager._qhrm(_)] for _ in sorted(set(g.subjects()))]
return ' '.join([g.namespace_manager._qhrm(_) for _ in sorted(set(g.subjects()))])
@prefix l: <http://www.w3.org/2000/01/rdf-schema#label> .
@prefix e: <http://uri.interlex.org/tgbugs/uris/readable/hasExistingId> .
@prefix FMA: <http://purl.org/sig/ont/fma/fma> .
@prefix UBERON: <http://purl.obolibrary.org/obo/UBERON_> .
# tissue
UBERON:0001013 l: "adipose tissue"; e: FMA:20110 .
# regions
UBERON:0002298 l: "brainstem"; e: FMA:79876 .
UBERON:0001016 l: "nervous system"; e: FMA:7157 .
UBERON:0000010 l: "peripheral nervous system"; e: FMA:9903 .
UBERON:0000013 l: "sympathetic nervous system"; e: FMA:9906 .
UBERON:0002005 l: "enteric nervous system"; e: FMA:66070 .
# TODO cardiovascular system # e.g. for blood pressure
# TODO cardiopulmonary system
# organs
UBERON:0000955 l: "brain"; e: FMA:50801 .
UBERON:0001155 l: "colon"; e: FMA:14543 .
UBERON:0002110 l: "gallbladder"; e: FMA:7202 .
UBERON:0000948 l: "heart"; e: FMA:7088 .
UBERON:0000160 l: "intestine"; e: FMA:7199 .
UBERON:0002113 l: "kidney"; e: FMA:7203 .
UBERON:0000059 l: "large intestine"; e: FMA:7201 .
UBERON:0002107 l: "liver"; e: FMA:7197 .
UBERON:0001556 l: "lower urinary tract"; e: FMA:45659 .
UBERON:0002048 l: "lung"; e: FMA:68877 .
UBERON:0001630 l: "muscle organ"; e: FMA:5022 .
UBERON:0001264 l: "pancreas"; e: FMA:7198 .
UBERON:0002097 l: "skin of body"; e: FMA:7163 .
UBERON:0002108 l: "small intestine"; e: FMA:7200 .
UBERON:0002240 l: "spinal cord"; e: FMA:7647 .
UBERON:0002106 l: "spleen"; e: FMA:7196 .
UBERON:0000945 l: "stomach"; e: FMA:7148 .
UBERON:0001255 l: "urinary bladder"; e: FMA:15900 .
# granular
UBERON:0000057 l: "urethra"; e: FMA:19667 .
UBERON:0001043 l: "esophagus"; e: FMA:7131 .
@prefix l: <http://www.w3.org/2000/01/rdf-schema#label> .
@prefix e: <http://uri.interlex.org/tgbugs/uris/readable/hasExistingId> .
@prefix FMA: <http://purl.org/sig/ont/fma/fma> .
@prefix UBERON: <http://purl.obolibrary.org/obo/UBERON_> .
# XXX sciatic nerve is missing from this list
# not actually cranial
UBERON:0002019 l: "accessory XI nerve"; e: FMA:6720 . # missing from the larger list
# nerves missing from the larger list
UBERON:0001646 l: "abducens nerve"; e: FMA:50867 .
UBERON:0001650 l: "hypoglossal nerve"; e: FMA:50871 .
UBERON:0001579 l: "olfactory nerve"; e: FMA:46787 .
UBERON:0001644 l: "trochlear nerve"; e: FMA:50865 .
UBERON:0003723 l: "vestibulocochlear nerve"; e: FMA:50869 .
# the larger list
UBERON:0034728 l: "autonomic nerve" .
UBERON:0009009 l: "carotid sinus nerve" .
UBERON:0009675 l: "chorda tympani branch of facial nerve" .
UBERON:0019198 l: "dorsal nerve of clitoris" .
UBERON:0019197 l: "dorsal nerve of penis" .
UBERON:0010380 l: "enteric nerve" .
UBERON:0010406 l: "cholinergic enteric nerve" .
UBERON:0001647 l: "facial nerve"; e: FMA:50868 .
UBERON:0001649 l: "glossopharyngeal nerve"; e: FMA:50870 .
UBERON:0001643 l: "oculomotor nerve"; e: FMA:50864 .
UBERON:0002924 l: "terminal nerve" .
UBERON:0001645 l: "trigeminal nerve"; e: FMA:50866 .
UBERON:0001759 l: "vagus nerve"; e: FMA:5731 .
# TODO vagus nerve branches
UBERON:0018680 l: "greater splanchnic nerve" .
UBERON:0003438 l: "iris nerve" .
UBERON:0011096 l: "lacrimal nerve" .
UBERON:0035642 l: "laryngeal nerve" .
UBERON:0011766 l: "left recurrent laryngeal nerve" .
UBERON:0011767 l: "right recurrent laryngeal nerve" .
UBERON:0003716 l: "recurrent laryngeal nerve" .
UBERON:0011326 l: "superior laryngeal nerve" .
UBERON:3010764 l: "laryngeus ventralis" .
UBERON:0001964 l: "least splanchnic nerve" .
UBERON:0018681 l: "lesser splanchnic nerve" .
UBERON:0003721 l: "lingual nerve" .
UBERON:0022301 l: "long ciliary nerve" .
UBERON:0018683 l: "lumbar splanchnic nerve" .
UBERON:0000377 l: "maxillary nerve" .
UBERON:0036143 l: "meningeal branch of mandibular nerve" .
UBERON:0017641 l: "meningeal branch of spinal nerve" .
UBERON:0022300 l: "nasociliary nerve" .
UBERON:0008810 l: "nasopalatine nerve" .
UBERON:0035650 l: "nerve of clitoris" .
UBERON:0035649 l: "nerve of penis" .
UBERON:0015162 l: "superior branch of oculomotor nerve" .
UBERON:0018675 l: "pelvic splanchnic nerve" .
UBERON:0011391 l: "perineal nerve" .
UBERON:0001884 l: "phrenic nerve" .
UBERON:0034725 l: "pterygopalatine nerve" .
UBERON:0011390 l: "pudendal nerve" .
UBERON:0009625 l: "sacral nerve" .
UBERON:0018684 l: "sacral splanchnic nerve" .
UBERON:0022302 l: "short ciliary nerve" .
UBERON:0003715 l: "splanchnic nerve" .
UBERON:0018679 l: "thoracic splanchnic nerve" .
UBERON:0001323 l: "tibial nerve" .
UBERON:0036216 l: "tympanic nerve" .
UBERON:0018412 l: "vidian nerve" .
# cervical nerve
UBERON:0000962 l: "nerve of cervical vertebra"; e: FMA:5859 .
UBERON:0002439 l: "myenteric nerve plexus"; e: FMA:63252 .
distributed ganglion that has not ensheathed there may be significant variablity between individuals in whether a plexius is fully ganglionated/ensheathed
the issue is that from the perspective the cell populations, they are actually the same population regardless of whether they are plexi or ganglia
maybe need to get these to converge onto the neuron populations so that we can merge the two
@prefix l: <http://www.w3.org/2000/01/rdf-schema#label> .
@prefix e: <http://uri.interlex.org/tgbugs/uris/readable/hasExistingId> .
@prefix syn: <http://uri.neuinfo.org/nif/nifstd/readable/synonym> .
@prefix FMA: <http://purl.org/sig/ont/fma/fma> .
@prefix UBERON: <http://purl.obolibrary.org/obo/UBERON_> .
UBERON:0001808 l: "parasympathetic ganglion" .
UBERON:0035776 l: "accessory ciliary ganglion" .
UBERON:0001805 l: "autonomic ganglion"; e: FMA:5889 .
UBERON:0014463 l: "cardiac ganglion" .
UBERON:0002262 l: "celiac ganglion" .
UBERON:0035783 l: "ganglion of ciliary nerve" .
UBERON:0001701 l: "glossopharyngeal ganglion" .
UBERON:0005360 l: "inferior glossopharyngeal IX ganglion" .
UBERON:0013500 l: "glossopharyngeal-vagus IX-X ganglion complex" .
UBERON:0035769 l: "mesenteric ganglion" .
UBERON:0005479 l: "superior mesenteric ganglion" .
UBERON:0005453 l: "inferior mesenteric ganglion" .
UBERON:0001989 l: "superior cervical ganglion" .
UBERON:0001990 l: "middle cervical ganglion" .
UBERON:0002440 l: "inferior cervical ganglion" .
UBERON:0003963 l: "otic ganglion" .
UBERON:0001807 l: "paravertebral ganglion" .
UBERON:0016508 l: "pelvic ganglion" .
UBERON:0003964 l: "prevertebral ganglion" .
UBERON:0003962 l: "pterygopalatine ganglion" .
UBERON:0005407 l: "sublingual ganglion" .
UBERON:0002059 l: "submandibular ganglion" .
UBERON:0001806 l: "sympathetic ganglion" .
UBERON:0005362 l: "vagus X ganglion" .
UBERON:0005364 l: "superior vagus X ganglion" .
UBERON:0005363 l: "inferior vagus X ganglion"; syn: "nodose ganglion" .
UBERON:0000408 l: "vertebral ganglion" .
UBERON:0002441 l: "cervicothoracic ganglion"; e: FMA:6469; syn: "stellate ganglion" .
select distinct
?organ_start
?label
(count(distinct(?ele)) as ?elements)
#?elements
?model
#?ele
#?type
# ?sp
#?s
#?op_wat
#?p
#?o
where {
values ?organ_start {
<<organ-subjects()>>
<<ganglia-subjects()>>
<<nerve-subjects()>>
}
?organ_start rdfs:label ?sl .
bind(str(?sl) as ?label)
# FIXME TODO traverse partonomy
optional {
values ?type { elements:Lyph elements:Group elements:Material elements:Chain }
?organ ( partOf: | rdfs:subClassOf )* ?organ_start .
#?organ apinatomy:annotates ?ele .
?ele apinatomy:ontologyTerms ?organ .
?ele a ?type .
?model ( apinatomy:lyphs | apinatomy:chains | apinatomy:groups | apinatomy:materials ) ?ele .
?model a elements:Graph .
#?ele apinatomy:inheritedOntologyTerms ?organ .
#?o ?p ?q .
}
}
group by ?organ_start ?label ?model
order by ?organ_start
#order by ?type ?organ ?model
#limit ?limit
https://docs.google.com/spreadsheets/d/1pgprwTr4bvAaex8cNLeoRLUgt0VU5tilbWi4BCWF1JE/edit#gid=219324374
organ-nerve-ganglia
select distinct
?part_start
(str(?sl) as ?start_label)
where {
?part_start rdfs:subClassOf+/owl:someValuesFrom+ UBERON:0001255 .
?part_start rdfs:label ?sl .
}
the nested version here is massively slow
select distinct
?part
(str(?l) as ?label)
where {
values ?part_0 { UBERON:0001255 }
#?part_1 rdfs:label ?l1 .
?part_1 rdfs:subClassOf ?bn0 .
?bn0 a owl:Restriction .
?bn0 owl:onProperty partOf: .
?bn0 owl:someValuesFrom ?part_0 .
optional {
#?part_2 rdfs:label ?l2 .
?part_2 rdfs:subClassOf ?bn1 .
?bn1 a owl:Restriction .
?bn1 owl:onProperty partOf: .
?bn1 owl:someValuesFrom ?part_1 .
optional {
#?part_3 rdfs:label ?l3 .
?part_3 rdfs:subClassOf ?bn2 .
?bn2 a owl:Restriction .
?bn2 owl:onProperty partOf: .
?bn2 owl:someValuesFrom ?part_2 .
}
}
#optional {
#?part_4 rdfs:label ?l4 .
#?part_4 rdfs:subClassOf ?bn3 .
#?bn3 a owl:Restriction .
#?bn3 owl:onProperty partOf: .
#?bn3 owl:someValuesFrom ?part_3 .
#}
?part a owl:Class .
?part rdfs:label ?l .
filter ( ?part = ?part_0 || ?part = ?part_1 || ?part = ?part_2 || ?part = ?part_3 ) #( || ?part = ?part_4 )
}
limit ?limit
select distinct
?part_1
where {
values ?part_0 { UBERON:0009958 }
?part_1 rdfs:label ?l .
?part_1 rdfs:subClassOf ?bn0 .
?bn0 a owl:Restriction .
?bn0 owl:onProperty partOf: .
?bn0 owl:someValuesFrom ?part_0 .
}
select distinct
?sigh
(str(?l) as ?label)
#?sigx
#(str(?lx) as ?labx)
where {
?sigh rdfs:subClassOf+/owl:someValuesFrom+ UBERON:0001255 . # consider also RO:0002433 usually go together
?sigh rdfs:label ?l .
# FIXME somehow male and female urethra are still being pulled in :/
#filter ( ?sigh != UBERON:0000057 )
#filter not exists { ?sigh rdfs:subClassOf/owl:someValuesFrom UBERON:0000057 . }
?sigh rdfs:subClassOf/owl:onProperty partOf: .
#?sigx rdfs:subClassOf ?bn .
#?bn a owl:Restriction .
#?bn owl:onProperty partOf: .
#?bn owl:someValuesFrom ?sigh .
#?sigx rdfs:label ?lx .
filter not exists { ?sigh rdfs:subClassOf/owl:onProperty <http://purl.obolibrary.org/obo/uberon/core#channels_into> . }
filter not exists { ?sigh rdfs:subClassOf/owl:onProperty <http://purl.obolibrary.org/obo/uberon/core#channels_from> . }
filter not exists { ?sigh rdfs:subClassOf/owl:onProperty BFO:0000051 . }
filter not exists { ?sigh rdfs:subClassOf/owl:onProperty RO:0002150 . }
filter not exists { ?sigh rdfs:subClassOf/owl:onProperty RO:0002221 . }
filter not exists { ?sigh rdfs:subClassOf/owl:onProperty RO:0002178 . }
}
order by ?label
select distinct
?part
?prop
(str(?l) as ?label)
?part_start
(str(?sl) as ?start_label)
where {
values ?wat { UBERON:0001255 }
# FIXME this is still completely broken because sparql and
# transitive queries over over owl restrictions are ... problematic
?part_start rdfs:subClassOf+/owl:someValuesFrom+ ?wat .
filter ( ?prop = partOf: )
?part_start rdfs:label ?sl .
?part_start rdfs:subClassOf ?bny .
?bny owl:onProperty ?prop .
?part rdfs:label ?l .
?part rdfs:subClassOf ?bn0 .
?bn0 a owl:Restriction .
?bn0 owl:onProperty partOf: .
?bn0 owl:someValuesFrom ?part_start .
}
order by ?start_label
from sparcur.sheets import Reports
class ONGRep:
_data = data
class options:
preview = False
to_sheets = True
@Reports.makeReportSheet('organ_start', sheet_name='organ-nerve-ganglia')
def populate(self, ext=None):
return self._data, 'organ-nerve-ganglia coverage report'
t = ONGRep()
#t.populate()
return t._data
1 + 2
from pyontutils.core import OntTerm
asdf = ['ILX:0727875',
'ILX:0727396',
'ILX:0727235',
'ILX:0736783',
'ILX:0725331',
'ILX:0724284',
'ILX:0732483',
'ILX:0725803',
'ILX:0723837',
'ILX:0737036',
'ILX:0725086',
'ILX:0736097',
'ILX:0733375',
'ILX:0730739',
'ILX:0734588',
'ILX:0728741',
'ILX:0728157',
'ILX:0724431',
'ILX:0728322',
'ILX:0486534',
'ILX:0731053',
'ILX:0734339',
'ILX:0731969',
'ILX:0726449',
'ILX:0734582',
'ILX:0731914',
'ILX:0729870',
'ILX:0728987',
'ILX:0736712',
'ILX:0735649',
'ILX:0730231',
'ILX:0725969',
'ILX:0725552',
'ILX:0729045',
'ILX:0732611',
'ILX:0724152',
'ILX:0724140',
'ILX:0736057',
'ILX:0726733',
'ILX:0735212',
'ILX:0726145',
'ILX:0736880',
'ILX:0732740',
'ILX:0730942',
'ILX:0736020',
'ILX:0733193',
'ILX:0733995',
'ILX:0503992',
'ILX:0734328',
'ILX:0724764',
'ILX:0729794',
'ILX:0734607',
'ILX:0727602',
'ILX:0735024',
'ILX:0725520',
'ILX:0728778',
'ILX:0726312',
'ILX:0733021',
'ILX:0732970',
'ILX:0725326',
'ILX:0725956',
'ILX:0726454',
'ILX:0734766',
'ILX:0733700',
'ILX:0733004',
'ILX:0732328',
'ILX:0735011',
'ILX:0734057',
'ILX:0730509',
'ILX:0727725',
'ILX:0730966',
'ILX:0729052',
'ILX:0736358',
'ILX:0727970',
'ILX:0736369']
qq = [OntTerm(a) for a in asdf]
[(repr(_), _('ilxtr:hasIlxPreferredId')[0].curie) for _ in qq]
start of a query that is similar to neru-7 but allows direct extraction of partial orders using sparql instead of needing to do an extended cypher load, this can probably be simplified significantly by deriving the partial order using only links and then finding the housing region/layer for each link see also region-populations
select distinct
?pop
#?link
#?region
#?link1
#?link2
#?l1
?region1 ?term_layer1
#?l2
?region2 ?term_layer2
where {
#?pop rdfs:subClassOf+ ilxtr:Neuron .
?pop apinatomy:annotates ?ngrp .
?ngrp apinatomy:description ?dyn .
filter contains(str(?dyn), "dynamic")
{
?ngrp apinatomy:lyphs ?lyph .
?lyph a elements:Lyph .
{
?lyph apinatomy:internalIn ?housing_lyph .
}
union
{
?lyph apinatomy:internalIn ?housing_layer .
?housing_layer apinatomy:layerIn ?housing_lyph .
?housing_layer apinatomy:ontologyTerms ?term_layer1
}
?housing_lyph apinatomy:conveys ?s_link0 .
?housing_lyph apinatomy:ontologyTerms ?region1 .
?lyph apinatomy:conveys ?soma_link .
#?soma_link apinatomy:source/apinatomy:targetOf|apinatomy:target/apinatomy:sourceOf ?soma_next . # XXX this doesn't work, because the apinatomy representation has explicit directionality when working with node/link graphs so we use rootOf which is bad because it assumes a chain, which is an abstraction that probably shouldn't be used for queries, but whatever
?soma_link apinatomy:source|apinatomy:target ?soma_node .
?soma_node apinatomy:rootOf ?some_chain .
?soma_node apinatomy:sourceOf|apinatomy:targetOf ?soma_next_link .
?some_chain apinatomy:levels ?soma_next_link .
?soma_next_link a elements:Link .
?soma_next_link apinatomy:conveyingLyph ?soma_next_lyph .
{
?soma_next_lyph apinatomy:internalIn ?snx_housing_lyph .
}
union
{
?soma_next_lyph apinatomy:internalIn ?snx_housing_layer .
?snx_housing_layer apinatomy:layerIn ?snx_housing_lyph .
?snx_housing_layer apinatomy:ontologyTerms ?term_layer2
}
?snx_housing_lyph apinatomy:conveys ?s_link3 .
?snx_housing_lyph apinatomy:ontologyTerms ?region2 .
}
union
{
?ngrp apinatomy:links ?link .
?link a elements:Link .
#?link (apinatomy:fasciculatesIn|apinatomy:endsIn)* ?lyph_or_layer .
#?lyph_or_layer apinatomy:layerIn* ?lyph .
#?lyph apinatomy:conveys* ?some_other_link .
#?lyph apinatomy:ontologyTerms ?region .
#?link apinatomy:conveyingLyph ?cl .
#?cl apinatomy:topology ?cl_topo ;
#apinatomy:interitedOntologyTerms* ?cl_iot .
?link (apinatomy:next|apinatomy:nextChainStartLevels)* ?link1 .
#?link1 apinatomy:target+ ?node1 .
#?node1 apinatomy:rootOf+ ?chain1 .
#?chain1 apinatomy:levels+ ?link2 .
#?ngrp apinatomy:links ?b3 . # this line doesn't work quite the same way it does in cypher because it implies ?b3 = ?link
filter (?l1 = ?link1)
?l1 apinatomy:next|apinatomy:nextChainStartLevels ?l2 .
?l1 a elements:Link .
{
?l1 apinatomy:fasciculatesIn|apinatomy:endsIn ?lyph1 .
?lyph1 apinatomy:conveys ?some_other_link1 ;
apinatomy:ontologyTerms ?region1 .
}
union
{
?l1 apinatomy:fasciculatesIn|apinatomy:endsIn ?layer1 .
?layer1 apinatomy:layerIn ?lyph1 .
?layer1 apinatomy:ontologyTerms ?term_layer1 .
?lyph1 apinatomy:conveys ?some_other_link1 ;
apinatomy:ontologyTerms ?region1 .
}
?l2 a elements:Link .
{
?l2 apinatomy:fasciculatesIn|apinatomy:endsIn ?lyph2 .
?lyph2 apinatomy:conveys ?some_other_link2 ;
apinatomy:ontologyTerms ?region2 .
}
union
{
?l2 apinatomy:fasciculatesIn|apinatomy:endsIn ?layer2 .
?layer2 apinatomy:layerIn ?lyph2 .
?layer2 apinatomy:ontologyTerms ?term_layer2 .
?lyph2 apinatomy:conveys ?some_other_link2 ;
apinatomy:ontologyTerms ?region2 .
}
#union # don't run this it will be a disaster
#{
#?lyph apinatomy:internalIn ?housing_lyph .
#?housing_lyph apinatomy:ontologyTerms ?region1 . # FIXME this is surely wrong
#}
# TODO need soma links
#apinatomy:fasciculatesIn|apinatomy:endsIn ?lyph_or_layer1 .
#?lyph_or_layer1 apinatomy:layerIn* ?lyph1 .
#?lyph1 apinatomy:conveys* ?some_other_link1 .
#?lyph1 apinatomy:ontologyTerms ?region1 .
#?l2 a elements:Link ;
#(apinatomy:fasciculatesIn|apinatomy:endsIn)? ?lyph_or_layer2 .
#?lyph_or_layer2 apinatomy:layerIn* ?lyph2 .
#?lyph2 apinatomy:conveys* ?some_other_link2 .
#?lyph2 apinatomy:ontologyTerms ?region2 .
}
}
order by str(?pop)
#limit 99
q_sn7 = """
<<sparql-neru-7>>
"""
q_sn7_out = query(q_sn7)
pops = set(r[0] for r in q_sn7_out[1:]) # XXX clearly missing some populations from the list such as aacar-10v aacar-14 etc.
#print(sorted(pops))
Unclaimed regions from FMA/UBERON in the TOO map
Define the TOO map as the covering set of terms. It might not actually be, but that is how we will treat it. Probably want to avoid the immaterial entities.
Try to come up with a basis set from FMA as well.
If there are regional hierarchies that have been missed we will see them.
SELECT distinct ?o
WHERE {
?o a elements:Graph .
} order by str(?o)
select distinct
?graph
?lyphs
?label
WHERE {
# ?model apinatomy:hasGraph ?graph # TODO broken conversion to literal instead of uri at the moment
# sadly it seems that no one has managed to write an optimization that converts
# into this form when querying multiple predicates in the same expression
{
?graph a elements:Graph ;
rdfs:label ?label .
{ select ?graph (count(distinct(?o)) as ?lyphs ) where { ?graph apinatomy:lyphs ?o . } group by ?graph }
}
union
{
{ select (count(distinct(?graph_)) as ?graph ) where { ?graph_ a elements:Graph } }
bind("Total unique" as ?label)
{ select (count(distinct(?o)) as ?lyphs ) where { ?graph_ apinatomy:lyphs ?o . } }
} }
label | graph | lyphs | lyphs_input | externals | publications | nerus | neupops | neupops_pat | somas |
---|---|---|---|---|---|---|---|---|---|
ApiNATOMY model of the stomach | sstom:sawg-stomach | 668 | 37 | 77 | 8 | 14 | 14 | 14 | 14 |
Ardell Armour Cardiac Model | aacar:ard-arm-cardiac | 1827 | 137 | 161 | 2 | 17 | 17 | 17 | 41 |
Bolser-Lewis Model of the Physiology of the Superior Cervical Ganglion | bolew:bolser-lewis | 1151 | 107 | 141 | 239 | 29 | 29 | 29 | 29 |
Keast ApiNATOMY model of bladder innervation | kblad:keast-bladder | 2394 | 139 | 174 | 30 | 21 | 20 | 20 | 35 |
SAWG ApiNATOMY model of the descending colon | sdcol:sawg-distal-colon | 1066 | 89 | 135 | 5 | 18 | 18 | 18 | 24 |
SPARC Bronchomotor Flatmap | bromo:bronchomotor | 623 | 144 | 187 | 6 | 6 | 6 | 6 | 19 |
pancreas model | pancr:pancreas | 452 | 17 | 529 | 1 | 5 | 5 | 5 | 11 |
ApiNATOMY model of the spleen | splen:spleen | 580 | 47 | 103 | 5 | 5 | 5 | 5 | 8 |
Total unique | 8 | 8761 | 717 | 823 | 296 | 115 | 114 | 114 | 181 |
element | count |
---|---|
models | 8 |
models scigraph | 8 |
lyphs | 8761 |
lyphs input | 717 |
externals | 583 |
publications | 296 |
nerus | 115 |
neupops | 114 |
neupops pattern | 114 |
prefix | count |
---|---|
nlx | 1 |
CL | 3 |
GO | 5 |
NCIT | 5 |
CHEBI | 11 |
sao | 11 |
fma | 15 |
tgbugs | 114 |
ilx | 179 |
UBERON | 239 |
:SUM: | 583 |
:TOTAL: | 583 |
select distinct
?label
?graph
#?g
?lyphs
?lyphs_input
#?links
#?nodes
#?chains
#?coalescences
?externals
?publications
#?groups
?nerus
?neupops
?neupops_pat
?somas
<<apinat-model-summary-where>>
WHERE {
# ?model apinatomy:hasGraph ?graph # TODO broken conversion to literal instead of uri at the moment
# sadly it seems that no one has managed to write an optimization that converts
# into this form when querying multiple predicates in the same expression
{
?graph a elements:Graph ;
rdfs:label ?l .
bind(str(?l) as ?label) # avoid issues with graphs loaded multiple times
{ select ?graph (count(distinct(?o)) as ?lyphs ) where { ?graph apinatomy:lyphs ?o . } group by ?graph }
{ select ?graph (count(distinct(?o)) as ?lyphs_input ) where
{ ?graph apinatomy:lyphs ?o .
filter not exists { ?o apinatomy:isTemplate true . }
filter not exists { ?o apinatomy:generated true . } } group by ?graph }
{ select ?graph (count(distinct(?o)) as ?links ) where { ?graph apinatomy:links ?o . } group by ?graph }
{ select ?graph (count(distinct(?o)) as ?nodes ) where { ?graph apinatomy:nodes ?o . } group by ?graph }
{ select ?graph (count(distinct(?o)) as ?chains ) where { ?graph apinatomy:chains ?o . } group by ?graph }
{ select ?graph (count(distinct(?o)) as ?coalescences) where { ?graph apinatomy:coalescences ?o . } group by ?graph }
{ select ?graph (count(distinct(?o)) as ?externals ) where { ?graph apinatomy:ontologyTerms ?o . } group by ?graph }
optional
{ select ?graph (count(distinct(?o)) as ?publications) where { ?graph apinatomy:references ?o . } group by ?graph }
{ select ?graph (count(distinct(?o)) as ?groups ) where { ?graph apinatomy:groups ?o . } group by ?graph }
optional
{ select ?graph (count(distinct(?o)) as ?nerus ) where
{ ?graph apinatomy:groups ?o .
?o apinatomy:description ?d .
filter(contains(str(?d), "dynamic")) } group by ?graph }
optional
{ select ?graph (count(distinct(?o)) as ?neupops ) where
{ ?graph apinatomy:ontologyTerms ?o .
?o rdfs:subClassOf+ ilxtr:NeuronEBM . } group by ?graph }
optional
{ select ?graph (count(distinct(?o)) as ?neupops_pat ) where
{ ?graph apinatomy:ontologyTerms ?o .
filter contains(str(?o), "/neuron-type-") } group by ?graph }
optional
{ select ?graph (count(distinct(?o)) as ?somas ) where
{ ?graph apinatomy:lyphs ?o .
?o apinatomy:ontologyTerms NLX:154731 . } group by ?graph }
}
union
{
{ select (count(distinct(?graph_)) as ?graph ) where { ?graph_ a elements:Graph } }
bind("Total unique" as ?label)
{ select (count(distinct(?o)) as ?lyphs ) where { ?graph_ apinatomy:lyphs ?o . } }
{ select (count(distinct(?o)) as ?lyphs_input ) where
{ ?graph_ apinatomy:lyphs ?o .
filter not exists { ?o apinatomy:isTemplate true . }
filter not exists { ?o apinatomy:generated true . } } }
{ select (count(distinct(?o)) as ?links ) where { ?graph_ apinatomy:links ?o . } }
{ select (count(distinct(?o)) as ?nodes ) where { ?graph_ apinatomy:nodes ?o . } }
{ select (count(distinct(?o)) as ?chains ) where { ?graph_ apinatomy:chains ?o . } }
{ select (count(distinct(?o)) as ?coalescences) where { ?graph_ apinatomy:coalescences ?o . } }
{ select (count(distinct(?o)) as ?externals ) where { ?graph_ apinatomy:ontologyTerms ?o . } }
{ select (count(distinct(?o)) as ?publications) where { ?graph_ apinatomy:references ?o . } }
{ select (count(distinct(?o)) as ?groups ) where { ?graph_ apinatomy:groups ?o . } }
{ select (count(distinct(?o)) as ?nerus ) where
{ ?graph_ apinatomy:groups ?o .
?o apinatomy:description ?d .
filter(contains(str(?d), "dynamic")) } }
optional
{ select (count(distinct(?o)) as ?neupops ) where
{ ?graph_ apinatomy:ontologyTerms ?o .
?o rdfs:subClassOf+ ilxtr:NeuronEBM . } }
optional
{ select (count(distinct(?o)) as ?neupops_pat ) where
{ ?graph_ apinatomy:ontologyTerms ?o .
filter contains(str(?o), "/neuron-type-") } }
optional
{ select (count(distinct(?o)) as ?somas ) where
{ ?graph_ apinatomy:lyphs ?o .
?o apinatomy:ontologyTerms NLX:154731 . } }
}
}
SELECT (COUNT(*) as ?count) {
<<sparql-apinat-models>>
}
SELECT DISTINCT
(?s as ?id)
(str(?l) as ?label)
WHERE {
?s a elements:Graph .
?s rdfs:label ?l.
}
SELECT DISTINCT
?o (str(?l) as ?label) (str(?v) as ?version)
WHERE {
?o a owl:Ontology ;
rdfs:label ?l ;
apinatomy:hasGraph ?g .
?g a elements:Graph .
?g apinatomy:version ?v .
}
Return ApiNATOMY Graph resources and their associated Ontology resource.
MATCH ({iri: "https://apinatomy.org/uris/elements/Graph"})<-[:type]-(g)<-[e:apinatomy:hasGraph]-(o:Ontology) RETURN g, e, o
Return the list of all ApiNATOMY models in the database.
MATCH ({iri: "https://apinatomy.org/uris/elements/Graph"})
<-[:type]-(g)-[:isDefinedBy]->(o:Ontology)
RETURN o
SELECT (COUNT(DISTINCT ?s) as ?total_lyphs)
WHERE { ?s a elements:Lyph . }
total_lyphs |
---|
8162 |
generated vs input s? rdf:type element:Lyph
SELECT DISTINCT
(COUNT(DISTINCT ?s) as ?input_lyphs)
#?s
#?p
#?o
WHERE {
?s a elements:Lyph .
#?s ?p ?o .
FILTER NOT EXISTS { ?s apinatomy:isTemplate true . }
FILTER NOT EXISTS { ?s apinatomy:generated true . }
#FILTER ( ! ( ?p = apinatomy:isTemplate && ?o = true ) )
#FILTER ( ! ( ?p = apinatomy:generated && ?o = true ) )
#?s apinatomy:generated ?o .
}
LIMIT ?limit
input_lyphs |
---|
742 |
apinatomy:references average number of publications per unit? (for now no) will also want the full listing of publications select count distinct o? select distinct o? s? apinat:publication o?
SELECT DISTINCT
(COUNT(DISTINCT ?pub) as ?publications)
WHERE { ?s apinatomy:references ?pub . }
publications |
---|
293 |
both model level and lyph level
count of apinatomy:ontologyTerms by prefix UBERON, GO, CHEBI, etc. full listing of terms as well
"UBERON" "EMAPA" "fma" "CHEBI" "GO" "sao" "CL" "nlx" "ilx" "tgbugs" "NCBITaxon" "NCIT" "pubmed" "doi" "ncit"
SELECT
?prefix
(COUNT(DISTINCT ?s) AS ?count)
WHERE {
{
VALUES ?prefix { <<apinat-search-prefixes()>> }
?s a elements:OntologyTerm .
FILTER CONTAINS(str(?s), ?prefix)
} UNION {
SELECT (":SUM:" AS ?prefix) ?s
{
VALUES ?pre { <<apinat-search-prefixes()>> }
?s a elements:OntologyTerm .
FILTER CONTAINS(str(?s), ?pre)
}
} UNION {
BIND(":TOTAL:" AS ?prefix)
{ SELECT ?s WHERE { ?s a elements:OntologyTerm . } }
}
}
GROUP BY ?prefix
ORDER BY ?count
SELECT (COUNT(DISTINCT(?s)) as ?count) WHERE { ?s a elements:OntologyTerm . }
SELECT DISTINCT
?l ?s
WHERE {
?s a elements:OntologyTerm .
?l ?p ?s .
FILTER(CONTAINS(str(?s), "doi") || CONTAINS(str(?s), "pubmed") || CONTAINS(str(?s), "ncit"))
}
ORDER BY ?l ?s
LIMIT ?limit
Total neuron populations including those that are unidentified or are in error
SELECT (COUNT(*) as ?count) {
<<apinat-nerus>>
}
count |
---|
117 |
SELECT DISTINCT
?group
(str(?l) as ?label)
WHERE {
?group a elements:Group .
?group apinatomy:description ?d
filter(contains(str(?d), "dynamic"))
?group rdfs:label ?l .
}
order by ?group
SELECT (COUNT(*) as ?count) {
<<apinat-neupops>>
}
count |
---|
117 |
SELECT DISTINCT
?neupop
(str(?pl) as ?preferred_label)
(str(?l) as ?label)
WHERE {
?neupop a elements:OntologyTerm .
?neupop rdfs:subClassOf+ ilxtr:NeuronEBM .
OPTIONAL { ?neupop skos:prefLabel ?pl . }
OPTIONAL { ?neupop rdfs:label ?l . }
}
SELECT (COUNT(*) as ?count) {
<<apinat-neupops-pat>>
}
count |
---|
117 |
SELECT DISTINCT
?neupop
(str(?pl) as ?preferred_label)
(str(?l) as ?label)
WHERE {
?neupop a elements:OntologyTerm .
FILTER CONTAINS(str(?neupop), "/neuron-type-")
OPTIONAL { ?neupop skos:prefLabel ?pl . }
OPTIONAL { ?neupop rdfs:label ?l . }
}
Keast Bolser Lewis First pass NLP output
experimental
MATCH
(neuron:Class{iri: "http://uri.neuinfo.org/nif/nifstd/sao1417703748"})<-[:subClassOf*1..]-
(neupop)
//(neupop:Class{iri: $neupop_id})
-[e:ilxtr:hasLocationPhenotype!]->(blank)
-[q]->(more)
//-[q:BFO:0000050]->(more)
RETURN e, q
MATCH (neupop:Class{iri: $neupop_id})-[e:ilxtr:hasPhenotype!]->(phenotype) RETURN e
from pprint import pprint
from pyontutils.scigraph import Cypher, Vocabulary
sgc = Cypher()
query = """
<<npo-basic-phenotypes>>
"""
def get_phenotypes(neupop_id):
d = sgc.execute(query=query, limit=99999, output='application/json', neupop_id=neupop_id)
good = [e for e in d['edges'] if 'meta' in e and e['meta']['owlType'] == ['subClassOf']
and not e['obj'].startswith('_:')]
return good
pprint(get_phenotypes('ilxtr:neuron-type-keast-1'))
SELECT DISTINCT
?s
WHERE {
?s rdfs:subClassOf+ SAO:1813327414 . # NOTE this counts cells
}
from collections import defaultdict
from pprint import pprint
from neurondm.compiled.common_usage_types import *
neurons = config.neurons()
#pprint(neurons)
#pprint(dir(neurons[0]))
# pprint(neurons[0].edges)
#pprint([n for n in neurons if ilxtr.hasSomaLocatedIn in n.edges][0])
#pprint([n for n in neurons if ilxtr.hasAxonLocatedIn in n.edges][0])
#pprint([n for n in neurons if ilxtr.hasAxonPresynapticElementIn in n.edges][0])
#pprint([n for n in neurons if ilxtr.hasDendriteLocatedIn in n.edges][0])
x = defaultdict(list)
for n in neurons:
for somar in [pe.p for pe in n.pes if pe.e == ilxtr.hasSomaLocatedIn]:
for axonr in [pe.p for pe in n.pes if pe.e in (ilxtr.hasAxonPresynapticElementIn, ilxtr.hasProjectionPhenotype)]:
# via may be incorrect here if an axon location applies only to one collateral for a terminal
# this is why we need the partial order
x[somar].append(axonr)
pprint(dict(x))
# via axon
pprint([n for n in neurons if ilxtr.hasAxonLocatedIn in n.edges][:1])
# axon terminal in apinatomy
# region A is axonally forward connect to B forward here means soma -> axon terminal
pprint([n for n in neurons if ilxtr.hasProjectionPhenotype in n.edges][:1])
pprint([n for n in neurons if ilxtr.hasAxonPresynapticElementIn in n.edges][:1])
# soma
pprint([n for n in neurons if ilxtr.hasSomaLocatedIn in n.edges][:1])
pprint([n for n in neurons if ilxtr.hasSomaLocatedInLayer in n.edges][:1])
# via dendrite
pprint([n for n in neurons if ilxtr.hasDendriteLocatedIn in n.edges][:1])
# dendrite terminal for sensory neurons in apinatomy
# region A is dendritically forward connect to B forward here means dendrite terminal -> soma
pprint([n for n in neurons if ilxtr.hasSensorySubcellularElementIn in n.edges][:1])
pprint([n for n in neurons if ilxtr.hasForwardConnectionPhenotype in n.edges][:1])
pprint([n for n in neurons if ilxtr.hasReverseConnectionPhenotype in n.edges][:1])
#pprint([n for n in neurons if EntailedPhenotype('UBERON:0002790', 'ilxtr:hasAxonLocatedIn') in n.pes ])
#pprint([n for n in neurons if ilxtr.hasSomaLocatedIn in n.edges])
#pprint([n for n in neurons if Phenotype('UBERON:0002610', 'ilxtr:hasSomaLocatedIn') in n.pes ])
cypher
:x a owl:Class ;
owl:equivalentClass [ a owl:Restriction ;
owl:intersectionOf (
[ a owl:Restriction ;
owl:onProperty ilxtr:hasSomaLocatedIn ;
owl:someValuesFrom [ a owl:Restriction ;
owl:onProperty :partOf ;
owl:someValuesFrom ?my-region ;
] ;
] ;
)
]
MATCH (neuron)-[e]->
// (blank)-[:ilxtr:hasPhenotype]->(phenotype)
(blanka)-[:ilxtr:hasAxonLocatedIn]->(blankb)-[edge]->(region_or_blank)
//(blanka)-[:ilxtr:hasSomaLocatedIn]->(blankb)-[:BFO:0000050]->(region_or_blank)
// or_blank happens if it is a union of regions i.e. a population with somas in more than one region
//,(region_or_blank: Class{iri: "UBERON:0001950"})
//RETURN region_or_blank
//RETURN neuron
RETURN edge
select distinct ?p ?o
where {
# ilxtr:neuron-type-keast-1 ?p ?o
ilxtr:neuron-type-keast-1 owl:equivalentClass ?b1 .
?b1 owl:intersectionOf ?b2 .
?b2 ?unkp ?b3 .
# lists
?b3 owl:onProperty ?p .
?b3 owl:someValuesFrom ?o .
}
select distinct ?neuron ?prop ?value ?prop2 ?value2 # ?p ?ox # ?p2 ?o2 # ?p3 # ?o3 ?p4 ?o4 ?p5 ?o5 ?p6 ?o6
where {
#ilxtr:neuron-type-keast-1 owl:equivalentClass ?o .
?neuron a owl:Class .
?neuron ilxtr:simpleLocalLabel ?sll . # XXX hack to filter for neurons
?neuron owl:equivalentClass ?o .
# ?o ?p2 ?o2 .
?o owl:intersectionOf ?list .
?list rdf:rest*/rdf:first ?elem . # FIXME at least one elem subClassOf neuron or cell
?elem a owl:Restriction .
?elem owl:onProperty ?prop .
?elem owl:someValuesFrom ?value .
OPTIONAL {
?value a owl:Restriction .
?value owl:onProperty ?prop2 .
?value owl:someValuesFrom ?value2 .
# ?value ?p ?ox .
#OPTIONAL {
#?ox ?p2 ?o2 .
#?o2 a owl:Class .
#}
}
# then do optional for location vs other types
#?o3 ?p4 ?o4 .
#?o4 ?p5 ?o5 . # first on property hits here
#?o5 ?p6 ?o6 .
# TODO list optional ???
}
limit 300
MATCH path = (neuron)
//MATCH path = (neuron:Class{iri: "ilxtr:neuron-type-keast-1"})
-[:equivalentClass|subClassOf]->(hrm)
RETURN path
select * where { ?s rdfs:subClassOf ilxtr:NeuronNerves }
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
,
(neugrp)
-[:apinatomy:links]->(link_start)
-[b:apinatomy:endsIn*0..1]->(lyph_or_layer)
//-[:apinatomy:topology*0..1]->(top)
,
(neugrp)
-[:apinatomy:links]->(link)
//<-[c:apinatomy:bundles|apinatomy:endBundles]-
-[c:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->
(lyph_or_layer) // real lyphs convey things, layers do not
-[d:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
,
(lyph_or_layer) // FIXME WHERE ARE MY DENDRITES MOTHER FUCKER
-[z:apinatomy:cloneOf*0..1]->()
-[y:apinatomy:external|apinatomy:inheritedOntologyTerms*0..1]->(layer)
,
(lyph)
-[e:apinatomy:external]->(region)
,
(link) // use apinatomy:next to extract ordering information
-[f:apinatomy:next*0..]->()
//-[f:apinatomy:next|apinatomy:nextChainStartLevels*0..]->()
// FIXME these should be collapsing into a single relationship
-[g:apinatomy:target*0..1]->()
-[h:apinatomy:rootOf*0..1]->()
-[i:apinatomy:levels*0..1]->()
<-[:apinatomy:links]-(neugrp)
,
p2 = (link)
-[cle:apinatomy:conveyingLyph]->(cl)
-[:apinatomy:topology]->()
,
(cl)
-[x:apinatomy:inheritedOntologyTerms*0..1]->()
//WHERE top.iri IN ["https://apinatomy.org/uris/readable/BAG", "https://apinatomy.org/uris/readable/BAG2"]
// publications
WITH neugrp, a, b, c, d, e, f, g, h, i, x, y, z // p2 //, b
OPTIONAL MATCH path = (neugrp)
-[:apinatomy:publications]->(pub)
-[:type]->(:Class{iri: "https://apinatomy.org/uris/elements/Publication"}) // cannot be curied, dynamic endpoints will not expand it
RETURN a, b, c, d, e, f, g, h, i, path, x, y, z //, p2
UNION
// this part usually only returns the soma housing lyph
MATCH (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
-[b:apinatomy:lyphs]->(lyph)
//<-[c:apinatomy:internalLyphs]-()
-[c:apinatomy:internalIn]->()
-[d:apinatomy:external*0..1]->(region)
// this variant shows the dead end lyphs that correspond to the fasciculatesIn links above
//-[c:apinatomy:internalIn*0..1]->()
//-[d:apinatomy:external*0..1]->(region)
RETURN a, b, c, d, null AS e, null AS f, null AS g, null AS h, null AS i, null AS path, null as x, null as y, null as z//, null as p2
MATCH p1 = (neupop:Class{iri: $neupop_id})
-[a:apinatomy:annotates]->(neugrp:NamedIndividual{`https://apinatomy.org/uris/readable/description`: "dynamic"}) // FIXME HACK
,
p2 = (neugrp)
-[:apinatomy:links]->(link)
-[:apinatomy:fasciculatesIn|apinatomy:endsIn*0..1]->(lyph_or_layer) // real lyphs convey things, layers do not
-[:apinatomy:layerIn*0..1]->(lyph)
-[:apinatomy:conveys*0..1]->() // make sure we are at a real lyph
,
p3 = (lyph)
-[e:apinatomy:external]->(region)
,
p4 = (link) // use apinatomy:next to extract ordering information
-[:apinatomy:next*0..]->()
//-[f:apinatomy:next|apinatomy:nextChainStartLevels*0..]->()
// FIXME these should be collapsing into a single relationship
-[:apinatomy:target*0..1]->()
-[:apinatomy:rootOf*0..1]->()
-[:apinatomy:levels*0..1]->()
<-[:apinatomy:links]-(neugrp)
,
p5 = (link)
-[:apinatomy:conveyingLyph]->(cl)
-[:apinatomy:topology]->()
,
p6 = (cl)
-[:apinatomy:inheritedOntologyTerms*0..1]->()
//,
//p7 = (layer)
//-[:apinatomy:layerIn:*0..1]->(lyph) // FIXME this is wrong it will bull in unrelated layers
//,
//p8 = (link)
// TODO need a layer for th elinks too I think
// XXX it turns out that neru-3 already has all the information we need?????
RETURN p1, p2, p3, p4, p5, p6
(defun report-apinat ()
(message "TODO apinat report")
)
(defun report-organs ()
(message "TODO organs report")
)
(defun test-config ()
(message "TODO test config")
)
(defun test-neurons ()
(message "TODO test neurons")
)
(defun test-datasets ()
(message "TODO test datasets")
)
(defun test-protocols ()
(message "TODO test protocols")
)
;; minimal reval
(unless (featurep 'reval)
(defvar reval-cache-directory (concat user-emacs-directory "reval/cache/"))
(defun reval-minimal (cypher checksum path-or-url &rest alternates)
"Simplified and compact implementation of reval."
(let* (done (o url-handler-mode) (csn (symbol-name checksum))
(cache-path (concat reval-cache-directory (substring csn 0 2) "/" csn
"-" (file-name-nondirectory path-or-url))))
(url-handler-mode)
(unwind-protect
(cl-loop for path-or-url in (cons cache-path (cons path-or-url alternates))
do (when (file-exists-p path-or-url)
(let* ((buffer (find-file-noselect path-or-url))
(buffer-checksum (intern (secure-hash cypher buffer))))
(if (eq buffer-checksum checksum)
(progn
(unless (string= path-or-url cache-path)
(let ((parent-path (file-name-directory cache-path))
make-backup-files)
(unless (file-directory-p parent-path)
(make-directory parent-path t))
(with-current-buffer buffer
(write-file cache-path))))
(eval-buffer buffer)
(setq done t))
(kill-buffer buffer) ; kill so cannot accidentally evaled
(error "reval: checksum mismatch! %s" path-or-url))))
until done)
(unless o
(url-handler-mode 0)))))
(defalias 'reval #'reval-minimal)
(reval 'sha256 '3620321396c967395913ff19ce507555acb92335b0545e4bd05ec0e673a0b33b
"https://raw.githubusercontent.com/tgbugs/orgstrap/300b1d5518af53d76d950097bcbcd7046cfa2285/reval.el"))
(let ((ghost "https://raw.githubusercontent.com/tgbugs/orgstrap/"))
(unless (featurep 'ow)
(reval 'sha256 'b5f27e2ca406874307debdd311cd47f73b2ade2fd73b8c8f9834e1c724dc7053
;;"~/git/orgstrap/ow.el"
(concat ghost "b9fcad308e10ab2a0d4bf752dc510bb278bba689" "/ow.el")))
(unless (featurep 'blazegraph)
(reval 'sha256 '8f54a319227ee6d9ca457ad77be955ba6b1a98a36564dbda61fa6892192afd51
;;"~/git/orgstrap/services/blazegraph.el"
(concat ghost "abb93f698d3cfeeea607856bec98ae1d6cfe39c9" "/services/blazegraph.el"))))
Tangle helper for bare paragraphs.