UNPKG

hra-api

Version:

The Human Reference Atlas (HRA) API deployed to https://apps.humanatlas.io/api/

337 lines (326 loc) 14.6 kB
// 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 select(query, endpoint) { const resp = await fetchSparql(query, endpoint, "text/csv"); const text = await resp.text(); const { data } = Papa.parse(text, { header: true, skipEmptyLines: true, dynamicTyping: true }); return data || []; } 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), singleValueFields = /* @__PURE__ */ new Set()) { return JSON.parse(JSON.stringify(jsonld2), (key, value) => { if (singleValueFields.has(key)) { value = ensureSingleValue(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 ensureSingleValue(value) { if (Array.isArray(value)) { return value[0]; } else { return 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", hraVersions: { "@id": "ccf:hraVersion" }, 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/>\nPREFIX dcat: <http://www.w3.org/ns/dcat#>\nPREFIX dct:\ <http://purl.org/dc/terms/>\nPREFIX hint: <http://www.bigdata.com/queryHints#> \nPREFIX owl: <http://www.w3.org/2002/07/o\ wl#>\nPREFIX prov: <http://www.w3.org/ns/prov#>\nPREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\nPREFIX skos: <http:/\ /www.w3.org/2004/02/skos/core#>\nPREFIX schema: <http://schema.org/>\nPREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\nPREF\ IX LOD: <https://lod.humanatlas.io>\nPREFIX HRA: <https://purl.humanatlas.io/collection/hra-api>\nPREFIX body: <http://pur\ l.obolibrary.org/obo/UBERON_0013702>\n\nCONSTRUCT {\n ?lod a dcat:Catalog ;\n dcat:last ?latestLodPurl ;\n rdfs:seeAls\ o ?graphPurl ;\n dct:title ?title ;\n schema:additionalType ?doType ;\n schema:name ?doName ;\n ccf:latestVersio\ n ?doVersion ;\n ccf:hraVersion ?hraVersion ;\n schema:version ?version ;\n schema:dateCreated ?lastUpdated ;\n \ dcat:dataset ?lodPurl ;\n ccf:organ ?organ ;\n ccf:organ_id ?organ_id ;\n ccf:cell_count ?unique_cells ;\n ccf:b\ iomarker_count ?unique_biomarkers .\n}\nWHERE {\n GRAPH LOD: {\n ?lod a dcat:Catalog ;\n dcat:dataset ?lodPurl .\n \n\ ?lodPurl a dcat:Dataset ;\n schema:version ?version ;\n rdfs:seeAlso ?graphPurlVersioned .\n\n BIND(IRI(STR\ BEFORE(STR(?graphPurlVersioned), CONCAT('/', ?version))) as ?graphPurl)\n }\n\n {\n SELECT DISTINCT *\n WHERE {\n \ GRAPH ?graphPurl {\n ?graphPurl rdfs:seeAlso ?latestLodPurl .\n }\n\n GRAPH LOD: {\n # organ, unique\ _cells, unique_biomarkers\n ?lod a dcat:Catalog ;\n dcat:dataset ?latestLodPurl .\n \n ?latest\ LodPurl\n schema:additionalType ?doType ;\n schema:name ?doName ;\n schema:version ?doVersion ;\n\ prov:wasDerivedFrom [\n dct:title ?title ;\n schema:dateCreated ?lastUpdated ;\n ]\ .\n }\n }\n }\n\n OPTIONAL {\n GRAPH LOD: {\n [] a dcat:Dataset ;\n schema:additionalType ?hraType ;\ \n schema:name ?hraName ;\n schema:version ?hraVersion ;\n prov:hadMember ?graphPurlVersioned .\n\ FILTER(?hraType = 'collection' && ?hraName = 'hra')\n }\n }\n\n OPTIONAL {\n SELECT DISTINCT ?graphPurl ?organ \ ?organ_id {\n {\n SELECT (SAMPLE(?organ) as ?organ) ?organ_id\n WHERE {\n GRAPH HRA: {\n \ ?refOrgan a ccf:SpatialEntity ;\n ccf:has_reference_organ ?refOrgan ;\n ccf:representatio\ n_of ?refOrganTerm .\n \n ?organ_id ccf:ccf_part_of body: .\n ?organ_id ccf:ccf_pref_label\ ?organ_label .\n ?refOrganTerm ccf:ccf_part_of* ?organ_id .\n FILTER(!CONTAINS(STR(?organ_label), '\ system'))\n \n BIND(LCASE(?organ_label) as ?organ)\n }\n }\n GROUP BY ?organ_id\n \ ORDER BY ?organ\n }\n GRAPH HRA: {\n ?organ_id dct:isReferencedBy ?graphPurl .\n }\n }\n }\n\n \ OPTIONAL {\n SELECT ?graphPurl (COUNT(DISTINCT ?cell_id) as ?unique_cells) {\n GRAPH HRA: {\n ?cell_id ccf:\ ccf_asctb_type ?type ;\n dct:isReferencedBy ?graphPurl .\n FILTER(?type = 'CT')\n }\n }\n GROUP BY\ ?graphPurl\n }\n\n OPTIONAL {\n SELECT ?graphPurl (COUNT(DISTINCT ?biomarker) as ?unique_biomarkers) {\n GRAPH HRA\ : {\n ?biomarker ccf:ccf_asctb_type ?type ;\n dct:isReferencedBy ?graphPurl .\n FILTER(?type = 'BM')\ \n }\n }\n GROUP BY ?graphPurl\n }\n}"; // src/library/hra-kg/operations/digital-objects.js function reformatResponse(jsonld2) { const results = normalizeJsonLd(ensureGraphArray(jsonld2), /* @__PURE__ */ new Set(["hraVersions", "versions", "organs", "organIds"])); for (const result of results) { result.hraVersions = sortVersions(result.hraVersions || []); 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") { 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); } // src/library/hra-kg/queries/do-search.rq var do_search_default = "PREFIX ccf: <http://purl.org/ccf/>\nPREFIX dcat: <http://www.w3.org/ns/dcat#>\nPREFIX dct: <http:\ //purl.org/dc/terms/>\nPREFIX hint: <http://www.bigdata.com/queryHints#> \nPREFIX owl: <http://www.w3.org/2002/07/owl#>\nPR\ EFIX prov: <http://www.w3.org/ns/prov#>\nPREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\nPREFIX skos: <http://www.w3\ .org/2004/02/skos/core#>\nPREFIX schema: <http://schema.org/>\nPREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\nPREFIX LOD:\ <https://lod.humanatlas.io>\nPREFIX HRA: <https://purl.humanatlas.io/collection/hra-api>\nPREFIX body: <http://purl.oboli\ brary.org/obo/UBERON_0013702>\n\nSELECT DISTINCT ?purl\nWHERE {\n GRAPH LOD: {\n ?lod a dcat:Catalog ;\n dcat:dataset\ ?lodPurl .\n \n ?lodPurl a dcat:Dataset ;\n schema:version ?version ;\n rdfs:seeAlso ?graphPurlVersioned .\n\n \ BIND(IRI(STRBEFORE(STR(?graphPurlVersioned), CONCAT('/', ?version))) as ?purl)\n }\n #{{FILTER}}\n}\nORDER BY ?purl\n"; // src/library/hra-kg/utils/filter-sparql-query.js function termFilter(terms) { const quotedTerms = terms.map((s) => `(<${s}>)`).join(" "); return ` { SELECT DISTINCT ?purl WHERE { VALUES (?term) { ${quotedTerms} } GRAPH HRA: { ?term dct:isReferencedBy ?purl . } } }`; } function hraVersionFilter(versions) { const quotedVersions = versions.map((v) => `'${v}'`).join(", "); return ` FILTER EXISTS { GRAPH LOD: { [] a dcat:Dataset ; schema:version ?version ; rdfs:seeAlso ?graphPurlVersioned . [] a dcat:Dataset ; schema:additionalType ?hraType ; schema:name ?hraName ; schema:version ?hraVersion ; prov:hadMember ?graphPurlVersioned . FILTER(?hraType = 'collection' && ?hraName = 'hra' && ?hraVersion IN (${quotedVersions})) BIND(IRI(STRBEFORE(STR(?graphPurlVersioned), CONCAT('/', ?version))) as ?purl) } } `; } function getFilterQuery(filter) { const { ontologyTerms, cellTypeTerms, biomarkerTerms, hraVersions } = filter; const filters = []; if (ontologyTerms?.length > 0) { filters.push(termFilter(ontologyTerms)); } if (cellTypeTerms?.length > 0) { filters.push(termFilter(cellTypeTerms)); } if (biomarkerTerms?.length > 0) { filters.push(termFilter(biomarkerTerms)); } if (hraVersions?.length > 0) { filters.push(hraVersionFilter(hraVersions)); } return filters.join("\n"); } async function filterSparqlQuery(sparqlQuery, filter = {}, endpoint = "https://lod.humanatlas.io/sparql") { const sparqlFilter = getFilterQuery(filter, endpoint); const filteredQuery = sparqlQuery.replace("#{{FILTER}}", sparqlFilter); return filteredQuery; } // src/library/hra-kg/operations/do-search.js function reformatResponse2(records) { return records.map((row) => row.purl); } async function doSearch(filter, endpoint = "https://lod.humanatlas.io/sparql") { const filteredQuery = await filterSparqlQuery(do_search_default, filter, endpoint); const results = reformatResponse2(await select(filteredQuery, endpoint)); return results; } // src/library/hra-kg/queries/asctb-term-occurences.rq var asctb_term_occurences_default = "PREFIX ccf: <http://purl.org/ccf/>\nPREFIX dcat: <http://www.w3.org/ns/dcat#>\nPREFIX\ dct: <http://purl.org/dc/terms/>\nPREFIX hint: <http://www.bigdata.com/queryHints#> \nPREFIX owl: <http://www.w3.org/2002\ /07/owl#>\nPREFIX prov: <http://www.w3.org/ns/prov#>\nPREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\nPREFIX skos: <h\ ttp://www.w3.org/2004/02/skos/core#>\nPREFIX schema: <http://schema.org/>\nPREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\ \nPREFIX LOD: <https://lod.humanatlas.io>\nPREFIX HRA: <https://purl.humanatlas.io/collection/hra-api>\nPREFIX body: <http:\ //purl.obolibrary.org/obo/UBERON_0013702>\n\nSELECT ?iri (COUNT(DISTINCT ?purl) as ?count)\nWHERE {\n GRAPH HRA: {\n ?iri\ ccf:ccf_asctb_type [] ;\n dct:isReferencedBy ?purl .\n #{{FILTER}}\n }\n}\nGROUP BY ?iri\n"; // src/library/hra-kg/operations/asctb-term-occurences.js function reformatResponse3(records) { return records.reduce((acc, row) => (acc[row["iri"]] = row["count"], acc), {}); } async function getAsctbTermOccurences(filter, endpoint = "https://lod.humanatlas.io/sparql") { const filteredQuery = await filterSparqlQuery(asctb_term_occurences_default, filter, endpoint); const results = reformatResponse3(await select(filteredQuery, endpoint)); return results; } export { doSearch, getAsctbTermOccurences, getDigitalObjects };