hra-api
Version:
The Human Reference Atlas (HRA) API deployed to https://apps.humanatlas.io/api/
333 lines (309 loc) • 9.26 kB
JavaScript
// src/library/hra-kg/operations/digital-objects.js
import { coerce, rsort } from "semver";
// src/library/shared/utils/sparql.js
import jsonld from "jsonld";
import Papa from "papaparse";
jsonld.documentLoader = async (documentUrl) => {
const document = await fetch(documentUrl).then((r) => r.json());
return {
contextUrl: null,
document,
documentUrl
};
};
function fetchSparql(query, endpoint, mimetype) {
const body = new URLSearchParams({ query });
return fetch(endpoint, {
method: "POST",
headers: {
Accept: mimetype,
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": body.toString().length.toString()
},
body
});
}
async function construct(query, endpoint, frame = void 0) {
const resp = await fetchSparql(query, endpoint, "application/ld+json");
const json = await resp.json();
if (frame) {
return await jsonld.frame(json, frame);
} else {
return json;
}
}
// src/library/v1/utils/jsonld-compat.js
function expandIri(iri) {
return iri && typeof iri === "string" ? iri.replace("ccf:", "http://purl.org/ccf/").replace("ccf1:", "http://purl.org/\
ccf/latest/ccf.owl#").replace("../sig/ont/fma/fma", "http://purl.org/sig/ont/fma/fma").replace("fma:", "http://purl.org/\
sig/ont/fma/fma").replace("http://purl.obolibrary.org/obo/FMA_", "http://purl.org/sig/ont/fma/fma") : iri;
}
var DEFAULT_STRING_FIELDS = ["creator", "creator_first_name", "creator_last_name"];
function normalizeJsonLd(jsonld2, arrayFields = /* @__PURE__ */ new Set(), stringFields = new Set(DEFAULT_STRING_FIELDS)) {
return JSON.parse(JSON.stringify(jsonld2), (key, value) => {
if (arrayFields.has(key)) {
value = ensureArray(value);
}
if (stringFields.has(key)) {
value = ensureString(value);
}
if (typeof value === "object" && value?.["@type"] && value["@value"] && (value["@type"].startsWith("xsd:") || value["\
@type"].startsWith("http://www.w3.org/2001/XMLSchema#"))) {
switch (value["@type"]) {
case "http://www.w3.org/2001/XMLSchema#integer":
case "http://www.w3.org/2001/XMLSchema#double":
case "http://www.w3.org/2001/XMLSchema#decimal":
case "xsd:integer":
case "xsd:double":
case "xsd:decimal":
return Number(value["@value"]);
case "http://www.w3.org/2001/XMLSchema#date":
case "xsd:date":
return value["@value"];
default:
return value;
}
} else if (Array.isArray(value)) {
return value.map(expandIri);
} else {
return expandIri(value);
}
});
}
function ensureString(value, arrayElementSeparator = "; ") {
if (Array.isArray(value)) {
return value.map(ensureString).join(arrayElementSeparator);
} else if (value?.["@value"]) {
return value["@value"];
} else {
return value;
}
}
function ensureArray(thing) {
if (Array.isArray(thing)) {
return thing;
} else if (thing) {
return [thing];
} else {
return [];
}
}
function ensureNumber(value) {
if (value?.["@type"]) {
return Number(value["@value"]);
} else if (typeof value === "string") {
return Number(value);
} else {
return value;
}
}
function ensureGraphArray(results) {
if (results?.["@graph"]) {
return results["@graph"];
} else if (results?.["@id"]) {
delete results["@context"];
return [results];
} else {
return [];
}
}
// src/library/hra-kg/frames/digital-objects.jsonld
var digital_objects_default = {
"@context": {
dcat: "http://www.w3.org/ns/dcat#",
dct: "http://purl.org/dc/terms/",
schema: "http://schema.org/",
ccf: "http://purl.org/ccf/",
rdfs: "http://www.w3.org/2000/01/rdf-schema#",
purl: {
"@id": "rdfs:seeAlso",
"@type": "@id"
},
lod: {
"@id": "dcat:last",
"@type": "@id"
},
title: "dct:title",
doType: "schema:additionalType",
doName: "schema:name",
doVersion: "ccf:latestVersion",
lastUpdated: "schema:dateCreated",
versions: {
"@id": "schema:version"
},
datasets: {
"@id": "dcat:dataset",
"@type": "@id"
},
cell_count: {
"@id": "ccf:cell_count",
"@type": "http://www.w3.org/2001/XMLSchema#integer"
},
biomarker_count: {
"@id": "ccf:biomarker_count",
"@type": "http://www.w3.org/2001/XMLSchema#integer"
},
organs: "ccf:organ",
organIds: {
"@id": "ccf:organ_id",
"@type": "@id"
}
},
"@type": "dcat:Catalog"
};
// src/library/hra-kg/queries/digital-objects.rq
var digital_objects_default2 = `PREFIX ccf: <http://purl.org/ccf/>
PREFIX dcat: <http://www.w3.org/ns/dcat#>
PREFIX dct: <http://purl.org/dc/terms/>
PREFIX hint: <http://www.bigdata.com/queryHints#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX prov: <http://www.w3.org/ns/prov#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
PREFIX schema: <http://schema.org/>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
PREFIX LOD: <https://lod.humanatlas.io>
PREFIX HRA: <https://purl.humanatlas.io/collection/hra-api>
PREFIX body: <http://purl.obolibrary.org/obo/UBERON_0013702>
CONSTRUCT {
?lod a dcat:Catalog ;
dcat:last ?latestLodPurl ;
rdfs:seeAlso ?graphPurl ;
dct:title ?title ;
schema:additionalType ?doType ;
schema:name ?doName ;
ccf:latestVersion ?doVersion ;
schema:version ?version ;
schema:dateCreated ?lastUpdated ;
dcat:dataset ?lodPurl ;
ccf:organ ?organ ;
ccf:organ_id ?organ_id ;
ccf:cell_count ?unique_cells ;
ccf:biomarker_count ?unique_biomarkers .
}
WHERE {
hint:Query hint:optimizer "Runtime" .
GRAPH LOD: {
?lod a dcat:Catalog ;
dcat:dataset ?lodPurl .
?lodPurl a dcat:Dataset ;
schema:version ?version ;
rdfs:seeAlso ?graphPurlVersioned .
BIND(IRI(STRBEFORE(STR(?graphPurlVersioned), CONCAT('/', ?version))) as ?graphPurl)
}
{
SELECT DISTINCT *
WHERE {
GRAPH ?graphPurl {
?graphPurl rdfs:seeAlso ?latestLodPurl .
}
GRAPH LOD: {
# organ, unique_cells, unique_biomarkers
?lod a dcat:Catalog ;
dcat:dataset ?latestLodPurl .
?latestLodPurl
schema:additionalType ?doType ;
schema:name ?doName ;
schema:version ?doVersion ;
prov:wasDerivedFrom [
dct:title ?title ;
schema:dateCreated ?lastUpdated ;
] .
}
}
}
OPTIONAL {
SELECT DISTINCT ?graphPurl ?organ ?organ_id {
{
SELECT (SAMPLE(?organ) as ?organ) ?organ_id
WHERE {
GRAPH HRA: {
?refOrgan a ccf:SpatialEntity ;
ccf:has_reference_organ ?refOrgan ;
ccf:representation_of ?refOrganTerm .
?organ_id ccf:ccf_part_of body: .
?organ_id ccf:ccf_pref_label ?organ_label .
?refOrganTerm ccf:ccf_part_of* ?organ_id .
FILTER(!CONTAINS(STR(?organ_label), ' system'))
BIND(LCASE(?organ_label) as ?organ)
}
}
GROUP BY ?organ_id
ORDER BY ?organ
}
GRAPH ?graphPurl {
?graphPurl rdfs:seeAlso ?lodPurl .
{
?organ_id ?pred1 [] .
} UNION {
[] ?pred2 ?organ_id .
FILTER(isIRI(?organ_id))
}
}
}
}
OPTIONAL {
SELECT ?graphPurl (COUNT(DISTINCT ?cell_id) as ?unique_cells) {
GRAPH HRA: {
?cell_id ccf:ccf_asctb_type ?type .
FILTER(?type = 'CT')
}
GRAPH ?graphPurl {
?graphPurl rdfs:seeAlso ?lodPurl .
{
?cell_id ?pred1 [] .
} UNION {
[] ?pred2 ?cell_id .
FILTER(isIRI(?cell_id))
}
}
}
GROUP BY ?graphPurl
}
OPTIONAL {
SELECT ?graphPurl (COUNT(DISTINCT ?biomarker) as ?unique_biomarkers) {
GRAPH HRA: {
?biomarker ccf:ccf_asctb_type ?type .
FILTER(?type = 'BM')
}
GRAPH ?graphPurl {
?graphPurl rdfs:seeAlso ?lodPurl .
{
?biomarker ?pred1 [] .
} UNION {
[] ?pred2 ?biomarker .
FILTER(isIRI(?biomarker))
}
}
}
GROUP BY ?graphPurl
}
}`;
// src/library/hra-kg/operations/digital-objects.js
function reformatResponse(jsonld2) {
const results = normalizeJsonLd(ensureGraphArray(jsonld2), /* @__PURE__ */ new Set(["versions", "organs", "organIds"]));
for (const result of results) {
result.versions = sortVersions(result.versions);
results.cell_count = ensureNumber(results.cell_count) || 0;
results.biomarker_count = ensureNumber(results.biomarker_count) || 0;
}
return {
"@context": jsonld2["@context"],
"@graph": results
};
}
async function getDigitalObjects(endpoint = "https://lod.humanatlas.io/sparql") {
return reformatResponse(await construct(digital_objects_default2, endpoint, digital_objects_default));
}
function sortVersions(versions) {
return rsort(
versions.map((version) => {
const semver = coerce(version, true);
semver.original = version;
return semver;
})
).map((semver) => semver.original);
}
export {
getDigitalObjects
};