diff --git a/.autorc b/.autorc index f63bd72..dc7eb7f 100644 --- a/.autorc +++ b/.autorc @@ -12,9 +12,9 @@ [ "omit-commits", { - "username": "dependabot[bot]", + "username": ["dependabot[bot]", "pre-commit-ci[bot]"], "subject": "[pre-commit.ci]", - "labels": "_bot" + "labels": ["_bot", "skip-release"] } ] ], diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f68d237..4ee9056 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: repos: - repo: https://github.com/psf/black - rev: 24.3.0 + rev: 24.4.0 hooks: - id: black args: @@ -22,7 +22,7 @@ repos: - --per-file-ignores=./app/api/models.py:F722 - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-yaml - id: pretty-format-json diff --git a/.template-env b/.template-env deleted file mode 100644 index afcae33..0000000 --- a/.template-env +++ /dev/null @@ -1,19 +0,0 @@ -# THIS IS A TEMPLATE .env FILE. MAKE A COPY OF THIS FILE NAMED .env AND MODIFY VALUES AS NEEDED. -# For more info on each variable, see https://neurobagel.org/infrastructure/#set-the-environment-variables -NB_GRAPH_USERNAME=DBUSER # REPLACE DBUSER WITH YOUR GRAPH DATABASE USERNAME -NB_GRAPH_PASSWORD=DBPASSWORD # REPLACE DBPASSWORD WITH YOUR GRAPH DATABASE PASSWORD -NB_GRAPH_DB=test_data/query -NB_RETURN_AGG=true -NB_API_TAG=latest -# To allow requests from browser tools like the query tool -# deployed locally with default port settings; edit as needed for your setup -NB_API_ALLOWED_ORIGINS="https://localhost:3000 http://localhost:3000" -NB_GRAPH_IMG=stardog/stardog:8.2.2-java11-preview -## ADDITIONAL CONFIGURABLE PARAMETERS: Uncomment and modify values of the below variables as needed to use non-default values. -# NB_API_PORT_HOST=8000 -# NB_API_PORT=8000 -# NB_GRAPH_ROOT_HOST=~/stardog-home -# NB_GRAPH_ROOT_CONT=/var/opt/stardog -# NB_GRAPH_ADDRESS=graph -# NB_GRAPH_PORT_HOST=5820 -# NB_GRAPH_PORT=5820 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e5e0bba --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,58 @@ +# v0.2.1 (Tue Apr 16 2024) + +#### ๐Ÿ› Bug Fixes + +- [FIX] Address performance issues in SPARQL query [#308](https://github.com/neurobagel/api/pull/308) ([@surchs](https://github.com/surchs)) +- [FIX] Disable timeout for request to graph [#305](https://github.com/neurobagel/api/pull/305) ([@alyssadai](https://github.com/alyssadai)) + +#### Authors: 2 + +- Alyssa Dai ([@alyssadai](https://github.com/alyssadai)) +- Sebastian Urchs ([@surchs](https://github.com/surchs)) + +--- + +# v0.2.0 (Thu Apr 11 2024) + +:tada: This release contains work from a new contributor! :tada: + +Thank you, Abdul Samad Siddiqui ([@samadpls](https://github.com/samadpls)), for all your work! + +### Release Notes + +#### [MNT] Release new data model ([#300](https://github.com/neurobagel/api/pull/300)) + +We have updated the Neurobagel data model to allow users to specify phenotypic information at the session level (https://github.com/neurobagel/planning/issues/83). This release updates the node API so it can understand the new graph data. + +--- + +#### ๐Ÿ’ฅ Breaking Changes + +- [REF] Make session count names clearer in query response [#282](https://github.com/neurobagel/api/pull/282) ([@alyssadai](https://github.com/alyssadai)) +- [ENH] Support queries of session-level phenotypic attributes [#264](https://github.com/neurobagel/api/pull/264) ([@alyssadai](https://github.com/alyssadai)) + +#### ๐Ÿš€ Enhancements + +- [ENH] Added root endpoint with welcome message and API docs link [#286](https://github.com/neurobagel/api/pull/286) ([@samadpls](https://github.com/samadpls)) +- [MNT] Release new data model [#300](https://github.com/neurobagel/api/pull/300) ([@surchs](https://github.com/surchs)) +- Delete .github/workflows/add_pr2project.yml [#244](https://github.com/neurobagel/api/pull/244) ([@surchs](https://github.com/surchs)) + +#### ๐Ÿ“ Documentation + +- [DOC] Added warning about quoting in `.env` file for Docker commands [#284](https://github.com/neurobagel/api/pull/284) ([@samadpls](https://github.com/samadpls)) +- [DOC] Add sample default SPARQL query to repo [#277](https://github.com/neurobagel/api/pull/277) ([@alyssadai](https://github.com/alyssadai)) + +#### ๐Ÿงช Tests + +- [TST] Refactor tests [#269](https://github.com/neurobagel/api/pull/269) ([@alyssadai](https://github.com/alyssadai)) + +#### ๐Ÿ”ฉ Dependency Updates + +- Bumped fastapi, starlette, and typing_extensions [#295](https://github.com/neurobagel/api/pull/295) ([@rmanaem](https://github.com/rmanaem)) + +#### Authors: 4 + +- Abdul Samad Siddiqui ([@samadpls](https://github.com/samadpls)) +- Alyssa Dai ([@alyssadai](https://github.com/alyssadai)) +- Arman Jahanpour ([@rmanaem](https://github.com/rmanaem)) +- Sebastian Urchs ([@surchs](https://github.com/surchs)) diff --git a/README.md b/README.md index 6239e01..b68931c 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ git clone https://github.com/neurobagel/api.git ### Set the environment variables Create a file called `.env` in the root of the repository to store the environment variables used by the app. -This repository contains a [template `.env` file](/.template-env) that you can copy and edit. +See the Neurobagel recipes repo for a [template `.env` file](https://github.com/neurobagel/recipes/blob/main/dev/template.env) you can copy and edit. To run API requests against a graph, at least two environment variables must be set: `NB_GRAPH_USERNAME` and `NB_GRAPH_PASSWORD`. @@ -65,31 +65,22 @@ To run API requests against a graph, at least two environment variables must be The below instructions for Docker and Python assume that you have at least set `NB_GRAPH_USERNAME` and `NB_GRAPH_PASSWORD` in your `.env`. ### Docker -First, [install docker](https://docs.docker.com/get-docker/). +First, [install Docker](https://docs.docker.com/get-docker/). You can then run a Docker container for the API in one of three ways: #### Option 1 (RECOMMENDED): Use the `docker-compose.yaml` file -First, [install docker compose](https://docs.docker.com/compose/install/). +First, [install Docker Compose](https://docs.docker.com/compose/install/). -If needed, update your `.env` file with optional environment variables for the docker compose configuration. +Refer to our [official documentation](https://neurobagel.org/infrastructure/#launch-the-neurobagel-node-api-and-graph-stack) for instructions on using the template configuration files from our [recipes](https://github.com/neurobagel/recipes) repository to spin up a local Neurobagel API and graph backend with Docker Compose. **TIP:** Double check that the environment variables are resolved with your expected values using the command `docker compose config`. -> :information_source: **Note: Deploying the Neurobagel query tool** -> -> When you deploy the API locally with `docker compose`, -> you will only spin up the graph backend and the API service. -> If you want to use the graphical browser query tool -> as a standalone service for your local API, -> you will have to deploy it manually. -> Please refer to our [documentation for details](https://neurobagel.org/infrastructure/#as-a-standalone-service). - -Use Docker Compose to spin up the containers by running the following in the repository root (where the `docker-compose.yml` file is): +Use Docker Compose to spin up your API and graph containers by running the following in the directory where the `docker-compose.yml` file is): ```bash docker compose up -d ``` -If you want to ensure you have the latest images use the command below: +Or, to ensure you have the latest images: ```bash docker compose pull && docker compose up -d diff --git a/app/api/crud.py b/app/api/crud.py index 96a4028..876b82c 100644 --- a/app/api/crud.py +++ b/app/api/crud.py @@ -19,7 +19,7 @@ ] -def post_query_to_graph(query: str, timeout: float = 30.0) -> dict: +def post_query_to_graph(query: str, timeout: float = None) -> dict: """ Makes a post request to the graph API to perform a query, using parameters from the environment. @@ -30,7 +30,7 @@ def post_query_to_graph(query: str, timeout: float = 30.0) -> dict: query : str The full SPARQL query string. timeout : float, optional - The maximum duration for the request, by default 5.0 seconds. + The maximum duration for the request in seconds, by default None. Returns ------- diff --git a/app/api/utility.py b/app/api/utility.py index 9280fc5..1f39193 100644 --- a/app/api/utility.py +++ b/app/api/utility.py @@ -206,28 +206,14 @@ def create_query( nb:hasLabel ?session_id. OPTIONAL {{ ?session nb:hasAcquisition/nb:hasContrastType ?image_modal. - OPTIONAL {{ - ?session nb:hasFilePath ?session_file_path. - }} - }} - OPTIONAL {{ - ?dataset_uuid nb:hasPortalURI ?dataset_portal_uri. - }} - OPTIONAL {{ - ?session nb:hasAge ?age. - }} - OPTIONAL {{ - ?session nb:hasSex ?sex. - }} - OPTIONAL {{ - ?session nb:hasDiagnosis ?diagnosis. - }} - OPTIONAL {{ - ?session nb:isSubjectGroup ?subject_group. - }} - OPTIONAL {{ - ?session nb:hasAssessment ?assessment. + OPTIONAL {{?session nb:hasFilePath ?session_file_path.}} }} + OPTIONAL {{?dataset_uuid nb:hasPortalURI ?dataset_portal_uri.}} + OPTIONAL {{?session nb:hasAge ?age.}} + OPTIONAL {{?session nb:hasSex ?sex.}} + OPTIONAL {{?session nb:hasDiagnosis ?diagnosis.}} + OPTIONAL {{?session nb:isSubjectGroup ?subject_group.}} + OPTIONAL {{?session nb:hasAssessment ?assessment.}} {{ SELECT ?subject (count(distinct ?phenotypic_session) as ?num_matching_phenotypic_sessions) WHERE {{ @@ -235,21 +221,12 @@ def create_query( OPTIONAL {{ ?subject nb:hasSession ?phenotypic_session. ?phenotypic_session a nb:PhenotypicSession. - OPTIONAL {{ - ?phenotypic_session nb:hasAge ?age. - }} - OPTIONAL {{ - ?phenotypic_session nb:hasSex ?sex. - }} - OPTIONAL {{ - ?phenoypic_session nb:hasDiagnosis ?diagnosis. - }} - OPTIONAL {{ - ?phenotypic_session nb:isSubjectGroup ?subject_group. - }} - OPTIONAL {{ - ?phenotypic_session nb:hasAssessment ?assessment. - }} + + OPTIONAL {{?phenotypic_session nb:hasAge ?age.}} + OPTIONAL {{?phenotypic_session nb:hasSex ?sex.}} + OPTIONAL {{?phenotypic_session nb:hasDiagnosis ?diagnosis.}} + OPTIONAL {{?phenotypic_session nb:isSubjectGroup ?subject_group.}} + OPTIONAL {{?phenotypic_session nb:hasAssessment ?assessment.}} }} {phenotypic_session_level_filters} }} GROUP BY ?subject @@ -260,7 +237,8 @@ def create_query( ?subject a nb:Subject. OPTIONAL {{ ?subject nb:hasSession ?imaging_session. - ?imaging_session nb:hasAcquisition/nb:hasContrastType ?image_modal. + ?imaging_session a nb:ImagingSession; + nb:hasAcquisition/nb:hasContrastType ?image_modal. }} {imaging_session_level_filters} }} GROUP BY ?subject diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index d78b0bb..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,22 +0,0 @@ -version: "3.8" - -services: - api: - image: "neurobagel/api:${NB_API_TAG:-latest}" - ports: - - "${NB_API_PORT_HOST:-8000}:${NB_API_PORT:-8000}" - environment: - NB_GRAPH_USERNAME: ${NB_GRAPH_USERNAME} - NB_GRAPH_PASSWORD: ${NB_GRAPH_PASSWORD} - NB_GRAPH_ADDRESS: ${NB_GRAPH_ADDRESS:-graph} - NB_GRAPH_PORT: ${NB_GRAPH_PORT:-5820} - NB_GRAPH_DB: ${NB_GRAPH_DB:-test_data/query} - NB_RETURN_AGG: ${NB_RETURN_AGG:-true} - NB_API_PORT: ${NB_API_PORT:-8000} - NB_API_ALLOWED_ORIGINS: ${NB_API_ALLOWED_ORIGINS} - graph: - image: "${NB_GRAPH_IMG:-stardog/stardog:8.2.2-java11-preview}" - volumes: - - "${NB_GRAPH_ROOT_HOST:-~/stardog-home}:${NB_GRAPH_ROOT_CONT:-/var/opt/stardog}" - ports: - - "${NB_GRAPH_PORT_HOST:-5820}:${NB_GRAPH_PORT:-5820}" diff --git a/docs/default_neurobagel_query.rq b/docs/default_neurobagel_query.rq index 3d48d11..c4dc71c 100644 --- a/docs/default_neurobagel_query.rq +++ b/docs/default_neurobagel_query.rq @@ -18,28 +18,14 @@ WHERE { nb:hasLabel ?session_id. OPTIONAL { ?session nb:hasAcquisition/nb:hasContrastType ?image_modal. - OPTIONAL { - ?session nb:hasFilePath ?session_file_path. - } - } - OPTIONAL { - ?dataset_uuid nb:hasPortalURI ?dataset_portal_uri. - } - OPTIONAL { - ?session nb:hasAge ?age. - } - OPTIONAL { - ?session nb:hasSex ?sex. - } - OPTIONAL { - ?session nb:hasDiagnosis ?diagnosis. - } - OPTIONAL { - ?session nb:isSubjectGroup ?subject_group. - } - OPTIONAL { - ?session nb:hasAssessment ?assessment. - } + OPTIONAL {?session nb:hasFilePath ?session_file_path.} + } + OPTIONAL {?dataset_uuid nb:hasPortalURI ?dataset_portal_uri.} + OPTIONAL {?session nb:hasAge ?age.} + OPTIONAL {?session nb:hasSex ?sex.} + OPTIONAL {?session nb:hasDiagnosis ?diagnosis.} + OPTIONAL {?session nb:isSubjectGroup ?subject_group.} + OPTIONAL {?session nb:hasAssessment ?assessment.} { SELECT ?subject (count(distinct ?phenotypic_session) as ?num_matching_phenotypic_sessions) WHERE { @@ -47,21 +33,12 @@ WHERE { OPTIONAL { ?subject nb:hasSession ?phenotypic_session. ?phenotypic_session a nb:PhenotypicSession. - OPTIONAL { - ?phenotypic_session nb:hasAge ?age. - } - OPTIONAL { - ?phenotypic_session nb:hasSex ?sex. - } - OPTIONAL { - ?phenoypic_session nb:hasDiagnosis ?diagnosis. - } - OPTIONAL { - ?phenotypic_session nb:isSubjectGroup ?subject_group. - } - OPTIONAL { - ?phenotypic_session nb:hasAssessment ?assessment. - } + + OPTIONAL {?phenotypic_session nb:hasAge ?age.} + OPTIONAL {?phenotypic_session nb:hasSex ?sex.} + OPTIONAL {?phenotypic_session nb:hasDiagnosis ?diagnosis.} + OPTIONAL {?phenotypic_session nb:isSubjectGroup ?subject_group.} + OPTIONAL {?phenotypic_session nb:hasAssessment ?assessment.} } } GROUP BY ?subject @@ -72,7 +49,8 @@ WHERE { ?subject a nb:Subject. OPTIONAL { ?subject nb:hasSession ?imaging_session. - ?imaging_session nb:hasAcquisition/nb:hasContrastType ?image_modal. + ?imaging_session a nb:ImagingSession; + nb:hasAcquisition/nb:hasContrastType ?image_modal. } } GROUP BY ?subject diff --git a/requirements.txt b/requirements.txt index c9449e3..92c1a4c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,16 +6,16 @@ coverage==7.0.0 click==8.1.3 distlib==0.3.6 exceptiongroup==1.0.4 -fastapi==0.95.2 +fastapi==0.110.1 filelock==3.8.0 h11==0.14.0 httpcore==0.16.2 httpx==0.23.1 identify==2.5.9 -idna==3.4 +idna==3.7 iniconfig==1.1.1 nodeenv==1.7.0 -orjson==3.8.6 +orjson==3.9.15 packaging==21.3 pandas==1.5.2 platformdirs==2.5.4 @@ -27,9 +27,9 @@ pytest==7.2.0 PyYAML==6.0 rfc3986==1.5.0 sniffio==1.3.0 -starlette==0.27.0 +starlette==0.37.2 toml==0.10.2 tomli==2.0.1 -typing_extensions==4.4.0 +typing_extensions==4.11.0 uvicorn==0.20.0 virtualenv==20.16.7