From c6a506d473b01c63fc9fe88087fd7ecfc3b39d21 Mon Sep 17 00:00:00 2001 From: Jermiah Joseph Date: Sun, 4 Feb 2024 11:12:21 -0500 Subject: [PATCH 1/8] feat: retrieve new series after a given date, +docs +tests --- docs/Tutorial.ipynb | 51 ++++++++++++++++++++++++- src/nbiatoolkit/nbia.py | 28 +++++++++++++- src/nbiatoolkit/utils/nbia_endpoints.py | 5 +-- src/nbiatoolkit/utils/parsers.py | 10 ++++- tests/test_nbia.py | 11 +++++- 5 files changed, 93 insertions(+), 12 deletions(-) diff --git a/docs/Tutorial.ipynb b/docs/Tutorial.ipynb index 0286f34..39a9704 100644 --- a/docs/Tutorial.ipynb +++ b/docs/Tutorial.ipynb @@ -23,7 +23,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -44,7 +44,7 @@ { "data": { "text/plain": [ - "'0.18.1'" + "'0.22.1'" ] }, "execution_count": 2, @@ -668,6 +668,53 @@ "pprint(seriesbyPatientJSON[0])" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### get New Series after a given date\n", + "\n", + "``` python\n", + "getNewSeries(\n", + " Date: Union[str, datetime], # (required) accepted formats:\n", + " # \"%Y-%m-%d\", \"%Y/%m/%d\", \"%Y%m%d\", \n", + " # \"%m/%d/%Y\", \"%d/%m/%Y\", \"%d-%m-%Y\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "01/01/2024\n", + "Total new series after 2024-01-01: 4751\n", + "{'BodyPartExamined': 'BREAST',\n", + " 'Collection': 'Advanced-MRI-Breast-Lesions',\n", + " 'ImageCount': 580,\n", + " 'Manufacturer': 'GE MEDICAL SYSTEMS',\n", + " 'ManufacturerModelName': 'Signa HDxt',\n", + " 'Modality': 'MR',\n", + " 'PatientID': 'AMBL-376',\n", + " 'SeriesDate': '2005-04-14 00:00:00.0',\n", + " 'SeriesDescription': 'AX Sen Vibrant MultiPhase',\n", + " 'SeriesInstanceUID': '1.3.6.1.4.1.14519.5.2.1.196168555404542578475976858220037429361',\n", + " 'SeriesNumber': 5,\n", + " 'SoftwareVersions': '24',\n", + " 'StudyInstanceUID': '1.3.6.1.4.1.14519.5.2.1.201692485188138093977458202425301357349'}\n" + ] + } + ], + "source": [ + "newSeries = client.getNewSeries(Date=\"2024/01/01\")\n", + "print(f\"Total new series after 2024-01-01: {len(newSeries)}\")\n", + "pprint(newSeries[0])" + ] + }, { "cell_type": "markdown", "metadata": {}, diff --git a/src/nbiatoolkit/nbia.py b/src/nbiatoolkit/nbia.py index 14e4fe9..a3dd876 100644 --- a/src/nbiatoolkit/nbia.py +++ b/src/nbiatoolkit/nbia.py @@ -11,7 +11,7 @@ from tqdm import tqdm from pyfiglet import Figlet import os - +from datetime import datetime # set __version__ variable __version__ = "0.22.1" @@ -51,12 +51,14 @@ def __init__( def headers(self): return self._api_headers + def query_api( self, endpoint: NBIA_ENDPOINTS, params: dict = {} ) -> Union[list, dict, bytes]: query_url = NBIA_ENDPOINTS.BASE_URL.value + endpoint.value self.log.debug("Querying API endpoint: %s", query_url) + self.log.debug("Query parameters: %s", params) response: requests.Response try: response = requests.get(url=query_url, headers=self.headers, params=params) @@ -172,7 +174,10 @@ def getPatients(self, Collection: str = "") -> Union[list[dict[str, str]], None] return patientList - def getNewPatients(self, Collection: str, Date: str) -> Union[list[dict[str, str]], None]: + def getNewPatients(self, + Collection: str, + Date: Union[str, datetime], + ) -> Union[list[dict[str, str]], None]: assert Collection is not None assert Date is not None @@ -298,6 +303,25 @@ def getSeries( return response + def getNewSeries( + self, + Date: Union[str, datetime], + ) -> Union[list[dict], None]: + assert Date is not None and isinstance(Date, (str, datetime)), \ + "Date must be a string or datetime object" + + # for some reason this endpoint requires the date in %d/%m/%Y format + fromDate = convertDateFormat(input_date=Date, format="%d/%m/%Y") + PARAMS = self.parsePARAMS({"fromDate": fromDate}) + + response = self.query_api(endpoint=NBIA_ENDPOINTS.GET_UPDATED_SERIES, params=PARAMS) + + if not isinstance(response, list): + self.log.error("Expected list, but received: %s", type(response)) + return None + + return response + def downloadSeries( self, SeriesInstanceUID: Union[str, list], diff --git a/src/nbiatoolkit/utils/nbia_endpoints.py b/src/nbiatoolkit/utils/nbia_endpoints.py index 0ab2a66..df3361b 100644 --- a/src/nbiatoolkit/utils/nbia_endpoints.py +++ b/src/nbiatoolkit/utils/nbia_endpoints.py @@ -22,15 +22,12 @@ class NBIA_ENDPOINTS(Enum): GET_STUDIES = "v2/getPatientStudy" GET_SERIES = "v2/getSeries" + GET_UPDATED_SERIES = "v2/getUpdatedSeries" # ?fromDate=01/01/2024 DOWNLOAD_SERIES = "v2/getImageWithMD5Hash" - GET_UPDATED_SERIES = "v2/getUpdatedSeries" # ?fromDate=01/01/2024 - # https://services.cancerimagingarchive.net/nbia-api/services/v2/getSeriesMetaData?SeriesInstanceUID=1.3.6.1.4.1.9590.100.1.2.374115997511889073021386151921807063992 - # https://services.cancerimagingarchive.net/nbia-api/services/v2/getSeriesSize?SeriesInstanceUID=1.3.6.1.4.1.9590.100.1.2.374115997511889073021386151921807063992 - # curl -H "Authorization:Bearer YOUR_ACCESS_TOKEN" -k "https://services.cancerimagingarchive.net/nbia-api/services/v2/getSeries" # curl -H "Authorization:Bearer YOUR_ACCESS_TOKEN" -k "https://services.cancerimagingarchive.net/nbia-api/services/v2/getSeriesMetaData" # curl -H "Authorization:Bearer YOUR_ACCESS_TOKEN" -k "https://services.cancerimagingarchive.net/nbia-api/services/v2/getSeriesSize" diff --git a/src/nbiatoolkit/utils/parsers.py b/src/nbiatoolkit/utils/parsers.py index 9d55d54..56b2136 100644 --- a/src/nbiatoolkit/utils/parsers.py +++ b/src/nbiatoolkit/utils/parsers.py @@ -1,6 +1,6 @@ from bs4 import BeautifulSoup from datetime import datetime - +from typing import Union def clean_html(html_string: str) -> str: """ @@ -39,7 +39,10 @@ def convertMillis(millis: int) -> str: return datetime.fromtimestamp(millis / 1000.0).strftime('%Y-%m-%d') -def convertDateFormat(input_date: str, format: str = "%Y/%m/%d") -> str: +def convertDateFormat( + input_date: Union[str, datetime], + format: str = "%Y/%m/%d" +) -> str: """ Converts the input date to the desired format. @@ -56,6 +59,9 @@ def convertDateFormat(input_date: str, format: str = "%Y/%m/%d") -> str: possible_formats = [ "%Y-%m-%d", "%Y/%m/%d", "%Y%m%d", "%m/%d/%Y", "%d/%m/%Y", "%d-%m-%Y" ] + if isinstance(input_date, datetime): + return input_date.strftime(format) + # Try parsing the input date with each possible format for date_format in possible_formats: try: diff --git a/tests/test_nbia.py b/tests/test_nbia.py index a197a8d..296788d 100644 --- a/tests/test_nbia.py +++ b/tests/test_nbia.py @@ -93,7 +93,7 @@ def test_getPatients(nbia_patients): assert "PatientSex" in nbia_patients[0] def test_getNewPatients(nbia_client): - patients = nbia_client.getNewPatients('TCGA-BLCA', Date = "2019-01-01") + patients = nbia_client.getNewPatients('CMB-LCA', Date = "2022/12/06") assert isinstance(patients, list) assert len(patients) > 0 assert isinstance(patients[0], dict) @@ -144,7 +144,14 @@ def test_fail_getSeries(nbia_client, nbia_collections, nbia_patients): assert isinstance(seriesList, list) assert len(seriesList) > 0 assert isinstance(seriesList[0], dict) - + +def test_getNewSeries(nbia_client): + Date = "01/01/2024" + series = nbia_client.getNewSeries(Date) + assert isinstance(series, list) or series is None + if series is not None: + assert all(isinstance(s, dict) for s in series) + def test_downloadSeries(nbia_client, nbia_collections, nbia_patients): seriesList = nbia_client.getSeries( Collection=nbia_collections[0], From 68e883124dc7a30c197236e64d4bf5d1faa57f4c Mon Sep 17 00:00:00 2001 From: Jermiah Joseph Date: Sun, 4 Feb 2024 11:20:24 -0500 Subject: [PATCH 2/8] build: Add labels and update maintainer information in Dockerfile --- Dockerfile | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 296dadf..5eff8ab 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,14 +6,20 @@ # docker build -t nbiatoolkit . # # ADD LABELS HERE + FROM python:3.12-slim -LABEL maintainer="Jermiah Joseph" +LABEL maintainer="Jermiah Joseph jermiahjoseph98@gmail.com" +LABEL description="This is a Dockerfile for the nbiatoolkit package." +LABEL license="MIT" +LABEL usage="docker run -it --rm NBIAToolkit --help" +LABEL org.opencontainers.image.source="github.com/jjjermiah/nbiatoolkit" # install the dependencies +RUN pip install --upgrade pip RUN python -m pip install nbiatoolkit -RUN python -c 'import nbiatoolkit; print(nbiatoolkit.version())' +RUN NBIAToolkit --help # On run, open a bash shell CMD ["/bin/bash"] From 77dc291a0b60c4958b52b924c0056dedea56971e Mon Sep 17 00:00:00 2001 From: Jermiah Joseph Date: Sun, 4 Feb 2024 11:20:35 -0500 Subject: [PATCH 3/8] build: Update pytest parallelism and add Codecov artifact upload --- .github/workflows/main.yml | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index adb8f9e..e616a7f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,12 +32,13 @@ jobs: - name: Test with pytest run: | - poetry run pytest -n 2 --cov --cov-report xml:coverage-report/coverage.xml + # Github action runners now have 4 cores + poetry run pytest -n 4 --cov --cov-report xml:coverage-report/coverage.xml - name: Build documentation run: poetry run make html --directory docs/ - - name: Upload coverage report + - name: Upload coverage report artifact to be used by Codecov uses: actions/upload-artifact@v2 with: name: coverage-report @@ -74,10 +75,10 @@ jobs: issues: write pull-requests: write - # needs: Continuous-Integration + needs: Continuous-Integration # if pulling to main, deploy to PyPI - # if: github.ref == 'refs/heads/main' + if: github.ref == 'refs/heads/main' # Set up operating system runs-on: ubuntu-latest @@ -100,11 +101,6 @@ jobs: - name: Install package run: poetry install - - # Existing jobs... - - - # This action uses Python Semantic Release v8 # What this action does: # - Determines the next version number based on the commit history @@ -142,10 +138,6 @@ jobs: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} - - name: Print latest tag name - run: | - printf "%s\n" "${LATEST_TAG}" - - name: Print branch name run: | printf "LATEST TAG: %s\n" "${LATEST_TAG}" From 4a7d242f5afd137a5384b31edb4bfad1faa65278 Mon Sep 17 00:00:00 2001 From: Jermiah Joseph Date: Sun, 4 Feb 2024 11:26:57 -0500 Subject: [PATCH 4/8] fix: fix error from getCollections conflicting -prefix argument --- src/nbiatoolkit/nbia_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nbiatoolkit/nbia_cli.py b/src/nbiatoolkit/nbia_cli.py index 7c08ff4..39c35f2 100644 --- a/src/nbiatoolkit/nbia_cli.py +++ b/src/nbiatoolkit/nbia_cli.py @@ -59,7 +59,7 @@ def _initialize_parser(description: str) -> argparse.ArgumentParser: ) credentials.add_argument( - "-p", "--password", action="store", type=str, default= "", #help="Password for the NBIA API (default: '')" + "-pw", "--password", action="store", type=str, default= "", #help="Password for the NBIA API (default: '')" ) # make the credentials group show up first From 473c5a72a623fd4241831ae203f522741eee0097 Mon Sep 17 00:00:00 2001 From: Jermiah Joseph Date: Sun, 4 Feb 2024 11:30:37 -0500 Subject: [PATCH 5/8] separate build documentation to prevent running it on every machine --- .github/workflows/main.yml | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e616a7f..36bb1fc 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,9 +35,6 @@ jobs: # Github action runners now have 4 cores poetry run pytest -n 4 --cov --cov-report xml:coverage-report/coverage.xml - - name: Build documentation - run: poetry run make html --directory docs/ - - name: Upload coverage report artifact to be used by Codecov uses: actions/upload-artifact@v2 with: @@ -66,6 +63,29 @@ jobs: verbose: true name: codecov-umbrella + Build-Documentation: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python 3.12 + uses: actions/setup-python@v4 + with: + python-version: 3.12 + + - name: Install poetry + uses: snok/install-poetry@v1 + + - name: Install dependencies + run: poetry install + + - name: Build documentation + run: | + poetry run mkdocs build + + + Continuous-Deployment: @@ -75,7 +95,7 @@ jobs: issues: write pull-requests: write - needs: Continuous-Integration + needs: [Continuous-Integration, Build-Documentation] # if pulling to main, deploy to PyPI if: github.ref == 'refs/heads/main' From 1cf31bb0570d1f79086bf4c4edfdf94a16ebd98a Mon Sep 17 00:00:00 2001 From: Jermiah Joseph Date: Sun, 4 Feb 2024 11:40:00 -0500 Subject: [PATCH 6/8] fix: Update .gitignore and build documentation --- .github/workflows/main.yml | 2 +- .gitignore | 3 +- poetry.lock | 139 ++++++++++++++++++++++++++++++++++++- pyproject.toml | 1 + 4 files changed, 142 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 36bb1fc..60fd58c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -82,7 +82,7 @@ jobs: - name: Build documentation run: | - poetry run mkdocs build + poetry run make html --directory docs/ diff --git a/.gitignore b/.gitignore index 1a998f2..d7de9aa 100644 --- a/.gitignore +++ b/.gitignore @@ -148,4 +148,5 @@ driver.py data/* sandbox -docs/data/* \ No newline at end of file +docs/data/* +docs/autoapi \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index c70f88a..29da1e7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -683,6 +683,23 @@ files = [ {file = "fqdn-1.4.0.tar.gz", hash = "sha256:30e8f2e685ce87cdace4712fd97c5d09f5e6fa519bbb66e8f188f6a7cb3a5c4e"}, ] +[[package]] +name = "ghp-import" +version = "2.1.0" +description = "Copy your docs directly to the gh-pages branch." +optional = false +python-versions = "*" +files = [ + {file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"}, + {file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"}, +] + +[package.dependencies] +python-dateutil = ">=2.8.1" + +[package.extras] +dev = ["flake8", "markdown", "twine", "wheel"] + [[package]] name = "gitdb" version = "4.0.11" @@ -1345,6 +1362,21 @@ files = [ {file = "jupyterlab_widgets-3.0.9.tar.gz", hash = "sha256:6005a4e974c7beee84060fdfba341a3218495046de8ae3ec64888e5fe19fdb4c"}, ] +[[package]] +name = "markdown" +version = "3.5.2" +description = "Python implementation of John Gruber's Markdown." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Markdown-3.5.2-py3-none-any.whl", hash = "sha256:d43323865d89fc0cb9b20c75fc8ad313af307cc087e84b657d9eec768eddeadd"}, + {file = "Markdown-3.5.2.tar.gz", hash = "sha256:e1ac7b3dc550ee80e602e71c1d168002f062e49f1b11e26a36264dafd4df2ef8"}, +] + +[package.extras] +docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] +testing = ["coverage", "pyyaml"] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -1482,6 +1514,17 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "mergedeep" +version = "1.3.4" +description = "A deep merge function for 🐍." +optional = false +python-versions = ">=3.6" +files = [ + {file = "mergedeep-1.3.4-py3-none-any.whl", hash = "sha256:70775750742b25c0d8f36c55aed03d24c3384d17c951b3175d898bd778ef0307"}, + {file = "mergedeep-1.3.4.tar.gz", hash = "sha256:0096d52e9dad9939c3d975a774666af186eda617e6ca84df4c94dec30004f2a8"}, +] + [[package]] name = "mistune" version = "3.0.2" @@ -1493,6 +1536,36 @@ files = [ {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] +[[package]] +name = "mkdocs" +version = "1.5.3" +description = "Project documentation with Markdown." +optional = false +python-versions = ">=3.7" +files = [ + {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, + {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, +] + +[package.dependencies] +click = ">=7.0" +colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} +ghp-import = ">=1.0" +jinja2 = ">=2.11.1" +markdown = ">=3.2.1" +markupsafe = ">=2.0.1" +mergedeep = ">=1.3.4" +packaging = ">=20.5" +pathspec = ">=0.11.1" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" +pyyaml-env-tag = ">=0.1" +watchdog = ">=2.0" + +[package.extras] +i18n = ["babel (>=2.9.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] + [[package]] name = "myst-nb" version = "1.0.0" @@ -1726,6 +1799,17 @@ files = [ qa = ["flake8 (==3.8.3)", "mypy (==0.782)"] testing = ["docopt", "pytest (<6.0.0)"] +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + [[package]] name = "pexpect" version = "4.9.0" @@ -2244,6 +2328,20 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "pyyaml-env-tag" +version = "0.1" +description = "A custom YAML tag for referencing environment variables in YAML files. " +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyyaml_env_tag-0.1-py3-none-any.whl", hash = "sha256:af31106dec8a4d68c60207c1886031cbf839b68aa7abccdb19868200532c2069"}, + {file = "pyyaml_env_tag-0.1.tar.gz", hash = "sha256:70092675bda14fdec33b31ba77e7543de9ddc88f2e5b99160396572d11525bdb"}, +] + +[package.dependencies] +pyyaml = "*" + [[package]] name = "pyzmq" version = "25.1.2" @@ -3185,6 +3283,45 @@ brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "watchdog" +version = "3.0.0" +description = "Filesystem events monitoring" +optional = false +python-versions = ">=3.7" +files = [ + {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:336adfc6f5cc4e037d52db31194f7581ff744b67382eb6021c868322e32eef41"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a70a8dcde91be523c35b2bf96196edc5730edb347e374c7de7cd20c43ed95397"}, + {file = "watchdog-3.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:adfdeab2da79ea2f76f87eb42a3ab1966a5313e5a69a0213a3cc06ef692b0e96"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2b57a1e730af3156d13b7fdddfc23dea6487fceca29fc75c5a868beed29177ae"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ade88d0d778b1b222adebcc0927428f883db07017618a5e684fd03b83342bd9"}, + {file = "watchdog-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e447d172af52ad204d19982739aa2346245cc5ba6f579d16dac4bfec226d2e7"}, + {file = "watchdog-3.0.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:9fac43a7466eb73e64a9940ac9ed6369baa39b3bf221ae23493a9ec4d0022674"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8ae9cda41fa114e28faf86cb137d751a17ffd0316d1c34ccf2235e8a84365c7f"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f70b4aa53bd743729c7475d7ec41093a580528b100e9a8c5b5efe8899592fc"}, + {file = "watchdog-3.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4f94069eb16657d2c6faada4624c39464f65c05606af50bb7902e036e3219be3"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c5f84b5194c24dd573fa6472685b2a27cc5a17fe5f7b6fd40345378ca6812e3"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3aa7f6a12e831ddfe78cdd4f8996af9cf334fd6346531b16cec61c3b3c0d8da0"}, + {file = "watchdog-3.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:233b5817932685d39a7896b1090353fc8efc1ef99c9c054e46c8002561252fb8"}, + {file = "watchdog-3.0.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:13bbbb462ee42ec3c5723e1205be8ced776f05b100e4737518c67c8325cf6100"}, + {file = "watchdog-3.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8f3ceecd20d71067c7fd4c9e832d4e22584318983cabc013dbf3f70ea95de346"}, + {file = "watchdog-3.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c9d8c8ec7efb887333cf71e328e39cffbf771d8f8f95d308ea4125bf5f90ba64"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:0e06ab8858a76e1219e68c7573dfeba9dd1c0219476c5a44d5333b01d7e1743a"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:d00e6be486affb5781468457b21a6cbe848c33ef43f9ea4a73b4882e5f188a44"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:c07253088265c363d1ddf4b3cdb808d59a0468ecd017770ed716991620b8f77a"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:5113334cf8cf0ac8cd45e1f8309a603291b614191c9add34d33075727a967709"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:51f90f73b4697bac9c9a78394c3acbbd331ccd3655c11be1a15ae6fe289a8c83"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:ba07e92756c97e3aca0912b5cbc4e5ad802f4557212788e72a72a47ff376950d"}, + {file = "watchdog-3.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:d429c2430c93b7903914e4db9a966c7f2b068dd2ebdd2fa9b9ce094c7d459f33"}, + {file = "watchdog-3.0.0-py3-none-win32.whl", hash = "sha256:3ed7c71a9dccfe838c2f0b6314ed0d9b22e77d268c67e015450a29036a81f60f"}, + {file = "watchdog-3.0.0-py3-none-win_amd64.whl", hash = "sha256:4c9956d27be0bb08fc5f30d9d0179a855436e655f046d288e2bcc11adfae893c"}, + {file = "watchdog-3.0.0-py3-none-win_ia64.whl", hash = "sha256:5d9f3a10e02d7371cd929b5d8f11e87d4bad890212ed3901f9b4d68767bee759"}, + {file = "watchdog-3.0.0.tar.gz", hash = "sha256:4d98a320595da7a7c5a18fc48cb633c2e73cda78f93cac2ef42d42bf609a33f9"}, +] + +[package.extras] +watchmedo = ["PyYAML (>=3.10)"] + [[package]] name = "wcwidth" version = "0.2.13" @@ -3267,4 +3404,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.10 || 3.12" -content-hash = "97ac1f53e300daf6cab586cde0658a24a2bf1ab9e372a3d087eec0df4c700e54" +content-hash = "0f600e634224bacd092672aabc61602f3543a44707edc76d92998648a472f132" diff --git a/pyproject.toml b/pyproject.toml index 77d8f02..1835bf2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,6 +29,7 @@ pytest = "^7.4.3" jupyter = "^1.0.0" pytest-cov = ">=4.0.0" pytest-xdist = ">=3.5.0" +mkdocs = "1.5.3" myst-nb = {version = "^1.0.0", python = "^3.9"} sphinx-autoapi = "^3.0.0" sphinx-rtd-theme = "^1.3.0" From ccd44bb01e375968903b0b86edd8c2d666a71abf Mon Sep 17 00:00:00 2001 From: Jermiah Joseph Date: Sun, 4 Feb 2024 11:50:09 -0500 Subject: [PATCH 7/8] fix: remove sem-ver commit message --- .github/workflows/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 60fd58c..dc94e05 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -132,7 +132,6 @@ jobs: uses: python-semantic-release/python-semantic-release@master with: github_token: ${{ secrets.GITHUB_TOKEN }} - git_commit_message: 'chore(release): release ${next_version}' - name: Install packaging-related tool run: @@ -333,7 +332,7 @@ jobs: git add . # Commit with a timestamp - git commit -m "Update README with latest version: $LATEST_TAG" + git commit -m "chore: Update README: $LATEST_TAG" # Push changes to the remote repository # if github.head_ref is not null From 99c5777e58e6d94ff3199f7f8062523c97dc42a7 Mon Sep 17 00:00:00 2001 From: Jermiah Joseph Date: Sun, 4 Feb 2024 11:50:42 -0500 Subject: [PATCH 8/8] feat: add getStudies and getNewSeries CLI tools --- pyproject.toml | 10 ++++--- src/nbiatoolkit/nbia_cli.py | 54 ++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1835bf2..aaf79cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,11 +10,13 @@ readme = "README.md" dicomsort = "nbiatoolkit.nbia_cli:DICOMSorter_cli" NBIAToolkit = "nbiatoolkit:version" getCollections = "nbiatoolkit.nbia_cli:getCollections_cli" -getPatients = "nbiatoolkit.nbia_cli:getPatients_cli" getBodyPartCounts = "nbiatoolkit.nbia_cli:getBodyPartCounts_cli" -downloadSingleSeries = "nbiatoolkit.nbia_cli:downloadSingleSeries_cli" -getSeries = "nbiatoolkit.nbia_cli:getSeries_cli" +getPatients = "nbiatoolkit.nbia_cli:getPatients_cli" getNewPatients = "nbiatoolkit.nbia_cli:getNewPatients_cli" +getStudies = "nbiatoolkit.nbia_cli:getStudies_cli" +getSeries = "nbiatoolkit.nbia_cli:getSeries_cli" +getNewSeries = "nbiatoolkit.nbia_cli:getNewSeries_cli" +downloadSingleSeries = "nbiatoolkit.nbia_cli:downloadSingleSeries_cli" [tool.poetry.dependencies] python = ">=3.10 || 3.12" @@ -54,7 +56,7 @@ dist_path = "dist/" upload_to_release = true upload_to_pypi = false remove_dist = false -commit_message = "chore(release): {version}" +commit_message = "chore(sem-ver): {version}" patch_without_tag = true [tool.semantic_release.commit_parser_options] diff --git a/src/nbiatoolkit/nbia_cli.py b/src/nbiatoolkit/nbia_cli.py index 39c35f2..6b80010 100644 --- a/src/nbiatoolkit/nbia_cli.py +++ b/src/nbiatoolkit/nbia_cli.py @@ -28,10 +28,12 @@ def version(): # run each command with -h to see the available options commands = [ "getCollections", + "getBodyPartCounts", "getPatients", "getNewPatients", - "getBodyPartCounts", + "getStudies", "getSeries", + "getNewSeries", "downloadSingleSeries", "dicomsort" ] @@ -278,6 +280,40 @@ def getBodyPartCounts_cli() -> None: func=NBIAClient(args.username, args.password).getBodyPartCounts, Collection=args.collection ) +def getStudies_cli() -> None: + global query + query = f"getStudies" + p = _initialize_parser(description=f"NBIAToolkit: {query}. Get studies from a collection.") + + p.add_argument( + "-c", + "--collection", + action="store", + required=True, + type=str, + ) + + p.add_argument( + "-p", + "--patientID", + action="store", + default="", + type=str, + ) + + p.add_argument( + "-s", "--studyInstanceUID", + action="store", + default="", + type=str, + ) + + args = _add_extra_args(p) + + return getResults_cli(func=NBIAClient(args.username, args.password).getStudies, Collection=args.collection, PatientID=args.patientID, StudyInstanceUID=args.studyInstanceUID) + + + def getSeries_cli() -> None: global query @@ -367,6 +403,22 @@ def getSeries_cli() -> None: Manufacturer=args.manufacturer, ) +def getNewSeries_cli() -> None: + global query + query = f"newSeries" + p = _initialize_parser(description=f"NBIAToolkit: {query}. Get new series from a collection since a given date.") + + p.add_argument( + "-d", "--date", + action="store", + required=True, + type=str, + help="The date to filter by, i.e '2021-01-01' or '2019/12/31", + ) + + args = _add_extra_args(p) + + return getResults_cli(func=NBIAClient(args.username, args.password).getNewSeries, Date=args.date) def downloadSingleSeries_cli() -> None: global query