Skip to content

Latest commit

 

History

History
executable file
·
6978 lines (6171 loc) · 230 KB

queries.org

File metadata and controls

executable file
·
6978 lines (6171 loc) · 230 KB

SPARC queries

<<sparql-settings>>

<<cypher-settings>>

Data queries

Datasets

Dataset Predicates

SELECT DISTINCT
?p
# ?pp
# ?po
WHERE {
  ?dataset a sparc:Dataset .
  ?dataset ?p ?o .
  # ?p ?pp ?po .
} ORDER BY ?p

Electrophysiology datasets

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
}

Datasets by contents updated time

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)

Human dataset queries

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)]

Test

Originally from sparcur.reports.SparqlQueries.

Dataset about

SELECT DISTINCT
?dataset
?about
WHERE {
  ?type rdfs:subClassOf* sparc:Resource .
  ?dataset rdf:type ?type .
  ?dataset isAbout: ?about .
}
LIMIT ?limit

Dataset subjects

SELECT DISTINCT
?dataset
?subj
WHERE {
    ?startsubj a sparc:Subject .
    ?startsubj TEMP:hasDerivedInformationAsParticipant ?dataset .
    ?subj a sparc:Subject .
    ?subj  TEMP:hasDerivedInformationAsParticipant ?dataset .
}
LIMIT ?limit

Dataset groups

SELECT DISTINCT
?dataset
?group
?subj
WHERE {
    ?startsubj TEMP:hasDerivedInformationAsParticipant ?dataset .
    ?subj  TEMP:hasDerivedInformationAsParticipant ?dataset .
    ?subj  TEMP:hasAssignedGroup ?group .
} LIMIT ?limit

Dataset bundle

SELECT DISTINCT
?dataset
WHERE {
    ?startdataset TEMP:collectionTitle ?string .
    ?dataset  TEMP:collectionTitle ?string .
}
LIMIT ?limit

Dataset subject species

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

Dataset human subjects and samples

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

Dataset milestone completion date

SELECT DISTINCT
?dataset
?date
WHERE {
    ?dataset TEMP:milestoneCompletionDate ?date .
}
ORDER BY ASC(?date)
LIMIT ?limit

Award affiliations

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

Connectivity datasets

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

Protocols

Protocol general report

How to interpret this report.

The rows are ordered by

  1. whether there is a dataset directly associated with the protocol id
  2. whether the protocol has a human readable uri.
  3. 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)

Total protocols

XXX FIXME producing complete nonsense right now

SELECT
(COUNT(DISTINCT ?protocol) AS ?count)
#DISTINCT ?protocol
WHERE { ?protocol a sparc:Protocol . }
#order by str(?protocol)

Total protocols with at least one protcur annotation

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 )

Published protocols with complex protcur annotations

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 .

Conditions studied

Experimental groups

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

Techniques

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

Test

Originally from sparcur.reports.SparqlQueries.

Protocol techniques

SELECT DISTINCT
?protocol
?technique
WHERE {
    ?protocol rdf:type sparc:Protocol .
    ?protocol TEMP:protocolEmploysTechnique ?technique .
}
LIMIT ?limit

Protocol aspects

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

Protocol inputs

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

Protocol species dose

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

Protocols with known anaesthetic or analgesic roles

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

exploration

aspect counts

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)

input counts

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))

samples

few have additional parameterize

select distinct
?ast_in
where {
?ast_in TEMP:hasValue sparc:Sample ;
  TEMP:protcurChildren ?ast_n .
}
explore
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

dilution

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))

age

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))

techniques

select distinct
#?protocol
?tech
(count(?tech) as ?ct)
where {
?protocol a sparc:Protocol ;
   TEMP:protocolEmploysTechnique ?tech .
} group by ?tech order by desc(?ct)

techniques raw

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)

microscopy

explore

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?
maybe example query
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
datasetprotocolid_speciesspeciesid_regionregionvalueunit
dataset:d484110a-e6e3-4574-aab2-418703c978e2pio.api:22831NCBITaxon:10116Rattus norvegicusUBERON:0005363inferior vagus X ganglion40unit:fold
dataset:d484110a-e6e3-4574-aab2-418703c978e2pio.api:22831NCBITaxon:10116Rattus norvegicusUBERON:0005363inferior vagus X ganglion63unit:fold
dataset:e4bfb720-a367-42ab-92dd-31fd7eefb82epio.api:22831NCBITaxon:10116Rattus norvegicusUBERON:0005363inferior vagus X ganglion40unit:fold
dataset:e4bfb720-a367-42ab-92dd-31fd7eefb82epio.api:22831NCBITaxon:10116Rattus norvegicusUBERON:0005363inferior vagus X ganglion63unit:fold
dataset:6fa2666c-aa3d-4e27-a405-7848fc061b04pio.api:19131NCBITaxon:10116Rattus norvegicusUBERON:0001759vagus nerve20unit:fold
dataset:ff6eb067-62d4-4bfb-b4b2-15ad65db0999pio.api:19143NCBITaxon:10090Mus musculusUBERON:0001759vagus nerve20unit:fold

