diff --git a/Dockerfile b/Dockerfile
index e768cf9..9b57d85 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,8 @@
-FROM python:3.6.8
-MAINTAINER albert.merono@vu.nl
+#FROM python:3.6.8
+FROM python:3.9.13
+LABEL org.opencontainers.image.authors="ORIGINAL: albert.merono@vu.nl; THIS VERSION: mark.wilkinson@upm.es"
+LABEL org.opencontainers.image.documentation="https://github.com/markwilkinson/grlc/blob/master/README.md"
+RUN apt-get update && apt-get full-upgrade -y
# Default values for env variables
ARG GRLC_GITHUB_ACCESS_TOKEN=
@@ -22,13 +25,17 @@ ENV GRLC_INSTALL_DIR="${GRLC_HOME}/grlc" \
GRLC_RUNTIME_DIR="${GRLC_CACHE_DIR}/runtime"
RUN apt-get update \
- && DEBIAN_FRONTEND=noninteractive apt-get install -y nginx git-core logrotate python-pip locales gettext-base sudo build-essential apt-utils \
+ && DEBIAN_FRONTEND=noninteractive apt-get install -y nginx git-core logrotate python3-pip locales gettext-base sudo build-essential apt-utils \
&& update-locale LANG=C.UTF-8 LC_MESSAGES=POSIX \
&& locale-gen en_US.UTF-8 \
&& DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales \
&& rm -rf /var/lib/apt/lists/*
-RUN curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
+RUN apt-get update && apt-get dist-upgrade -y
+
+
+RUN curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
+RUN chmod a+r /usr/share/keyrings/nodesource.gpg
RUN apt-get update && apt-get install -y nodejs
COPY ./ ${GRLC_INSTALL_DIR}
@@ -48,3 +55,4 @@ VOLUME ["${GRLC_DATA_DIR}", "${GRLC_LOG_DIR}"]
WORKDIR ${GRLC_INSTALL_DIR}
ENTRYPOINT ["/sbin/entrypoint.sh"]
CMD ["app:start"]
+
diff --git a/README.md b/README.md
index aa7b2e7..76e3f70 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,13 @@
+# Shallot
+## Kinda like grlc, but not as powerful ;-)
+
-[![PyPI version](https://badge.fury.io/py/grlc.svg)](https://badge.fury.io/py/grlc)
-[![DOI](https://zenodo.org/badge/46131212.svg)](https://zenodo.org/badge/latestdoi/46131212)
-[![Build Status](https://travis-ci.org/CLARIAH/grlc.svg?branch=master)](https://travis-ci.org/CLARIAH/grlc)
+# NOTE: This is a highly crippled version of the original grlc server
+
+It is intended to be used in secure environments. Specifically, the GitHub and YAML file integration has been disabled. Only local queries will be available.
+## Original Documentation from https://raw.githubusercontent.com/CLARIAH/grlc/ is below
grlc, the git repository linked data API constructor, automatically builds Web APIs using shared SPARQL queries. http://grlc.io/
diff --git a/docker-assets/assets/build/install.sh b/docker-assets/assets/build/install.sh
index e0ef183..954b463 100644
--- a/docker-assets/assets/build/install.sh
+++ b/docker-assets/assets/build/install.sh
@@ -18,11 +18,14 @@ passwd -d ${GRLC_USER}
cd ${GRLC_INSTALL_DIR}
chown ${GRLC_USER}:${GRLC_USER} ${GRLC_HOME} -R
-
pip install --upgrade pip
+pip install 'setuptools<58'
+pip install 'docutils'
pip install .
-npm install git2prov
+#npm install git2prov
+#npm audit fix
+
#move nginx logs to ${GITLAB_LOG_DIR}/nginx
sed -i \
@@ -31,7 +34,7 @@ sed -i \
/etc/nginx/nginx.conf
# configure gitlab log rotation
- cat > /etc/logrotate.d/grlc << EOF
+ cat > /etc/logrotate.d/grlc << EOF1
${GRLC_LOG_DIR}/grlc/*.log {
weekly
missingok
@@ -41,10 +44,10 @@ sed -i \
notifempty
copytruncate
}
- EOF
+EOF1
# configure gitlab vhost log rotation
- cat > /etc/logrotate.d/grlc-nginx << EOF
+ cat > /etc/logrotate.d/grlc-nginx << EOF2
${GRLC_LOG_DIR}/nginx/*.log {
weekly
missingok
@@ -54,4 +57,4 @@ sed -i \
notifempty
copytruncate
}
- EOF
+EOF2
diff --git a/openapi.json b/openapi.json
new file mode 100644
index 0000000..7650e77
--- /dev/null
+++ b/openapi.json
@@ -0,0 +1,229 @@
+{
+ "openapi": "3.0.1",
+ "info": {
+ "title": "Duchenne Parent Project Shallot",
+ "description": "The FAIR Data Point Shallot server for the Duchenne Parent Project",
+ "contact": {
+ "name": "Mark Wilkinson",
+ "url": "https://fairdata.systems"
+ },
+ "version": "local"
+ },
+ "servers": [
+ {
+ "url": "//fairdata.services/api-local/"
+ }
+ ],
+ "paths": {
+ "/count": {
+ "get": {
+ "tags": [
+ "Patient Count"
+ ],
+ "summary": "Returns the number of patients in the registry with the corresponding disease code",
+ "description": "\n\n```\n#+ summary: Returns the number of patients in the registry with the corresponding disease code\n#+ tags:\n#+ - Patient Count\n#+ defaults:\n#+ - type: http://www.orpha.net/ORDO/Orphanet_98896\n#+ endpoint_in_url: False\n\nPREFIX sio: \nselect (count(?p) as ?count) where { \n ?p sio:SIO_000228 ?role . # person has role role\n ?role sio:SIO_000356 ?process . # is realized in process\n ?process sio:SIO_000229 ?output . #has output output\n ?output sio:SIO_000628 ?attribute . # output refers to attribute\n\t?attribute a ?_type_iri . # attribute is a orphacode\n}\n\n```",
+ "parameters": [
+ {
+ "name": "type",
+ "in": "query",
+ "description": "A value of type string (iri) that will substitute ?_type_iri in the original query",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "format": "iri",
+ "default": "http://www.orpha.net/ORDO/Orphanet_98896"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Query response",
+ "content": {
+ "text/csv": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ "text/html": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "Unexpected error",
+ "content": {
+ "text/csv": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ },
+ "text/html": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/kpi-ttd": {
+ "get": {
+ "tags": [
+ "KPI diagnosis-delay"
+ ],
+ "summary": "Returns the Key Performance Indicator of the delay between symptom onset and diagnosis. This data is aggregated by disease, and by year of diagnosis, and is measured in days.",
+ "description": "\n\n```\n#+ summary: Returns the Key Performance Indicator of the delay between symptom onset and diagnosis. This data is aggregated by disease, and by year of diagnosis, and is measured in days.\n#+ tags:\n#+ - KPI diagnosis-delay\n#+ defaults:\n#+ \n#+ endpoint_in_url: False\n\n################################################################\n# list diagnosis and time from onset to diagnosis\n################################################################\n\nPREFIX sio: \nPREFIX rdfs: \nPREFIX rdf: \nPREFIX xsd: \nPREFIX ofn: \n\nSELECT DISTINCT ?ORDO ?yearOfDiagnosis (xsd:integer(ROUND(AVG(?timeOnsetToDiagnosis))) as ?avgoffset)\nWHERE {\n BIND(xsd:integer(ofn:asDays(?onsetdate - ?diagnosisdate)) AS ?timeOnsetToDiagnosis)\n# BIND(xsd:integer(ofn:asDays(?diagnosisdate - ?onsetdate)) AS ?timeOnsetToDiagnosis)\n BIND(SUBSTR(str(?diagnosisdate), 1,4) AS ?yearOfDiagnosis)\n {\n SELECT ?ORDO ?diagnosisdate WHERE {\n GRAPH ?g {\n ?person sio:SIO_000228 ?role1 . # person has role role\n ?role1 sio:SIO_000356 ?process1 . # is realized in process\n ?process1 a . # diagnostic process\n ?process1 sio:SIO_000229 ?output1 . #has output output \n ?output1 a . # diagnosis code\n ?output1 sio:SIO_000628 ?diagnosis1 . # output refers to attribute\n ?diagnosis1 a ?ORDO .\n FILTER(!(?ORDO = sio:SIO_000614)) . # not an \"attribute\" diagnosis\n\t \t}\n \t\t?g sio:SIO_000680 ?startdate .\n \t\t?startdate sio:SIO_000300 ?diagnosisdate .\n }\n }\n {\n SELECT ?onsetdate WHERE {\n ?person sio:SIO_000228 ?role2 . # person has role role\n ?role2 sio:SIO_000356 ?process2 . # is realized in process\n ?process2 sio:SIO_000229 ?output2 . #has output output\n ?output2 sio:SIO_000300 ?onsetdate .\n ?output2 sio:SIO_000628 ?attribute2 . # output refers to attribute\n ?attribute2 a . \n }\n }\n} group by ?ORDO ?yearOfDiagnosis order by ?yearOfDiagnosis ?ORDO\n\n\n```",
+ "responses": {
+ "200": {
+ "description": "Query response",
+ "content": {
+ "text/csv": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ "text/html": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "Unexpected error",
+ "content": {
+ "text/csv": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ },
+ "text/html": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/phenotype-frequencies": {
+ "get": {
+ "tags": [
+ "Phenotype frequency"
+ ],
+ "summary": "Returns the number of patients in the registry that have had a phenotype code at any time",
+ "description": "\n\n```\n#+ summary: Returns the number of patients in the registry that have had a phenotype code at any time\n#+ tags:\n#+ - Phenotype frequency\n#+ defaults:\n#+ \n#+ endpoint_in_url: False\n\nPREFIX sio: \nselect ?type (count(?type) as ?frequency) where {\n select distinct ?p ?type where {\n ?p sio:SIO_000228 ?role . # person has role role\n ?role sio:SIO_000356 ?process . # is realized in process\n ?process sio:SIO_000229 ?output . #has output output\n ?output sio:SIO_000628 ?attribute . # output refers to attribute\n ?attribute a ?type .\n FILTER(!(?type = sio:SIO_000614)) . # not an \"attribute\" type\n }\n} group by ?type\n\n```",
+ "responses": {
+ "200": {
+ "description": "Query response",
+ "content": {
+ "text/csv": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ },
+ "text/html": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {}
+ }
+ }
+ }
+ }
+ },
+ "default": {
+ "description": "Unexpected error",
+ "content": {
+ "text/csv": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ },
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ },
+ "text/html": {
+ "schema": {
+ "$ref": "#/components/schemas/Message"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "components": {
+ "schemas": {
+ "Message": {
+ "type": "string"
+ }
+ }
+ },
+ "x-original-swagger-version": "2.0"
+}
\ No newline at end of file
diff --git a/openapi.yaml b/openapi.yaml
new file mode 100644
index 0000000..ed0debe
--- /dev/null
+++ b/openapi.yaml
@@ -0,0 +1,106 @@
+openapi: "3.0.1"
+info:
+ title: SPARQL OpenAPI
+ version: "10"
+ description: |
+ This is a heavily trimmed copy of the RDF4J REST API that includes only the SPARQL endpoint GET and POST definitions
+
+ From this endpoint we serve the BGV Administrative Collection information (collecting group, date, etc.)
+
+externalDocs:
+ url: https://rdf4j.org/documentation/reference/rest-api/
+
+servers:
+ - url: https://bgv.cbgp.upm.es
+ description: SPARQL server for the BANCO DE GERMOPLASMA VEGETAL-UPM
+
+tags:
+ - name: SPARQL
+ description: SPARQL Query execution
+
+components:
+ requestBodies:
+ RdfData:
+ description: RDF data payload
+ content:
+ application/rdf+xml:
+ schema:
+ type: object
+ xml:
+ name: RDF
+ namespace: http://www.w3.org/1999/02/22-rdf-syntax-ns#
+ text/plain:
+ schema:
+ type: string
+ text/turtle:
+ schema:
+ type: string
+ text/rdf+n3:
+ schema:
+ type: string
+ text/x-nquads:
+ schema:
+ type: string
+ application/ld+json:
+ schema:
+ type: object
+ format: json
+ application/rdf+json:
+ schema:
+ type: object
+ format: json
+ application/trix:
+ schema:
+ type: object
+ xml:
+ name: TriX
+ application/x-trig:
+ schema:
+ type: string
+ application/x-binary-rdf:
+ schema:
+ type: string
+ format: binary
+ responses:
+ 200SparqlResult:
+ description: SPARQL query result
+ content:
+ application/sparql-results+json:
+ examples:
+ SelectQueryResult:
+ $ref: "#/components/examples/SparqlJsonBindings"
+ examples:
+ SparqlJsonBindings:
+ value:
+ head:
+ vars: [ "s", "p", "o" ]
+ results:
+ bindings:
+ - s:
+ type: "uri"
+ value: "http://example.org/s1"
+ - p:
+ type: "uri"
+ value: "http://example.org/p1"
+ - o:
+ type: "literal"
+ value: "foo"
+paths:
+ /repositories/administrative:
+ get:
+ tags:
+ - SPARQL
+ summary: Execute SPARQL query
+ description: |
+ Execute a SPARQL query on the repository. The result format is based on the type of result (boolean, variable bindings, or RDF data) and the negotiated acceptable content-type. Note that RDF4J supports executing SPARQL queries with either a GET or a POST request. POST is supported for queries that are too large to be encoded as a query parameter.
+ parameters:
+ - name: query
+ in: query
+ description: The query to evaluate
+ required: true
+ schema:
+ type: string
+ example: SELECT DISTINCT ?type WHERE {?s a ?type}
+ responses:
+ '200':
+ $ref: "#/components/responses/200SparqlResult"
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
index d12ef86..b860284 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,9 +1,10 @@
docopt==0.6.2
-docutils==0.17.1
Flask==1.0.2
-Flask-Cors==3.0.6
-gevent==1.4.0
-greenlet==0.4.15
+Flask-Cors==3.0.9
+urllib3==1.26.5
+itsdangerous==2.0.1
+gevent==21.12.0
+greenlet==1.1.0
html5lib==1.0.1
isodate==0.5.4
keepalive==0.5
@@ -13,10 +14,9 @@ pyparsing==2.0.7
PyYAML==5.4
rdflib==5.0.0
rdflib-jsonld==0.4.0
-requests==2.20.0
+requests
six==1.12.0
simplejson==3.16.0
-setuptools>=38.6.0
SPARQLTransformer==2.1.1
SPARQLWrapper==1.8.2
werkzeug>=0.16.0
diff --git a/setup.py b/setup.py
index 21f524a..f9190b8 100644
--- a/setup.py
+++ b/setup.py
@@ -55,5 +55,5 @@
package_data = { 'grlc': grlc_data },
include_package_data=True,
data_files=[('citation/grlc', ['CITATION.cff'])],
- python_requires='>=3.7, <=3.8',
+ python_requires='>=3.9, <=3.10',
)
diff --git a/src/fileLoaders.py b/src/fileLoaders.py
index efde936..0602067 100644
--- a/src/fileLoaders.py
+++ b/src/fileLoaders.py
@@ -71,13 +71,15 @@ def __init__(self, user, repo, subdir=None, sha=None, prov=None):
self.subdir = (subdir + "/") if subdir else ""
self.sha = sha if sha else NotSet
self.prov = prov
- gh = Github(static.ACCESS_TOKEN)
+ #gh = Github(static.ACCESS_TOKEN)
try:
- self.gh_repo = gh.get_repo(user + '/' + repo, lazy=False)
+ #self.gh_repo = gh.get_repo(user + '/' + repo, lazy=False)
+ raise Exception("GitHub Access is disabled for this grlc server")
except BadCredentialsException:
raise Exception('BadCredentials: have you set up github_access_token on config.ini ?')
except Exception:
- raise Exception('Repo not found: ' + user + '/' + repo)
+ raise Exception('GitHub Access has been disabled for this server' )
+# raise Exception('Repo not found: ' + user + '/' + repo)
def fetchFiles(self):
"""Returns a list of file items contained on the github repo."""
@@ -262,27 +264,32 @@ class URLLoader(BaseLoader):
specification from a specification YAML file located on a remote server."""
def __init__(self, spec_url):
- """Create a new URLLoader.
-
- Keyword arguments:
- spec_url -- URL where the specification YAML file is located."""
- headers = {'Accept' : 'text/yaml'}
- resp = requests.get(spec_url, headers=headers)
- if resp.status_code == 200:
- self.spec = yaml.load(resp.text)
- self.spec['url'] = spec_url
- self.spec['files'] = {}
- for queryUrl in self.spec['queries']:
- queryNameExt = path.basename(queryUrl)
- queryName = path.splitext(queryNameExt)[0] # Remove extention
- item = {
- 'name': queryName,
- 'download_url': queryUrl
- }
- self.spec['files'][queryNameExt] = item
- del self.spec['queries']
- else:
- raise Exception(resp.text)
+ try:
+ raise Exception("YAML file access is disabled for this grlc server")
+ except Exception:
+ raise Exception("YAML file access is disabled for this grlc server")
+
+ # """Create a new URLLoader.
+
+ # Keyword arguments:
+ # spec_url -- URL where the specification YAML file is located."""
+ # headers = {'Accept' : 'text/yaml'}
+ # resp = requests.get(spec_url, headers=headers)
+ # if resp.status_code == 200:
+ # self.spec = yaml.load(resp.text)
+ # self.spec['url'] = spec_url
+ # self.spec['files'] = {}
+ # for queryUrl in self.spec['queries']:
+ # queryNameExt = path.basename(queryUrl)
+ # queryName = path.splitext(queryNameExt)[0] # Remove extention
+ # item = {
+ # 'name': queryName,
+ # 'download_url': queryUrl
+ # }
+ # self.spec['files'][queryNameExt] = item
+ # del self.spec['queries']
+ # else:
+ # raise Exception(resp.text)
def fetchFiles(self):
"""Returns a list of file items contained on specification."""
diff --git a/swagger.json b/swagger.json
new file mode 100644
index 0000000..0e742c0
--- /dev/null
+++ b/swagger.json
@@ -0,0 +1,133 @@
+{
+ "basePath": "/api-local/",
+ "definitions": {
+ "Message": {
+ "type": "string"
+ }
+ },
+ "host": "fairdata.services",
+ "info": {
+ "contact": {
+ "name": "Mark Wilkinson",
+ "url": "https://fairdata.systems"
+ },
+ "description": "The FAIR Data Point Shallot server for the Duchenne Parent Project",
+ "title": "Duchenne Parent Project Shallot",
+ "version": "local"
+ },
+ "next_commit": null,
+ "paths": {
+ "/count": {
+ "get": {
+ "description": "\n\n```\n#+ summary: Returns the number of patients in the registry with the corresponding disease code\n#+ tags:\n#+ - Patient Count\n#+ defaults:\n#+ - type: http://www.orpha.net/ORDO/Orphanet_98896\n#+ endpoint_in_url: False\n\nPREFIX sio: \nselect (count(?p) as ?count) where { \n ?p sio:SIO_000228 ?role . # person has role role\n ?role sio:SIO_000356 ?process . # is realized in process\n ?process sio:SIO_000229 ?output . #has output output\n ?output sio:SIO_000628 ?attribute . # output refers to attribute\n\t?attribute a ?_type_iri . # attribute is a orphacode\n}\n\n```",
+ "parameters": [
+ {
+ "default": "http://www.orpha.net/ORDO/Orphanet_98896",
+ "description": "A value of type string (iri) that will substitute ?_type_iri in the original query",
+ "format": "iri",
+ "in": "query",
+ "name": "type",
+ "required": true,
+ "type": "string"
+ }
+ ],
+ "produces": [
+ "text/csv",
+ "application/json",
+ "text/html"
+ ],
+ "responses": {
+ "200": {
+ "description": "Query response",
+ "schema": {
+ "items": {
+ "properties": null,
+ "type": "object"
+ },
+ "type": "array"
+ }
+ },
+ "default": {
+ "description": "Unexpected error",
+ "schema": {
+ "$ref": "#/definitions/Message"
+ }
+ }
+ },
+ "summary": "Returns the number of patients in the registry with the corresponding disease code",
+ "tags": [
+ "Patient Count"
+ ]
+ }
+ },
+ "/kpi-ttd": {
+ "get": {
+ "description": "\n\n```\n#+ summary: Returns the Key Performance Indicator of the delay between symptom onset and diagnosis. This data is aggregated by disease, and by year of diagnosis, and is measured in days.\n#+ tags:\n#+ - KPI diagnosis-delay\n#+ defaults:\n#+ \n#+ endpoint_in_url: False\n\n################################################################\n# list diagnosis and time from onset to diagnosis\n################################################################\n\nPREFIX sio: \nPREFIX rdfs: \nPREFIX rdf: \nPREFIX xsd: \nPREFIX ofn: \n\nSELECT DISTINCT ?ORDO ?yearOfDiagnosis (xsd:integer(ROUND(AVG(?timeOnsetToDiagnosis))) as ?avgoffset)\nWHERE {\n BIND(xsd:integer(ofn:asDays(?onsetdate - ?diagnosisdate)) AS ?timeOnsetToDiagnosis)\n# BIND(xsd:integer(ofn:asDays(?diagnosisdate - ?onsetdate)) AS ?timeOnsetToDiagnosis)\n BIND(SUBSTR(str(?diagnosisdate), 1,4) AS ?yearOfDiagnosis)\n {\n SELECT ?ORDO ?diagnosisdate WHERE {\n GRAPH ?g {\n ?person sio:SIO_000228 ?role1 . # person has role role\n ?role1 sio:SIO_000356 ?process1 . # is realized in process\n ?process1 a . # diagnostic process\n ?process1 sio:SIO_000229 ?output1 . #has output output \n ?output1 a . # diagnosis code\n ?output1 sio:SIO_000628 ?diagnosis1 . # output refers to attribute\n ?diagnosis1 a ?ORDO .\n FILTER(!(?ORDO = sio:SIO_000614)) . # not an \"attribute\" diagnosis\n\t \t}\n \t\t?g sio:SIO_000680 ?startdate .\n \t\t?startdate sio:SIO_000300 ?diagnosisdate .\n }\n }\n {\n SELECT ?onsetdate WHERE {\n ?person sio:SIO_000228 ?role2 . # person has role role\n ?role2 sio:SIO_000356 ?process2 . # is realized in process\n ?process2 sio:SIO_000229 ?output2 . #has output output\n ?output2 sio:SIO_000300 ?onsetdate .\n ?output2 sio:SIO_000628 ?attribute2 . # output refers to attribute\n ?attribute2 a . \n }\n }\n} group by ?ORDO ?yearOfDiagnosis order by ?yearOfDiagnosis ?ORDO\n\n\n```",
+ "parameters": [],
+ "produces": [
+ "text/csv",
+ "application/json",
+ "text/html"
+ ],
+ "responses": {
+ "200": {
+ "description": "Query response",
+ "schema": {
+ "items": {
+ "properties": null,
+ "type": "object"
+ },
+ "type": "array"
+ }
+ },
+ "default": {
+ "description": "Unexpected error",
+ "schema": {
+ "$ref": "#/definitions/Message"
+ }
+ }
+ },
+ "summary": "Returns the Key Performance Indicator of the delay between symptom onset and diagnosis. This data is aggregated by disease, and by year of diagnosis, and is measured in days.",
+ "tags": [
+ "KPI diagnosis-delay"
+ ]
+ }
+ },
+ "/phenotype-frequencies": {
+ "get": {
+ "description": "\n\n```\n#+ summary: Returns the number of patients in the registry that have had a phenotype code at any time\n#+ tags:\n#+ - Phenotype frequency\n#+ defaults:\n#+ \n#+ endpoint_in_url: False\n\nPREFIX sio: \nselect ?type (count(?type) as ?frequency) where {\n select distinct ?p ?type where {\n ?p sio:SIO_000228 ?role . # person has role role\n ?role sio:SIO_000356 ?process . # is realized in process\n ?process sio:SIO_000229 ?output . #has output output\n ?output sio:SIO_000628 ?attribute . # output refers to attribute\n ?attribute a ?type .\n FILTER(!(?type = sio:SIO_000614)) . # not an \"attribute\" type\n }\n} group by ?type\n\n```",
+ "parameters": [],
+ "produces": [
+ "text/csv",
+ "application/json",
+ "text/html"
+ ],
+ "responses": {
+ "200": {
+ "description": "Query response",
+ "schema": {
+ "items": {
+ "properties": null,
+ "type": "object"
+ },
+ "type": "array"
+ }
+ },
+ "default": {
+ "description": "Unexpected error",
+ "schema": {
+ "$ref": "#/definitions/Message"
+ }
+ }
+ },
+ "summary": "Returns the number of patients in the registry that have had a phenotype code at any time",
+ "tags": [
+ "Phenotype frequency"
+ ]
+ }
+ }
+ },
+ "prev_commit": null,
+ "schemes": [],
+ "swagger": "2.0"
+}
\ No newline at end of file