pressure

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

Datasets following same protocol with different subjects

Completeness

SELECT DISTINCT
?dataset
?completeness
WHERE {
  ?dataset a sparc:Dataset .
  ?dataset TEMP:completenessOfDataset ?completeness .
}
LIMIT ?limit

Dataset collections

SELECT DISTINCT
?title
?dataset
WHERE {
    ?startdataset TEMP:collectionTitle ?title .
    ?dataset  TEMP:collectionTitle ?title .
}
ORDER BY ASC(?title)
LIMIT ?limit

Subjects

Members

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

Total

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 .
}

Subject Metadata

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

By sex

SELECT DISTINCT
(COUNT(DISTINCT ?subject) as ?count_subject)
WHERE {
  ?dataset a sparc:Dataset .
  ?dataset TEMP:isAboutParticipant ?subject .
  ?subject a sparc:Subject .
}

Samples

Members

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

Total

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 .
}

Sample predicates

SELECT DISTINCT
?p
WHERE {
  ?sample a sparc:Sample .
  ?sample ?p ?o .
}

Sample Metadata

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

Anatomical entities

Dataset

Involves

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

About

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

Sample Source

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

Protocol

Simple

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")
}

Protocol triples

SELECT DISTINCT
?protocol
?p
?o
WHERE {
  ?protocol a sparc:Protocol .
  ?protocol ?p ?o
  FILTER CONTAINS(str(?protocol), "protocols.io")
} LIMIT ?limit

Involves

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

Protc annotations

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 .

Uberon tests

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 .
}

Associated scaffolds

Manifest files

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

Contributors

Count

SELECT DISTINCT
(COUNT(DISTINCT ?person) as ?cp)
WHERE {
  ?person a sparc:Person .
}
LIMIT ?limit

ORCiD

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

Other

NOTE These are not yet in the ttl file, the queries written here will not work yet.

File types

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

Has Raw Data

SELECT DISTINCT
?dataset
?raw
WHERE {
  ?dataset a sparc:Dataset .
  ?dataset TEMP:containsFolderForRawData ?raw .  # TODO not 100% on the modelling here
}
LIMIT ?limit

Has Derived Data

SELECT DISTINCT
?dataset
?derived
WHERE {
  ?dataset a sparc:Dataset .
  ?dataset TEMP:containsFolderForDerivedData ?derived .  # TODO not 100% on the modelling here
}
LIMIT ?limit

Has Code

SELECT DISTINCT
?dataset
?code
WHERE {
  ?dataset a sparc:Dataset .
  ?dataset TEMP:containsFolderForCode ?code .  # TODO not 100% on the modelling here
}
LIMIT ?limit

Used in simulation

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

Subject reconciliation

first pass requires that the subject_id be identical

v2

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

v1

# :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 helper

call

simple

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)

terminal regions

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])

connectivity pairs

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.

  1. The id for the neuronal process involved in the connection.
  2. 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.
  3. 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)

neru

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

asdf

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

heatmaps

get the numbers along the axis, so n populations

color code by process type

costimulation by location

neupop by region

<<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)

generate npo representation of apinatomy population location phenotypes

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>>

region by region

SciGraph cypher queries

These can be tested against the execute endpoint as well (if the SciGraph server is running the patch to align the behavior).

sigh

// :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"})
idlabel

neru

neru-7

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

neru-6

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>>

neru-5

query

<<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

neru-4

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

./images/neru-4.svg

neru-3

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

./images/neru-3.svg

neru-2

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

neru-1

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

all populations

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

neru populations

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

neru model populations

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

neru model populations and references

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

neru regions projected to

neru regions dendrited to

neru regions with processes from

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

neru projects to

neru neurites to

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

neru population projects to

neru populations projecting to

Given an anatomical region return a list of neuron types that project to that region.

<<cypher-neru-terminal-type>>

neru populations with axons in

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

neru populations dendriting to

Given an anatomical region return a list of neuron types that have dendrite terminals in that region.

<<cypher-neru-terminal-type>>

neru populations with dendrites in

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

neru populations with neurites in

neru populations with processes in

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

neru populations by phenotype

neru phenotype by population

existing

sparc

organParts

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

parcellationArtifacts

MATCH path = (artifact)
-[:subClassOf*0..2]->(parent)
-[:ilxtr:isDefinedInTaxon]->(species)
WHERE artifact.iri <> "http://www.w3.org/2002/07/owl#Nothing"
RETURN path

parcellationArtifacts/{species-id}

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

artifactRoots/{artifact-id}

MATCH path = (root)
-[:ilxtr:isDefinedBy]->(a)<-[:subClassOf*0..2]
-(artifact:Class{iri: "${artifact-id}"})
RETURN path

artifactLabels/{artifact-id}

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

rootLabels/{root-id}

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

parcellationRoots

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

parcellationRoots/{species-id}

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

parcellationRoots/{species-id}/{region-id}

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

parcellationRootsFMA/{species-id}/{fma-id}

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

parcellationGraph

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

organList

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

speciesList

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

sparc community terms

MATCH
(t)-[:isDefinedBy]->(graph:Ontology{iri: "http://uri.interlex.org/sparc/ontologies/community-terms"})
RETURN t

anatomyPhenotypes

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

phenotypeAnatomy

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

direct hpo count

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                               |
+------------------------------------+

hpo count

XXX need cypher normal json results so we can use count

MATCH (c)-[:subClassOf*0..]->(b:Class{iri: $start}) RETURN c

shortestSimple

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

neurons

connectivity

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

connectedRegions

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

apinat

bundles/{start-id}

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

old-bundles/{start-id}

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

somas

MATCH (c:Class{iri: "http://uri.neuinfo.org/nif/nifstd/nlx_154731"})
-[:apinatomy:annotates]->(soma:NamedIndividual)
RETURN soma

housing-lyphs

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

housing-lyphs/{start-id}

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

soma-processes

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

soma-processes/{start-id}

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

weird-soma-processes/{process-id}

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

yaml file

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>>

NPO competency queries

npo species

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

npo phenotypes

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)

npo locations

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

npo partial orders

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

old notes

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

ApiNATOMY competency queries

wbrcm ontology terms

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 counts per model

Expected number of somas and neupops.

model-idneupopssomas
ard-arm-cardiac1241
bolser-lewis2929
bronchomotor619
keast-bladder2034
sawg-distal-colon1723
sawg-stomach1414

somas

somas >= neupops

The number of somas for distinct populations in a given model.

populations

the number of neuron populations as defined by the neurulator that have an ontology identifier

neuron part per region per model

model-iddiag abbrevexternalsomasaxonsaxon termdenddend term
bolser-lewisSCG17
keast-bladder
bronchomotor
ard-arm-cardiac
sawg-distal-colon
sawg-stomach

expected locations

use NPO as a top down constraint on the locations of somas etc.

somas

could do this by population or generically

population process location

soma-processes can also be checked using NPO but not needed for simple cases

model-idneupopdiag abbrevexternal
bolser-lewisqPN
bolser-lewisqC4
bolser-lewisqPHRNIC
bolser-lewisqDIAPHRAGM

location process populations

bundles NPO here as well

model-iddiag abbrevexternalneupop
bolser-lewisVAGUS9 total

cross model

expect populations from models to have processes in common location

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.

externaldiag abbrevmodel-idneupop
UBERON:0006457T1bolser-lewis1 2 3 6 7
UBERON:0006457T1keast-bladder20
UBERON:0001894DIENCbolser-lewis1 26
UBERON:0001894Diencephalonkeast-bladder13 14 15 16 17 18
UBERON:0005453IMGkeast-bladder3 6 7 11
UBERON:0005453IMGsawg-distal-colonB D F G H Q
UBERON:0018683LumSplNkeast-bladder6 7 11
UBERON:0018683LumSplNsawg-distal-colonB

vagus

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)

visualize all populations that have some process in the IMG

Images of nerus that have some process in the IMG, from keast-bladder and sawg-distal-colon.

kg queries

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

neuron type keast 5 projects to

RETURN region

Expected.

externallabel
UBERON:0016508pelvic ganglion

img processes query

Input

UBERON:0005453inferior 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 blaze

simple sckan queries over blazegraph https://github.com/smtifahim/Loading-Simple-SCKAN/tree/main/sckan-to-simple-sckan

inserts

insert { ?s ?np ?o }
<<simple-sckan-load-1-where>>

queries

#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 ]
  }}

hackathon 2023

inserts

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.

https://raw.githubusercontent.com/smtifahim/Loading-Simple-SCKAN/main/sckan-to-simple-sckan/input_ttl/simple-sckan-properties.ttl

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>>

queries

from https://github.com/smtifahim/Loading-Simple-SCKAN/blob/main/sckan-to-simple-sckan/sparql-query/simple-sckan-constructs.rq

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)
}

owl restriction over transitive properties issues

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 .
}

sigh

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

Sanity checks

Other queries run against various representations of the data.

JSON

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 queries

General metadata and housekeeping queries.

List all loaded ontologies

SELECT ?s WHERE { ?s a owl:Ontology }
MATCH (o:Ontology) RETURN o

predicates

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))

versions

Useful version information is not present in all ontology files at the moment.

embedded load provenance record

SELECT ?p ?o WHERE {
build:prov ?p ?o .
}
MATCH
(p)-[i:build:id]-(),
(p)-[e]-()
RETURN i, e

curation-export.ttl

select ?s ?tes ?vi where {
  ?s TEMP:TimestampExportStart ?tes ;
     owl:versionInfo ?vi .
}

protcur.ttl

select distinct ?o where {
  <https://cassava.ucsd.edu/sparc/ontologies/protcur.ttl> owl:versionInfo ?o
}

apinat models

From cypher-apinat-graphs now includes the external stable model id in the results as well
MATCH ({iri: "https://apinatomy.org/uris/elements/Graph"})<-[:type]-(g)<-[e:apinatomy:hasGraph]-(o:Ontology) RETURN g, e, o

Use cases

Connectivity dashboard

organs

# 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 .

nerves

@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 .

plexi

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

consult with SAWG about these

ganglia

@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" .

add synonyms

neuron population by organ

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

neuron population by nerve

neuron population by ganglion

devel

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]

ApiNATOMY

sparql extract ApiNATOMY partial orders for use in NPO

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))

Coverage of FMA by the TOO map.

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.

Summary statistics

debug

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 . } }
} }

Dashboard

labelgraphlyphslyphs_inputexternalspublicationsnerusneupopsneupops_patsomas
ApiNATOMY model of the stomachsstom:sawg-stomach6683777814141414
Ardell Armour Cardiac Modelaacar:ard-arm-cardiac1827137161217171741
Bolser-Lewis Model of the Physiology of the Superior Cervical Ganglionbolew:bolser-lewis115110714123929292929
Keast ApiNATOMY model of bladder innervationkblad:keast-bladder23941391743021202035
SAWG ApiNATOMY model of the descending colonsdcol:sawg-distal-colon106689135518181824
SPARC Bronchomotor Flatmapbromo:bronchomotor623144187666619
pancreas modelpancr:pancreas45217529155511
ApiNATOMY model of the spleensplen:spleen5804710355558
Total unique88761717823296115114114181
elementcount
models8
models scigraph8
lyphs8761
lyphs input717
externals583
publications296
nerus115
neupops114
neupops pattern114
prefixcount
nlx1
CL3
GO5
NCIT5
CHEBI11
sao11
fma15
tgbugs114
ilx179
UBERON239
: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 . } }
  }
}

Queries

ApiNATOMY sourced
models
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
number of lyphs
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
publications referenced

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
species

both model level and lyph level

terms employed in annotation

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 . }
external issues publications appearing as external ids, unmapped prefixes etc. FIXME where are these coming from?
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
Number of neurulated groups

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
Number of neuron populations with external ids and correct subClassOf.
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 . }
}
Number of neuron populations with external ids that match the neuron-type pattern.
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 . }
}
NPO sourced queries

Keast Bolser Lewis First pass NLP output

location

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
phenotypes for neuron
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'))
number of neuron populations aka neuron types
SELECT DISTINCT
?s
WHERE {
    ?s rdfs:subClassOf+ SAO:1813327414 . # NOTE this counts cells
}
basic connectivity
python
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
number of distinct phenotypes
number of dimensions
number of phenotype values per phenotype dimension
number of anatomical regionsnumber of speciesnumber of x

Extras

neru

select * where { ?s rdfs:subClassOf ilxtr:NeuronNerves }

neru-reduced for monqiue

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

neru-explore

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

Bootstrap

(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.

Local Variables