From b677be57ac63bdf60fae6a8e956b4de7d609faf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 17 Aug 2023 21:31:52 +0200 Subject: [PATCH 01/45] Feat: 1st mkdocs pages --- docs/contacts.md | 16 +++ docs/demos.md | 171 +++++++++++++++++++++++++++++++++ docs/documentation.md | 0 docs/index.md | 12 +++ docs/purpose.md | 0 docs/releases/release1.11.5.md | 17 ++++ docs/releases/releases.md | 32 ++++++ docs/releases/roadmap.md | 3 + docs/to-start.md | 0 mkdocs.yml | 21 ++++ 10 files changed, 272 insertions(+) create mode 100644 docs/contacts.md create mode 100644 docs/demos.md create mode 100644 docs/documentation.md create mode 100644 docs/index.md create mode 100644 docs/purpose.md create mode 100644 docs/releases/release1.11.5.md create mode 100644 docs/releases/releases.md create mode 100644 docs/releases/roadmap.md create mode 100644 docs/to-start.md create mode 100644 mkdocs.yml diff --git a/docs/contacts.md b/docs/contacts.md new file mode 100644 index 00000000..786b0f58 --- /dev/null +++ b/docs/contacts.md @@ -0,0 +1,16 @@ +# **Contacts** + +## **Maintainers Team** + +- **Owner :** *[Gabriel Couture](mailto:gabriel.couture@criucpq.ulaval.ca)* +- **Developer :** *[Gabriel Couture](mailto:gabriel.couture@criucpq.ulaval.ca)*, *[Yannick Lemaréchal](mailto:yannick.lemarechal@criucpq.ulaval.ca)* +- **Sponsor :** *Université Laval* +- **Team :** *Paradim* + + +## **Useful links** + +- [Orthanc](https://www.orthanc-server.com/) +- [PARADIM](https://paradim.science) +- [Salon des utilisateurs du socle](https://mail.google.com/chat/u/0/#chat/space/AAAApatFLqs) + diff --git a/docs/demos.md b/docs/demos.md new file mode 100644 index 00000000..28961ed9 --- /dev/null +++ b/docs/demos.md @@ -0,0 +1,171 @@ + + +Installation +------------ +```sh +$ pip install pyorthanc +``` + +Example of usage +---------------- +Be sure that Orthanc is running. The default URL (if running locally) is `http://localhost:8042`. + +#### Getting access to patients, studies, series and instances information: + +```python +from pyorthanc import Orthanc + +orthanc = Orthanc('http://localhost:8042', username='username', password='password') + +# To get patients identifier and main information +patients_identifiers = orthanc.get_patients() + +for patient_identifier in patients_identifiers: + # To get patient information + patient_info = orthanc.get_patients_id(patient_identifier) + + patient_name = patient_info['MainDicomTags']['PatientName'] + ... + study_identifiers = patient_info['Studies'] + +# To get patient's studies identifier and main information +for study_identifier in study_identifiers: + # To get Study info + study_info = orthanc.get_studies_id(study_identifier) + + study_date = study_info['MainDicomTags']['StudyDate'] + ... + series_identifiers = study_info['Series'] + +# To get study's series identifier and main information +for series_identifier in series_identifiers: + # Get series info + series_info = orthanc.get_series_id(series_identifier) + + modality = series_info['MainDicomTags']['Modality'] + ... + instance_identifiers = series_info['Instances'] + +# and so on ... +for instance_identifier in instance_identifiers: + instance_info = orthanc.get_instances_id(instance_identifier) + ... +``` + +#### Find patients with certain characteristics in an Orthanc instance: +Each patient is a tree. Layers in each tree have the following structure +`Patient` -> `Study` -> `Series` -> `Instance` +that correspond to the provided filter functions. + +```python +from pyorthanc import find, Orthanc + +orthanc = Orthanc(url='http://localhost:8042/', username='username', password='password') +patients = find( + orthanc=orthanc, + series_filter=lambda s: s.modality == 'RTDOSE' # Optional: filter with pyorthanc.Series object +) + +for patient in patients: + patient_info = patient.get_main_information() + patient.id_ # Access PatientID + patient.name # Access PatientName + + patient.get_zip() # DICOM files' content in bytes + + anonymized_patient_1 = patient.anonymize() # New patient that was anonymized by Orthanc + anonymized_patient_2 = patient.anonymize( + keep=['PatientName'], # You can keep/remove/replace the DICOM tags you want + replace={'PatientID': 'TheNewPatientID'}, + remove=['ReferringPhysicianName'], + force=True # Needed when changing PatientID/StudyInstanceUID/SeriesInstanceUID/SOPInstanceUID + ) + ... + + for study in patient.studies: + study.date # Date as a datetime object + study.referring_physician_name + ... + + for series in study.series: + series.modality # Should be 'RTDOSE' because of the series_filter parameters + ... + for instance in series.instances: + # Getting content by tag + instance.get_content_by_tag('ManufacturerModelName') # == 'Pinnable3' + # Or + instance.get_content_by_tag('0008-1090') # == 'Pinnable3' + + pydicom_dataset = instance.get_pydicom() # Retrieve the DICOM file and make a pydicom.FileDataset + pydicom_dataset.pixel_array # You can access the pydicom.FileDataset attribute + +``` + + +#### Upload DICOM files to Orthanc: + +```python +from pyorthanc import Orthanc + +orthanc = Orthanc('http://localhost:8042', 'username', 'password') + +with open('A_DICOM_INSTANCE_PATH.dcm', 'rb') as file: + orthanc.post_instances(file.read()) +``` + +#### Getting list of connected remote modalities: +```python +from pyorthanc import Orthanc + +orthanc = Orthanc('http://localhost:8042', 'username', 'password') + +orthanc.get_modalities() +``` + +#### Query (C-Find) and Retrieve (C-Move) from remote modality: + +```python +from pyorthanc import RemoteModality, Orthanc + +orthanc = Orthanc('http://localhost:8042', 'username', 'password') + +modality = RemoteModality(orthanc, 'modality') + +# Query (C-Find) on modality +data = {'Level': 'Study', 'Query': {'PatientID': '*'}} +query_response = modality.query(data=data) + +answer = modality.get_query_answers()[query_response['ID']] +print(answer) + +# Retrieve (C-Move) results of query on a target modality (AET) +modality.move(query_response['ID'], {'TargetAet': 'target_modality'}) +``` + +#### Anonymize patient: +```python +from pyorthanc import Orthanc, Patient + +orthanc = Orthanc('http://localhost:8042', 'username', 'password') + +patient_identifier = orthanc.get_patients()[0] + +anonymized_patient = Patient(patient_identifier, orthanc).anonymize( + keep=['PatientName'], # You can keep/remove/replace the DICOM tags you want + replace={'PatientID': 'TheNewPatientID'}, + remove=['ReferringPhysicianName'], + force=True # Needed when changing PatientID/StudyInstanceUID/SeriesInstanceUID/SOPInstanceUID +) +# Or directly with +orthanc.post_patients_id_anonymize(patient_identifier) + +# result is: (you can retrieve DICOM file from ID) +# {'ID': 'dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', +# 'Path': '/patients/dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', +# 'PatientID': 'dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', +# 'Type': 'Patient'} +``` + +#### Transfer data from a PACS to a Orthanc server: + +[dicom-transfer](https://github.com/ylemarechal/dicom-transfer) \ No newline at end of file diff --git a/docs/documentation.md b/docs/documentation.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..62734ae2 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,12 @@ +# **Presentation** +Python library that wraps the Orthanc REST API and facilitates the manipulation +of data with several cool utilities. + +## **What for ?** + +The aim of the PyOrthanc module is to easy use the Orthanc Dicom server API. +It has an access to the full available Orthanc API and get the useful return without dealing with http requests. + + +## **Functionalities** + diff --git a/docs/purpose.md b/docs/purpose.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/releases/release1.11.5.md b/docs/releases/release1.11.5.md new file mode 100644 index 00000000..7a468d01 --- /dev/null +++ b/docs/releases/release1.11.5.md @@ -0,0 +1,17 @@ + +### Release 1.11.5 + +PyOrthanc v1.11.5 follow Orthanc version 1.11.3. + +This release mostly improves the `find()` function. It now takes an `Orthanc` object rather than an URL. This allows better control of the configuration for the connection to the Orthanc server. + +For example: +```python +from pyorthanc import Orthanc, find + +orthanc = Orthanc(url='http://localhost:8042/', username='username', password='password') +patients = find( + orthanc=orthanc, + series_filter=lambda s: s.modality == 'RTDOSE' # Optional: filter with pyorthanc.Series object +) +``` diff --git a/docs/releases/releases.md b/docs/releases/releases.md new file mode 100644 index 00000000..c07bef6c --- /dev/null +++ b/docs/releases/releases.md @@ -0,0 +1,32 @@ + +### Lastest release : 1.12.1 + +The Orthanc client has been regenerated on the Orthanc 1.12.1 version (source of the [changelist](https://hg.orthanc-server.com/orthanc/file/Orthanc-1.12.1/NEWS)). + +From 1.12.1: + + - API version upgraded to 21 + - "/tools/create-dicom" can now be used to create Encapsulated 3D + - Manufacturing Model IODs (MTL, OBJ, or STL) + - Added a route to delete the output of an asynchronous job (right now + - only for archive jobs): e.g. DELETE /jobs/../archive + +From 1.12.0: + + - New URIs "/.../{id}/labels/{label}" to test/set/remove labels + - "/patients/{id}", "/studies/{id}", "/series/{id}" and "/instances/{id}" + - contain the "Labels" field + - "/tools/find" now accepts the "Labels" and "LabelsConstraint" arguments + - "/tools/labels" lists all the labels that are associated with any resource + - "/system": added "UserMetadata" and "HasLabels" + - Added option "?numeric" if listing metadata + +Also, the new client has been generated with the simple-openapi-client 0.4.0, which implies: + + - Allow the client Orthanc to return raw responses + - Update httpx dependencies + +Details: + + - All tests made with unittest has been refactored to use pytest + diff --git a/docs/releases/roadmap.md b/docs/releases/roadmap.md new file mode 100644 index 00000000..7ddcf432 --- /dev/null +++ b/docs/releases/roadmap.md @@ -0,0 +1,3 @@ + +### Roadmap +- \ No newline at end of file diff --git a/docs/to-start.md b/docs/to-start.md new file mode 100644 index 00000000..e69de29b diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..40fd0b22 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,21 @@ +site_name: PyOrthanc +site_description: PyOrthanc library +repo_url: https://github.com/gacou54/pyorthanc +repo_name: gacou54/pyorthanc + + +nav: + - 'General informations': + - 'Presentation': 'index.md' + - 'Purpose': 'purpose.md' + - 'Contacts': 'contacts.md' + + - 'Releases & Roadmap': + - 'Release': + - '1.12.1' : 'releases/releases.md' + - '1.11.5': 'releases/release1.11.5.md' + - 'Roadmap' : 'releases/roadmap.md' + + - 'Démos': 'demos.md' + + - 'More information': 'documentation.md' From 14dfb3a56d1a27b188360944794b0311206b9918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 17 Aug 2023 21:39:51 +0200 Subject: [PATCH 02/45] Feat: 1st mkdocs pages --- docs/contacts.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/contacts.md b/docs/contacts.md index 786b0f58..147edb59 100644 --- a/docs/contacts.md +++ b/docs/contacts.md @@ -12,5 +12,3 @@ - [Orthanc](https://www.orthanc-server.com/) - [PARADIM](https://paradim.science) -- [Salon des utilisateurs du socle](https://mail.google.com/chat/u/0/#chat/space/AAAApatFLqs) - From 10439b5db9be8ac459aa1009e2c4b6055ea700eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 17 Aug 2023 21:50:54 +0200 Subject: [PATCH 03/45] Feat: change mkdocs pages --- docs/releases/releases.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/releases/releases.md b/docs/releases/releases.md index c07bef6c..87cc2edd 100644 --- a/docs/releases/releases.md +++ b/docs/releases/releases.md @@ -1,5 +1,5 @@ - -### Lastest release : 1.12.1 +Lastest release : 1.12.1 +------------ The Orthanc client has been regenerated on the Orthanc 1.12.1 version (source of the [changelist](https://hg.orthanc-server.com/orthanc/file/Orthanc-1.12.1/NEWS)). @@ -30,3 +30,20 @@ Details: - All tests made with unittest has been refactored to use pytest +Release 1.11.5 +------------ + +PyOrthanc v1.11.5 follow Orthanc version 1.11.3. + +This release mostly improves the `find()` function. It now takes an `Orthanc` object rather than an URL. This allows better control of the configuration for the connection to the Orthanc server. + +For example: +```python +from pyorthanc import Orthanc, find + +orthanc = Orthanc(url='http://localhost:8042/', username='username', password='password') +patients = find( + orthanc=orthanc, + series_filter=lambda s: s.modality == 'RTDOSE' # Optional: filter with pyorthanc.Series object +) +``` From 72ea88aee332ebab268485f01d8dc823074ed5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 17 Aug 2023 21:52:56 +0200 Subject: [PATCH 04/45] Feat: change mkdocs pages --- mkdocs.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 40fd0b22..c1bed8e3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,9 +11,7 @@ nav: - 'Contacts': 'contacts.md' - 'Releases & Roadmap': - - 'Release': - - '1.12.1' : 'releases/releases.md' - - '1.11.5': 'releases/release1.11.5.md' + - 'Releases': 'releases/releases.md' - 'Roadmap' : 'releases/roadmap.md' - 'Démos': 'demos.md' From 6bcbed37ee269871b795031511bd882f4ee3e233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 17 Aug 2023 21:57:26 +0200 Subject: [PATCH 05/45] Feat: change mkdocs pages --- mkdocs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index c1bed8e3..7214055b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,6 +2,8 @@ site_name: PyOrthanc site_description: PyOrthanc library repo_url: https://github.com/gacou54/pyorthanc repo_name: gacou54/pyorthanc +theme: + name: material nav: From da2e8c270c1a0e33f87fa3003e09fd3913a432bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 17 Aug 2023 21:59:46 +0200 Subject: [PATCH 06/45] Feat: add ci --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..38bff15e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: ci +on: + push: + branches: + - main +permissions: + contents: write +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.x + - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV + - uses: actions/cache@v3 + with: + key: mkdocs-material-${{ env.cache_id }} + path: .cache + restore-keys: | + mkdocs-material- + - run: pip install mkdocs-material + - run: mkdocs gh-deploy --force From 482737ba9261eec3bb1efb509820a10366501dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 17 Aug 2023 22:41:00 +0200 Subject: [PATCH 07/45] Feat: add examples --- docs/demos.md | 40 +- examples/access_informations/README.md | 26 + .../access_patient_information.py | 32 + examples/docker-compose.yaml | 15 + examples/orthanc.json | 948 ++++++++++++++++++ examples/requirements.txt | 1 + mkdocs.yml | 2 +- 7 files changed, 1024 insertions(+), 40 deletions(-) create mode 100644 examples/access_informations/README.md create mode 100644 examples/access_informations/access_patient_information.py create mode 100644 examples/docker-compose.yaml create mode 100644 examples/orthanc.json create mode 100644 examples/requirements.txt diff --git a/docs/demos.md b/docs/demos.md index 28961ed9..b59facf3 100644 --- a/docs/demos.md +++ b/docs/demos.md @@ -12,45 +12,7 @@ Be sure that Orthanc is running. The default URL (if running locally) is `http:/ #### Getting access to patients, studies, series and instances information: -```python -from pyorthanc import Orthanc - -orthanc = Orthanc('http://localhost:8042', username='username', password='password') - -# To get patients identifier and main information -patients_identifiers = orthanc.get_patients() - -for patient_identifier in patients_identifiers: - # To get patient information - patient_info = orthanc.get_patients_id(patient_identifier) - - patient_name = patient_info['MainDicomTags']['PatientName'] - ... - study_identifiers = patient_info['Studies'] - -# To get patient's studies identifier and main information -for study_identifier in study_identifiers: - # To get Study info - study_info = orthanc.get_studies_id(study_identifier) - - study_date = study_info['MainDicomTags']['StudyDate'] - ... - series_identifiers = study_info['Series'] - -# To get study's series identifier and main information -for series_identifier in series_identifiers: - # Get series info - series_info = orthanc.get_series_id(series_identifier) - - modality = series_info['MainDicomTags']['Modality'] - ... - instance_identifiers = series_info['Instances'] - -# and so on ... -for instance_identifier in instance_identifiers: - instance_info = orthanc.get_instances_id(instance_identifier) - ... -``` +[Doc](../examples/access_informations/README.md) #### Find patients with certain characteristics in an Orthanc instance: Each patient is a tree. Layers in each tree have the following structure diff --git a/examples/access_informations/README.md b/examples/access_informations/README.md new file mode 100644 index 00000000..ecc4ffd2 --- /dev/null +++ b/examples/access_informations/README.md @@ -0,0 +1,26 @@ +# Acces to patient-study-series-instance informations + + +## Run Orthanc + +To run a local Orthanc with Docker, just run +```bash +docker compose up -d +``` + +The default URL (if running locally) is `http://localhost:8042`. + +## Prepare environment +```bash +python3 -m venv .venv +source .venv/bin/activate +pip install pyorthanc +``` + +## Get the python file +[access_patient_information.py](./access_patient_information.py) + +## Acces to patient-study-series-instance informatios +```bash +python access_patient_information.py +``` diff --git a/examples/access_informations/access_patient_information.py b/examples/access_informations/access_patient_information.py new file mode 100644 index 00000000..fc7da262 --- /dev/null +++ b/examples/access_informations/access_patient_information.py @@ -0,0 +1,32 @@ +from pyorthanc import Orthanc + +orthanc = Orthanc('http://localhost:8042', username='orthanc', password='orthanc') + +# To get patients identifier and main information +patients_identifiers = orthanc.get_patients() + +for patient_identifier in patients_identifiers: + # To get patient information + patient_info = orthanc.get_patients_id(patient_identifier) + patient_name = patient_info['MainDicomTags']['PatientName'] + study_identifiers = patient_info['Studies'] + +# To get patient's studies identifier and main information +for study_identifier in study_identifiers: + # To get Study info + study_info = orthanc.get_studies_id(study_identifier) + study_date = study_info['MainDicomTags']['StudyDate'] + series_identifiers = study_info['Series'] + +# To get study's series identifier and main information +for series_identifier in series_identifiers: + series_info = orthanc.get_series_id(series_identifier) + modality = series_info['MainDicomTags']['Modality'] + instance_identifiers = series_info['Instances'] + +# and so on ... +for instance_identifier in instance_identifiers: + instance_info = orthanc.get_instances_id(instance_identifier) + + # Get SOPInstanceUID + print(instance_info['MainDicomTags']['SOPInstanceUID']) diff --git a/examples/docker-compose.yaml b/examples/docker-compose.yaml new file mode 100644 index 00000000..3ad51acd --- /dev/null +++ b/examples/docker-compose.yaml @@ -0,0 +1,15 @@ +version: '3.3' +services: + orthanc: + image: jodogne/orthanc-plugins:1.12.1 + command: /run/secrets/ # Path to the configuration files (stored as secrets) + ports: + - 4242:4242 + - 8042:8042 + secrets: + - orthanc.json + environment: + - ORTHANC_NAME=HelloWorld +secrets: + orthanc.json: + file: orthanc.json \ No newline at end of file diff --git a/examples/orthanc.json b/examples/orthanc.json new file mode 100644 index 00000000..ba0d9848 --- /dev/null +++ b/examples/orthanc.json @@ -0,0 +1,948 @@ +{ + /** + * General configuration of Orthanc + * + * As a general recommendation, you should always favour absolute + * paths when you need to provide a path to a file or a directory. + * This is not done in this configuration file since we don't know + * where Orthanc is going to be installed. + **/ + + // The logical name of this instance of Orthanc. This one is + // displayed in Orthanc Explorer and at the URI "/system". + "Name" : "${ORTHANC_NAME} in Docker Compose", + + // Path to the directory that holds the heavyweight files (i.e. the + // raw DICOM instances). Backslashes must be either escaped by + // doubling them, or replaced by forward slashes "/". + "StorageDirectory" : "/var/lib/orthanc/db", + + // Path to the directory that holds the SQLite index (if unset, the + // value of StorageDirectory is used). This index could be stored on + // a RAM-drive or a SSD device for performance reasons. + "IndexDirectory" : "/var/lib/orthanc/db", + + // Path to the directory where Orthanc stores its large temporary + // files. The content of this folder can be safely deleted once + // Orthanc is stopped. The folder must exist. The corresponding + // filesystem must be properly sized, given that for instance a ZIP + // archive of DICOM images created by a job can weight several GBs, + // and that there might be up to "min(JobsHistorySize, + // MediaArchiveSize)" archives to be stored simultaneously. If not + // set, Orthanc will use the default temporary folder of the + // operating system (such as "/tmp/" on UNIX-like systems, or + // "C:/Temp" on Microsoft Windows). + // "TemporaryDirectory" : "/tmp/Orthanc/", + + // Enable the transparent compression of the DICOM instances + "StorageCompression" : false, + + // Maximum size of the storage in MB (a value of "0" indicates no + // limit on the storage size) + "MaximumStorageSize" : 0, + + // Maximum number of patients that can be stored at a given time + // in the storage (a value of "0" indicates no limit on the number + // of patients) + "MaximumPatientCount" : 0, + + // Action to take when the maximum storage is reached. + // By default, the patients are recycled ("Recycle" mode). + // In "Reject" mode, the sender will receive a 0xA700 DIMSE status code + // if the instance was sent through C-Store, a 507 HTTP status code + // if using the REST API and a 0xA700 Failure reason when using + // DicomWeb Stow-RS + // Allowed values: "Recycle", "Reject" + // (new in Orthanc 1.11.2) + "MaximumStorageMode" : "Recycle", + + // Maximum size of the storage cache in MB. The storage cache + // is stored in RAM and contains a copy of recently accessed + // files (written or read). A value of "0" indicates the cache + // is disabled. (new in Orthanc 1.10.0) + "MaximumStorageCacheSize" : 128, + + // List of paths to the custom Lua scripts that are to be loaded + // into this instance of Orthanc + "LuaScripts" : [ + ], + + // The period (in seconds) between 2 calls of the "OnHeartBeat" + // lua callback. O means the heart beat is disabled. + // TODO: text below for Orthanc book: + // Note: that the period is actually not the delay between + // the end of an execution and the triggering of the next one. + // Since there is only one lua context, if other lua code is being + // executed, the heart beat might be delayed even more. + "LuaHeartBeatPeriod" : 0, + + // List of paths to the plugins that are to be loaded into this + // instance of Orthanc (e.g. "./libPluginTest.so" for Linux, or + // "./PluginTest.dll" for Windows). These paths can refer to + // folders, in which case they will be scanned non-recursively to + // find shared libraries. Backslashes must be either escaped by + // doubling them, or replaced by forward slashes "/". + "Plugins" : [ + "/usr/share/orthanc/plugins", "/usr/local/share/orthanc/plugins" + ], + + // Maximum number of processing jobs that are simultaneously running + // at any given time. A value of "0" indicates to use all the + // available CPU logical cores. To emulate Orthanc <= 1.3.2, set + // this value to "1". + "ConcurrentJobs" : 2, + + // Defines the number of threads that are used to execute each type of + // jobs (for the jobs that can be parallelized). + // A value of "0" indicates to use all the available CPU logical cores. + // (new in Orthanc 1.11.3) + "JobsEngineThreadsCount" : { + "ResourceModification": 1 // for /anonymize, /modify + }, + + /** + * Configuration of the HTTP server + **/ + + // Enable the HTTP server. If this parameter is set to "false", + // Orthanc acts as a pure DICOM server. The REST API and Orthanc + // Explorer will not be available. + "HttpServerEnabled" : true, + + // Enable/disable the Orthanc Explorer Web user interface. This + // option is only meaningful if the "HttpServerEnabled" option is + // set to "true" (new in Orthanc 1.8.2). + "OrthancExplorerEnabled" : true, + + // HTTP port for the REST services and for the GUI + "HttpPort" : 8042, + + // When the following option is "true", if an error is encountered + // while calling the REST API, a JSON message describing the error + // is put in the HTTP answer. This feature can be disabled if the + // HTTP client does not properly handles such answers. + "HttpDescribeErrors" : true, + + // Enable HTTP compression to improve network bandwidth utilization, + // at the expense of more computations on the server. Orthanc + // supports the "gzip" and "deflate" HTTP encodings. + "HttpCompressionEnabled" : true, + + // Enable the publication of the content of the Orthanc server as a + // WebDAV share (new in Orthanc 1.8.0). On the localhost, the WebDAV + // share is mapped as "http://localhost:8042/webdav/". + "WebDavEnabled" : true, + + // Whether to allow deletions through the WebDAV share. This is + // disabled by default to avoid accidental loss of DICOM instances. + "WebDavDeleteAllowed" : false, + + // Whether to allow uploads through the WebDAV share. + "WebDavUploadAllowed" : true, + + + + /** + * Configuration of the DICOM server + **/ + + // Enable the DICOM server. If this parameter is set to "false", + // Orthanc acts as a pure REST server. It will not be possible to + // receive files or to do query/retrieve through the DICOM protocol. + "DicomServerEnabled" : true, + + // The DICOM Application Entity Title (cannot be longer than 16 + // characters) + "DicomAet" : "ORTHANC", + + // Check whether the called AET corresponds to the AET of Orthanc + // during an incoming DICOM SCU request + "DicomCheckCalledAet" : false, + + // The DICOM port + "DicomPort" : 4242, + + // The default encoding that is assumed for DICOM files without + // "SpecificCharacterSet" DICOM tag, and that is used when answering + // C-FIND requests (including worklists). The allowed values are + // "Ascii", "Utf8", "Latin1", "Latin2", "Latin3", "Latin4", + // "Latin5", "Cyrillic", "Windows1251", "Arabic", "Greek", "Hebrew", + // "Thai", "Japanese", "Chinese", "JapaneseKanji", "Korean", and + // "SimplifiedChinese". + "DefaultEncoding" : "Latin1", + + // The transfer syntaxes that are accepted by Orthanc C-STORE SCP. + // This is an array listing the accepted transfer syntax UIDs. Each + // entry can contain wildcards ("?" or "*"). By default, all the + // known transfer syntaxes are accepted. (new in Orthanc 1.9.0) + "AcceptedTransferSyntaxes" : [ "1.2.840.10008.1.*" ], + + // User-friendly groups of transfer syntaxes that can be enabled or + // disabled at once. These options are applied after the main + // "AcceptedTransferSyntaxes" option has been applied (if present). + /** + "DeflatedTransferSyntaxAccepted" : true, + "JpegTransferSyntaxAccepted" : true, + "Jpeg2000TransferSyntaxAccepted" : true, + "JpegLosslessTransferSyntaxAccepted" : true, + "JpipTransferSyntaxAccepted" : true, + "Mpeg2TransferSyntaxAccepted" : true, + "RleTransferSyntaxAccepted" : true, + "Mpeg4TransferSyntaxAccepted" : true, // New in Orthanc 1.6.0 + "H265TransferSyntaxAccepted" : true, // New in Orthanc 1.9.0 + **/ + + // Whether Orthanc accepts to act as C-STORE SCP for unknown storage + // SOP classes (aka. "promiscuous mode") + "UnknownSopClassAccepted" : false, + + // Set the timeout (in seconds) after which the DICOM associations + // are closed by the Orthanc SCP (server) if no further DIMSE + // command is received from the SCU (client). + "DicomScpTimeout" : 30, + + + + /** + * Security-related options for the HTTP server + **/ + + // Whether remote hosts can connect to the HTTP server + "RemoteAccessAllowed" : true, + + // Whether or not SSL is enabled + "SslEnabled" : false, + + // Path to the SSL certificate used by the HTTP server. The file + // must be stored in the PEM format, and must contain both the + // certificate and the private key. This option is only meaningful + // if "SslEnabled" is true. + "SslCertificate" : "certificate.pem", + + // Sets the minimum accepted SSL protocol version + // (cf. "ssl_protocol_version" option of civetweb). By default, + // require SSL 1.2. This option is only meaningful if "SslEnabled" + // is true. (new in Orthanc 1.8.2) + // + // Value => Protocols + // 0 SSL2+SSL3+TLS1.0+TLS1.1+TLS1.2 + // 1 SSL3+TLS1.0+TLS1.1+TLS1.2 + // 2 TLS1.0+TLS1.1+TLS1.2 + // 3 TLS1.1+TLS1.2 + // 4 TLS1.2 + "SslMinimumProtocolVersion" : 4, + + // Set the accepted ciphers for SSL connections. The ciphers must be + // provided as a list of strings. If not set, this will default to + // FIPS 140-2 ciphers. This option is only meaningful if + // "SslEnabled" is true. (new in Orthanc 1.8.2) + /** + "SslCiphersAccepted" : [ "AES128-GCM-SHA256" ], + **/ + + // Whether or not peer client certificates shall be checked. This + // option is only meaningful if "SslEnabled" is true. + "SslVerifyPeers" : false, + + // Path to a file containing the concatenation of the client SSL + // certificate(s) that are trusted to verify the identify of remote + // HTTP clients. The individual certificate(s) must be stored in the + // PEM format. This option is only meaningful if "SslVerifyPeers" + // is true. + "SslTrustedClientCertificates" : "trustedClientCertificates.pem", + + // Whether or not the password protection is enabled (using HTTP + // basic access authentication). Starting with Orthanc 1.5.8, if + // "AuthenticationEnabled" is not explicitly set, authentication is + // enabled iff. remote access is allowed (i.e. the default value of + // "AuthenticationEnabled" equals that of "RemoteAccessAllowed"). + /** + "AuthenticationEnabled" : true, + **/ + + // The list of the registered users. Because Orthanc uses HTTP + // Basic Authentication, the passwords are stored as plain text. + //"RegisteredUsers" : { + // "alice" : "alicePassword" + //}, + + + + /** + * Security-related options for the DICOM connections (SCU/SCP) + **/ + + // Whether DICOM TLS is enabled in the Orthanc SCP (new in Orthanc 1.9.0) + "DicomTlsEnabled" : false, + + // Path to the TLS certificate file (in PEM format) to be used for + // both Orthanc SCP (incoming DICOM connections) and Orthanc SCU + // (outgoing DICOM connections). Note that contrarily to the + // "SslCertificate" option, the certificate and its private key must + // be split into two separate files. (new in Orthanc 1.9.0) + /** + "DicomTlsCertificate" : "orthanc.crt", + **/ + + // Path to the file containing the private key (in PEM format) that + // corresponds to the TLS certificate specified in option + // "DicomTlsCertificate". (new in Orthanc 1.9.0) + /** + "DicomTlsPrivateKey" : "orthanc.key", + **/ + + // Path to a file containing all the TLS certificates that Orthanc + // can trust, both for its SCP (incoming DICOM connections) and SCU + // (outgoing DICOM connections). This file must contain a sequence + // of PEM certificates. (new in Orthanc 1.9.0) + /** + "DicomTlsTrustedCertificates" : "trusted.crt", + **/ + + // Whether Orthanc rejects DICOM TLS connections to/from remote + // modalities that do not provide a certificate. Setting this option + // to "true" (resp. "false") corresponds to "--require-peer-cert" + // (resp. "--verify-peer-cert") in the DCMTK command-line + // tools. (new in Orthanc 1.9.3) + "DicomTlsRemoteCertificateRequired" : true, + + // Whether the Orthanc SCP allows incoming C-ECHO requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Orthanc 1.3.0 + // is the only version to behave as if this argument were set to "false". + "DicomAlwaysAllowEcho" : true, + + // Whether the Orthanc SCP allows incoming C-STORE requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above) + "DicomAlwaysAllowStore" : true, + + // Whether the Orthanc SCP allows incoming C-FIND requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Setting this + // option to "true" implies security risks. (new in Orthanc 1.9.0) + // Note: From Orthanc 1.10.0, this option only applies to C-FIND + // requests for patients/studies/series/instances. Use option + // "DicomAlwaysAllowFindWorklist" for worklists. + "DicomAlwaysAllowFind" : false, + + // Whether the Orthanc SCP allows incoming C-FIND requests for worklists, + // even from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Setting this + // option to "true" implies security risks. (new in Orthanc 1.10.0) + "DicomAlwaysAllowFindWorklist" : false, + + // Whether the Orthanc SCP allows incoming C-GET requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Setting this + // option to "true" implies security risks. (new in Orthanc 1.9.0) + "DicomAlwaysAllowGet" : false, + + // Whether the Orthanc SCP allows incoming C-MOVE requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Setting this + // option to "true" implies security risks. (new in Orthanc 1.9.7) + "DicomAlwaysAllowMove" : false, + + // Whether Orthanc checks the IP/hostname address of the remote + // modality initiating a DICOM connection (as listed in the + // "DicomModalities" option above). If this option is set to + // "false", Orthanc only checks the AET of the remote modality. + "DicomCheckModalityHost" : false, + + + + /** + * Network topology + **/ + + // The list of the known DICOM modalities. This option is ignored if + // "DicomModalitiesInDatabase" is set to "true", in which case you + // must use the REST API to define modalities. + "DicomModalities" : { + /** + * Uncommenting the following line would enable Orthanc to + * connect to an instance of the "storescp" open-source DICOM + * store (shipped in the DCMTK distribution), as started by the + * command line "storescp 2000". The first parameter is the + * AET of the remote modality (cannot be longer than 16 + * characters), the second one is the remote network address, + * and the third one is the TCP port number corresponding + * to the DICOM protocol on the remote modality (usually 104). + **/ + // "sample" : [ "STORESCP", "127.0.0.1", 2000 ] + + /** + * A fourth parameter is available to enable patches for + * specific PACS manufacturers. The allowed values are currently: + * - "Generic" (default value), + * - "GenericNoWildcardInDates" (to replace "*" by "" in date fields + * in outgoing C-FIND requests originating from Orthanc), + * - "GenericNoUniversalWildcard" (to replace "*" by "" in all fields + * in outgoing C-FIND SCU requests originating from Orthanc), + * - "Vitrea", + * - "GE" (Enterprise Archive, MRI consoles and Advantage Workstation + * from GE Healthcare). + * + * This parameter is case-sensitive. + **/ + // "vitrea" : [ "VITREA", "192.168.1.1", 104, "Vitrea" ] + + /** + * By default, the Orthanc SCP accepts all DICOM commands (C-ECHO, + * C-STORE, C-FIND, C-MOVE, C-GET and storage commitment) issued by the + * registered remote SCU modalities. Starting with Orthanc 1.5.0, + * it is possible to specify which DICOM commands are allowed, + * separately for each remote modality, using the syntax + * below. + * + * The "AllowEcho" (resp. "AllowStore") option only has an effect + * respectively if global option "DicomAlwaysAllowEcho" + * (resp. "DicomAlwaysAllowStore") is set to "false". + * + * Starting with Orthanc 1.7.0, "AllowTranscoding" can be used to + * disable the transcoding to uncompressed transfer syntaxes if + * this remote modality doesn't support compressed transfer + * syntaxes. This option currently applies to Orthanc C-GET SCP + * and to Orthanc C-STORE SCU. This option only has an effect if + * the global option "EnableTranscoding" is set to "true". + * + * By default, all "Allow*" options are true. + * "AllowStorageCommitment" is actually an alias for + * "AllowNAction" & "AllowEventReport". + * + * The "UseDicomTls" option specifies whether DICOM TLS should be + * used when opening a SCU connection from Orthanc to this remote + * modality. By default, DICOM TLS is not enabled. + * + * The "LocalAet" option allows one to overwrite the global + * "DicomAet" configuration option in order to specify another AET + * for Orthanc when initiating an SCU to this very specific + * modality. Similarly, "Timeout" allows one to overwrite the + * global value "DicomScuTimeout" on a per-modality basis. + **/ + //"untrusted" : { + // "AET" : "ORTHANC", + // "Port" : 104, + // "Host" : "127.0.0.1", + // "Manufacturer" : "Generic", + // "AllowEcho" : false, + // "AllowFind" : false, + // "AllowFindWorklist" : false, // new in 1.10.0 + // "AllowGet" : false, + // "AllowMove" : false, + // "AllowStore" : true, + // "AllowStorageCommitment" : false, // new in 1.6.0 + // "AllowTranscoding" : true, // new in 1.7.0 + // "UseDicomTls" : false, // new in 1.9.0 + // "LocalAet" : "HELLO", // new in 1.9.0 + // "Timeout" : 60 // new in 1.9.1 + //} + }, + + // Whether to store the DICOM modalities in the Orthanc database + // instead of in this configuration file (new in Orthanc 1.5.0) + "DicomModalitiesInDatabase" : false, + + // Whether the C-ECHO SCU is automatically followed by a C-FIND SCU, + // while testing the connectivity from Orthanc to a remote DICOM + // modality. This allows one to check that the remote modality does + // accept C-FIND requests from Orthanc (new in Orthanc 1.8.1). + "DicomEchoChecksFind" : false, + + // The timeout (in seconds) after which the DICOM associations are + // considered as closed by the Orthanc SCU (client) if the remote + // DICOM SCP (server) does not answer. + "DicomScuTimeout" : 10, + + // During a C-STORE SCU request initiated by Orthanc, if the remote + // modality doesn't support the original transfer syntax of some + // DICOM instance, specify which transfer syntax should be preferred + // to transcode this instance (provided the remote modality accepts + // this syntax). In Orthanc between 1.7.0 and 1.8.2, this parameter + // was implicitly set to "Little Endian Implicit" + // (1.2.840.10008.1.2). In Orthanc <= 1.6.1 and in Orthanc >= 1.9.0, + // this parameter is by default set to "Little Endian Explicit" + // (1.2.840.10008.1.2.1). This parameter can possibly correspond to + // a compressed transfer syntax. (new in Orthanc 1.9.0) + "DicomScuPreferredTransferSyntax" : "1.2.840.10008.1.2.1", + + // Number of threads that are used by the embedded DICOM server. + // This defines the number of concurrent DICOM operations that can + // be run. Note: This is not limiting the number of concurrent + // connections. With a single thread, if a C-Find is received during + // e.g the transcoding of an incoming C-Store, it will have to wait + // until the end of the C-Store before being processed. (new in + // Orthanc 1.10.0, before this version, the value was fixed to 4) + "DicomThreadsCount" : 4, + + // The list of the known Orthanc peers. This option is ignored if + // "OrthancPeersInDatabase" is set to "true", in which case you must + // use the REST API to define Orthanc peers. + "OrthancPeers" : { + /** + * Each line gives the base URL of an Orthanc peer, possibly + * followed by the username/password pair (if the password + * protection is enabled on the peer). + **/ + // "peer" : [ "http://127.0.0.1:8043/", "alice", "alicePassword" ] + // "peer2" : [ "http://127.0.0.1:8044/" ] + + /** + * This is another, more advanced format to define Orthanc + * peers. It notably allows one to specify HTTP headers, a HTTPS + * client certificate in the PEM format (as in the "--cert" option + * of curl), or to enable PKCS#11 authentication for smart cards. + * + * The "Timeout" option allows one to overwrite the global value + * "HttpTimeout" on a per-peer basis. + **/ + // "peer" : { + // "Url" : "http://127.0.0.1:8043/", + // "Username" : "alice", + // "Password" : "alicePassword", + // "HttpHeaders" : { "Token" : "Hello world" }, + // "CertificateFile" : "client.crt", + // "CertificateKeyFile" : "client.key", + // "CertificateKeyPassword" : "certpass", + // "Pkcs11" : false, + // "Timeout" : 42 // New in Orthanc 1.9.1 + // } + }, + + // Whether to store the Orthanc peers in the Orthanc database + // instead of in this configuration file (new in Orthanc 1.5.0) + "OrthancPeersInDatabase" : false, + + // Parameters of the HTTP proxy to be used by Orthanc. If set to the + // empty string, no HTTP proxy is used. For instance: + // "HttpProxy" : "192.168.0.1:3128" + // "HttpProxy" : "proxyUser:proxyPassword@192.168.0.1:3128" + "HttpProxy" : "", + + // If set to "true", debug messages from libcurl will be issued + // whenever Orthanc makes an outgoing HTTP request. This is notably + // useful to debug HTTPS-related problems. + "HttpVerbose" : false, + + // Set the timeout for HTTP requests issued by Orthanc (in seconds). + "HttpTimeout" : 60, + + // Enable the verification of the peers during HTTPS requests. This + // option must be set to "false" if using self-signed certificates. + // Pay attention that setting this option to "false" results in + // security risks! + // Reference: http://curl.haxx.se/docs/sslcerts.html + "HttpsVerifyPeers" : true, + + // Path to the CA (certification authority) certificates to validate + // peers in HTTPS requests. From curl documentation ("--cacert" + // option): "Tells curl to use the specified certificate file to + // verify the peers. The file may contain multiple CA + // certificates. The certificate(s) must be in PEM format." On + // Debian-based systems, this option can be set to + // "/etc/ssl/certs/ca-certificates.crt" + "HttpsCACertificates" : "/etc/ssl/certs/ca-certificates.crt", + + + + /** + * Advanced options + **/ + + // Dictionary of symbolic names for the user-defined metadata. Each + // entry must map an unique string to an unique number between 1024 + // and 65535. Reserved values: + // - The Orthanc whole-slide imaging plugin uses metadata 4200 + "UserMetadata" : { + // "Sample" : 1024 + }, + + // Dictionary of symbolic names for the user-defined types of + // attached files. Each entry must map an unique string to an unique + // number between 1024 and 65535. Optionally, a second argument can + // provided to specify a MIME content type for the attachment. + "UserContentType" : { + // "sample" : 1024 + // "sample2" : [ 1025, "application/pdf" ] + }, + + // Number of seconds without receiving any instance before a + // patient, a study or a series is considered as stable. + "StableAge" : 60, + + // By default, Orthanc compares AET (Application Entity Titles) in a + // case-insensitive way. Setting this option to "true" will enable + // case-sensitive matching. + "StrictAetComparison" : false, + + // When the following option is "true", the MD5 of the DICOM files + // will be computed and stored in the Orthanc database. This + // information can be used to detect disk corruption, at the price + // of a small performance overhead. + "StoreMD5ForAttachments" : true, + + // The maximum number of results for a single C-FIND request at the + // Patient, Study or Series level. Setting this option to "0" means + // no limit. + "LimitFindResults" : 0, + + // The maximum number of results for a single C-FIND request at the + // Instance level. Setting this option to "0" means no limit. + "LimitFindInstances" : 0, + + // If this option is set to "true" (default behavior until Orthanc + // 1.3.2), Orthanc will log the resources that are exported to other + // DICOM modalities or Orthanc peers, inside the URI + // "/exports". Setting this option to "false" is useful to prevent + // the index to grow indefinitely in auto-routing tasks (this is the + // default behavior since Orthanc 1.4.0). + "LogExportedResources" : false, + + // Enable or disable HTTP Keep-Alive (persistent HTTP + // connections). Setting this option to "true" prevents Orthanc + // issue #32 ("HttpServer does not support multiple HTTP requests in + // the same TCP stream"), but can possibly slow down HTTP clients + // that do not support persistent connections. The default behavior + // used to be "false" in Orthanc <= 1.5.1. Setting this option to + // "false" is also recommended if Orthanc is compiled against + // Mongoose. + "KeepAlive" : true, + + // Defines the Keep-Alive timeout in seconds. + // (new in Orthanc 1.11.3) + "KeepAliveTimeout" : 1, + + // Enable or disable Nagle's algorithm. Only taken into + // consideration if Orthanc is compiled to use CivetWeb. Experiments + // show that best performance can be obtained by setting both + // "KeepAlive" and "TcpNoDelay" to "true". Beware however of + // caveats: https://eklitzke.org/the-caveats-of-tcp-nodelay + "TcpNoDelay" : true, + + // Number of threads that are used by the embedded HTTP server. + "HttpThreadsCount" : 50, + + // If this option is set to "false", Orthanc will run in index-only + // mode. The DICOM files will not be stored on the drive: Orthanc + // only indexes the small subset of the so-called "main DICOM tags" + // in its SQL database. Note that this option might prevent the + // upgrade to newer versions of Orthanc. Also note that this + // behavior might not be available with the storage area plugins. + "StoreDicom" : true, + + // DICOM associations initiated by Lua scripts are kept open as long + // as new DICOM commands are issued. This option sets the number of + // seconds of inactivity to wait before automatically closing a + // DICOM association used by Lua. If set to 0, the connection is + // closed immediately. This option is only used in Lua scripts. + "DicomAssociationCloseDelay" : 5, + + // Maximum number of query/retrieve DICOM requests that are + // maintained by Orthanc. The least recently used requests get + // deleted as new requests are issued. + "QueryRetrieveSize" : 100, + + // When handling a C-FIND SCP request, setting this flag to "true" + // will enable case-sensitive match for PN value representation + // (such as PatientName). By default, the search is + // case-insensitive, which does not follow the DICOM standard. + "CaseSensitivePN" : false, + + // Configure PKCS#11 to use hardware security modules (HSM) and + // smart cards when carrying on HTTPS client authentication. + /** + "Pkcs11" : { + "Module" : "/usr/local/lib/libbeidpkcs11.so", + "Module" : "C:/Windows/System32/beidpkcs11.dll", + "Pin" : "1234", + "Verbose" : true + } + **/ + + // If set to "false", Orthanc will not load its default dictionary + // of private tags. This might be necessary if you cannot import a + // DICOM file encoded using the Implicit VR Endian transfer syntax, + // and containing private tags: Such an import error might stem from + // a bad dictionary. You can still list your private tags of + // interest in the "Dictionary" configuration option below. + "LoadPrivateDictionary" : true, + + // Locale to be used by Orthanc. Currently, only used if comparing + // strings in a case-insensitive way. It should be safe to keep this + // value undefined, which lets Orthanc autodetect the suitable locale. + // "Locale" : "en_US.UTF-8", + + // Register a new tag in the dictionary of DICOM tags that are known + // to Orthanc. Each line must contain the tag (formatted as 2 + // hexadecimal numbers), the value representation (2 upcase + // characters), a nickname for the tag, possibly the minimum + // multiplicity (> 0 with defaults to 1), possibly the maximum + // multiplicity (0 means arbitrary multiplicity, defaults to 1), and + // possibly the Private Creator (for private tags). + // Note: For private tags, you should only declare the lower 8 bits + // of the element since the higher 8 bits may vary from one file to + // the other. + "Dictionary" : { + // "0014,1020" : [ "DA", "ValidationExpiryDate", 1, 1 ] + // "00e1,c2" : [ "UI", "PET-CT Multi Modality Name", 1, 1, "ELSCINT1" ] + // "7053,03" : [ "ST", "Original Image Filename", 1, 1, "Philips PET Private Group" ] + // "2001,5f" : [ "SQ", "StackSequence", 1, 1, "Philips Imaging DD 001" ] + }, + + // Load a set of external DICOM dictionaries in order to replace the + // default dictionaries. This option must contain a set of files in + // the DCMTK format. The order of the dictionaries *is* + // important. This option can be used to turn Orthanc into a DICONDE + // server. (new in Orthanc 1.9.4) + /** + "ExternalDictionaries" : [ + "/usr/share/libdcmtk12/dicom.dic", + "/usr/share/libdcmtk12/diconde.dic" + ] + **/ + + // Whether to run DICOM C-MOVE operations synchronously. If set to + // "false" (asynchronous mode), each incoming C-MOVE request results + // in the creation of a new background job. Up to Orthanc 1.3.2, the + // implicit behavior was to use synchronous C-MOVE ("true"). Between + // Orthanc 1.4.0 and 1.4.2, the default behavior was set to + // asynchronous C-MOVE ("false"). Since Orthanc 1.5.0, the default + // behavior is back to synchronous C-MOVE ("true", which ensures + // backward compatibility with Orthanc <= 1.3.2). + "SynchronousCMove" : true, + + // Maximum number of completed jobs that are kept in memory. A + // processing job is considered as complete once it is tagged as + // "Success" or "Failure". Since Orthanc 1.5.0, a value of "0" + // indicates to keep no job in memory (i.e. jobs are removed from + // the history as soon as they are completed), which prevents the + // use of some features of Orthanc (typically, synchronous mode in + // REST API) and should be avoided for non-developers. + "JobsHistorySize" : 10, + + // Whether to save the jobs into the Orthanc database. If this + // option is set to "true", the pending/running/completed jobs are + // automatically reloaded from the database if Orthanc is stopped + // then restarted (except if the "--no-jobs" command-line argument + // is specified). This option should be set to "false" if multiple + // Orthanc servers are using the same database (e.g. if PostgreSQL + // or MariaDB/MySQL is used). + "SaveJobs" : true, + + // Specifies how Orthanc reacts when it receives a DICOM instance + // whose SOPInstanceUID is already stored. If set to "true", the new + // instance replaces the old one. If set to "false", the new + // instance is discarded and the old one is kept. Up to Orthanc + // 1.4.1, the implicit behavior corresponded to "false". + "OverwriteInstances" : false, + + // Maximum number of ZIP/media archives that are maintained by + // Orthanc, as a response to the asynchronous creation of archives. + // The least recently used archives get deleted as new archives are + // generated. This option was introduced in Orthanc 1.5.0, and has + // no effect on the synchronous generation of archives. + "MediaArchiveSize" : 1, + + // Performance setting to specify how Orthanc accesses the storage + // area during find operations (C-FIND, /tools/find API route and + // QIDO-RS in dicom-web). Three modes are available: (1) "Always" + // allows Orthanc to read the storage area as soon as it needs an + // information that is not present in its database (slowest mode), + // (2) "Never" prevents Orthanc from accessing the storage area, and + // makes it uses exclusively its database (fastest mode), and (3) + // "Answers" allows Orthanc to read the storage area to generate its + // answers, but not to filter the DICOM resources (balance between + // the two modes). By default, the mode is "Always", which + // corresponds to the behavior of Orthanc <= 1.5.0. + "StorageAccessOnFind" : "Always", + + // Whether Orthanc monitors its metrics (new in Orthanc 1.5.4). If + // set to "true", the metrics can be retrieved at + // "/tools/metrics-prometheus" formetted using the Prometheus + // text-based exposition format. + "MetricsEnabled" : true, + + // Whether calls to URI "/tools/execute-script" is enabled. Starting + // with Orthanc 1.5.8, this URI is disabled by default for security. + "ExecuteLuaEnabled" : false, + + // Whether the REST API can write to the filesystem (e.g. in + // /instances/../export route). Starting with Orthanc 1.12.0, + // this URI is disabled by default for security. + "RestApiWriteToFileSystemEnabled": false, + + // Set the timeout while serving HTTP requests by the embedded Web + // server, in seconds. This corresponds to option + // "request_timeout_ms" of Mongoose/Civetweb. It will set the socket + // options "SO_RCVTIMEO" and "SO_SNDTIMEO" to the specified value. + "HttpRequestTimeout" : 30, + + // Set the default private creator that is used by Orthanc when it + // looks for a private tag in its dictionary (cf. "Dictionary" + // option), or when it creates/modifies a DICOM file (new in Orthanc 1.6.0). + "DefaultPrivateCreator" : "", + + // Maximum number of storage commitment reports (i.e. received from + // remote modalities) to be kept in memory (new in Orthanc 1.6.0). + "StorageCommitmentReportsSize" : 100, + + // Whether Orthanc transcodes DICOM files to an uncompressed + // transfer syntax over the DICOM protocol, if the remote modality + // does not support compressed transfer syntaxes (new in Orthanc 1.7.0). + "TranscodeDicomProtocol" : true, + + // If some plugin to decode/transcode DICOM instances is installed, + // this option specifies whether the built-in decoder/transcoder of + // Orthanc (that uses DCMTK) is applied before or after the plugins, + // or is not applied at all (new in Orthanc 1.7.0). The allowed + // values for this option are "After" (default value, corresponding + // to the behavior of Orthanc <= 1.6.1), "Before", or "Disabled". + "BuiltinDecoderTranscoderOrder" : "After", + + // If this option is set, Orthanc will transparently transcode any + // incoming DICOM instance to the given transfer syntax before + // storing it into its database. Beware that this might result in + // high CPU usage (if transcoding to some compressed transfer + // syntax), or in higher disk consumption (if transcoding to an + // uncompressed syntax). Also, beware that transcoding to a transfer + // syntax with lossy compression (notably JPEG) will change the + // "SOPInstanceUID" DICOM tag, and thus the Orthanc identifier at + // the instance level, which might break external workflow. + /** + "IngestTranscoding" : "1.2.840.10008.1.2", + **/ + + // Whether ingest transcoding is applied to incoming DICOM instances + // that have an uncompressed transfer syntax, i.e. Little Endian + // Implicit, Little Endian Explicit or Big Endian Explicit (new in + // Orthanc 1.8.2). + "IngestTranscodingOfUncompressed" : true, + + // Whether ingest transcoding is applied to incoming DICOM instances + // that have a compressed transfer syntax (new in Orthanc 1.8.2). + "IngestTranscodingOfCompressed" : true, + + // The compression level that is used when transcoding to one of the + // lossy/JPEG transfer syntaxes (integer between 1 and 100). + "DicomLossyTranscodingQuality" : 90, + + // Whether "fsync()" is called after each write to the storage area + // (new in Orthanc 1.7.4). If this option is set to "true", Orthanc + // will run more slowly, but the DICOM are guaranteed to be + // immediately written to the disk. This option only makes sense if + // the builtin filesystem storage area is used. It defaults to + // "false" in Orthanc <= 1.7.3, and to "true" in Orthanc >= 1.7.4. + "SyncStorageArea" : true, + + // If specified, on compatible systems, call "mallopt(M_ARENA_MAX, + // ...)" while starting Orthanc. This has the same effect at setting + // the environment variable "MALLOC_ARENA_MAX". This avoids large + // growth in RES memory if the threads of the embedded HTTP server + // have to allocate large chunks of memory (typically the case with + // large DICOM files). By setting "MallocArenaMax" to "N", these + // threads share "N" memory pools (known as "arenas"). Setting this + // option to "0" doesn't call mallopt()", which was the behavior of + // Orthanc <= 1.8.1. + "MallocArenaMax" : 5, + + // Deidentify/anonymize the contents of the logs (notably C-FIND, + // C-GET, and C-MOVE queries submitted to Orthanc) according to + // Table E.1-1 of the DICOM standard (new in Orthanc 1.8.2) + "DeidentifyLogs" : true, + + // If "DeidentifyLogs" is true, this sets the DICOM standard to + // follow for the deidentification/anonymization of the query + // contents. Possible values are "2008", "2017c", "2021b" (new + // in Orthanc 1.8.2), and "2023b" (new in Orthanc 1.12.1) + "DeidentifyLogsDicomVersion" : "2023b", + + // Maximum length of the PDU (Protocol Data Unit) in the DICOM + // network protocol, expressed in bytes. This value affects both + // Orthanc SCU and Orthanc SCP. It defaults to 16KB. The allowed + // range is [4096,131072]. (new in Orthanc 1.9.0) + "MaximumPduLength" : 16384, + + // Arbitrary identifier of this Orthanc server when storing its + // global properties if a custom index plugin is used. This + // identifier is only useful in the case of multiple + // readers/writers, in order to avoid collisions between multiple + // Orthanc servers. If unset, this identifier is taken as a SHA-1 + // hash derived from the MAC addresses of the network interfaces, + // and from the AET and TCP ports used by Orthanc. Manually setting + // this option is needed in Docker/Kubernetes environments. (new in + // Orthanc 1.9.2) + /** + "DatabaseServerIdentifier" : "Orthanc1", + **/ + + // Whether Orthanc protects the modification of metadata and + // attachments using revisions, which is done using the HTTP headers + // "ETag", "If-Match" and "If-None-Match" in the calls to the REST + // API. This is needed to handle collisions between concurrent + // modifications in the case of multiple writers. The database + // back-end must support this option, which is notably *not* yet the + // case of the built-in SQLite index. (new in Orthanc 1.9.2) + "CheckRevisions" : false, + + // Whether Orthanc streams ZIP archive/media to the HTTP + // client. Setting this option to "false" corresponds to the + // behavior of Orthanc <= 1.9.3: The ZIP is first entirely written + // to a temporary file, then sent to the client (which necessitates + // disk space and might lead to HTTP timeouts on large archives). If + // set to "true", the chunks of the ZIP file are progressively sent + // as soon as one DICOM file gets compressed (new in Orthanc 1.9.4) + "SynchronousZipStream" : true, + + // Default number of loader threads when generating Zip archive/media. + // A value of 0 means reading and writing are performed in sequence + // (default behaviour). A value > 1 is meaningful only if the storage + // is a distributed network storage (e.g object storage plugin). + // (new experimental feature in Orthanc 1.10.0) + "ZipLoaderThreads": 0, + + // Extra Main Dicom tags that are stored in DB together with all default + // Main Dicom tags that are already stored. + // see https://book.orthanc-server.com/faq/main-dicom-tags.html + // (new in Orthanc 1.11.0) + // Sequences tags are not supported. + /** + "ExtraMainDicomTags" : { + "Instance" : [ + "Rows", + "Columns", + "ImageType", + "SOPClassUID", + "ContentDate", + "ContentTime", + "FrameOfReferenceUID", + "PixelSpacing", + "SpecificCharacterSet", + "BitsAllocated" + ], + "Series" : [], + "Study": [], + "Patient": [] + }, + */ + + // Enables/disables warnings in the logs. + // "true" enables a warning. All warnings are enabled by default + // see https://book.orthanc-server.com/faq/main-dicom-tags.html#warnings + // (new in Orthanc 1.11.0) + "Warnings" : { + // A "RequestedTags" has been read from storage which is slower than + // reading it from DB. + // You might want to store this tag in ExtraMainDicomTags to build + // the response faster. + "W001_TagsBeingReadFromStorage": true, + + // Retrieving a list of Main dicom tags from a resource that has been + // saved with another "ExtraMainDicomTags" configuration which means that + // your response might be incomplete/inconsistent. + // You should call patients|studies|series|instances/../reconstruct to rebuild + // the DB. You may also check for the "Housekeeper" plugin + "W002_InconsistentDicomTagsInDb": true + } + +} diff --git a/examples/requirements.txt b/examples/requirements.txt new file mode 100644 index 00000000..02a5c6fa --- /dev/null +++ b/examples/requirements.txt @@ -0,0 +1 @@ +pyorthanc==1.11.5 \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 7214055b..6e2b49f8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -16,6 +16,6 @@ nav: - 'Releases': 'releases/releases.md' - 'Roadmap' : 'releases/roadmap.md' - - 'Démos': 'demos.md' + - 'Demos': 'demos.md' - 'More information': 'documentation.md' From f085e1005399daf8cb192b7825aea125940a2036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 17 Aug 2023 22:53:46 +0200 Subject: [PATCH 08/45] Feat: add examples --- docs/demos.md | 2 +- {examples => docs/examples}/access_informations/README.md | 0 .../examples}/access_informations/access_patient_information.py | 0 {examples => docs/examples}/docker-compose.yaml | 0 {examples => docs/examples}/orthanc.json | 0 {examples => docs/examples}/requirements.txt | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename {examples => docs/examples}/access_informations/README.md (100%) rename {examples => docs/examples}/access_informations/access_patient_information.py (100%) rename {examples => docs/examples}/docker-compose.yaml (100%) rename {examples => docs/examples}/orthanc.json (100%) rename {examples => docs/examples}/requirements.txt (100%) diff --git a/docs/demos.md b/docs/demos.md index b59facf3..b0cc9289 100644 --- a/docs/demos.md +++ b/docs/demos.md @@ -12,7 +12,7 @@ Be sure that Orthanc is running. The default URL (if running locally) is `http:/ #### Getting access to patients, studies, series and instances information: -[Doc](../examples/access_informations/README.md) +[Doc](examples/access_informations/README.md) #### Find patients with certain characteristics in an Orthanc instance: Each patient is a tree. Layers in each tree have the following structure diff --git a/examples/access_informations/README.md b/docs/examples/access_informations/README.md similarity index 100% rename from examples/access_informations/README.md rename to docs/examples/access_informations/README.md diff --git a/examples/access_informations/access_patient_information.py b/docs/examples/access_informations/access_patient_information.py similarity index 100% rename from examples/access_informations/access_patient_information.py rename to docs/examples/access_informations/access_patient_information.py diff --git a/examples/docker-compose.yaml b/docs/examples/docker-compose.yaml similarity index 100% rename from examples/docker-compose.yaml rename to docs/examples/docker-compose.yaml diff --git a/examples/orthanc.json b/docs/examples/orthanc.json similarity index 100% rename from examples/orthanc.json rename to docs/examples/orthanc.json diff --git a/examples/requirements.txt b/docs/examples/requirements.txt similarity index 100% rename from examples/requirements.txt rename to docs/examples/requirements.txt From ce521eed550c92aeacfc351fc0629eab2e341bc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Fri, 18 Aug 2023 09:33:49 +0200 Subject: [PATCH 09/45] Feat: add examples --- docs/demos.md | 147 ++++-------------- docs/examples/access_informations/README.md | 13 +- .../access_informations/docker-compose.yaml | 7 + docs/examples/docker-compose.yaml | 10 +- mkdocs.yml | 1 + 5 files changed, 46 insertions(+), 132 deletions(-) create mode 100644 docs/examples/access_informations/docker-compose.yaml diff --git a/docs/demos.md b/docs/demos.md index b0cc9289..3062f43d 100644 --- a/docs/demos.md +++ b/docs/demos.md @@ -1,133 +1,44 @@ - - -Installation ------------- -```sh -$ pip install pyorthanc -``` - Example of usage ---------------- Be sure that Orthanc is running. The default URL (if running locally) is `http://localhost:8042`. -#### Getting access to patients, studies, series and instances information: - -[Doc](examples/access_informations/README.md) - -#### Find patients with certain characteristics in an Orthanc instance: -Each patient is a tree. Layers in each tree have the following structure -`Patient` -> `Study` -> `Series` -> `Instance` -that correspond to the provided filter functions. - -```python -from pyorthanc import find, Orthanc +Here is a list of examples to helps you getting started with pyorthanc -orthanc = Orthanc(url='http://localhost:8042/', username='username', password='password') -patients = find( - orthanc=orthanc, - series_filter=lambda s: s.modality == 'RTDOSE' # Optional: filter with pyorthanc.Series object -) +| Purpose | +|---------------------------------------------------------------| +| [Access instance informations](https://github.com/ylemarechal/pyorthanc/tree/main/docs/examples/access_informations) | +|[Transfer data from a PACS to a Orthanc server](https://github.com/ylemarechal/dicom-transfer)| -for patient in patients: - patient_info = patient.get_main_information() - patient.id_ # Access PatientID - patient.name # Access PatientName - - patient.get_zip() # DICOM files' content in bytes - - anonymized_patient_1 = patient.anonymize() # New patient that was anonymized by Orthanc - anonymized_patient_2 = patient.anonymize( - keep=['PatientName'], # You can keep/remove/replace the DICOM tags you want - replace={'PatientID': 'TheNewPatientID'}, - remove=['ReferringPhysicianName'], - force=True # Needed when changing PatientID/StudyInstanceUID/SeriesInstanceUID/SOPInstanceUID - ) - ... +## First steps - for study in patient.studies: - study.date # Date as a datetime object - study.referring_physician_name - ... +- Applications installed + - [x] Python3.10 + - [x] Docker - for series in study.series: - series.modality # Should be 'RTDOSE' because of the series_filter parameters - ... - for instance in series.instances: - # Getting content by tag - instance.get_content_by_tag('ManufacturerModelName') # == 'Pinnable3' - # Or - instance.get_content_by_tag('0008-1090') # == 'Pinnable3' +## Some useful commands - pydicom_dataset = instance.get_pydicom() # Retrieve the DICOM file and make a pydicom.FileDataset - pydicom_dataset.pixel_array # You can access the pydicom.FileDataset attribute - +### Prepare python environment +```bash +python3 -m venv .venv +source .venv/bin/activate +pip install pyorthanc ``` -#### Upload DICOM files to Orthanc: - -```python -from pyorthanc import Orthanc - -orthanc = Orthanc('http://localhost:8042', 'username', 'password') - -with open('A_DICOM_INSTANCE_PATH.dcm', 'rb') as file: - orthanc.post_instances(file.read()) -``` - -#### Getting list of connected remote modalities: -```python -from pyorthanc import Orthanc - -orthanc = Orthanc('http://localhost:8042', 'username', 'password') - -orthanc.get_modalities() +### Docker commands +Start Orthanc +```bash +docker compose up -d ``` - -#### Query (C-Find) and Retrieve (C-Move) from remote modality: - -```python -from pyorthanc import RemoteModality, Orthanc - -orthanc = Orthanc('http://localhost:8042', 'username', 'password') - -modality = RemoteModality(orthanc, 'modality') - -# Query (C-Find) on modality -data = {'Level': 'Study', 'Query': {'PatientID': '*'}} -query_response = modality.query(data=data) - -answer = modality.get_query_answers()[query_response['ID']] -print(answer) - -# Retrieve (C-Move) results of query on a target modality (AET) -modality.move(query_response['ID'], {'TargetAet': 'target_modality'}) +Stop Orthanc +```bash +docker compose stop ``` - -#### Anonymize patient: -```python -from pyorthanc import Orthanc, Patient - -orthanc = Orthanc('http://localhost:8042', 'username', 'password') - -patient_identifier = orthanc.get_patients()[0] - -anonymized_patient = Patient(patient_identifier, orthanc).anonymize( - keep=['PatientName'], # You can keep/remove/replace the DICOM tags you want - replace={'PatientID': 'TheNewPatientID'}, - remove=['ReferringPhysicianName'], - force=True # Needed when changing PatientID/StudyInstanceUID/SeriesInstanceUID/SOPInstanceUID -) -# Or directly with -orthanc.post_patients_id_anonymize(patient_identifier) - -# result is: (you can retrieve DICOM file from ID) -# {'ID': 'dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', -# 'Path': '/patients/dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', -# 'PatientID': 'dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', -# 'Type': 'Patient'} +Restart Orthanc +```bash +docker compose restart ``` - -#### Transfer data from a PACS to a Orthanc server: - -[dicom-transfer](https://github.com/ylemarechal/dicom-transfer) \ No newline at end of file +Delete Orthanc container +```bash +docker compose down +``` \ No newline at end of file diff --git a/docs/examples/access_informations/README.md b/docs/examples/access_informations/README.md index ecc4ffd2..d2178a6c 100644 --- a/docs/examples/access_informations/README.md +++ b/docs/examples/access_informations/README.md @@ -1,5 +1,11 @@ # Acces to patient-study-series-instance informations +In this tutorial, you can access to all patients, study, series and instances information. Use it with a small batch of +data in the Orthanc server + +## Get the python file +[access_patient_information.py](./access_patient_information.py) +[docker-compose.yaml](./docker-compose.yaml) ## Run Orthanc @@ -17,10 +23,7 @@ source .venv/bin/activate pip install pyorthanc ``` -## Get the python file -[access_patient_information.py](./access_patient_information.py) - -## Acces to patient-study-series-instance informatios +## Run PyOrthanc script ```bash python access_patient_information.py -``` +``` \ No newline at end of file diff --git a/docs/examples/access_informations/docker-compose.yaml b/docs/examples/access_informations/docker-compose.yaml new file mode 100644 index 00000000..78867963 --- /dev/null +++ b/docs/examples/access_informations/docker-compose.yaml @@ -0,0 +1,7 @@ +version: '3.3' +services: + orthanc: + image: jodogne/orthanc-plugins:1.12.1 + ports: + - 4242:4242 + - 8042:8042 \ No newline at end of file diff --git a/docs/examples/docker-compose.yaml b/docs/examples/docker-compose.yaml index 3ad51acd..78867963 100644 --- a/docs/examples/docker-compose.yaml +++ b/docs/examples/docker-compose.yaml @@ -2,14 +2,6 @@ version: '3.3' services: orthanc: image: jodogne/orthanc-plugins:1.12.1 - command: /run/secrets/ # Path to the configuration files (stored as secrets) ports: - 4242:4242 - - 8042:8042 - secrets: - - orthanc.json - environment: - - ORTHANC_NAME=HelloWorld -secrets: - orthanc.json: - file: orthanc.json \ No newline at end of file + - 8042:8042 \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 6e2b49f8..960d69f3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -18,4 +18,5 @@ nav: - 'Demos': 'demos.md' + - 'More information': 'documentation.md' From 7c06f8cb95289c7b1beabb824bd452b0eca9ec97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Fri, 18 Aug 2023 09:38:28 +0200 Subject: [PATCH 10/45] Feat: add examples --- docs/demos.md | 2 +- examples/docker-compose.yaml | 7 + examples/installation.md | 38 ++ examples/orthanc.json | 948 +++++++++++++++++++++++++++++++++++ examples/requirements.txt | 1 + 5 files changed, 995 insertions(+), 1 deletion(-) create mode 100644 examples/docker-compose.yaml create mode 100644 examples/installation.md create mode 100644 examples/orthanc.json create mode 100644 examples/requirements.txt diff --git a/docs/demos.md b/docs/demos.md index 3062f43d..932adfdf 100644 --- a/docs/demos.md +++ b/docs/demos.md @@ -6,7 +6,7 @@ Here is a list of examples to helps you getting started with pyorthanc | Purpose | |---------------------------------------------------------------| -| [Access instance informations](https://github.com/ylemarechal/pyorthanc/tree/main/docs/examples/access_informations) | +| [Access instance informations](https://github.com/ylemarechal/pyorthanc/tree/main/examples/access_informations) | |[Transfer data from a PACS to a Orthanc server](https://github.com/ylemarechal/dicom-transfer)| ## First steps diff --git a/examples/docker-compose.yaml b/examples/docker-compose.yaml new file mode 100644 index 00000000..78867963 --- /dev/null +++ b/examples/docker-compose.yaml @@ -0,0 +1,7 @@ +version: '3.3' +services: + orthanc: + image: jodogne/orthanc-plugins:1.12.1 + ports: + - 4242:4242 + - 8042:8042 \ No newline at end of file diff --git a/examples/installation.md b/examples/installation.md new file mode 100644 index 00000000..aa0d5cde --- /dev/null +++ b/examples/installation.md @@ -0,0 +1,38 @@ +## First steps + +- Applications installed + - [x] Python3.10 + - [x] Docker + + +## Prepare Orthanc +For the examples, we use a vanilla Orthanc inside a docker. The first step is to prepare a dedicated directory, +and copy/past the below code in a file called ```docker-compose.yaml``` +```yaml +version: '3.3' +services: + orthanc: + image: jodogne/orthanc-plugins:1.12.1 + ports: + - 4242:4242 + - 8042:8042 +``` +You can also dowload it directly from this [link](./docker-compose.yaml) + +## Run Orthanc + +To run a local Orthanc with Docker, just run this command in the same directory of your ```docker-compose.yaml``` file + +```bash +docker compose up -d +``` + +The default URL (if running locally) is `http://localhost:8042`. + +## Prepare environment +```bash +python3 -m venv .venv +source .venv/bin/activate +pip install pyorthanc +``` + diff --git a/examples/orthanc.json b/examples/orthanc.json new file mode 100644 index 00000000..ba0d9848 --- /dev/null +++ b/examples/orthanc.json @@ -0,0 +1,948 @@ +{ + /** + * General configuration of Orthanc + * + * As a general recommendation, you should always favour absolute + * paths when you need to provide a path to a file or a directory. + * This is not done in this configuration file since we don't know + * where Orthanc is going to be installed. + **/ + + // The logical name of this instance of Orthanc. This one is + // displayed in Orthanc Explorer and at the URI "/system". + "Name" : "${ORTHANC_NAME} in Docker Compose", + + // Path to the directory that holds the heavyweight files (i.e. the + // raw DICOM instances). Backslashes must be either escaped by + // doubling them, or replaced by forward slashes "/". + "StorageDirectory" : "/var/lib/orthanc/db", + + // Path to the directory that holds the SQLite index (if unset, the + // value of StorageDirectory is used). This index could be stored on + // a RAM-drive or a SSD device for performance reasons. + "IndexDirectory" : "/var/lib/orthanc/db", + + // Path to the directory where Orthanc stores its large temporary + // files. The content of this folder can be safely deleted once + // Orthanc is stopped. The folder must exist. The corresponding + // filesystem must be properly sized, given that for instance a ZIP + // archive of DICOM images created by a job can weight several GBs, + // and that there might be up to "min(JobsHistorySize, + // MediaArchiveSize)" archives to be stored simultaneously. If not + // set, Orthanc will use the default temporary folder of the + // operating system (such as "/tmp/" on UNIX-like systems, or + // "C:/Temp" on Microsoft Windows). + // "TemporaryDirectory" : "/tmp/Orthanc/", + + // Enable the transparent compression of the DICOM instances + "StorageCompression" : false, + + // Maximum size of the storage in MB (a value of "0" indicates no + // limit on the storage size) + "MaximumStorageSize" : 0, + + // Maximum number of patients that can be stored at a given time + // in the storage (a value of "0" indicates no limit on the number + // of patients) + "MaximumPatientCount" : 0, + + // Action to take when the maximum storage is reached. + // By default, the patients are recycled ("Recycle" mode). + // In "Reject" mode, the sender will receive a 0xA700 DIMSE status code + // if the instance was sent through C-Store, a 507 HTTP status code + // if using the REST API and a 0xA700 Failure reason when using + // DicomWeb Stow-RS + // Allowed values: "Recycle", "Reject" + // (new in Orthanc 1.11.2) + "MaximumStorageMode" : "Recycle", + + // Maximum size of the storage cache in MB. The storage cache + // is stored in RAM and contains a copy of recently accessed + // files (written or read). A value of "0" indicates the cache + // is disabled. (new in Orthanc 1.10.0) + "MaximumStorageCacheSize" : 128, + + // List of paths to the custom Lua scripts that are to be loaded + // into this instance of Orthanc + "LuaScripts" : [ + ], + + // The period (in seconds) between 2 calls of the "OnHeartBeat" + // lua callback. O means the heart beat is disabled. + // TODO: text below for Orthanc book: + // Note: that the period is actually not the delay between + // the end of an execution and the triggering of the next one. + // Since there is only one lua context, if other lua code is being + // executed, the heart beat might be delayed even more. + "LuaHeartBeatPeriod" : 0, + + // List of paths to the plugins that are to be loaded into this + // instance of Orthanc (e.g. "./libPluginTest.so" for Linux, or + // "./PluginTest.dll" for Windows). These paths can refer to + // folders, in which case they will be scanned non-recursively to + // find shared libraries. Backslashes must be either escaped by + // doubling them, or replaced by forward slashes "/". + "Plugins" : [ + "/usr/share/orthanc/plugins", "/usr/local/share/orthanc/plugins" + ], + + // Maximum number of processing jobs that are simultaneously running + // at any given time. A value of "0" indicates to use all the + // available CPU logical cores. To emulate Orthanc <= 1.3.2, set + // this value to "1". + "ConcurrentJobs" : 2, + + // Defines the number of threads that are used to execute each type of + // jobs (for the jobs that can be parallelized). + // A value of "0" indicates to use all the available CPU logical cores. + // (new in Orthanc 1.11.3) + "JobsEngineThreadsCount" : { + "ResourceModification": 1 // for /anonymize, /modify + }, + + /** + * Configuration of the HTTP server + **/ + + // Enable the HTTP server. If this parameter is set to "false", + // Orthanc acts as a pure DICOM server. The REST API and Orthanc + // Explorer will not be available. + "HttpServerEnabled" : true, + + // Enable/disable the Orthanc Explorer Web user interface. This + // option is only meaningful if the "HttpServerEnabled" option is + // set to "true" (new in Orthanc 1.8.2). + "OrthancExplorerEnabled" : true, + + // HTTP port for the REST services and for the GUI + "HttpPort" : 8042, + + // When the following option is "true", if an error is encountered + // while calling the REST API, a JSON message describing the error + // is put in the HTTP answer. This feature can be disabled if the + // HTTP client does not properly handles such answers. + "HttpDescribeErrors" : true, + + // Enable HTTP compression to improve network bandwidth utilization, + // at the expense of more computations on the server. Orthanc + // supports the "gzip" and "deflate" HTTP encodings. + "HttpCompressionEnabled" : true, + + // Enable the publication of the content of the Orthanc server as a + // WebDAV share (new in Orthanc 1.8.0). On the localhost, the WebDAV + // share is mapped as "http://localhost:8042/webdav/". + "WebDavEnabled" : true, + + // Whether to allow deletions through the WebDAV share. This is + // disabled by default to avoid accidental loss of DICOM instances. + "WebDavDeleteAllowed" : false, + + // Whether to allow uploads through the WebDAV share. + "WebDavUploadAllowed" : true, + + + + /** + * Configuration of the DICOM server + **/ + + // Enable the DICOM server. If this parameter is set to "false", + // Orthanc acts as a pure REST server. It will not be possible to + // receive files or to do query/retrieve through the DICOM protocol. + "DicomServerEnabled" : true, + + // The DICOM Application Entity Title (cannot be longer than 16 + // characters) + "DicomAet" : "ORTHANC", + + // Check whether the called AET corresponds to the AET of Orthanc + // during an incoming DICOM SCU request + "DicomCheckCalledAet" : false, + + // The DICOM port + "DicomPort" : 4242, + + // The default encoding that is assumed for DICOM files without + // "SpecificCharacterSet" DICOM tag, and that is used when answering + // C-FIND requests (including worklists). The allowed values are + // "Ascii", "Utf8", "Latin1", "Latin2", "Latin3", "Latin4", + // "Latin5", "Cyrillic", "Windows1251", "Arabic", "Greek", "Hebrew", + // "Thai", "Japanese", "Chinese", "JapaneseKanji", "Korean", and + // "SimplifiedChinese". + "DefaultEncoding" : "Latin1", + + // The transfer syntaxes that are accepted by Orthanc C-STORE SCP. + // This is an array listing the accepted transfer syntax UIDs. Each + // entry can contain wildcards ("?" or "*"). By default, all the + // known transfer syntaxes are accepted. (new in Orthanc 1.9.0) + "AcceptedTransferSyntaxes" : [ "1.2.840.10008.1.*" ], + + // User-friendly groups of transfer syntaxes that can be enabled or + // disabled at once. These options are applied after the main + // "AcceptedTransferSyntaxes" option has been applied (if present). + /** + "DeflatedTransferSyntaxAccepted" : true, + "JpegTransferSyntaxAccepted" : true, + "Jpeg2000TransferSyntaxAccepted" : true, + "JpegLosslessTransferSyntaxAccepted" : true, + "JpipTransferSyntaxAccepted" : true, + "Mpeg2TransferSyntaxAccepted" : true, + "RleTransferSyntaxAccepted" : true, + "Mpeg4TransferSyntaxAccepted" : true, // New in Orthanc 1.6.0 + "H265TransferSyntaxAccepted" : true, // New in Orthanc 1.9.0 + **/ + + // Whether Orthanc accepts to act as C-STORE SCP for unknown storage + // SOP classes (aka. "promiscuous mode") + "UnknownSopClassAccepted" : false, + + // Set the timeout (in seconds) after which the DICOM associations + // are closed by the Orthanc SCP (server) if no further DIMSE + // command is received from the SCU (client). + "DicomScpTimeout" : 30, + + + + /** + * Security-related options for the HTTP server + **/ + + // Whether remote hosts can connect to the HTTP server + "RemoteAccessAllowed" : true, + + // Whether or not SSL is enabled + "SslEnabled" : false, + + // Path to the SSL certificate used by the HTTP server. The file + // must be stored in the PEM format, and must contain both the + // certificate and the private key. This option is only meaningful + // if "SslEnabled" is true. + "SslCertificate" : "certificate.pem", + + // Sets the minimum accepted SSL protocol version + // (cf. "ssl_protocol_version" option of civetweb). By default, + // require SSL 1.2. This option is only meaningful if "SslEnabled" + // is true. (new in Orthanc 1.8.2) + // + // Value => Protocols + // 0 SSL2+SSL3+TLS1.0+TLS1.1+TLS1.2 + // 1 SSL3+TLS1.0+TLS1.1+TLS1.2 + // 2 TLS1.0+TLS1.1+TLS1.2 + // 3 TLS1.1+TLS1.2 + // 4 TLS1.2 + "SslMinimumProtocolVersion" : 4, + + // Set the accepted ciphers for SSL connections. The ciphers must be + // provided as a list of strings. If not set, this will default to + // FIPS 140-2 ciphers. This option is only meaningful if + // "SslEnabled" is true. (new in Orthanc 1.8.2) + /** + "SslCiphersAccepted" : [ "AES128-GCM-SHA256" ], + **/ + + // Whether or not peer client certificates shall be checked. This + // option is only meaningful if "SslEnabled" is true. + "SslVerifyPeers" : false, + + // Path to a file containing the concatenation of the client SSL + // certificate(s) that are trusted to verify the identify of remote + // HTTP clients. The individual certificate(s) must be stored in the + // PEM format. This option is only meaningful if "SslVerifyPeers" + // is true. + "SslTrustedClientCertificates" : "trustedClientCertificates.pem", + + // Whether or not the password protection is enabled (using HTTP + // basic access authentication). Starting with Orthanc 1.5.8, if + // "AuthenticationEnabled" is not explicitly set, authentication is + // enabled iff. remote access is allowed (i.e. the default value of + // "AuthenticationEnabled" equals that of "RemoteAccessAllowed"). + /** + "AuthenticationEnabled" : true, + **/ + + // The list of the registered users. Because Orthanc uses HTTP + // Basic Authentication, the passwords are stored as plain text. + //"RegisteredUsers" : { + // "alice" : "alicePassword" + //}, + + + + /** + * Security-related options for the DICOM connections (SCU/SCP) + **/ + + // Whether DICOM TLS is enabled in the Orthanc SCP (new in Orthanc 1.9.0) + "DicomTlsEnabled" : false, + + // Path to the TLS certificate file (in PEM format) to be used for + // both Orthanc SCP (incoming DICOM connections) and Orthanc SCU + // (outgoing DICOM connections). Note that contrarily to the + // "SslCertificate" option, the certificate and its private key must + // be split into two separate files. (new in Orthanc 1.9.0) + /** + "DicomTlsCertificate" : "orthanc.crt", + **/ + + // Path to the file containing the private key (in PEM format) that + // corresponds to the TLS certificate specified in option + // "DicomTlsCertificate". (new in Orthanc 1.9.0) + /** + "DicomTlsPrivateKey" : "orthanc.key", + **/ + + // Path to a file containing all the TLS certificates that Orthanc + // can trust, both for its SCP (incoming DICOM connections) and SCU + // (outgoing DICOM connections). This file must contain a sequence + // of PEM certificates. (new in Orthanc 1.9.0) + /** + "DicomTlsTrustedCertificates" : "trusted.crt", + **/ + + // Whether Orthanc rejects DICOM TLS connections to/from remote + // modalities that do not provide a certificate. Setting this option + // to "true" (resp. "false") corresponds to "--require-peer-cert" + // (resp. "--verify-peer-cert") in the DCMTK command-line + // tools. (new in Orthanc 1.9.3) + "DicomTlsRemoteCertificateRequired" : true, + + // Whether the Orthanc SCP allows incoming C-ECHO requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Orthanc 1.3.0 + // is the only version to behave as if this argument were set to "false". + "DicomAlwaysAllowEcho" : true, + + // Whether the Orthanc SCP allows incoming C-STORE requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above) + "DicomAlwaysAllowStore" : true, + + // Whether the Orthanc SCP allows incoming C-FIND requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Setting this + // option to "true" implies security risks. (new in Orthanc 1.9.0) + // Note: From Orthanc 1.10.0, this option only applies to C-FIND + // requests for patients/studies/series/instances. Use option + // "DicomAlwaysAllowFindWorklist" for worklists. + "DicomAlwaysAllowFind" : false, + + // Whether the Orthanc SCP allows incoming C-FIND requests for worklists, + // even from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Setting this + // option to "true" implies security risks. (new in Orthanc 1.10.0) + "DicomAlwaysAllowFindWorklist" : false, + + // Whether the Orthanc SCP allows incoming C-GET requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Setting this + // option to "true" implies security risks. (new in Orthanc 1.9.0) + "DicomAlwaysAllowGet" : false, + + // Whether the Orthanc SCP allows incoming C-MOVE requests, even + // from SCU modalities it does not know about (i.e. that are not + // listed in the "DicomModalities" option above). Setting this + // option to "true" implies security risks. (new in Orthanc 1.9.7) + "DicomAlwaysAllowMove" : false, + + // Whether Orthanc checks the IP/hostname address of the remote + // modality initiating a DICOM connection (as listed in the + // "DicomModalities" option above). If this option is set to + // "false", Orthanc only checks the AET of the remote modality. + "DicomCheckModalityHost" : false, + + + + /** + * Network topology + **/ + + // The list of the known DICOM modalities. This option is ignored if + // "DicomModalitiesInDatabase" is set to "true", in which case you + // must use the REST API to define modalities. + "DicomModalities" : { + /** + * Uncommenting the following line would enable Orthanc to + * connect to an instance of the "storescp" open-source DICOM + * store (shipped in the DCMTK distribution), as started by the + * command line "storescp 2000". The first parameter is the + * AET of the remote modality (cannot be longer than 16 + * characters), the second one is the remote network address, + * and the third one is the TCP port number corresponding + * to the DICOM protocol on the remote modality (usually 104). + **/ + // "sample" : [ "STORESCP", "127.0.0.1", 2000 ] + + /** + * A fourth parameter is available to enable patches for + * specific PACS manufacturers. The allowed values are currently: + * - "Generic" (default value), + * - "GenericNoWildcardInDates" (to replace "*" by "" in date fields + * in outgoing C-FIND requests originating from Orthanc), + * - "GenericNoUniversalWildcard" (to replace "*" by "" in all fields + * in outgoing C-FIND SCU requests originating from Orthanc), + * - "Vitrea", + * - "GE" (Enterprise Archive, MRI consoles and Advantage Workstation + * from GE Healthcare). + * + * This parameter is case-sensitive. + **/ + // "vitrea" : [ "VITREA", "192.168.1.1", 104, "Vitrea" ] + + /** + * By default, the Orthanc SCP accepts all DICOM commands (C-ECHO, + * C-STORE, C-FIND, C-MOVE, C-GET and storage commitment) issued by the + * registered remote SCU modalities. Starting with Orthanc 1.5.0, + * it is possible to specify which DICOM commands are allowed, + * separately for each remote modality, using the syntax + * below. + * + * The "AllowEcho" (resp. "AllowStore") option only has an effect + * respectively if global option "DicomAlwaysAllowEcho" + * (resp. "DicomAlwaysAllowStore") is set to "false". + * + * Starting with Orthanc 1.7.0, "AllowTranscoding" can be used to + * disable the transcoding to uncompressed transfer syntaxes if + * this remote modality doesn't support compressed transfer + * syntaxes. This option currently applies to Orthanc C-GET SCP + * and to Orthanc C-STORE SCU. This option only has an effect if + * the global option "EnableTranscoding" is set to "true". + * + * By default, all "Allow*" options are true. + * "AllowStorageCommitment" is actually an alias for + * "AllowNAction" & "AllowEventReport". + * + * The "UseDicomTls" option specifies whether DICOM TLS should be + * used when opening a SCU connection from Orthanc to this remote + * modality. By default, DICOM TLS is not enabled. + * + * The "LocalAet" option allows one to overwrite the global + * "DicomAet" configuration option in order to specify another AET + * for Orthanc when initiating an SCU to this very specific + * modality. Similarly, "Timeout" allows one to overwrite the + * global value "DicomScuTimeout" on a per-modality basis. + **/ + //"untrusted" : { + // "AET" : "ORTHANC", + // "Port" : 104, + // "Host" : "127.0.0.1", + // "Manufacturer" : "Generic", + // "AllowEcho" : false, + // "AllowFind" : false, + // "AllowFindWorklist" : false, // new in 1.10.0 + // "AllowGet" : false, + // "AllowMove" : false, + // "AllowStore" : true, + // "AllowStorageCommitment" : false, // new in 1.6.0 + // "AllowTranscoding" : true, // new in 1.7.0 + // "UseDicomTls" : false, // new in 1.9.0 + // "LocalAet" : "HELLO", // new in 1.9.0 + // "Timeout" : 60 // new in 1.9.1 + //} + }, + + // Whether to store the DICOM modalities in the Orthanc database + // instead of in this configuration file (new in Orthanc 1.5.0) + "DicomModalitiesInDatabase" : false, + + // Whether the C-ECHO SCU is automatically followed by a C-FIND SCU, + // while testing the connectivity from Orthanc to a remote DICOM + // modality. This allows one to check that the remote modality does + // accept C-FIND requests from Orthanc (new in Orthanc 1.8.1). + "DicomEchoChecksFind" : false, + + // The timeout (in seconds) after which the DICOM associations are + // considered as closed by the Orthanc SCU (client) if the remote + // DICOM SCP (server) does not answer. + "DicomScuTimeout" : 10, + + // During a C-STORE SCU request initiated by Orthanc, if the remote + // modality doesn't support the original transfer syntax of some + // DICOM instance, specify which transfer syntax should be preferred + // to transcode this instance (provided the remote modality accepts + // this syntax). In Orthanc between 1.7.0 and 1.8.2, this parameter + // was implicitly set to "Little Endian Implicit" + // (1.2.840.10008.1.2). In Orthanc <= 1.6.1 and in Orthanc >= 1.9.0, + // this parameter is by default set to "Little Endian Explicit" + // (1.2.840.10008.1.2.1). This parameter can possibly correspond to + // a compressed transfer syntax. (new in Orthanc 1.9.0) + "DicomScuPreferredTransferSyntax" : "1.2.840.10008.1.2.1", + + // Number of threads that are used by the embedded DICOM server. + // This defines the number of concurrent DICOM operations that can + // be run. Note: This is not limiting the number of concurrent + // connections. With a single thread, if a C-Find is received during + // e.g the transcoding of an incoming C-Store, it will have to wait + // until the end of the C-Store before being processed. (new in + // Orthanc 1.10.0, before this version, the value was fixed to 4) + "DicomThreadsCount" : 4, + + // The list of the known Orthanc peers. This option is ignored if + // "OrthancPeersInDatabase" is set to "true", in which case you must + // use the REST API to define Orthanc peers. + "OrthancPeers" : { + /** + * Each line gives the base URL of an Orthanc peer, possibly + * followed by the username/password pair (if the password + * protection is enabled on the peer). + **/ + // "peer" : [ "http://127.0.0.1:8043/", "alice", "alicePassword" ] + // "peer2" : [ "http://127.0.0.1:8044/" ] + + /** + * This is another, more advanced format to define Orthanc + * peers. It notably allows one to specify HTTP headers, a HTTPS + * client certificate in the PEM format (as in the "--cert" option + * of curl), or to enable PKCS#11 authentication for smart cards. + * + * The "Timeout" option allows one to overwrite the global value + * "HttpTimeout" on a per-peer basis. + **/ + // "peer" : { + // "Url" : "http://127.0.0.1:8043/", + // "Username" : "alice", + // "Password" : "alicePassword", + // "HttpHeaders" : { "Token" : "Hello world" }, + // "CertificateFile" : "client.crt", + // "CertificateKeyFile" : "client.key", + // "CertificateKeyPassword" : "certpass", + // "Pkcs11" : false, + // "Timeout" : 42 // New in Orthanc 1.9.1 + // } + }, + + // Whether to store the Orthanc peers in the Orthanc database + // instead of in this configuration file (new in Orthanc 1.5.0) + "OrthancPeersInDatabase" : false, + + // Parameters of the HTTP proxy to be used by Orthanc. If set to the + // empty string, no HTTP proxy is used. For instance: + // "HttpProxy" : "192.168.0.1:3128" + // "HttpProxy" : "proxyUser:proxyPassword@192.168.0.1:3128" + "HttpProxy" : "", + + // If set to "true", debug messages from libcurl will be issued + // whenever Orthanc makes an outgoing HTTP request. This is notably + // useful to debug HTTPS-related problems. + "HttpVerbose" : false, + + // Set the timeout for HTTP requests issued by Orthanc (in seconds). + "HttpTimeout" : 60, + + // Enable the verification of the peers during HTTPS requests. This + // option must be set to "false" if using self-signed certificates. + // Pay attention that setting this option to "false" results in + // security risks! + // Reference: http://curl.haxx.se/docs/sslcerts.html + "HttpsVerifyPeers" : true, + + // Path to the CA (certification authority) certificates to validate + // peers in HTTPS requests. From curl documentation ("--cacert" + // option): "Tells curl to use the specified certificate file to + // verify the peers. The file may contain multiple CA + // certificates. The certificate(s) must be in PEM format." On + // Debian-based systems, this option can be set to + // "/etc/ssl/certs/ca-certificates.crt" + "HttpsCACertificates" : "/etc/ssl/certs/ca-certificates.crt", + + + + /** + * Advanced options + **/ + + // Dictionary of symbolic names for the user-defined metadata. Each + // entry must map an unique string to an unique number between 1024 + // and 65535. Reserved values: + // - The Orthanc whole-slide imaging plugin uses metadata 4200 + "UserMetadata" : { + // "Sample" : 1024 + }, + + // Dictionary of symbolic names for the user-defined types of + // attached files. Each entry must map an unique string to an unique + // number between 1024 and 65535. Optionally, a second argument can + // provided to specify a MIME content type for the attachment. + "UserContentType" : { + // "sample" : 1024 + // "sample2" : [ 1025, "application/pdf" ] + }, + + // Number of seconds without receiving any instance before a + // patient, a study or a series is considered as stable. + "StableAge" : 60, + + // By default, Orthanc compares AET (Application Entity Titles) in a + // case-insensitive way. Setting this option to "true" will enable + // case-sensitive matching. + "StrictAetComparison" : false, + + // When the following option is "true", the MD5 of the DICOM files + // will be computed and stored in the Orthanc database. This + // information can be used to detect disk corruption, at the price + // of a small performance overhead. + "StoreMD5ForAttachments" : true, + + // The maximum number of results for a single C-FIND request at the + // Patient, Study or Series level. Setting this option to "0" means + // no limit. + "LimitFindResults" : 0, + + // The maximum number of results for a single C-FIND request at the + // Instance level. Setting this option to "0" means no limit. + "LimitFindInstances" : 0, + + // If this option is set to "true" (default behavior until Orthanc + // 1.3.2), Orthanc will log the resources that are exported to other + // DICOM modalities or Orthanc peers, inside the URI + // "/exports". Setting this option to "false" is useful to prevent + // the index to grow indefinitely in auto-routing tasks (this is the + // default behavior since Orthanc 1.4.0). + "LogExportedResources" : false, + + // Enable or disable HTTP Keep-Alive (persistent HTTP + // connections). Setting this option to "true" prevents Orthanc + // issue #32 ("HttpServer does not support multiple HTTP requests in + // the same TCP stream"), but can possibly slow down HTTP clients + // that do not support persistent connections. The default behavior + // used to be "false" in Orthanc <= 1.5.1. Setting this option to + // "false" is also recommended if Orthanc is compiled against + // Mongoose. + "KeepAlive" : true, + + // Defines the Keep-Alive timeout in seconds. + // (new in Orthanc 1.11.3) + "KeepAliveTimeout" : 1, + + // Enable or disable Nagle's algorithm. Only taken into + // consideration if Orthanc is compiled to use CivetWeb. Experiments + // show that best performance can be obtained by setting both + // "KeepAlive" and "TcpNoDelay" to "true". Beware however of + // caveats: https://eklitzke.org/the-caveats-of-tcp-nodelay + "TcpNoDelay" : true, + + // Number of threads that are used by the embedded HTTP server. + "HttpThreadsCount" : 50, + + // If this option is set to "false", Orthanc will run in index-only + // mode. The DICOM files will not be stored on the drive: Orthanc + // only indexes the small subset of the so-called "main DICOM tags" + // in its SQL database. Note that this option might prevent the + // upgrade to newer versions of Orthanc. Also note that this + // behavior might not be available with the storage area plugins. + "StoreDicom" : true, + + // DICOM associations initiated by Lua scripts are kept open as long + // as new DICOM commands are issued. This option sets the number of + // seconds of inactivity to wait before automatically closing a + // DICOM association used by Lua. If set to 0, the connection is + // closed immediately. This option is only used in Lua scripts. + "DicomAssociationCloseDelay" : 5, + + // Maximum number of query/retrieve DICOM requests that are + // maintained by Orthanc. The least recently used requests get + // deleted as new requests are issued. + "QueryRetrieveSize" : 100, + + // When handling a C-FIND SCP request, setting this flag to "true" + // will enable case-sensitive match for PN value representation + // (such as PatientName). By default, the search is + // case-insensitive, which does not follow the DICOM standard. + "CaseSensitivePN" : false, + + // Configure PKCS#11 to use hardware security modules (HSM) and + // smart cards when carrying on HTTPS client authentication. + /** + "Pkcs11" : { + "Module" : "/usr/local/lib/libbeidpkcs11.so", + "Module" : "C:/Windows/System32/beidpkcs11.dll", + "Pin" : "1234", + "Verbose" : true + } + **/ + + // If set to "false", Orthanc will not load its default dictionary + // of private tags. This might be necessary if you cannot import a + // DICOM file encoded using the Implicit VR Endian transfer syntax, + // and containing private tags: Such an import error might stem from + // a bad dictionary. You can still list your private tags of + // interest in the "Dictionary" configuration option below. + "LoadPrivateDictionary" : true, + + // Locale to be used by Orthanc. Currently, only used if comparing + // strings in a case-insensitive way. It should be safe to keep this + // value undefined, which lets Orthanc autodetect the suitable locale. + // "Locale" : "en_US.UTF-8", + + // Register a new tag in the dictionary of DICOM tags that are known + // to Orthanc. Each line must contain the tag (formatted as 2 + // hexadecimal numbers), the value representation (2 upcase + // characters), a nickname for the tag, possibly the minimum + // multiplicity (> 0 with defaults to 1), possibly the maximum + // multiplicity (0 means arbitrary multiplicity, defaults to 1), and + // possibly the Private Creator (for private tags). + // Note: For private tags, you should only declare the lower 8 bits + // of the element since the higher 8 bits may vary from one file to + // the other. + "Dictionary" : { + // "0014,1020" : [ "DA", "ValidationExpiryDate", 1, 1 ] + // "00e1,c2" : [ "UI", "PET-CT Multi Modality Name", 1, 1, "ELSCINT1" ] + // "7053,03" : [ "ST", "Original Image Filename", 1, 1, "Philips PET Private Group" ] + // "2001,5f" : [ "SQ", "StackSequence", 1, 1, "Philips Imaging DD 001" ] + }, + + // Load a set of external DICOM dictionaries in order to replace the + // default dictionaries. This option must contain a set of files in + // the DCMTK format. The order of the dictionaries *is* + // important. This option can be used to turn Orthanc into a DICONDE + // server. (new in Orthanc 1.9.4) + /** + "ExternalDictionaries" : [ + "/usr/share/libdcmtk12/dicom.dic", + "/usr/share/libdcmtk12/diconde.dic" + ] + **/ + + // Whether to run DICOM C-MOVE operations synchronously. If set to + // "false" (asynchronous mode), each incoming C-MOVE request results + // in the creation of a new background job. Up to Orthanc 1.3.2, the + // implicit behavior was to use synchronous C-MOVE ("true"). Between + // Orthanc 1.4.0 and 1.4.2, the default behavior was set to + // asynchronous C-MOVE ("false"). Since Orthanc 1.5.0, the default + // behavior is back to synchronous C-MOVE ("true", which ensures + // backward compatibility with Orthanc <= 1.3.2). + "SynchronousCMove" : true, + + // Maximum number of completed jobs that are kept in memory. A + // processing job is considered as complete once it is tagged as + // "Success" or "Failure". Since Orthanc 1.5.0, a value of "0" + // indicates to keep no job in memory (i.e. jobs are removed from + // the history as soon as they are completed), which prevents the + // use of some features of Orthanc (typically, synchronous mode in + // REST API) and should be avoided for non-developers. + "JobsHistorySize" : 10, + + // Whether to save the jobs into the Orthanc database. If this + // option is set to "true", the pending/running/completed jobs are + // automatically reloaded from the database if Orthanc is stopped + // then restarted (except if the "--no-jobs" command-line argument + // is specified). This option should be set to "false" if multiple + // Orthanc servers are using the same database (e.g. if PostgreSQL + // or MariaDB/MySQL is used). + "SaveJobs" : true, + + // Specifies how Orthanc reacts when it receives a DICOM instance + // whose SOPInstanceUID is already stored. If set to "true", the new + // instance replaces the old one. If set to "false", the new + // instance is discarded and the old one is kept. Up to Orthanc + // 1.4.1, the implicit behavior corresponded to "false". + "OverwriteInstances" : false, + + // Maximum number of ZIP/media archives that are maintained by + // Orthanc, as a response to the asynchronous creation of archives. + // The least recently used archives get deleted as new archives are + // generated. This option was introduced in Orthanc 1.5.0, and has + // no effect on the synchronous generation of archives. + "MediaArchiveSize" : 1, + + // Performance setting to specify how Orthanc accesses the storage + // area during find operations (C-FIND, /tools/find API route and + // QIDO-RS in dicom-web). Three modes are available: (1) "Always" + // allows Orthanc to read the storage area as soon as it needs an + // information that is not present in its database (slowest mode), + // (2) "Never" prevents Orthanc from accessing the storage area, and + // makes it uses exclusively its database (fastest mode), and (3) + // "Answers" allows Orthanc to read the storage area to generate its + // answers, but not to filter the DICOM resources (balance between + // the two modes). By default, the mode is "Always", which + // corresponds to the behavior of Orthanc <= 1.5.0. + "StorageAccessOnFind" : "Always", + + // Whether Orthanc monitors its metrics (new in Orthanc 1.5.4). If + // set to "true", the metrics can be retrieved at + // "/tools/metrics-prometheus" formetted using the Prometheus + // text-based exposition format. + "MetricsEnabled" : true, + + // Whether calls to URI "/tools/execute-script" is enabled. Starting + // with Orthanc 1.5.8, this URI is disabled by default for security. + "ExecuteLuaEnabled" : false, + + // Whether the REST API can write to the filesystem (e.g. in + // /instances/../export route). Starting with Orthanc 1.12.0, + // this URI is disabled by default for security. + "RestApiWriteToFileSystemEnabled": false, + + // Set the timeout while serving HTTP requests by the embedded Web + // server, in seconds. This corresponds to option + // "request_timeout_ms" of Mongoose/Civetweb. It will set the socket + // options "SO_RCVTIMEO" and "SO_SNDTIMEO" to the specified value. + "HttpRequestTimeout" : 30, + + // Set the default private creator that is used by Orthanc when it + // looks for a private tag in its dictionary (cf. "Dictionary" + // option), or when it creates/modifies a DICOM file (new in Orthanc 1.6.0). + "DefaultPrivateCreator" : "", + + // Maximum number of storage commitment reports (i.e. received from + // remote modalities) to be kept in memory (new in Orthanc 1.6.0). + "StorageCommitmentReportsSize" : 100, + + // Whether Orthanc transcodes DICOM files to an uncompressed + // transfer syntax over the DICOM protocol, if the remote modality + // does not support compressed transfer syntaxes (new in Orthanc 1.7.0). + "TranscodeDicomProtocol" : true, + + // If some plugin to decode/transcode DICOM instances is installed, + // this option specifies whether the built-in decoder/transcoder of + // Orthanc (that uses DCMTK) is applied before or after the plugins, + // or is not applied at all (new in Orthanc 1.7.0). The allowed + // values for this option are "After" (default value, corresponding + // to the behavior of Orthanc <= 1.6.1), "Before", or "Disabled". + "BuiltinDecoderTranscoderOrder" : "After", + + // If this option is set, Orthanc will transparently transcode any + // incoming DICOM instance to the given transfer syntax before + // storing it into its database. Beware that this might result in + // high CPU usage (if transcoding to some compressed transfer + // syntax), or in higher disk consumption (if transcoding to an + // uncompressed syntax). Also, beware that transcoding to a transfer + // syntax with lossy compression (notably JPEG) will change the + // "SOPInstanceUID" DICOM tag, and thus the Orthanc identifier at + // the instance level, which might break external workflow. + /** + "IngestTranscoding" : "1.2.840.10008.1.2", + **/ + + // Whether ingest transcoding is applied to incoming DICOM instances + // that have an uncompressed transfer syntax, i.e. Little Endian + // Implicit, Little Endian Explicit or Big Endian Explicit (new in + // Orthanc 1.8.2). + "IngestTranscodingOfUncompressed" : true, + + // Whether ingest transcoding is applied to incoming DICOM instances + // that have a compressed transfer syntax (new in Orthanc 1.8.2). + "IngestTranscodingOfCompressed" : true, + + // The compression level that is used when transcoding to one of the + // lossy/JPEG transfer syntaxes (integer between 1 and 100). + "DicomLossyTranscodingQuality" : 90, + + // Whether "fsync()" is called after each write to the storage area + // (new in Orthanc 1.7.4). If this option is set to "true", Orthanc + // will run more slowly, but the DICOM are guaranteed to be + // immediately written to the disk. This option only makes sense if + // the builtin filesystem storage area is used. It defaults to + // "false" in Orthanc <= 1.7.3, and to "true" in Orthanc >= 1.7.4. + "SyncStorageArea" : true, + + // If specified, on compatible systems, call "mallopt(M_ARENA_MAX, + // ...)" while starting Orthanc. This has the same effect at setting + // the environment variable "MALLOC_ARENA_MAX". This avoids large + // growth in RES memory if the threads of the embedded HTTP server + // have to allocate large chunks of memory (typically the case with + // large DICOM files). By setting "MallocArenaMax" to "N", these + // threads share "N" memory pools (known as "arenas"). Setting this + // option to "0" doesn't call mallopt()", which was the behavior of + // Orthanc <= 1.8.1. + "MallocArenaMax" : 5, + + // Deidentify/anonymize the contents of the logs (notably C-FIND, + // C-GET, and C-MOVE queries submitted to Orthanc) according to + // Table E.1-1 of the DICOM standard (new in Orthanc 1.8.2) + "DeidentifyLogs" : true, + + // If "DeidentifyLogs" is true, this sets the DICOM standard to + // follow for the deidentification/anonymization of the query + // contents. Possible values are "2008", "2017c", "2021b" (new + // in Orthanc 1.8.2), and "2023b" (new in Orthanc 1.12.1) + "DeidentifyLogsDicomVersion" : "2023b", + + // Maximum length of the PDU (Protocol Data Unit) in the DICOM + // network protocol, expressed in bytes. This value affects both + // Orthanc SCU and Orthanc SCP. It defaults to 16KB. The allowed + // range is [4096,131072]. (new in Orthanc 1.9.0) + "MaximumPduLength" : 16384, + + // Arbitrary identifier of this Orthanc server when storing its + // global properties if a custom index plugin is used. This + // identifier is only useful in the case of multiple + // readers/writers, in order to avoid collisions between multiple + // Orthanc servers. If unset, this identifier is taken as a SHA-1 + // hash derived from the MAC addresses of the network interfaces, + // and from the AET and TCP ports used by Orthanc. Manually setting + // this option is needed in Docker/Kubernetes environments. (new in + // Orthanc 1.9.2) + /** + "DatabaseServerIdentifier" : "Orthanc1", + **/ + + // Whether Orthanc protects the modification of metadata and + // attachments using revisions, which is done using the HTTP headers + // "ETag", "If-Match" and "If-None-Match" in the calls to the REST + // API. This is needed to handle collisions between concurrent + // modifications in the case of multiple writers. The database + // back-end must support this option, which is notably *not* yet the + // case of the built-in SQLite index. (new in Orthanc 1.9.2) + "CheckRevisions" : false, + + // Whether Orthanc streams ZIP archive/media to the HTTP + // client. Setting this option to "false" corresponds to the + // behavior of Orthanc <= 1.9.3: The ZIP is first entirely written + // to a temporary file, then sent to the client (which necessitates + // disk space and might lead to HTTP timeouts on large archives). If + // set to "true", the chunks of the ZIP file are progressively sent + // as soon as one DICOM file gets compressed (new in Orthanc 1.9.4) + "SynchronousZipStream" : true, + + // Default number of loader threads when generating Zip archive/media. + // A value of 0 means reading and writing are performed in sequence + // (default behaviour). A value > 1 is meaningful only if the storage + // is a distributed network storage (e.g object storage plugin). + // (new experimental feature in Orthanc 1.10.0) + "ZipLoaderThreads": 0, + + // Extra Main Dicom tags that are stored in DB together with all default + // Main Dicom tags that are already stored. + // see https://book.orthanc-server.com/faq/main-dicom-tags.html + // (new in Orthanc 1.11.0) + // Sequences tags are not supported. + /** + "ExtraMainDicomTags" : { + "Instance" : [ + "Rows", + "Columns", + "ImageType", + "SOPClassUID", + "ContentDate", + "ContentTime", + "FrameOfReferenceUID", + "PixelSpacing", + "SpecificCharacterSet", + "BitsAllocated" + ], + "Series" : [], + "Study": [], + "Patient": [] + }, + */ + + // Enables/disables warnings in the logs. + // "true" enables a warning. All warnings are enabled by default + // see https://book.orthanc-server.com/faq/main-dicom-tags.html#warnings + // (new in Orthanc 1.11.0) + "Warnings" : { + // A "RequestedTags" has been read from storage which is slower than + // reading it from DB. + // You might want to store this tag in ExtraMainDicomTags to build + // the response faster. + "W001_TagsBeingReadFromStorage": true, + + // Retrieving a list of Main dicom tags from a resource that has been + // saved with another "ExtraMainDicomTags" configuration which means that + // your response might be incomplete/inconsistent. + // You should call patients|studies|series|instances/../reconstruct to rebuild + // the DB. You may also check for the "Housekeeper" plugin + "W002_InconsistentDicomTagsInDb": true + } + +} diff --git a/examples/requirements.txt b/examples/requirements.txt new file mode 100644 index 00000000..02a5c6fa --- /dev/null +++ b/examples/requirements.txt @@ -0,0 +1 @@ +pyorthanc==1.11.5 \ No newline at end of file From 5ab222659630310ecd5e2548ca80fa97b6b33101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Fri, 18 Aug 2023 09:40:40 +0200 Subject: [PATCH 11/45] Feat: add examples --- examples/access_informations/README.md | 29 +++++++++++++++++ .../access_patient_information.py | 32 +++++++++++++++++++ .../access_informations/docker-compose.yaml | 7 ++++ 3 files changed, 68 insertions(+) create mode 100644 examples/access_informations/README.md create mode 100644 examples/access_informations/access_patient_information.py create mode 100644 examples/access_informations/docker-compose.yaml diff --git a/examples/access_informations/README.md b/examples/access_informations/README.md new file mode 100644 index 00000000..d2178a6c --- /dev/null +++ b/examples/access_informations/README.md @@ -0,0 +1,29 @@ +# Acces to patient-study-series-instance informations + +In this tutorial, you can access to all patients, study, series and instances information. Use it with a small batch of +data in the Orthanc server + +## Get the python file +[access_patient_information.py](./access_patient_information.py) +[docker-compose.yaml](./docker-compose.yaml) + +## Run Orthanc + +To run a local Orthanc with Docker, just run +```bash +docker compose up -d +``` + +The default URL (if running locally) is `http://localhost:8042`. + +## Prepare environment +```bash +python3 -m venv .venv +source .venv/bin/activate +pip install pyorthanc +``` + +## Run PyOrthanc script +```bash +python access_patient_information.py +``` \ No newline at end of file diff --git a/examples/access_informations/access_patient_information.py b/examples/access_informations/access_patient_information.py new file mode 100644 index 00000000..fc7da262 --- /dev/null +++ b/examples/access_informations/access_patient_information.py @@ -0,0 +1,32 @@ +from pyorthanc import Orthanc + +orthanc = Orthanc('http://localhost:8042', username='orthanc', password='orthanc') + +# To get patients identifier and main information +patients_identifiers = orthanc.get_patients() + +for patient_identifier in patients_identifiers: + # To get patient information + patient_info = orthanc.get_patients_id(patient_identifier) + patient_name = patient_info['MainDicomTags']['PatientName'] + study_identifiers = patient_info['Studies'] + +# To get patient's studies identifier and main information +for study_identifier in study_identifiers: + # To get Study info + study_info = orthanc.get_studies_id(study_identifier) + study_date = study_info['MainDicomTags']['StudyDate'] + series_identifiers = study_info['Series'] + +# To get study's series identifier and main information +for series_identifier in series_identifiers: + series_info = orthanc.get_series_id(series_identifier) + modality = series_info['MainDicomTags']['Modality'] + instance_identifiers = series_info['Instances'] + +# and so on ... +for instance_identifier in instance_identifiers: + instance_info = orthanc.get_instances_id(instance_identifier) + + # Get SOPInstanceUID + print(instance_info['MainDicomTags']['SOPInstanceUID']) diff --git a/examples/access_informations/docker-compose.yaml b/examples/access_informations/docker-compose.yaml new file mode 100644 index 00000000..78867963 --- /dev/null +++ b/examples/access_informations/docker-compose.yaml @@ -0,0 +1,7 @@ +version: '3.3' +services: + orthanc: + image: jodogne/orthanc-plugins:1.12.1 + ports: + - 4242:4242 + - 8042:8042 \ No newline at end of file From 687446f16ae3410fc5a369eb3430f5d32fd4facf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Fri, 18 Aug 2023 09:42:29 +0200 Subject: [PATCH 12/45] Feat: add examples --- examples/access_informations/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/access_informations/README.md b/examples/access_informations/README.md index d2178a6c..d216696e 100644 --- a/examples/access_informations/README.md +++ b/examples/access_informations/README.md @@ -3,8 +3,9 @@ In this tutorial, you can access to all patients, study, series and instances information. Use it with a small batch of data in the Orthanc server -## Get the python file +## Files needed [access_patient_information.py](./access_patient_information.py) + [docker-compose.yaml](./docker-compose.yaml) ## Run Orthanc From a7ecb1797e50cc9caf8d61c027208d5721227a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Fri, 18 Aug 2023 09:44:57 +0200 Subject: [PATCH 13/45] Feat: add examples --- docs/demos.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/demos.md b/docs/demos.md index 932adfdf..d7b06bd7 100644 --- a/docs/demos.md +++ b/docs/demos.md @@ -11,9 +11,8 @@ Here is a list of examples to helps you getting started with pyorthanc ## First steps -- Applications installed - - [x] Python3.10 - - [x] Docker +- [x] Python3.10 +- [x] Docker ## Some useful commands From 60c22b12d348e2726827977c8e979d4e98f12634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Fri, 18 Aug 2023 09:45:58 +0200 Subject: [PATCH 14/45] Feat: add examples --- docs/demos.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/demos.md b/docs/demos.md index d7b06bd7..f6ecf898 100644 --- a/docs/demos.md +++ b/docs/demos.md @@ -4,10 +4,10 @@ Be sure that Orthanc is running. The default URL (if running locally) is `http:/ Here is a list of examples to helps you getting started with pyorthanc -| Purpose | -|---------------------------------------------------------------| +| code | +|-----------------------------------------------------------------------------------------------------------------| | [Access instance informations](https://github.com/ylemarechal/pyorthanc/tree/main/examples/access_informations) | -|[Transfer data from a PACS to a Orthanc server](https://github.com/ylemarechal/dicom-transfer)| +| [Transfer data from a PACS to a Orthanc server](https://github.com/ylemarechal/dicom-transfer) | ## First steps From 65a7aff99be38ac0652301c77526a30738ccd803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Fri, 18 Aug 2023 09:50:12 +0200 Subject: [PATCH 15/45] Feat: add examples --- docs/demos.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/docs/demos.md b/docs/demos.md index f6ecf898..06403e3c 100644 --- a/docs/demos.md +++ b/docs/demos.md @@ -16,14 +16,6 @@ Here is a list of examples to helps you getting started with pyorthanc ## Some useful commands -### Prepare python environment -```bash -python3 -m venv .venv -source .venv/bin/activate -pip install pyorthanc -``` - - ### Docker commands Start Orthanc ```bash From 51d4e7d88783ff6260d2e8f3bf12e5d81a317078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Tue, 22 Aug 2023 16:11:15 +0200 Subject: [PATCH 16/45] Feat: add api ref --- docs/api/async_client.md | 3 +++ docs/api/filtering.md | 3 +++ docs/api/instance.md | 3 +++ docs/api/orthanc.md | 3 +++ docs/api/patient.md | 3 +++ docs/api/remote.md | 3 +++ docs/api/series.md | 3 +++ docs/api/study.md | 3 +++ docs/api/usage.md | 0 docs/api/util.md | 3 +++ docs/citation.md | 0 docs/css/custom.css | 10 +++++++++ mkdocs.yml | 46 ++++++++++++++++++++++++++++++++++------ 13 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 docs/api/async_client.md create mode 100644 docs/api/filtering.md create mode 100644 docs/api/instance.md create mode 100644 docs/api/orthanc.md create mode 100644 docs/api/patient.md create mode 100644 docs/api/remote.md create mode 100644 docs/api/series.md create mode 100644 docs/api/study.md create mode 100644 docs/api/usage.md create mode 100644 docs/api/util.md create mode 100644 docs/citation.md create mode 100644 docs/css/custom.css diff --git a/docs/api/async_client.md b/docs/api/async_client.md new file mode 100644 index 00000000..d512f1ab --- /dev/null +++ b/docs/api/async_client.md @@ -0,0 +1,3 @@ +::: pyorthanc.AsyncOrthanc + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/filtering.md b/docs/api/filtering.md new file mode 100644 index 00000000..892f54ce --- /dev/null +++ b/docs/api/filtering.md @@ -0,0 +1,3 @@ +::: pyorthanc.filtering + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/instance.md b/docs/api/instance.md new file mode 100644 index 00000000..f3996213 --- /dev/null +++ b/docs/api/instance.md @@ -0,0 +1,3 @@ +::: pyorthanc.Instance + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/orthanc.md b/docs/api/orthanc.md new file mode 100644 index 00000000..324a1bca --- /dev/null +++ b/docs/api/orthanc.md @@ -0,0 +1,3 @@ +::: pyorthanc.Orthanc + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/patient.md b/docs/api/patient.md new file mode 100644 index 00000000..ebd685f9 --- /dev/null +++ b/docs/api/patient.md @@ -0,0 +1,3 @@ +::: pyorthanc.Patient + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/remote.md b/docs/api/remote.md new file mode 100644 index 00000000..7a2b1b18 --- /dev/null +++ b/docs/api/remote.md @@ -0,0 +1,3 @@ +::: pyorthanc.RemoteModality + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/series.md b/docs/api/series.md new file mode 100644 index 00000000..73d4d8d3 --- /dev/null +++ b/docs/api/series.md @@ -0,0 +1,3 @@ +::: pyorthanc.Series + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/study.md b/docs/api/study.md new file mode 100644 index 00000000..adf2f95e --- /dev/null +++ b/docs/api/study.md @@ -0,0 +1,3 @@ +::: pyorthanc.Study + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/usage.md b/docs/api/usage.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/api/util.md b/docs/api/util.md new file mode 100644 index 00000000..b81cdd64 --- /dev/null +++ b/docs/api/util.md @@ -0,0 +1,3 @@ +::: pyorthanc.util + :docstring: + :members: \ No newline at end of file diff --git a/docs/citation.md b/docs/citation.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/css/custom.css b/docs/css/custom.css new file mode 100644 index 00000000..ced5d751 --- /dev/null +++ b/docs/css/custom.css @@ -0,0 +1,10 @@ +div.autodoc-docstring { + padding-left: 20px; + margin-bottom: 30px; + border-left: 5px solid rgba(230, 230, 230); +} + +div.autodoc-members { + padding-left: 20px; + margin-bottom: 15px; +} \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 960d69f3..5b4176e3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,19 +4,51 @@ repo_url: https://github.com/gacou54/pyorthanc repo_name: gacou54/pyorthanc theme: name: material - + features: + - navigation.sections + - content.code.copy + - content.code.select nav: - - 'General informations': - - 'Presentation': 'index.md' - - 'Purpose': 'purpose.md' - - 'Contacts': 'contacts.md' + - 'Introduction': 'index.md' # README + - 'Usage': + - 'Quick Start': 'tutorial/quickstart.md' + - 'Advanced Usage': 'tutorial/advanced.md' + - 'Api Reference': + 'Orthanc': 'api/orthanc.md' + 'Asynchronous Orthanc': 'api/async_client.md' + 'Patient': 'api/patient.md' + 'Study': 'api/study.md' + 'Series': 'api/series.md' + 'Instance': 'api/instance.md' + 'Filtering': 'api/filtering.md' + 'Remote': 'api/remote.md' + 'Util': 'api/util.md' + - 'Releases & Roadmap': - 'Releases': 'releases/releases.md' - 'Roadmap' : 'releases/roadmap.md' - - 'Demos': 'demos.md' + - 'More informations': + - 'Contacts': 'contacts.md' + - 'Citation': 'citation.md' + + + +markdown_extensions: + - admonition + - codehilite: + css_class: highlight +plugins: + - search + - mkdocstrings: + handlers: + python: + options: + docstring_style: numpy + default_handler: python - - 'More information': 'documentation.md' +extra_css: + - css/custom.css \ No newline at end of file From cfad689b63260d5170cb6dff4fcc91077cdf4066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Tue, 22 Aug 2023 16:14:00 +0200 Subject: [PATCH 17/45] Feat: add api ref --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 38bff15e..0b3bb983 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,5 +20,5 @@ jobs: path: .cache restore-keys: | mkdocs-material- - - run: pip install mkdocs-material + - run: pip install mkdocs-material mkdocstrings mkdocstrings-python - run: mkdocs gh-deploy --force From 811f86e66f58b665095f438fc09cb92c90d3644a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Tue, 22 Aug 2023 17:14:03 +0200 Subject: [PATCH 18/45] Feat: add api ref --- docs/citation.md | 4 ++ docs/contributing.md | 29 +++++++++++++ docs/tutorial/advanced.md | 9 ++++ docs/tutorial/quickstart.md | 82 +++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 docs/contributing.md create mode 100644 docs/tutorial/advanced.md create mode 100644 docs/tutorial/quickstart.md diff --git a/docs/citation.md b/docs/citation.md index e69de29b..09fa9c69 100644 --- a/docs/citation.md +++ b/docs/citation.md @@ -0,0 +1,4 @@ + +## Citation +If you publish using PyOrthanc, we kindly ask that you credit us. PyOrthanc can be found on Zenodo : +[https://zenodo.org/record/7086219](https://zenodo.org/record/7086219). \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 00000000..3087d48c --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,29 @@ +You can contribute to this project with the following steps: + +1. First, fork the project on Github + +2. Clone the project + +```shell + git clone https://github.com//pyorthanc +``` + +3. Enter the project and create a poetry environment + (this project use the [poetry](https://python-poetry.org/) for dependency management) + +```shell + cd pyorthanc +``` +```shell + peotry install +``` + +4. Make a new git branch where you will apply the changes +```shell + git checkout -b your-branch-name +``` + Now you can make your changes + +5. Once done, `git add`, `git commit` and `git push` the changes. + +6. Make a Pull Request from your branch to the [pyorthanc repository](https://github.com/gacou54/pyorthanc). \ No newline at end of file diff --git a/docs/tutorial/advanced.md b/docs/tutorial/advanced.md new file mode 100644 index 00000000..fea1cee4 --- /dev/null +++ b/docs/tutorial/advanced.md @@ -0,0 +1,9 @@ +Example of usage +---------------- + +Here is a list of complete examples with pyorthanc + +| code | +|-----------------------------------------------------------------------------------------------------------------| +| [Transfer data from a PACS to a Orthanc server](https://github.com/ylemarechal/dicom-transfer) | + diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md new file mode 100644 index 00000000..bc336cf0 --- /dev/null +++ b/docs/tutorial/quickstart.md @@ -0,0 +1,82 @@ +# First steps + +## Requirements + +- [x] Python3.10 + +## Installation + +```bash +python3 -m venv .venv +source .venv/bin/activate +pip install pyorthanc +``` +## Getting started +### Import pyorthanc library +```python +import pyorthanc +``` + +### Connect to Orthanc +Here are some quick how to examples to use pyorthanc +```python +from pyorthanc import Orthanc + +orthanc = Orthanc(url='http://localhost:8042/', + username='username', + password='password') +``` + + +### Upload DICOM files to Orthanc: + +```python +from pyorthanc import Orthanc + +orthanc = Orthanc(url='http://localhost:8042/', + username='username', + password='password') + +with open('A_DICOM_INSTANCE_PATH.dcm', 'rb') as file: + orthanc.post_instances(file.read()) +``` +### Getting list of connected remote modalities: +```python +from pyorthanc import Orthanc + +orthanc = Orthanc(url='http://localhost:8042/', + username='username', + password='password') + +orthanc.get_modalities() +``` + +Example of usage +---------------- +Be sure that Orthanc is running. The default URL (if running locally) is `http://localhost:8042`. + +Here is a list of examples to helps you getting started with pyorthanc + +| code | +|-----------------------------------------------------------------------------------------------------------------| +| [Access instance informations](https://github.com/ylemarechal/pyorthanc/tree/main/examples/access_informations) | + +## Some useful commands + +### Docker commands +Start Orthanc +```bash +docker compose up -d +``` +Stop Orthanc +```bash +docker compose stop +``` +Restart Orthanc +```bash +docker compose restart +``` +Delete Orthanc container +```bash +docker compose down +``` \ No newline at end of file From 2657239ee7f4636baa8ee5ab4cc0652dfa117a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Tue, 22 Aug 2023 17:14:15 +0200 Subject: [PATCH 19/45] Feat: add api ref --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 5b4176e3..adc561c6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -31,6 +31,7 @@ nav: - 'Roadmap' : 'releases/roadmap.md' - 'More informations': + - 'Contributing': 'contributing.md' - 'Contacts': 'contacts.md' - 'Citation': 'citation.md' From d767ced46874d5ed44298944e20559b00b3a37a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Tue, 22 Aug 2023 17:18:04 +0200 Subject: [PATCH 20/45] Feat: add api ref --- docs/contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contributing.md b/docs/contributing.md index 3087d48c..92292445 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -9,7 +9,7 @@ You can contribute to this project with the following steps: ``` 3. Enter the project and create a poetry environment - (this project use the [poetry](https://python-poetry.org/) for dependency management) + (this project use the [poetry](https://python-poetry.org/) for dependency management). ```shell cd pyorthanc From e6dc0450882b9603c52e19af0fc822f9eda98153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Thu, 24 Aug 2023 14:58:31 +0200 Subject: [PATCH 21/45] Feat: add citation --- docs/citation.md | 2 -- docs/contributing.md | 1 - 2 files changed, 3 deletions(-) diff --git a/docs/citation.md b/docs/citation.md index 09fa9c69..38e0f85f 100644 --- a/docs/citation.md +++ b/docs/citation.md @@ -1,4 +1,2 @@ - -## Citation If you publish using PyOrthanc, we kindly ask that you credit us. PyOrthanc can be found on Zenodo : [https://zenodo.org/record/7086219](https://zenodo.org/record/7086219). \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md index 92292445..53bf84ba 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -22,7 +22,6 @@ You can contribute to this project with the following steps: ```shell git checkout -b your-branch-name ``` - Now you can make your changes 5. Once done, `git add`, `git commit` and `git push` the changes. From d339a6bab043186ed49fedea666216f93c0d29de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 15:47:53 +0200 Subject: [PATCH 22/45] Feat: update with latest pyorthanc version --- docs/api/{orthanc.md => client.md} | 0 docs/api/find.md | 3 + docs/api/{ => resources}/instance.md | 0 docs/api/{ => resources}/patient.md | 0 docs/api/resources/resource.md | 3 + docs/api/{ => resources}/series.md | 0 docs/api/{ => resources}/study.md | 0 docs/api/retrieve.md | 3 + docs/api/usage.md | 0 docs/citation.md | 2 +- docs/examples/access_informations/README.md | 29 - .../access_patient_information.py | 32 - .../access_informations/docker-compose.yaml | 7 - docs/examples/docker-compose.yaml | 7 - docs/examples/orthanc.json | 948 ------------------ docs/examples/requirements.txt | 1 - docs/releases/release1.11.5.md | 17 - docs/tutorial/quickstart.md | 2 +- 18 files changed, 11 insertions(+), 1043 deletions(-) rename docs/api/{orthanc.md => client.md} (100%) create mode 100644 docs/api/find.md rename docs/api/{ => resources}/instance.md (100%) rename docs/api/{ => resources}/patient.md (100%) create mode 100644 docs/api/resources/resource.md rename docs/api/{ => resources}/series.md (100%) rename docs/api/{ => resources}/study.md (100%) create mode 100644 docs/api/retrieve.md delete mode 100644 docs/api/usage.md delete mode 100644 docs/examples/access_informations/README.md delete mode 100644 docs/examples/access_informations/access_patient_information.py delete mode 100644 docs/examples/access_informations/docker-compose.yaml delete mode 100644 docs/examples/docker-compose.yaml delete mode 100644 docs/examples/orthanc.json delete mode 100644 docs/examples/requirements.txt delete mode 100644 docs/releases/release1.11.5.md diff --git a/docs/api/orthanc.md b/docs/api/client.md similarity index 100% rename from docs/api/orthanc.md rename to docs/api/client.md diff --git a/docs/api/find.md b/docs/api/find.md new file mode 100644 index 00000000..464e2b9c --- /dev/null +++ b/docs/api/find.md @@ -0,0 +1,3 @@ +::: pyorthanc.find + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/instance.md b/docs/api/resources/instance.md similarity index 100% rename from docs/api/instance.md rename to docs/api/resources/instance.md diff --git a/docs/api/patient.md b/docs/api/resources/patient.md similarity index 100% rename from docs/api/patient.md rename to docs/api/resources/patient.md diff --git a/docs/api/resources/resource.md b/docs/api/resources/resource.md new file mode 100644 index 00000000..9f169fe5 --- /dev/null +++ b/docs/api/resources/resource.md @@ -0,0 +1,3 @@ +::: pyorthanc.resources.Resource + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/series.md b/docs/api/resources/series.md similarity index 100% rename from docs/api/series.md rename to docs/api/resources/series.md diff --git a/docs/api/study.md b/docs/api/resources/study.md similarity index 100% rename from docs/api/study.md rename to docs/api/resources/study.md diff --git a/docs/api/retrieve.md b/docs/api/retrieve.md new file mode 100644 index 00000000..4bf65b14 --- /dev/null +++ b/docs/api/retrieve.md @@ -0,0 +1,3 @@ +::: pyorthanc.retrieve + :docstring: + :members: \ No newline at end of file diff --git a/docs/api/usage.md b/docs/api/usage.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/citation.md b/docs/citation.md index 38e0f85f..1c06b46b 100644 --- a/docs/citation.md +++ b/docs/citation.md @@ -1,2 +1,2 @@ If you publish using PyOrthanc, we kindly ask that you credit us. PyOrthanc can be found on Zenodo : -[https://zenodo.org/record/7086219](https://zenodo.org/record/7086219). \ No newline at end of file +[https://doi.org/10.5281/zenodo.3387551](https://doi.org/10.5281/zenodo.3387551). \ No newline at end of file diff --git a/docs/examples/access_informations/README.md b/docs/examples/access_informations/README.md deleted file mode 100644 index d2178a6c..00000000 --- a/docs/examples/access_informations/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Acces to patient-study-series-instance informations - -In this tutorial, you can access to all patients, study, series and instances information. Use it with a small batch of -data in the Orthanc server - -## Get the python file -[access_patient_information.py](./access_patient_information.py) -[docker-compose.yaml](./docker-compose.yaml) - -## Run Orthanc - -To run a local Orthanc with Docker, just run -```bash -docker compose up -d -``` - -The default URL (if running locally) is `http://localhost:8042`. - -## Prepare environment -```bash -python3 -m venv .venv -source .venv/bin/activate -pip install pyorthanc -``` - -## Run PyOrthanc script -```bash -python access_patient_information.py -``` \ No newline at end of file diff --git a/docs/examples/access_informations/access_patient_information.py b/docs/examples/access_informations/access_patient_information.py deleted file mode 100644 index fc7da262..00000000 --- a/docs/examples/access_informations/access_patient_information.py +++ /dev/null @@ -1,32 +0,0 @@ -from pyorthanc import Orthanc - -orthanc = Orthanc('http://localhost:8042', username='orthanc', password='orthanc') - -# To get patients identifier and main information -patients_identifiers = orthanc.get_patients() - -for patient_identifier in patients_identifiers: - # To get patient information - patient_info = orthanc.get_patients_id(patient_identifier) - patient_name = patient_info['MainDicomTags']['PatientName'] - study_identifiers = patient_info['Studies'] - -# To get patient's studies identifier and main information -for study_identifier in study_identifiers: - # To get Study info - study_info = orthanc.get_studies_id(study_identifier) - study_date = study_info['MainDicomTags']['StudyDate'] - series_identifiers = study_info['Series'] - -# To get study's series identifier and main information -for series_identifier in series_identifiers: - series_info = orthanc.get_series_id(series_identifier) - modality = series_info['MainDicomTags']['Modality'] - instance_identifiers = series_info['Instances'] - -# and so on ... -for instance_identifier in instance_identifiers: - instance_info = orthanc.get_instances_id(instance_identifier) - - # Get SOPInstanceUID - print(instance_info['MainDicomTags']['SOPInstanceUID']) diff --git a/docs/examples/access_informations/docker-compose.yaml b/docs/examples/access_informations/docker-compose.yaml deleted file mode 100644 index 78867963..00000000 --- a/docs/examples/access_informations/docker-compose.yaml +++ /dev/null @@ -1,7 +0,0 @@ -version: '3.3' -services: - orthanc: - image: jodogne/orthanc-plugins:1.12.1 - ports: - - 4242:4242 - - 8042:8042 \ No newline at end of file diff --git a/docs/examples/docker-compose.yaml b/docs/examples/docker-compose.yaml deleted file mode 100644 index 78867963..00000000 --- a/docs/examples/docker-compose.yaml +++ /dev/null @@ -1,7 +0,0 @@ -version: '3.3' -services: - orthanc: - image: jodogne/orthanc-plugins:1.12.1 - ports: - - 4242:4242 - - 8042:8042 \ No newline at end of file diff --git a/docs/examples/orthanc.json b/docs/examples/orthanc.json deleted file mode 100644 index ba0d9848..00000000 --- a/docs/examples/orthanc.json +++ /dev/null @@ -1,948 +0,0 @@ -{ - /** - * General configuration of Orthanc - * - * As a general recommendation, you should always favour absolute - * paths when you need to provide a path to a file or a directory. - * This is not done in this configuration file since we don't know - * where Orthanc is going to be installed. - **/ - - // The logical name of this instance of Orthanc. This one is - // displayed in Orthanc Explorer and at the URI "/system". - "Name" : "${ORTHANC_NAME} in Docker Compose", - - // Path to the directory that holds the heavyweight files (i.e. the - // raw DICOM instances). Backslashes must be either escaped by - // doubling them, or replaced by forward slashes "/". - "StorageDirectory" : "/var/lib/orthanc/db", - - // Path to the directory that holds the SQLite index (if unset, the - // value of StorageDirectory is used). This index could be stored on - // a RAM-drive or a SSD device for performance reasons. - "IndexDirectory" : "/var/lib/orthanc/db", - - // Path to the directory where Orthanc stores its large temporary - // files. The content of this folder can be safely deleted once - // Orthanc is stopped. The folder must exist. The corresponding - // filesystem must be properly sized, given that for instance a ZIP - // archive of DICOM images created by a job can weight several GBs, - // and that there might be up to "min(JobsHistorySize, - // MediaArchiveSize)" archives to be stored simultaneously. If not - // set, Orthanc will use the default temporary folder of the - // operating system (such as "/tmp/" on UNIX-like systems, or - // "C:/Temp" on Microsoft Windows). - // "TemporaryDirectory" : "/tmp/Orthanc/", - - // Enable the transparent compression of the DICOM instances - "StorageCompression" : false, - - // Maximum size of the storage in MB (a value of "0" indicates no - // limit on the storage size) - "MaximumStorageSize" : 0, - - // Maximum number of patients that can be stored at a given time - // in the storage (a value of "0" indicates no limit on the number - // of patients) - "MaximumPatientCount" : 0, - - // Action to take when the maximum storage is reached. - // By default, the patients are recycled ("Recycle" mode). - // In "Reject" mode, the sender will receive a 0xA700 DIMSE status code - // if the instance was sent through C-Store, a 507 HTTP status code - // if using the REST API and a 0xA700 Failure reason when using - // DicomWeb Stow-RS - // Allowed values: "Recycle", "Reject" - // (new in Orthanc 1.11.2) - "MaximumStorageMode" : "Recycle", - - // Maximum size of the storage cache in MB. The storage cache - // is stored in RAM and contains a copy of recently accessed - // files (written or read). A value of "0" indicates the cache - // is disabled. (new in Orthanc 1.10.0) - "MaximumStorageCacheSize" : 128, - - // List of paths to the custom Lua scripts that are to be loaded - // into this instance of Orthanc - "LuaScripts" : [ - ], - - // The period (in seconds) between 2 calls of the "OnHeartBeat" - // lua callback. O means the heart beat is disabled. - // TODO: text below for Orthanc book: - // Note: that the period is actually not the delay between - // the end of an execution and the triggering of the next one. - // Since there is only one lua context, if other lua code is being - // executed, the heart beat might be delayed even more. - "LuaHeartBeatPeriod" : 0, - - // List of paths to the plugins that are to be loaded into this - // instance of Orthanc (e.g. "./libPluginTest.so" for Linux, or - // "./PluginTest.dll" for Windows). These paths can refer to - // folders, in which case they will be scanned non-recursively to - // find shared libraries. Backslashes must be either escaped by - // doubling them, or replaced by forward slashes "/". - "Plugins" : [ - "/usr/share/orthanc/plugins", "/usr/local/share/orthanc/plugins" - ], - - // Maximum number of processing jobs that are simultaneously running - // at any given time. A value of "0" indicates to use all the - // available CPU logical cores. To emulate Orthanc <= 1.3.2, set - // this value to "1". - "ConcurrentJobs" : 2, - - // Defines the number of threads that are used to execute each type of - // jobs (for the jobs that can be parallelized). - // A value of "0" indicates to use all the available CPU logical cores. - // (new in Orthanc 1.11.3) - "JobsEngineThreadsCount" : { - "ResourceModification": 1 // for /anonymize, /modify - }, - - /** - * Configuration of the HTTP server - **/ - - // Enable the HTTP server. If this parameter is set to "false", - // Orthanc acts as a pure DICOM server. The REST API and Orthanc - // Explorer will not be available. - "HttpServerEnabled" : true, - - // Enable/disable the Orthanc Explorer Web user interface. This - // option is only meaningful if the "HttpServerEnabled" option is - // set to "true" (new in Orthanc 1.8.2). - "OrthancExplorerEnabled" : true, - - // HTTP port for the REST services and for the GUI - "HttpPort" : 8042, - - // When the following option is "true", if an error is encountered - // while calling the REST API, a JSON message describing the error - // is put in the HTTP answer. This feature can be disabled if the - // HTTP client does not properly handles such answers. - "HttpDescribeErrors" : true, - - // Enable HTTP compression to improve network bandwidth utilization, - // at the expense of more computations on the server. Orthanc - // supports the "gzip" and "deflate" HTTP encodings. - "HttpCompressionEnabled" : true, - - // Enable the publication of the content of the Orthanc server as a - // WebDAV share (new in Orthanc 1.8.0). On the localhost, the WebDAV - // share is mapped as "http://localhost:8042/webdav/". - "WebDavEnabled" : true, - - // Whether to allow deletions through the WebDAV share. This is - // disabled by default to avoid accidental loss of DICOM instances. - "WebDavDeleteAllowed" : false, - - // Whether to allow uploads through the WebDAV share. - "WebDavUploadAllowed" : true, - - - - /** - * Configuration of the DICOM server - **/ - - // Enable the DICOM server. If this parameter is set to "false", - // Orthanc acts as a pure REST server. It will not be possible to - // receive files or to do query/retrieve through the DICOM protocol. - "DicomServerEnabled" : true, - - // The DICOM Application Entity Title (cannot be longer than 16 - // characters) - "DicomAet" : "ORTHANC", - - // Check whether the called AET corresponds to the AET of Orthanc - // during an incoming DICOM SCU request - "DicomCheckCalledAet" : false, - - // The DICOM port - "DicomPort" : 4242, - - // The default encoding that is assumed for DICOM files without - // "SpecificCharacterSet" DICOM tag, and that is used when answering - // C-FIND requests (including worklists). The allowed values are - // "Ascii", "Utf8", "Latin1", "Latin2", "Latin3", "Latin4", - // "Latin5", "Cyrillic", "Windows1251", "Arabic", "Greek", "Hebrew", - // "Thai", "Japanese", "Chinese", "JapaneseKanji", "Korean", and - // "SimplifiedChinese". - "DefaultEncoding" : "Latin1", - - // The transfer syntaxes that are accepted by Orthanc C-STORE SCP. - // This is an array listing the accepted transfer syntax UIDs. Each - // entry can contain wildcards ("?" or "*"). By default, all the - // known transfer syntaxes are accepted. (new in Orthanc 1.9.0) - "AcceptedTransferSyntaxes" : [ "1.2.840.10008.1.*" ], - - // User-friendly groups of transfer syntaxes that can be enabled or - // disabled at once. These options are applied after the main - // "AcceptedTransferSyntaxes" option has been applied (if present). - /** - "DeflatedTransferSyntaxAccepted" : true, - "JpegTransferSyntaxAccepted" : true, - "Jpeg2000TransferSyntaxAccepted" : true, - "JpegLosslessTransferSyntaxAccepted" : true, - "JpipTransferSyntaxAccepted" : true, - "Mpeg2TransferSyntaxAccepted" : true, - "RleTransferSyntaxAccepted" : true, - "Mpeg4TransferSyntaxAccepted" : true, // New in Orthanc 1.6.0 - "H265TransferSyntaxAccepted" : true, // New in Orthanc 1.9.0 - **/ - - // Whether Orthanc accepts to act as C-STORE SCP for unknown storage - // SOP classes (aka. "promiscuous mode") - "UnknownSopClassAccepted" : false, - - // Set the timeout (in seconds) after which the DICOM associations - // are closed by the Orthanc SCP (server) if no further DIMSE - // command is received from the SCU (client). - "DicomScpTimeout" : 30, - - - - /** - * Security-related options for the HTTP server - **/ - - // Whether remote hosts can connect to the HTTP server - "RemoteAccessAllowed" : true, - - // Whether or not SSL is enabled - "SslEnabled" : false, - - // Path to the SSL certificate used by the HTTP server. The file - // must be stored in the PEM format, and must contain both the - // certificate and the private key. This option is only meaningful - // if "SslEnabled" is true. - "SslCertificate" : "certificate.pem", - - // Sets the minimum accepted SSL protocol version - // (cf. "ssl_protocol_version" option of civetweb). By default, - // require SSL 1.2. This option is only meaningful if "SslEnabled" - // is true. (new in Orthanc 1.8.2) - // - // Value => Protocols - // 0 SSL2+SSL3+TLS1.0+TLS1.1+TLS1.2 - // 1 SSL3+TLS1.0+TLS1.1+TLS1.2 - // 2 TLS1.0+TLS1.1+TLS1.2 - // 3 TLS1.1+TLS1.2 - // 4 TLS1.2 - "SslMinimumProtocolVersion" : 4, - - // Set the accepted ciphers for SSL connections. The ciphers must be - // provided as a list of strings. If not set, this will default to - // FIPS 140-2 ciphers. This option is only meaningful if - // "SslEnabled" is true. (new in Orthanc 1.8.2) - /** - "SslCiphersAccepted" : [ "AES128-GCM-SHA256" ], - **/ - - // Whether or not peer client certificates shall be checked. This - // option is only meaningful if "SslEnabled" is true. - "SslVerifyPeers" : false, - - // Path to a file containing the concatenation of the client SSL - // certificate(s) that are trusted to verify the identify of remote - // HTTP clients. The individual certificate(s) must be stored in the - // PEM format. This option is only meaningful if "SslVerifyPeers" - // is true. - "SslTrustedClientCertificates" : "trustedClientCertificates.pem", - - // Whether or not the password protection is enabled (using HTTP - // basic access authentication). Starting with Orthanc 1.5.8, if - // "AuthenticationEnabled" is not explicitly set, authentication is - // enabled iff. remote access is allowed (i.e. the default value of - // "AuthenticationEnabled" equals that of "RemoteAccessAllowed"). - /** - "AuthenticationEnabled" : true, - **/ - - // The list of the registered users. Because Orthanc uses HTTP - // Basic Authentication, the passwords are stored as plain text. - //"RegisteredUsers" : { - // "alice" : "alicePassword" - //}, - - - - /** - * Security-related options for the DICOM connections (SCU/SCP) - **/ - - // Whether DICOM TLS is enabled in the Orthanc SCP (new in Orthanc 1.9.0) - "DicomTlsEnabled" : false, - - // Path to the TLS certificate file (in PEM format) to be used for - // both Orthanc SCP (incoming DICOM connections) and Orthanc SCU - // (outgoing DICOM connections). Note that contrarily to the - // "SslCertificate" option, the certificate and its private key must - // be split into two separate files. (new in Orthanc 1.9.0) - /** - "DicomTlsCertificate" : "orthanc.crt", - **/ - - // Path to the file containing the private key (in PEM format) that - // corresponds to the TLS certificate specified in option - // "DicomTlsCertificate". (new in Orthanc 1.9.0) - /** - "DicomTlsPrivateKey" : "orthanc.key", - **/ - - // Path to a file containing all the TLS certificates that Orthanc - // can trust, both for its SCP (incoming DICOM connections) and SCU - // (outgoing DICOM connections). This file must contain a sequence - // of PEM certificates. (new in Orthanc 1.9.0) - /** - "DicomTlsTrustedCertificates" : "trusted.crt", - **/ - - // Whether Orthanc rejects DICOM TLS connections to/from remote - // modalities that do not provide a certificate. Setting this option - // to "true" (resp. "false") corresponds to "--require-peer-cert" - // (resp. "--verify-peer-cert") in the DCMTK command-line - // tools. (new in Orthanc 1.9.3) - "DicomTlsRemoteCertificateRequired" : true, - - // Whether the Orthanc SCP allows incoming C-ECHO requests, even - // from SCU modalities it does not know about (i.e. that are not - // listed in the "DicomModalities" option above). Orthanc 1.3.0 - // is the only version to behave as if this argument were set to "false". - "DicomAlwaysAllowEcho" : true, - - // Whether the Orthanc SCP allows incoming C-STORE requests, even - // from SCU modalities it does not know about (i.e. that are not - // listed in the "DicomModalities" option above) - "DicomAlwaysAllowStore" : true, - - // Whether the Orthanc SCP allows incoming C-FIND requests, even - // from SCU modalities it does not know about (i.e. that are not - // listed in the "DicomModalities" option above). Setting this - // option to "true" implies security risks. (new in Orthanc 1.9.0) - // Note: From Orthanc 1.10.0, this option only applies to C-FIND - // requests for patients/studies/series/instances. Use option - // "DicomAlwaysAllowFindWorklist" for worklists. - "DicomAlwaysAllowFind" : false, - - // Whether the Orthanc SCP allows incoming C-FIND requests for worklists, - // even from SCU modalities it does not know about (i.e. that are not - // listed in the "DicomModalities" option above). Setting this - // option to "true" implies security risks. (new in Orthanc 1.10.0) - "DicomAlwaysAllowFindWorklist" : false, - - // Whether the Orthanc SCP allows incoming C-GET requests, even - // from SCU modalities it does not know about (i.e. that are not - // listed in the "DicomModalities" option above). Setting this - // option to "true" implies security risks. (new in Orthanc 1.9.0) - "DicomAlwaysAllowGet" : false, - - // Whether the Orthanc SCP allows incoming C-MOVE requests, even - // from SCU modalities it does not know about (i.e. that are not - // listed in the "DicomModalities" option above). Setting this - // option to "true" implies security risks. (new in Orthanc 1.9.7) - "DicomAlwaysAllowMove" : false, - - // Whether Orthanc checks the IP/hostname address of the remote - // modality initiating a DICOM connection (as listed in the - // "DicomModalities" option above). If this option is set to - // "false", Orthanc only checks the AET of the remote modality. - "DicomCheckModalityHost" : false, - - - - /** - * Network topology - **/ - - // The list of the known DICOM modalities. This option is ignored if - // "DicomModalitiesInDatabase" is set to "true", in which case you - // must use the REST API to define modalities. - "DicomModalities" : { - /** - * Uncommenting the following line would enable Orthanc to - * connect to an instance of the "storescp" open-source DICOM - * store (shipped in the DCMTK distribution), as started by the - * command line "storescp 2000". The first parameter is the - * AET of the remote modality (cannot be longer than 16 - * characters), the second one is the remote network address, - * and the third one is the TCP port number corresponding - * to the DICOM protocol on the remote modality (usually 104). - **/ - // "sample" : [ "STORESCP", "127.0.0.1", 2000 ] - - /** - * A fourth parameter is available to enable patches for - * specific PACS manufacturers. The allowed values are currently: - * - "Generic" (default value), - * - "GenericNoWildcardInDates" (to replace "*" by "" in date fields - * in outgoing C-FIND requests originating from Orthanc), - * - "GenericNoUniversalWildcard" (to replace "*" by "" in all fields - * in outgoing C-FIND SCU requests originating from Orthanc), - * - "Vitrea", - * - "GE" (Enterprise Archive, MRI consoles and Advantage Workstation - * from GE Healthcare). - * - * This parameter is case-sensitive. - **/ - // "vitrea" : [ "VITREA", "192.168.1.1", 104, "Vitrea" ] - - /** - * By default, the Orthanc SCP accepts all DICOM commands (C-ECHO, - * C-STORE, C-FIND, C-MOVE, C-GET and storage commitment) issued by the - * registered remote SCU modalities. Starting with Orthanc 1.5.0, - * it is possible to specify which DICOM commands are allowed, - * separately for each remote modality, using the syntax - * below. - * - * The "AllowEcho" (resp. "AllowStore") option only has an effect - * respectively if global option "DicomAlwaysAllowEcho" - * (resp. "DicomAlwaysAllowStore") is set to "false". - * - * Starting with Orthanc 1.7.0, "AllowTranscoding" can be used to - * disable the transcoding to uncompressed transfer syntaxes if - * this remote modality doesn't support compressed transfer - * syntaxes. This option currently applies to Orthanc C-GET SCP - * and to Orthanc C-STORE SCU. This option only has an effect if - * the global option "EnableTranscoding" is set to "true". - * - * By default, all "Allow*" options are true. - * "AllowStorageCommitment" is actually an alias for - * "AllowNAction" & "AllowEventReport". - * - * The "UseDicomTls" option specifies whether DICOM TLS should be - * used when opening a SCU connection from Orthanc to this remote - * modality. By default, DICOM TLS is not enabled. - * - * The "LocalAet" option allows one to overwrite the global - * "DicomAet" configuration option in order to specify another AET - * for Orthanc when initiating an SCU to this very specific - * modality. Similarly, "Timeout" allows one to overwrite the - * global value "DicomScuTimeout" on a per-modality basis. - **/ - //"untrusted" : { - // "AET" : "ORTHANC", - // "Port" : 104, - // "Host" : "127.0.0.1", - // "Manufacturer" : "Generic", - // "AllowEcho" : false, - // "AllowFind" : false, - // "AllowFindWorklist" : false, // new in 1.10.0 - // "AllowGet" : false, - // "AllowMove" : false, - // "AllowStore" : true, - // "AllowStorageCommitment" : false, // new in 1.6.0 - // "AllowTranscoding" : true, // new in 1.7.0 - // "UseDicomTls" : false, // new in 1.9.0 - // "LocalAet" : "HELLO", // new in 1.9.0 - // "Timeout" : 60 // new in 1.9.1 - //} - }, - - // Whether to store the DICOM modalities in the Orthanc database - // instead of in this configuration file (new in Orthanc 1.5.0) - "DicomModalitiesInDatabase" : false, - - // Whether the C-ECHO SCU is automatically followed by a C-FIND SCU, - // while testing the connectivity from Orthanc to a remote DICOM - // modality. This allows one to check that the remote modality does - // accept C-FIND requests from Orthanc (new in Orthanc 1.8.1). - "DicomEchoChecksFind" : false, - - // The timeout (in seconds) after which the DICOM associations are - // considered as closed by the Orthanc SCU (client) if the remote - // DICOM SCP (server) does not answer. - "DicomScuTimeout" : 10, - - // During a C-STORE SCU request initiated by Orthanc, if the remote - // modality doesn't support the original transfer syntax of some - // DICOM instance, specify which transfer syntax should be preferred - // to transcode this instance (provided the remote modality accepts - // this syntax). In Orthanc between 1.7.0 and 1.8.2, this parameter - // was implicitly set to "Little Endian Implicit" - // (1.2.840.10008.1.2). In Orthanc <= 1.6.1 and in Orthanc >= 1.9.0, - // this parameter is by default set to "Little Endian Explicit" - // (1.2.840.10008.1.2.1). This parameter can possibly correspond to - // a compressed transfer syntax. (new in Orthanc 1.9.0) - "DicomScuPreferredTransferSyntax" : "1.2.840.10008.1.2.1", - - // Number of threads that are used by the embedded DICOM server. - // This defines the number of concurrent DICOM operations that can - // be run. Note: This is not limiting the number of concurrent - // connections. With a single thread, if a C-Find is received during - // e.g the transcoding of an incoming C-Store, it will have to wait - // until the end of the C-Store before being processed. (new in - // Orthanc 1.10.0, before this version, the value was fixed to 4) - "DicomThreadsCount" : 4, - - // The list of the known Orthanc peers. This option is ignored if - // "OrthancPeersInDatabase" is set to "true", in which case you must - // use the REST API to define Orthanc peers. - "OrthancPeers" : { - /** - * Each line gives the base URL of an Orthanc peer, possibly - * followed by the username/password pair (if the password - * protection is enabled on the peer). - **/ - // "peer" : [ "http://127.0.0.1:8043/", "alice", "alicePassword" ] - // "peer2" : [ "http://127.0.0.1:8044/" ] - - /** - * This is another, more advanced format to define Orthanc - * peers. It notably allows one to specify HTTP headers, a HTTPS - * client certificate in the PEM format (as in the "--cert" option - * of curl), or to enable PKCS#11 authentication for smart cards. - * - * The "Timeout" option allows one to overwrite the global value - * "HttpTimeout" on a per-peer basis. - **/ - // "peer" : { - // "Url" : "http://127.0.0.1:8043/", - // "Username" : "alice", - // "Password" : "alicePassword", - // "HttpHeaders" : { "Token" : "Hello world" }, - // "CertificateFile" : "client.crt", - // "CertificateKeyFile" : "client.key", - // "CertificateKeyPassword" : "certpass", - // "Pkcs11" : false, - // "Timeout" : 42 // New in Orthanc 1.9.1 - // } - }, - - // Whether to store the Orthanc peers in the Orthanc database - // instead of in this configuration file (new in Orthanc 1.5.0) - "OrthancPeersInDatabase" : false, - - // Parameters of the HTTP proxy to be used by Orthanc. If set to the - // empty string, no HTTP proxy is used. For instance: - // "HttpProxy" : "192.168.0.1:3128" - // "HttpProxy" : "proxyUser:proxyPassword@192.168.0.1:3128" - "HttpProxy" : "", - - // If set to "true", debug messages from libcurl will be issued - // whenever Orthanc makes an outgoing HTTP request. This is notably - // useful to debug HTTPS-related problems. - "HttpVerbose" : false, - - // Set the timeout for HTTP requests issued by Orthanc (in seconds). - "HttpTimeout" : 60, - - // Enable the verification of the peers during HTTPS requests. This - // option must be set to "false" if using self-signed certificates. - // Pay attention that setting this option to "false" results in - // security risks! - // Reference: http://curl.haxx.se/docs/sslcerts.html - "HttpsVerifyPeers" : true, - - // Path to the CA (certification authority) certificates to validate - // peers in HTTPS requests. From curl documentation ("--cacert" - // option): "Tells curl to use the specified certificate file to - // verify the peers. The file may contain multiple CA - // certificates. The certificate(s) must be in PEM format." On - // Debian-based systems, this option can be set to - // "/etc/ssl/certs/ca-certificates.crt" - "HttpsCACertificates" : "/etc/ssl/certs/ca-certificates.crt", - - - - /** - * Advanced options - **/ - - // Dictionary of symbolic names for the user-defined metadata. Each - // entry must map an unique string to an unique number between 1024 - // and 65535. Reserved values: - // - The Orthanc whole-slide imaging plugin uses metadata 4200 - "UserMetadata" : { - // "Sample" : 1024 - }, - - // Dictionary of symbolic names for the user-defined types of - // attached files. Each entry must map an unique string to an unique - // number between 1024 and 65535. Optionally, a second argument can - // provided to specify a MIME content type for the attachment. - "UserContentType" : { - // "sample" : 1024 - // "sample2" : [ 1025, "application/pdf" ] - }, - - // Number of seconds without receiving any instance before a - // patient, a study or a series is considered as stable. - "StableAge" : 60, - - // By default, Orthanc compares AET (Application Entity Titles) in a - // case-insensitive way. Setting this option to "true" will enable - // case-sensitive matching. - "StrictAetComparison" : false, - - // When the following option is "true", the MD5 of the DICOM files - // will be computed and stored in the Orthanc database. This - // information can be used to detect disk corruption, at the price - // of a small performance overhead. - "StoreMD5ForAttachments" : true, - - // The maximum number of results for a single C-FIND request at the - // Patient, Study or Series level. Setting this option to "0" means - // no limit. - "LimitFindResults" : 0, - - // The maximum number of results for a single C-FIND request at the - // Instance level. Setting this option to "0" means no limit. - "LimitFindInstances" : 0, - - // If this option is set to "true" (default behavior until Orthanc - // 1.3.2), Orthanc will log the resources that are exported to other - // DICOM modalities or Orthanc peers, inside the URI - // "/exports". Setting this option to "false" is useful to prevent - // the index to grow indefinitely in auto-routing tasks (this is the - // default behavior since Orthanc 1.4.0). - "LogExportedResources" : false, - - // Enable or disable HTTP Keep-Alive (persistent HTTP - // connections). Setting this option to "true" prevents Orthanc - // issue #32 ("HttpServer does not support multiple HTTP requests in - // the same TCP stream"), but can possibly slow down HTTP clients - // that do not support persistent connections. The default behavior - // used to be "false" in Orthanc <= 1.5.1. Setting this option to - // "false" is also recommended if Orthanc is compiled against - // Mongoose. - "KeepAlive" : true, - - // Defines the Keep-Alive timeout in seconds. - // (new in Orthanc 1.11.3) - "KeepAliveTimeout" : 1, - - // Enable or disable Nagle's algorithm. Only taken into - // consideration if Orthanc is compiled to use CivetWeb. Experiments - // show that best performance can be obtained by setting both - // "KeepAlive" and "TcpNoDelay" to "true". Beware however of - // caveats: https://eklitzke.org/the-caveats-of-tcp-nodelay - "TcpNoDelay" : true, - - // Number of threads that are used by the embedded HTTP server. - "HttpThreadsCount" : 50, - - // If this option is set to "false", Orthanc will run in index-only - // mode. The DICOM files will not be stored on the drive: Orthanc - // only indexes the small subset of the so-called "main DICOM tags" - // in its SQL database. Note that this option might prevent the - // upgrade to newer versions of Orthanc. Also note that this - // behavior might not be available with the storage area plugins. - "StoreDicom" : true, - - // DICOM associations initiated by Lua scripts are kept open as long - // as new DICOM commands are issued. This option sets the number of - // seconds of inactivity to wait before automatically closing a - // DICOM association used by Lua. If set to 0, the connection is - // closed immediately. This option is only used in Lua scripts. - "DicomAssociationCloseDelay" : 5, - - // Maximum number of query/retrieve DICOM requests that are - // maintained by Orthanc. The least recently used requests get - // deleted as new requests are issued. - "QueryRetrieveSize" : 100, - - // When handling a C-FIND SCP request, setting this flag to "true" - // will enable case-sensitive match for PN value representation - // (such as PatientName). By default, the search is - // case-insensitive, which does not follow the DICOM standard. - "CaseSensitivePN" : false, - - // Configure PKCS#11 to use hardware security modules (HSM) and - // smart cards when carrying on HTTPS client authentication. - /** - "Pkcs11" : { - "Module" : "/usr/local/lib/libbeidpkcs11.so", - "Module" : "C:/Windows/System32/beidpkcs11.dll", - "Pin" : "1234", - "Verbose" : true - } - **/ - - // If set to "false", Orthanc will not load its default dictionary - // of private tags. This might be necessary if you cannot import a - // DICOM file encoded using the Implicit VR Endian transfer syntax, - // and containing private tags: Such an import error might stem from - // a bad dictionary. You can still list your private tags of - // interest in the "Dictionary" configuration option below. - "LoadPrivateDictionary" : true, - - // Locale to be used by Orthanc. Currently, only used if comparing - // strings in a case-insensitive way. It should be safe to keep this - // value undefined, which lets Orthanc autodetect the suitable locale. - // "Locale" : "en_US.UTF-8", - - // Register a new tag in the dictionary of DICOM tags that are known - // to Orthanc. Each line must contain the tag (formatted as 2 - // hexadecimal numbers), the value representation (2 upcase - // characters), a nickname for the tag, possibly the minimum - // multiplicity (> 0 with defaults to 1), possibly the maximum - // multiplicity (0 means arbitrary multiplicity, defaults to 1), and - // possibly the Private Creator (for private tags). - // Note: For private tags, you should only declare the lower 8 bits - // of the element since the higher 8 bits may vary from one file to - // the other. - "Dictionary" : { - // "0014,1020" : [ "DA", "ValidationExpiryDate", 1, 1 ] - // "00e1,c2" : [ "UI", "PET-CT Multi Modality Name", 1, 1, "ELSCINT1" ] - // "7053,03" : [ "ST", "Original Image Filename", 1, 1, "Philips PET Private Group" ] - // "2001,5f" : [ "SQ", "StackSequence", 1, 1, "Philips Imaging DD 001" ] - }, - - // Load a set of external DICOM dictionaries in order to replace the - // default dictionaries. This option must contain a set of files in - // the DCMTK format. The order of the dictionaries *is* - // important. This option can be used to turn Orthanc into a DICONDE - // server. (new in Orthanc 1.9.4) - /** - "ExternalDictionaries" : [ - "/usr/share/libdcmtk12/dicom.dic", - "/usr/share/libdcmtk12/diconde.dic" - ] - **/ - - // Whether to run DICOM C-MOVE operations synchronously. If set to - // "false" (asynchronous mode), each incoming C-MOVE request results - // in the creation of a new background job. Up to Orthanc 1.3.2, the - // implicit behavior was to use synchronous C-MOVE ("true"). Between - // Orthanc 1.4.0 and 1.4.2, the default behavior was set to - // asynchronous C-MOVE ("false"). Since Orthanc 1.5.0, the default - // behavior is back to synchronous C-MOVE ("true", which ensures - // backward compatibility with Orthanc <= 1.3.2). - "SynchronousCMove" : true, - - // Maximum number of completed jobs that are kept in memory. A - // processing job is considered as complete once it is tagged as - // "Success" or "Failure". Since Orthanc 1.5.0, a value of "0" - // indicates to keep no job in memory (i.e. jobs are removed from - // the history as soon as they are completed), which prevents the - // use of some features of Orthanc (typically, synchronous mode in - // REST API) and should be avoided for non-developers. - "JobsHistorySize" : 10, - - // Whether to save the jobs into the Orthanc database. If this - // option is set to "true", the pending/running/completed jobs are - // automatically reloaded from the database if Orthanc is stopped - // then restarted (except if the "--no-jobs" command-line argument - // is specified). This option should be set to "false" if multiple - // Orthanc servers are using the same database (e.g. if PostgreSQL - // or MariaDB/MySQL is used). - "SaveJobs" : true, - - // Specifies how Orthanc reacts when it receives a DICOM instance - // whose SOPInstanceUID is already stored. If set to "true", the new - // instance replaces the old one. If set to "false", the new - // instance is discarded and the old one is kept. Up to Orthanc - // 1.4.1, the implicit behavior corresponded to "false". - "OverwriteInstances" : false, - - // Maximum number of ZIP/media archives that are maintained by - // Orthanc, as a response to the asynchronous creation of archives. - // The least recently used archives get deleted as new archives are - // generated. This option was introduced in Orthanc 1.5.0, and has - // no effect on the synchronous generation of archives. - "MediaArchiveSize" : 1, - - // Performance setting to specify how Orthanc accesses the storage - // area during find operations (C-FIND, /tools/find API route and - // QIDO-RS in dicom-web). Three modes are available: (1) "Always" - // allows Orthanc to read the storage area as soon as it needs an - // information that is not present in its database (slowest mode), - // (2) "Never" prevents Orthanc from accessing the storage area, and - // makes it uses exclusively its database (fastest mode), and (3) - // "Answers" allows Orthanc to read the storage area to generate its - // answers, but not to filter the DICOM resources (balance between - // the two modes). By default, the mode is "Always", which - // corresponds to the behavior of Orthanc <= 1.5.0. - "StorageAccessOnFind" : "Always", - - // Whether Orthanc monitors its metrics (new in Orthanc 1.5.4). If - // set to "true", the metrics can be retrieved at - // "/tools/metrics-prometheus" formetted using the Prometheus - // text-based exposition format. - "MetricsEnabled" : true, - - // Whether calls to URI "/tools/execute-script" is enabled. Starting - // with Orthanc 1.5.8, this URI is disabled by default for security. - "ExecuteLuaEnabled" : false, - - // Whether the REST API can write to the filesystem (e.g. in - // /instances/../export route). Starting with Orthanc 1.12.0, - // this URI is disabled by default for security. - "RestApiWriteToFileSystemEnabled": false, - - // Set the timeout while serving HTTP requests by the embedded Web - // server, in seconds. This corresponds to option - // "request_timeout_ms" of Mongoose/Civetweb. It will set the socket - // options "SO_RCVTIMEO" and "SO_SNDTIMEO" to the specified value. - "HttpRequestTimeout" : 30, - - // Set the default private creator that is used by Orthanc when it - // looks for a private tag in its dictionary (cf. "Dictionary" - // option), or when it creates/modifies a DICOM file (new in Orthanc 1.6.0). - "DefaultPrivateCreator" : "", - - // Maximum number of storage commitment reports (i.e. received from - // remote modalities) to be kept in memory (new in Orthanc 1.6.0). - "StorageCommitmentReportsSize" : 100, - - // Whether Orthanc transcodes DICOM files to an uncompressed - // transfer syntax over the DICOM protocol, if the remote modality - // does not support compressed transfer syntaxes (new in Orthanc 1.7.0). - "TranscodeDicomProtocol" : true, - - // If some plugin to decode/transcode DICOM instances is installed, - // this option specifies whether the built-in decoder/transcoder of - // Orthanc (that uses DCMTK) is applied before or after the plugins, - // or is not applied at all (new in Orthanc 1.7.0). The allowed - // values for this option are "After" (default value, corresponding - // to the behavior of Orthanc <= 1.6.1), "Before", or "Disabled". - "BuiltinDecoderTranscoderOrder" : "After", - - // If this option is set, Orthanc will transparently transcode any - // incoming DICOM instance to the given transfer syntax before - // storing it into its database. Beware that this might result in - // high CPU usage (if transcoding to some compressed transfer - // syntax), or in higher disk consumption (if transcoding to an - // uncompressed syntax). Also, beware that transcoding to a transfer - // syntax with lossy compression (notably JPEG) will change the - // "SOPInstanceUID" DICOM tag, and thus the Orthanc identifier at - // the instance level, which might break external workflow. - /** - "IngestTranscoding" : "1.2.840.10008.1.2", - **/ - - // Whether ingest transcoding is applied to incoming DICOM instances - // that have an uncompressed transfer syntax, i.e. Little Endian - // Implicit, Little Endian Explicit or Big Endian Explicit (new in - // Orthanc 1.8.2). - "IngestTranscodingOfUncompressed" : true, - - // Whether ingest transcoding is applied to incoming DICOM instances - // that have a compressed transfer syntax (new in Orthanc 1.8.2). - "IngestTranscodingOfCompressed" : true, - - // The compression level that is used when transcoding to one of the - // lossy/JPEG transfer syntaxes (integer between 1 and 100). - "DicomLossyTranscodingQuality" : 90, - - // Whether "fsync()" is called after each write to the storage area - // (new in Orthanc 1.7.4). If this option is set to "true", Orthanc - // will run more slowly, but the DICOM are guaranteed to be - // immediately written to the disk. This option only makes sense if - // the builtin filesystem storage area is used. It defaults to - // "false" in Orthanc <= 1.7.3, and to "true" in Orthanc >= 1.7.4. - "SyncStorageArea" : true, - - // If specified, on compatible systems, call "mallopt(M_ARENA_MAX, - // ...)" while starting Orthanc. This has the same effect at setting - // the environment variable "MALLOC_ARENA_MAX". This avoids large - // growth in RES memory if the threads of the embedded HTTP server - // have to allocate large chunks of memory (typically the case with - // large DICOM files). By setting "MallocArenaMax" to "N", these - // threads share "N" memory pools (known as "arenas"). Setting this - // option to "0" doesn't call mallopt()", which was the behavior of - // Orthanc <= 1.8.1. - "MallocArenaMax" : 5, - - // Deidentify/anonymize the contents of the logs (notably C-FIND, - // C-GET, and C-MOVE queries submitted to Orthanc) according to - // Table E.1-1 of the DICOM standard (new in Orthanc 1.8.2) - "DeidentifyLogs" : true, - - // If "DeidentifyLogs" is true, this sets the DICOM standard to - // follow for the deidentification/anonymization of the query - // contents. Possible values are "2008", "2017c", "2021b" (new - // in Orthanc 1.8.2), and "2023b" (new in Orthanc 1.12.1) - "DeidentifyLogsDicomVersion" : "2023b", - - // Maximum length of the PDU (Protocol Data Unit) in the DICOM - // network protocol, expressed in bytes. This value affects both - // Orthanc SCU and Orthanc SCP. It defaults to 16KB. The allowed - // range is [4096,131072]. (new in Orthanc 1.9.0) - "MaximumPduLength" : 16384, - - // Arbitrary identifier of this Orthanc server when storing its - // global properties if a custom index plugin is used. This - // identifier is only useful in the case of multiple - // readers/writers, in order to avoid collisions between multiple - // Orthanc servers. If unset, this identifier is taken as a SHA-1 - // hash derived from the MAC addresses of the network interfaces, - // and from the AET and TCP ports used by Orthanc. Manually setting - // this option is needed in Docker/Kubernetes environments. (new in - // Orthanc 1.9.2) - /** - "DatabaseServerIdentifier" : "Orthanc1", - **/ - - // Whether Orthanc protects the modification of metadata and - // attachments using revisions, which is done using the HTTP headers - // "ETag", "If-Match" and "If-None-Match" in the calls to the REST - // API. This is needed to handle collisions between concurrent - // modifications in the case of multiple writers. The database - // back-end must support this option, which is notably *not* yet the - // case of the built-in SQLite index. (new in Orthanc 1.9.2) - "CheckRevisions" : false, - - // Whether Orthanc streams ZIP archive/media to the HTTP - // client. Setting this option to "false" corresponds to the - // behavior of Orthanc <= 1.9.3: The ZIP is first entirely written - // to a temporary file, then sent to the client (which necessitates - // disk space and might lead to HTTP timeouts on large archives). If - // set to "true", the chunks of the ZIP file are progressively sent - // as soon as one DICOM file gets compressed (new in Orthanc 1.9.4) - "SynchronousZipStream" : true, - - // Default number of loader threads when generating Zip archive/media. - // A value of 0 means reading and writing are performed in sequence - // (default behaviour). A value > 1 is meaningful only if the storage - // is a distributed network storage (e.g object storage plugin). - // (new experimental feature in Orthanc 1.10.0) - "ZipLoaderThreads": 0, - - // Extra Main Dicom tags that are stored in DB together with all default - // Main Dicom tags that are already stored. - // see https://book.orthanc-server.com/faq/main-dicom-tags.html - // (new in Orthanc 1.11.0) - // Sequences tags are not supported. - /** - "ExtraMainDicomTags" : { - "Instance" : [ - "Rows", - "Columns", - "ImageType", - "SOPClassUID", - "ContentDate", - "ContentTime", - "FrameOfReferenceUID", - "PixelSpacing", - "SpecificCharacterSet", - "BitsAllocated" - ], - "Series" : [], - "Study": [], - "Patient": [] - }, - */ - - // Enables/disables warnings in the logs. - // "true" enables a warning. All warnings are enabled by default - // see https://book.orthanc-server.com/faq/main-dicom-tags.html#warnings - // (new in Orthanc 1.11.0) - "Warnings" : { - // A "RequestedTags" has been read from storage which is slower than - // reading it from DB. - // You might want to store this tag in ExtraMainDicomTags to build - // the response faster. - "W001_TagsBeingReadFromStorage": true, - - // Retrieving a list of Main dicom tags from a resource that has been - // saved with another "ExtraMainDicomTags" configuration which means that - // your response might be incomplete/inconsistent. - // You should call patients|studies|series|instances/../reconstruct to rebuild - // the DB. You may also check for the "Housekeeper" plugin - "W002_InconsistentDicomTagsInDb": true - } - -} diff --git a/docs/examples/requirements.txt b/docs/examples/requirements.txt deleted file mode 100644 index 02a5c6fa..00000000 --- a/docs/examples/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pyorthanc==1.11.5 \ No newline at end of file diff --git a/docs/releases/release1.11.5.md b/docs/releases/release1.11.5.md deleted file mode 100644 index 7a468d01..00000000 --- a/docs/releases/release1.11.5.md +++ /dev/null @@ -1,17 +0,0 @@ - -### Release 1.11.5 - -PyOrthanc v1.11.5 follow Orthanc version 1.11.3. - -This release mostly improves the `find()` function. It now takes an `Orthanc` object rather than an URL. This allows better control of the configuration for the connection to the Orthanc server. - -For example: -```python -from pyorthanc import Orthanc, find - -orthanc = Orthanc(url='http://localhost:8042/', username='username', password='password') -patients = find( - orthanc=orthanc, - series_filter=lambda s: s.modality == 'RTDOSE' # Optional: filter with pyorthanc.Series object -) -``` diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index bc336cf0..679d8ddd 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -2,7 +2,7 @@ ## Requirements -- [x] Python3.10 +- [x] Python3.8 ## Installation From f8f34a5e911deedbe125fefd376bcbf3aea2597e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 15:48:06 +0200 Subject: [PATCH 23/45] Feat: update with latest pyorthanc version --- mkdocs.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index adc561c6..835a09ee 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -15,12 +15,14 @@ nav: - 'Quick Start': 'tutorial/quickstart.md' - 'Advanced Usage': 'tutorial/advanced.md' - 'Api Reference': - 'Orthanc': 'api/orthanc.md' + 'Orthanc': 'api/client.md' 'Asynchronous Orthanc': 'api/async_client.md' - 'Patient': 'api/patient.md' - 'Study': 'api/study.md' - 'Series': 'api/series.md' - 'Instance': 'api/instance.md' + 'Resource': 'api/resources/resource.md' + 'Patient': 'api/resources/patient.md' + 'Study': 'api/resources/study.md' + 'Series': 'api/resources/series.md' + 'Instance': 'api/resources/instance.md' + 'Find': 'api/find.md' 'Filtering': 'api/filtering.md' 'Remote': 'api/remote.md' 'Util': 'api/util.md' @@ -28,7 +30,7 @@ nav: - 'Releases & Roadmap': - 'Releases': 'releases/releases.md' - - 'Roadmap' : 'releases/roadmap.md' + - 'More informations': - 'Contributing': 'contributing.md' From cea5f819fc498c0d9fe4de25b1c6cc900a2f46a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 15:54:28 +0200 Subject: [PATCH 24/45] Feat: Add 1st example --- docs/tutorial/quickstart.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 679d8ddd..9f5a5ce8 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -59,7 +59,7 @@ Here is a list of examples to helps you getting started with pyorthanc | code | |-----------------------------------------------------------------------------------------------------------------| -| [Access instance informations](https://github.com/ylemarechal/pyorthanc/tree/main/examples/access_informations) | +| [Access instance informations](https://github.com/ylemarechal/pyorthanc-examples/tree/main/basic/access_informations) | ## Some useful commands From f34bb930a4d9ee066e35f2c6fd96f221d47ed173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 20:32:19 +0200 Subject: [PATCH 25/45] Feat: Add retrieve patient example --- docs/tutorial/quickstart.md | 59 ++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 9f5a5ce8..a11ca379 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -27,7 +27,6 @@ orthanc = Orthanc(url='http://localhost:8042/', password='password') ``` - ### Upload DICOM files to Orthanc: ```python @@ -51,6 +50,64 @@ orthanc = Orthanc(url='http://localhost:8042/', orthanc.get_modalities() ``` +### Find and download patients according to criteria: + +```python +from pyorthanc import Orthanc, find_patients, retrieve_and_write_patients + +orthanc = Orthanc(url='https://demo.orthanc-server.com', username='', password='') + +patients = find_patients( + client=orthanc, + query={'PatientName': 'COMUNIX'} # Optional: filter with pyorthanc.Series object +) +retrieve_and_write_patients(patients, '.') +``` + +#### Query (C-Find) and Retrieve (C-Move) from remote modality: + +```python +from pyorthanc import RemoteModality, Orthanc + +orthanc = Orthanc('http://localhost:8042', 'username', 'password') + +modality = RemoteModality(orthanc, 'modality') + +# Query (C-Find) on modality +data = {'Level': 'Study', 'Query': {'PatientID': '*'}} +query_response = modality.query(data=data) + +answer = modality.get_query_answers()[query_response['ID']] +print(answer) + +# Retrieve (C-Move) results of query on a target modality (AET) +modality.move(query_response['ID'], {'TargetAet': 'target_modality'}) +``` + +#### Anonymize patient: +```python +from pyorthanc import Orthanc, Patient + +orthanc = Orthanc('http://localhost:8042', 'username', 'password') + +patient_identifier = orthanc.get_patients()[0] + +anonymized_patient = Patient(patient_identifier, orthanc).anonymize( + keep=['PatientName'], # You can keep/remove/replace the DICOM tags you want + replace={'PatientID': 'TheNewPatientID'}, + remove=['ReferringPhysicianName'], + force=True # Needed when changing PatientID/StudyInstanceUID/SeriesInstanceUID/SOPInstanceUID +) +# Or directly with +orthanc.post_patients_id_anonymize(patient_identifier) + +# result is: (you can retrieve DICOM file from ID) +# {'ID': 'dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', +# 'Path': '/patients/dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', +# 'PatientID': 'dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', +# 'Type': 'Patient'} +``` + Example of usage ---------------- Be sure that Orthanc is running. The default URL (if running locally) is `http://localhost:8042`. From 8c7b86bbda288e8ab1caed1bbe4e1cca9bfb71d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 20:45:41 +0200 Subject: [PATCH 26/45] Feat: Add badges --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b117acd3..398d723d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +[![ci](https://github.com/gacou54/pyorthanc/workflows/Test/badge.svg)](https://github.com/gacou54/pyorthanc/actions?query=workflow%3ATest) +[![documentation](https://img.shields.io/badge/docs-mkdocs%20material-blue.svg?style=flat)](https://gacou54.github.io/pyorthanc/) # PyOrthanc **PyOrthanc** is a python client for the Orthanc REST API, which fully wraps all the methods of the REST API. Additionally, it provides many utility functions to interact with an Orthanc instance. @@ -75,7 +77,6 @@ job.wait_until_completion() # Or just wait on its completion new_patient = pyorthanc.Patient(job.content['ID'], client) ``` - ## Notes on versioning PyOrthanc has been rewritten almost entirely from `0.*.*`. The new `Orthanc` client is now automatically generated from `https://api.orthanc-server.com/`. From 469d29f39697ec3ecf3b7ab8688f0dbdabd45337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 20:46:15 +0200 Subject: [PATCH 27/45] Feat: Add badges --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 398d723d..5b304fd2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ Install PyOrthanc using pip: ```bash pip install pyorthanc ``` - --- Then use the client. If Orthanc is running locally, the default URL is `http://localhost:8042`. ```python From 2abd1a88a2dd606c7b561af025aa3574be77d262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 20:58:04 +0200 Subject: [PATCH 28/45] Feat: Add badges --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5b304fd2..2227368d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ [![ci](https://github.com/gacou54/pyorthanc/workflows/Test/badge.svg)](https://github.com/gacou54/pyorthanc/actions?query=workflow%3ATest) [![documentation](https://img.shields.io/badge/docs-mkdocs%20material-blue.svg?style=flat)](https://gacou54.github.io/pyorthanc/) +![PyPI - Version](https://img.shields.io/pypi/v/pyorthanc) +![PyPI - Downloads](https://img.shields.io/pypi/dm/pyorthanc) # PyOrthanc **PyOrthanc** is a python client for the Orthanc REST API, which fully wraps all the methods of the REST API. Additionally, it provides many utility functions to interact with an Orthanc instance. From 7a1c7d045cffe8d9a1d4148883f34a3657fd8459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 21:40:52 +0200 Subject: [PATCH 29/45] Feat: changes some doc files --- docs/css/custom.css | 10 ---------- docs/demos.md | 35 ---------------------------------- docs/documentation.md | 0 docs/index.md | 6 +++--- docs/tutorial/quickstart.md | 3 ++- examples/installation.md | 38 ------------------------------------- mkdocs.yml | 4 ---- 7 files changed, 5 insertions(+), 91 deletions(-) delete mode 100644 docs/css/custom.css delete mode 100644 docs/demos.md delete mode 100644 docs/documentation.md delete mode 100644 examples/installation.md diff --git a/docs/css/custom.css b/docs/css/custom.css deleted file mode 100644 index ced5d751..00000000 --- a/docs/css/custom.css +++ /dev/null @@ -1,10 +0,0 @@ -div.autodoc-docstring { - padding-left: 20px; - margin-bottom: 30px; - border-left: 5px solid rgba(230, 230, 230); -} - -div.autodoc-members { - padding-left: 20px; - margin-bottom: 15px; -} \ No newline at end of file diff --git a/docs/demos.md b/docs/demos.md deleted file mode 100644 index 06403e3c..00000000 --- a/docs/demos.md +++ /dev/null @@ -1,35 +0,0 @@ -Example of usage ----------------- -Be sure that Orthanc is running. The default URL (if running locally) is `http://localhost:8042`. - -Here is a list of examples to helps you getting started with pyorthanc - -| code | -|-----------------------------------------------------------------------------------------------------------------| -| [Access instance informations](https://github.com/ylemarechal/pyorthanc/tree/main/examples/access_informations) | -| [Transfer data from a PACS to a Orthanc server](https://github.com/ylemarechal/dicom-transfer) | - -## First steps - -- [x] Python3.10 -- [x] Docker - -## Some useful commands - -### Docker commands -Start Orthanc -```bash -docker compose up -d -``` -Stop Orthanc -```bash -docker compose stop -``` -Restart Orthanc -```bash -docker compose restart -``` -Delete Orthanc container -```bash -docker compose down -``` \ No newline at end of file diff --git a/docs/documentation.md b/docs/documentation.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/index.md b/docs/index.md index 62734ae2..b4d56b2f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,8 +5,8 @@ of data with several cool utilities. ## **What for ?** The aim of the PyOrthanc module is to easy use the Orthanc Dicom server API. -It has an access to the full available Orthanc API and get the useful return without dealing with http requests. +It has access to the full available Orthanc API and get the useful return without dealing with http requests. -## **Functionalities** - +It also allows you to find specifics series/studies/patients +according to complex filters \ No newline at end of file diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index a11ca379..236ef05d 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -50,6 +50,7 @@ orthanc = Orthanc(url='http://localhost:8042/', orthanc.get_modalities() ``` + ### Find and download patients according to criteria: ```python @@ -64,7 +65,7 @@ patients = find_patients( retrieve_and_write_patients(patients, '.') ``` -#### Query (C-Find) and Retrieve (C-Move) from remote modality: +### Query (C-Find) and Retrieve (C-Move) from remote modality: ```python from pyorthanc import RemoteModality, Orthanc diff --git a/examples/installation.md b/examples/installation.md deleted file mode 100644 index aa0d5cde..00000000 --- a/examples/installation.md +++ /dev/null @@ -1,38 +0,0 @@ -## First steps - -- Applications installed - - [x] Python3.10 - - [x] Docker - - -## Prepare Orthanc -For the examples, we use a vanilla Orthanc inside a docker. The first step is to prepare a dedicated directory, -and copy/past the below code in a file called ```docker-compose.yaml``` -```yaml -version: '3.3' -services: - orthanc: - image: jodogne/orthanc-plugins:1.12.1 - ports: - - 4242:4242 - - 8042:8042 -``` -You can also dowload it directly from this [link](./docker-compose.yaml) - -## Run Orthanc - -To run a local Orthanc with Docker, just run this command in the same directory of your ```docker-compose.yaml``` file - -```bash -docker compose up -d -``` - -The default URL (if running locally) is `http://localhost:8042`. - -## Prepare environment -```bash -python3 -m venv .venv -source .venv/bin/activate -pip install pyorthanc -``` - diff --git a/mkdocs.yml b/mkdocs.yml index 835a09ee..17020421 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -51,7 +51,3 @@ plugins: options: docstring_style: numpy default_handler: python - - -extra_css: - - css/custom.css \ No newline at end of file From 9651f2ba0aae7d107233208ce2eed95f843d00bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= Date: Wed, 30 Aug 2023 22:50:25 +0200 Subject: [PATCH 30/45] Feat: changes some doc files --- docs/citation.md | 1 + docs/contributing.md | 2 ++ docs/index.md | 41 ++++++++++++++++++++++++++++++------- docs/purpose.md | 0 docs/releases/releases.md | 9 ++++---- docs/to-start.md | 0 docs/tutorial/advanced.md | 9 ++++---- docs/tutorial/quickstart.md | 10 ++++----- mkdocs.yml | 6 ++++++ 9 files changed, 57 insertions(+), 21 deletions(-) delete mode 100644 docs/purpose.md delete mode 100644 docs/to-start.md diff --git a/docs/citation.md b/docs/citation.md index 1c06b46b..7a856d39 100644 --- a/docs/citation.md +++ b/docs/citation.md @@ -1,2 +1,3 @@ +# Citation If you publish using PyOrthanc, we kindly ask that you credit us. PyOrthanc can be found on Zenodo : [https://doi.org/10.5281/zenodo.3387551](https://doi.org/10.5281/zenodo.3387551). \ No newline at end of file diff --git a/docs/contributing.md b/docs/contributing.md index 53bf84ba..1f3dcf5b 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -1,3 +1,5 @@ +# Contribute + You can contribute to this project with the following steps: 1. First, fork the project on Github diff --git a/docs/index.md b/docs/index.md index b4d56b2f..f266f0fa 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,12 +1,39 @@ -# **Presentation** -Python library that wraps the Orthanc REST API and facilitates the manipulation -of data with several cool utilities. + + + -## **What for ?** +# PyOrthanc -The aim of the PyOrthanc module is to easy use the Orthanc Dicom server API. +Python library that wraps the Orthanc REST API and facilitates the manipulation of data with several cool utilities. +What for ? + +The aim of the PyOrthanc module is to easy use the Orthanc Dicom server API. It has access to the full available Orthanc API and get the useful return without dealing with http requests. -It also allows you to find specifics series/studies/patients -according to complex filters \ No newline at end of file +It also allows you to find specifics series/studies/patients according to complex filters + +## [First steps](tutorial/quickstart.md#first-steps) +### [Requirements](tutorial/quickstart.md#requirements) +### [Installation](tutorial/quickstart.md#installation) +### [Getting started](tutorial/quickstart.md#getting-started) +* [Import pyorthanc library](tutorial/quickstart.md#import-pyorthanc-library) +* [Connect to Orthanc](tutorial/quickstart.md#connect-to-orthanc) +* [Upload DICOM files to Orthanc:](tutorial/quickstart.md#upload-dicom-files-to-orthanc) +* [Getting list of connected remote modalities:](tutorial/quickstart.md#getting-list-of-connected-remote-modalities) +* [Find and download patients according to criteria:](tutorial/quickstart.md#find-and-download-patients-according-to-criteria) +* [Query (C-Find) and Retrieve (C-Move) from remote modality:](tutorial/quickstart.md#query-c-find-and-retrieve-c-move-from-remote-modality) +### [Full basic examples](tutorial/quickstart.md#full-basic-examples) +* [Access instance informations](tutorial/quickstart.md#access-instance-informations) +### [Some useful commands](tutorial/quickstart.md#some-useful-commands) +* [Docker commands](tutorial/quickstart.md#docker-commands) +### [Advanced examples](tutorial/advanced.md) +* [Transfer data from a PACS to a Orthanc server](tutorial/advanced.md#transfer-data-from-a-pacs-to-a-orthanc-server) +### [Releases](releases/releases.md) +* [Lastest release : 1.12.1](releases/releases.md#lastest-release-1121) +* [Release 1.11.5](releases/releases.md#release-1115) +## [Contribute](contributing.md#contribute) +## [Contacts](contacts.md#contacts) +* [Maintainers Team](contacts.md#maintainers-team) +* [Useful links](contacts.md#useful-links) +## [Citation](citation.md#citation) diff --git a/docs/purpose.md b/docs/purpose.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/releases/releases.md b/docs/releases/releases.md index 87cc2edd..3bcd7f11 100644 --- a/docs/releases/releases.md +++ b/docs/releases/releases.md @@ -1,5 +1,6 @@ -Lastest release : 1.12.1 ------------- +# Releases + +## Lastest release : 1.12.1 The Orthanc client has been regenerated on the Orthanc 1.12.1 version (source of the [changelist](https://hg.orthanc-server.com/orthanc/file/Orthanc-1.12.1/NEWS)). @@ -30,8 +31,8 @@ Details: - All tests made with unittest has been refactored to use pytest -Release 1.11.5 ------------- +## Release 1.11.5 + PyOrthanc v1.11.5 follow Orthanc version 1.11.3. diff --git a/docs/to-start.md b/docs/to-start.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/tutorial/advanced.md b/docs/tutorial/advanced.md index fea1cee4..66ee5773 100644 --- a/docs/tutorial/advanced.md +++ b/docs/tutorial/advanced.md @@ -1,9 +1,8 @@ -Example of usage ----------------- +# Advanced examples Here is a list of complete examples with pyorthanc -| code | -|-----------------------------------------------------------------------------------------------------------------| -| [Transfer data from a PACS to a Orthanc server](https://github.com/ylemarechal/dicom-transfer) | +## Transfer data from a PACS to a Orthanc server + +[Transfer data from a PACS to a Orthanc server](https://github.com/ylemarechal/dicom-transfer) diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 236ef05d..2d69ac2c 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -109,15 +109,15 @@ orthanc.post_patients_id_anonymize(patient_identifier) # 'Type': 'Patient'} ``` -Example of usage ----------------- +## Full basic examples + Be sure that Orthanc is running. The default URL (if running locally) is `http://localhost:8042`. Here is a list of examples to helps you getting started with pyorthanc -| code | -|-----------------------------------------------------------------------------------------------------------------| -| [Access instance informations](https://github.com/ylemarechal/pyorthanc-examples/tree/main/basic/access_informations) | +### Access instance informations + +[Get instance informations](https://github.com/ylemarechal/pyorthanc-examples/tree/main/basic/access_informations) ## Some useful commands diff --git a/mkdocs.yml b/mkdocs.yml index 17020421..83eddfc2 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -51,3 +51,9 @@ plugins: options: docstring_style: numpy default_handler: python +# - toc-md: +# header_level: +# pickup_description_class: false +# ignore_page_pattern: api/* +# remove_navigation_page_pattern: api/* + From 0bd386efb3b9b12c680c856d6e14201fe0e4ca63 Mon Sep 17 00:00:00 2001 From: gacou54 Date: Tue, 5 Sep 2023 09:22:39 -0400 Subject: [PATCH 31/45] short modification for index --- docs/index.md | 54 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 10 deletions(-) diff --git a/docs/index.md b/docs/index.md index f266f0fa..7254159c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,19 +3,56 @@ # PyOrthanc +**PyOrthanc** is a python client for the Orthanc REST API, which fully wraps all the methods of the REST API. +Additionally, it provides many utility functions to interact with an Orthanc instance. -Python library that wraps the Orthanc REST API and facilitates the manipulation of data with several cool utilities. -What for ? -The aim of the PyOrthanc module is to easy use the Orthanc Dicom server API. +--- +Install PyOrthanc +```bash +pip install pyorthanc +``` +--- +Then use the client: +```python +import pyorthanc -It has access to the full available Orthanc API and get the useful return without dealing with http requests. +client = pyorthanc.Orthanc('https://demo.orthanc-server.com') +patient_ids = client.get_patients() +``` +Interact with connected modalities -It also allows you to find specifics series/studies/patients according to complex filters +```python +import pyorthanc + +modality = pyorthanc.Modality(client, 'MY_MODALITY') +assert modality.echo() + +# C-Find on modality +response = modality.query({'Level': 'Study', 'Query': {'PatientID': '*'}}) + +# C-Move to target modality +modality.move(response['ID'], {'TargetAet': 'target_modality'}) +``` +Find patients +```python +patients = pyorthanc.find_patients(client, {'PatientID': '*P001'}) +for patient in patients: + patient.labels + patient.is_stable + patient.name + ... + for study in patient.studies: + study.labels + study.date + ... + for series in study.series: + ... + for instance in series.instances: + pydicom_ds = instance.get_pydicom() +``` ## [First steps](tutorial/quickstart.md#first-steps) -### [Requirements](tutorial/quickstart.md#requirements) -### [Installation](tutorial/quickstart.md#installation) ### [Getting started](tutorial/quickstart.md#getting-started) * [Import pyorthanc library](tutorial/quickstart.md#import-pyorthanc-library) * [Connect to Orthanc](tutorial/quickstart.md#connect-to-orthanc) @@ -25,14 +62,11 @@ It also allows you to find specifics series/studies/patients according to comple * [Query (C-Find) and Retrieve (C-Move) from remote modality:](tutorial/quickstart.md#query-c-find-and-retrieve-c-move-from-remote-modality) ### [Full basic examples](tutorial/quickstart.md#full-basic-examples) * [Access instance informations](tutorial/quickstart.md#access-instance-informations) -### [Some useful commands](tutorial/quickstart.md#some-useful-commands) -* [Docker commands](tutorial/quickstart.md#docker-commands) ### [Advanced examples](tutorial/advanced.md) * [Transfer data from a PACS to a Orthanc server](tutorial/advanced.md#transfer-data-from-a-pacs-to-a-orthanc-server) ### [Releases](releases/releases.md) * [Lastest release : 1.12.1](releases/releases.md#lastest-release-1121) * [Release 1.11.5](releases/releases.md#release-1115) -## [Contribute](contributing.md#contribute) ## [Contacts](contacts.md#contacts) * [Maintainers Team](contacts.md#maintainers-team) * [Useful links](contacts.md#useful-links) From 44983fb10d3b7e43b333af985caa818f27de652d Mon Sep 17 00:00:00 2001 From: gacou54 Date: Tue, 5 Sep 2023 09:23:23 -0400 Subject: [PATCH 32/45] Stop instanciating an client at each example --- docs/tutorial/quickstart.md | 80 +++++-------------------------------- 1 file changed, 10 insertions(+), 70 deletions(-) diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 2d69ac2c..1e213206 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -1,68 +1,37 @@ # First steps -## Requirements - -- [x] Python3.8 - ## Installation - ```bash -python3 -m venv .venv -source .venv/bin/activate pip install pyorthanc ``` ## Getting started -### Import pyorthanc library -```python -import pyorthanc -``` - ### Connect to Orthanc Here are some quick how to examples to use pyorthanc ```python from pyorthanc import Orthanc -orthanc = Orthanc(url='http://localhost:8042/', - username='username', - password='password') +orthanc = Orthanc(url='http://localhost:8042/', username='orthanc', password='orthanc') ``` ### Upload DICOM files to Orthanc: - ```python -from pyorthanc import Orthanc - -orthanc = Orthanc(url='http://localhost:8042/', - username='username', - password='password') - with open('A_DICOM_INSTANCE_PATH.dcm', 'rb') as file: - orthanc.post_instances(file.read()) + orthanc.post_instances(file.read()) ``` ### Getting list of connected remote modalities: ```python -from pyorthanc import Orthanc - -orthanc = Orthanc(url='http://localhost:8042/', - username='username', - password='password') - -orthanc.get_modalities() +modalities = orthanc.get_modalities() ``` - ### Find and download patients according to criteria: - ```python -from pyorthanc import Orthanc, find_patients, retrieve_and_write_patients - -orthanc = Orthanc(url='https://demo.orthanc-server.com', username='', password='') +from pyorthanc import find_patients, retrieve_and_write_patients patients = find_patients( client=orthanc, query={'PatientName': 'COMUNIX'} # Optional: filter with pyorthanc.Series object ) -retrieve_and_write_patients(patients, '.') +retrieve_and_write_patients(patients, './patients_path') ``` ### Query (C-Find) and Retrieve (C-Move) from remote modality: @@ -87,54 +56,25 @@ modality.move(query_response['ID'], {'TargetAet': 'target_modality'}) #### Anonymize patient: ```python -from pyorthanc import Orthanc, Patient - -orthanc = Orthanc('http://localhost:8042', 'username', 'password') +from pyorthanc import Patient patient_identifier = orthanc.get_patients()[0] +patient = Patient(patient_identifier, orthanc) -anonymized_patient = Patient(patient_identifier, orthanc).anonymize( +anonymized_patient = patient.anonymize( keep=['PatientName'], # You can keep/remove/replace the DICOM tags you want replace={'PatientID': 'TheNewPatientID'}, remove=['ReferringPhysicianName'], force=True # Needed when changing PatientID/StudyInstanceUID/SeriesInstanceUID/SOPInstanceUID ) -# Or directly with -orthanc.post_patients_id_anonymize(patient_identifier) - -# result is: (you can retrieve DICOM file from ID) -# {'ID': 'dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', -# 'Path': '/patients/dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', -# 'PatientID': 'dd41f2f1-24838e1e-f01746fc-9715072f-189eb0a2', -# 'Type': 'Patient'} ``` ## Full basic examples Be sure that Orthanc is running. The default URL (if running locally) is `http://localhost:8042`. -Here is a list of examples to helps you getting started with pyorthanc +Here is a list of examples to helps you getting started with pyorthanc. -### Access instance informations +### Access instance information [Get instance informations](https://github.com/ylemarechal/pyorthanc-examples/tree/main/basic/access_informations) - -## Some useful commands - -### Docker commands -Start Orthanc -```bash -docker compose up -d -``` -Stop Orthanc -```bash -docker compose stop -``` -Restart Orthanc -```bash -docker compose restart -``` -Delete Orthanc container -```bash -docker compose down -``` \ No newline at end of file From 07c29e70b7a5f2d3d1dbaf8921ca6aab22db461c Mon Sep 17 00:00:00 2001 From: gacou54 Date: Tue, 5 Sep 2023 11:03:55 -0400 Subject: [PATCH 33/45] Fix build due to lib refactor --- docs/api/filtering.md | 2 +- docs/api/find.md | 2 +- docs/api/resources/resource.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/filtering.md b/docs/api/filtering.md index 892f54ce..c7221d46 100644 --- a/docs/api/filtering.md +++ b/docs/api/filtering.md @@ -1,3 +1,3 @@ -::: pyorthanc.filtering +::: pyorthanc._filtering :docstring: :members: \ No newline at end of file diff --git a/docs/api/find.md b/docs/api/find.md index 464e2b9c..eafb9535 100644 --- a/docs/api/find.md +++ b/docs/api/find.md @@ -1,3 +1,3 @@ -::: pyorthanc.find +::: pyorthanc._find :docstring: :members: \ No newline at end of file diff --git a/docs/api/resources/resource.md b/docs/api/resources/resource.md index 9f169fe5..70866935 100644 --- a/docs/api/resources/resource.md +++ b/docs/api/resources/resource.md @@ -1,3 +1,3 @@ -::: pyorthanc.resources.Resource +::: pyorthanc._resources.Resource :docstring: :members: \ No newline at end of file From 9697e99c6f625f0bd8a65fd0af42342943177a91 Mon Sep 17 00:00:00 2001 From: gacou54 Date: Tue, 5 Sep 2023 13:50:19 -0400 Subject: [PATCH 34/45] Minor improvements in quickstart --- docs/tutorial/quickstart.md | 88 +++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 24 deletions(-) diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index 1e213206..c0138ce8 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -22,31 +22,21 @@ with open('A_DICOM_INSTANCE_PATH.dcm', 'rb') as file: ```python modalities = orthanc.get_modalities() ``` - -### Find and download patients according to criteria: -```python -from pyorthanc import find_patients, retrieve_and_write_patients - -patients = find_patients( - client=orthanc, - query={'PatientName': 'COMUNIX'} # Optional: filter with pyorthanc.Series object -) -retrieve_and_write_patients(patients, './patients_path') -``` - ### Query (C-Find) and Retrieve (C-Move) from remote modality: ```python -from pyorthanc import RemoteModality, Orthanc +from pyorthanc import Modality -orthanc = Orthanc('http://localhost:8042', 'username', 'password') +modality = Modality(orthanc, 'modality') -modality = RemoteModality(orthanc, 'modality') +# C-Echo +assert modality.echo() # Test the connection # Query (C-Find) on modality data = {'Level': 'Study', 'Query': {'PatientID': '*'}} query_response = modality.query(data=data) +# Inspect the answer answer = modality.get_query_answers()[query_response['ID']] print(answer) @@ -54,20 +44,70 @@ print(answer) modality.move(query_response['ID'], {'TargetAet': 'target_modality'}) ``` -#### Anonymize patient: +### Find and download patients according to criteria: ```python -from pyorthanc import Patient +from pyorthanc import find_patients, retrieve_and_write_patients -patient_identifier = orthanc.get_patients()[0] -patient = Patient(patient_identifier, orthanc) +patients = find_patients( + client=orthanc, + query={'PatientName': '*Gabriel'}, # Filter on PatientName + labels=['a-label'] # Filter on patients with the 'a-label' +) +``` -anonymized_patient = patient.anonymize( - keep=['PatientName'], # You can keep/remove/replace the DICOM tags you want - replace={'PatientID': 'TheNewPatientID'}, - remove=['ReferringPhysicianName'], - force=True # Needed when changing PatientID/StudyInstanceUID/SeriesInstanceUID/SOPInstanceUID +Write the patients DICOM files locally +```python +retrieve_and_write_patients(patients, './patients_path') +``` +Or manipulates the Patient object +```python +patient = patients[0] + +patient.name +patient.is_stable +patient.last_update + +patient.labels +patient.remove_label('a-label') +patient.add_label('a-new-label') +... +``` + +It is also possible to query the other resource levels +```python +from pyorthanc import find_studies, find_series, find_instances + +studies = find_studies(client=orthanc, query={...}, labels=[...]) +series = find_series(client=orthanc, query={...}, labels=[...]) +instances = find_instances(client=orthanc, query={...}, labels=[...]) +``` + +#### Anonymize patient +Resources (`Patient`, `Study`, `Series`, `Instance`) can be easily __anonymized__. +```python +import pyorthanc + +orthanc_patient_id = client.get_patients()[0] +patient = pyorthanc.Patient(orthanc_patient_id, client) +``` +Waiting for the anonymization process (this may raise a TimeOutError) +```python +new_patient = patient.anonymize() +new_patient_with_given_patient_id = patient.anonymize( + keep=['PatientName'], + replace={'PatientID': 'TheNewPatientID'}, + force=True # Needed when changing PatientID/StudyInstanceUID/SeriesInstanceUID/SOPInstanceUID ) ``` +For long-running job (i.e. large patient) or to submit many anonymization jobs at the same time, use +```python +job = patient.anonymize_as_job() +job.state # You can follow the job state + +job.wait_until_completion() # Or just wait on its completion +new_patient = pyorthanc.Patient(job.content['ID'], client) +``` + ## Full basic examples From 4134b3e1c2c9a877dbee5f63a5144fdb06383d05 Mon Sep 17 00:00:00 2001 From: gacou54 Date: Tue, 5 Sep 2023 14:23:01 -0400 Subject: [PATCH 35/45] Find resources with complex filters or filter on many resource levels --- docs/tutorial/quickstart.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/tutorial/quickstart.md b/docs/tutorial/quickstart.md index c0138ce8..98d79883 100644 --- a/docs/tutorial/quickstart.md +++ b/docs/tutorial/quickstart.md @@ -108,6 +108,27 @@ job.wait_until_completion() # Or just wait on its completion new_patient = pyorthanc.Patient(job.content['ID'], client) ``` +#### Find resources with complex filters or filter on many resource levels +The `pyorthanc.find()` function allow to find resources with filters on many levels, +or with complex filter. Each filter function takes an object that correspond to the resource level +and should return a boolean value. + +Note that when using the `find()` function, the state of the resources `Patient/Study/Series/Instance` +are locked. +```python +from datetime import datetime +from pyorthanc import find + +patients = find( + orthanc, + patient_filter=lambda patient: patient.last_update > datetime(year=2023, month=10, day=1), + study_filter=lambda study: 'thorax' in study.description.lower(), + series_filter=lambda series: series.modality == 'CT' +) +``` +__Note__ that this function may take a while to run since each resource level is filtered. +Using `find()` on large Orthanc server is not recommended. + ## Full basic examples From a471cd3d381ceaa32ce5aa1c540168b767660834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 21:15:16 +0200 Subject: [PATCH 36/45] =?UTF-8?q?=E2=9C=A8=20download=20nifti=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyorthanc/_resources/instance.py | 4 ++-- pyorthanc/_resources/resource.py | 36 +++++++++++++++++++++++++++++++- pyorthanc/_resources/series.py | 5 +++-- pyorthanc/errors.py | 4 ++++ 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/pyorthanc/_resources/instance.py b/pyorthanc/_resources/instance.py index 646bbc8d..e9bdf951 100644 --- a/pyorthanc/_resources/instance.py +++ b/pyorthanc/_resources/instance.py @@ -42,7 +42,7 @@ def get_dicom_file_content(self) -> bytes: """ return self.client.get_instances_id_file(self.id_) - def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False) -> None: + def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, file_format: str = 'zip') -> None: """Download the DICOM file to a target path or buffer This method is an alternative to the `.get_dicom_file_content()` method for large files. @@ -70,7 +70,7 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False) - dicom_bytes = buffer.read() ``` """ - self._download_file(f'{self.client.url}/instances/{self.id_}/file', filepath, with_progres) + self._download_file(f'{self.client.url}/instances/{self.id_}/file', filepath, with_progres, file_format=file_format) @property def uid(self) -> str: diff --git a/pyorthanc/_resources/resource.py b/pyorthanc/_resources/resource.py index ec837efe..81502197 100644 --- a/pyorthanc/_resources/resource.py +++ b/pyorthanc/_resources/resource.py @@ -5,6 +5,7 @@ from .. import errors, util from ..client import Orthanc +from ..errors import PluginNotEnabledError class Resource: @@ -76,14 +77,47 @@ def _make_response_format_params(self, simplify: bool = False, short: bool = Fal return params + def _is_plugin_installed(self, + plugin_name: str): + if plugin_name in self.client.get_plugins(): + return True + + return False + + def _is_neuro_plugin_installed(self): + try: + _ = self.client.get_plugins_id(id_='neuro') + return True + except: + return False + def _download_file( self, url: str, filepath: Union[str, BinaryIO], with_progress: bool = False, - params: Optional[QueryParamTypes] = None): + params: Optional[QueryParamTypes] = None, + file_format: str = 'zip'): + # Check if filepath is a path or a file object. if isinstance(filepath, str): is_file_object = False + if file_format.lower() not in ['zip', 'nii', 'nii.gz']: + raise ValueError( + "format should be one of ['zip', 'nii', 'nii.gz'], " + f"got '{file_format}' instead." + ) + + if file_format.lower() == 'zip': + url = f'{url}/archive' + elif file_format.lower() in ['nii', 'nii.gz']: + if not self._is_neuro_plugin_installed(): + raise PluginNotEnabledError( + 'Neuro plugin is not installed or enabled on Orthanc instance. More information on https://orthanc.uclouvain.be/book/plugins/neuro.html' + ) + url = f'{url}/nifti' + if file_format.lower() == 'nii.gz': + url += '?compress' + filepath = open(filepath, 'wb') elif hasattr(filepath, 'write') and hasattr(filepath, 'seek'): is_file_object = True diff --git a/pyorthanc/_resources/series.py b/pyorthanc/_resources/series.py index 91bffa4e..176843be 100644 --- a/pyorthanc/_resources/series.py +++ b/pyorthanc/_resources/series.py @@ -584,7 +584,7 @@ def get_zip(self) -> bytes: """ return self.client.get_series_id_archive(self.id_) - def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False) -> None: + def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, file_format: str = 'zip') -> None: """Download the zip file to a target path or buffer This method is an alternative to the `.get_zip()` method for large files. @@ -612,7 +612,8 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False) - zip_bytes = buffer.read() ``` """ - self._download_file(f'{self.client.url}/series/{self.id_}/archive', filepath, with_progres) + # self._download_file(f'{self.client.url}/series/{self.id_}/archive', filepath, with_progres) + self._download_file(f'{self.client.url}/series/{self.id_}', filepath, with_progres, file_format=file_format) def get_shared_tags(self, simplify: bool = False, short: bool = False) -> Dict: """Retrieve the shared tags of the series""" diff --git a/pyorthanc/errors.py b/pyorthanc/errors.py index 32c81b09..65431f81 100644 --- a/pyorthanc/errors.py +++ b/pyorthanc/errors.py @@ -8,3 +8,7 @@ class ModificationError(Exception): class NotInInternalEnvironmentError(Exception): pass + + +class PluginNotEnabledError(Exception): + pass \ No newline at end of file From 347976cc5badbd4cdc74106f848b3559fa400ad9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 21:17:01 +0200 Subject: [PATCH 37/45] add line --- pyorthanc/errors.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyorthanc/errors.py b/pyorthanc/errors.py index 65431f81..274b03e5 100644 --- a/pyorthanc/errors.py +++ b/pyorthanc/errors.py @@ -11,4 +11,4 @@ class NotInInternalEnvironmentError(Exception): class PluginNotEnabledError(Exception): - pass \ No newline at end of file + pass From 7165332458e16bb1af05847f24213bf2d4b667a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 21:22:56 +0200 Subject: [PATCH 38/45] add comments --- pyorthanc/_resources/instance.py | 8 +++++++- pyorthanc/_resources/series.py | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pyorthanc/_resources/instance.py b/pyorthanc/_resources/instance.py index e9bdf951..51e08e41 100644 --- a/pyorthanc/_resources/instance.py +++ b/pyorthanc/_resources/instance.py @@ -49,6 +49,8 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, f The `.get_dicom_file_content()` method will pull all the data in a single GET call, while `.download()` stream the data to a file or a buffer. Favor the `.download()` method to avoid timeout and memory issues. + file_format option accepts 'zip', 'nii', 'nii.gz' + Examples -------- @@ -68,9 +70,13 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, f # Now do whatever you want to do buffer.seek(0) dicom_bytes = buffer.read() + + # download instance in nii.gz format + instance.download('instance.nii.gz', file_format='nii.gz') + ``` """ - self._download_file(f'{self.client.url}/instances/{self.id_}/file', filepath, with_progres, file_format=file_format) + self._download_file(f'{self.client.url}/instances/{self.id_}/file', filepath, with_progres, file_format) @property def uid(self) -> str: diff --git a/pyorthanc/_resources/series.py b/pyorthanc/_resources/series.py index 176843be..69d998cb 100644 --- a/pyorthanc/_resources/series.py +++ b/pyorthanc/_resources/series.py @@ -591,6 +591,7 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, f The `.get_zip()` method will pull all the data in a single GET call, while `.download()` stream the data to a file or a buffer. Favor the `.download()` method to avoid timeout and memory issues. + file_format option accepts 'zip', 'nii', 'nii.gz' Examples -------- @@ -610,10 +611,13 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, f # Now do whatever you want to do buffer.seek(0) zip_bytes = buffer.read() + + # download series in nii.gz format + a_series.download('instance.nii.gz', file_format='nii.gz') ``` """ # self._download_file(f'{self.client.url}/series/{self.id_}/archive', filepath, with_progres) - self._download_file(f'{self.client.url}/series/{self.id_}', filepath, with_progres, file_format=file_format) + self._download_file(f'{self.client.url}/series/{self.id_}', filepath, with_progres, file_format) def get_shared_tags(self, simplify: bool = False, short: bool = False) -> Dict: """Retrieve the shared tags of the series""" From f5fd2a6e9901481f4fc2a9623dbb486a7113db99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 21:40:24 +0200 Subject: [PATCH 39/45] fix param --- pyorthanc/_resources/resource.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/pyorthanc/_resources/resource.py b/pyorthanc/_resources/resource.py index 81502197..35486ae1 100644 --- a/pyorthanc/_resources/resource.py +++ b/pyorthanc/_resources/resource.py @@ -1,6 +1,7 @@ import abc from typing import Any, BinaryIO, Dict, List, Optional, Union +from httpx import HTTPError from httpx._types import QueryParamTypes from .. import errors, util @@ -77,26 +78,19 @@ def _make_response_format_params(self, simplify: bool = False, short: bool = Fal return params - def _is_plugin_installed(self, - plugin_name: str): - if plugin_name in self.client.get_plugins(): - return True - - return False - def _is_neuro_plugin_installed(self): try: _ = self.client.get_plugins_id(id_='neuro') return True - except: + except HTTPError as e: return False def _download_file( self, url: str, filepath: Union[str, BinaryIO], with_progress: bool = False, - params: Optional[QueryParamTypes] = None, - file_format: str = 'zip'): + file_format: str = 'zip', + params: Optional[QueryParamTypes] = None,): # Check if filepath is a path or a file object. if isinstance(filepath, str): From 415110717fdb554e2759c55a3ea1d79394658127 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 22:00:24 +0200 Subject: [PATCH 40/45] add dcm file option --- pyorthanc/_resources/instance.py | 10 ++++++++-- pyorthanc/_resources/resource.py | 8 +++++--- pyorthanc/_resources/series.py | 5 +++++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/pyorthanc/_resources/instance.py b/pyorthanc/_resources/instance.py index 51e08e41..f54103f4 100644 --- a/pyorthanc/_resources/instance.py +++ b/pyorthanc/_resources/instance.py @@ -42,7 +42,7 @@ def get_dicom_file_content(self) -> bytes: """ return self.client.get_instances_id_file(self.id_) - def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, file_format: str = 'zip') -> None: + def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, file_format: str = 'dcm') -> None: """Download the DICOM file to a target path or buffer This method is an alternative to the `.get_dicom_file_content()` method for large files. @@ -76,7 +76,13 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, f ``` """ - self._download_file(f'{self.client.url}/instances/{self.id_}/file', filepath, with_progres, file_format) + if file_format.lower() not in ['dcm', 'nii', 'nii.gz']: + raise ValueError( + f"format should be one of ['dcm, 'nii', 'nii.gz'], " + f"got '{file_format}' instead." + ) + + self._download_file(f'{self.client.url}/instances/{self.id_}', filepath, with_progres, file_format) @property def uid(self) -> str: diff --git a/pyorthanc/_resources/resource.py b/pyorthanc/_resources/resource.py index 35486ae1..26bae39c 100644 --- a/pyorthanc/_resources/resource.py +++ b/pyorthanc/_resources/resource.py @@ -90,19 +90,21 @@ def _download_file( filepath: Union[str, BinaryIO], with_progress: bool = False, file_format: str = 'zip', - params: Optional[QueryParamTypes] = None,): + params: Optional[QueryParamTypes] = None, ): # Check if filepath is a path or a file object. if isinstance(filepath, str): is_file_object = False - if file_format.lower() not in ['zip', 'nii', 'nii.gz']: + if file_format.lower() not in ['dcm', 'zip', 'nii', 'nii.gz']: raise ValueError( - "format should be one of ['zip', 'nii', 'nii.gz'], " + f"format should be one of ['dcm, 'zip', 'nii', 'nii.gz'], " f"got '{file_format}' instead." ) if file_format.lower() == 'zip': url = f'{url}/archive' + elif file_format.lower() == 'dcm': + url = f'{url}/file' elif file_format.lower() in ['nii', 'nii.gz']: if not self._is_neuro_plugin_installed(): raise PluginNotEnabledError( diff --git a/pyorthanc/_resources/series.py b/pyorthanc/_resources/series.py index 69d998cb..b5f2d147 100644 --- a/pyorthanc/_resources/series.py +++ b/pyorthanc/_resources/series.py @@ -617,6 +617,11 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, f ``` """ # self._download_file(f'{self.client.url}/series/{self.id_}/archive', filepath, with_progres) + if file_format.lower() not in ['zip', 'nii', 'nii.gz']: + raise ValueError( + f"format should be one of ['zip', 'nii', 'nii.gz'], " + f"got '{file_format}' instead." + ) self._download_file(f'{self.client.url}/series/{self.id_}', filepath, with_progres, file_format) def get_shared_tags(self, simplify: bool = False, short: bool = False) -> Dict: From 9d9356c66daf1268c8b82ab50cf18312111cf189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 23:05:39 +0200 Subject: [PATCH 41/45] fix for studies and patients --- pyorthanc/_resources/patient.py | 2 +- pyorthanc/_resources/study.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyorthanc/_resources/patient.py b/pyorthanc/_resources/patient.py index 84fa5da5..e42094e0 100644 --- a/pyorthanc/_resources/patient.py +++ b/pyorthanc/_resources/patient.py @@ -139,7 +139,7 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False) - zip_bytes = buffer.read() ``` """ - self._download_file(f'{self.client.url}/patients/{self.id_}/archive', filepath, with_progres) + self._download_file(f'{self.client.url}/patients/{self.id_}', filepath, with_progres, 'zip') def get_patient_module(self, simplify: bool = False, short: bool = False) -> Dict: """Get patient module in a simplified version diff --git a/pyorthanc/_resources/study.py b/pyorthanc/_resources/study.py index 1bd50a30..b88b9dc1 100644 --- a/pyorthanc/_resources/study.py +++ b/pyorthanc/_resources/study.py @@ -563,7 +563,7 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False) - zip_bytes = buffer.read() ``` """ - self._download_file(f'{self.client.url}/studies/{self.id_}/archive', filepath, with_progres) + self._download_file(f'{self.client.url}/studies/{self.id_}', filepath, with_progres, 'zip') def get_shared_tags(self, simplify: bool = False, short: bool = False) -> Dict: """Retrieve the shared tags of the study""" From 7b4a1ab80ea3a75bc1e677fefebe01d6fc799a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 23:31:00 +0200 Subject: [PATCH 42/45] test fix --- pyorthanc/_resources/resource.py | 42 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/pyorthanc/_resources/resource.py b/pyorthanc/_resources/resource.py index 26bae39c..0b0fe7d9 100644 --- a/pyorthanc/_resources/resource.py +++ b/pyorthanc/_resources/resource.py @@ -82,7 +82,7 @@ def _is_neuro_plugin_installed(self): try: _ = self.client.get_plugins_id(id_='neuro') return True - except HTTPError as e: + except HTTPError: return False def _download_file( @@ -90,30 +90,30 @@ def _download_file( filepath: Union[str, BinaryIO], with_progress: bool = False, file_format: str = 'zip', - params: Optional[QueryParamTypes] = None, ): + params: Optional[QueryParamTypes] = None): + + if file_format.lower() not in ['dcm', 'zip', 'nii', 'nii.gz']: + raise ValueError( + f"format should be one of ['dcm, 'zip', 'nii', 'nii.gz'], " + f"got '{file_format}' instead." + ) + + if file_format.lower() == 'zip': + url = f'{url}/archive' + elif file_format.lower() == 'dcm': + url = f'{url}/file' + elif file_format.lower() in ['nii', 'nii.gz']: + if not self._is_neuro_plugin_installed(): + raise PluginNotEnabledError( + 'Neuro plugin is not installed or enabled on Orthanc instance. More information on https://orthanc.uclouvain.be/book/plugins/neuro.html' + ) + url = f'{url}/nifti' + if file_format.lower() == 'nii.gz': + url += '?compress' # Check if filepath is a path or a file object. if isinstance(filepath, str): is_file_object = False - if file_format.lower() not in ['dcm', 'zip', 'nii', 'nii.gz']: - raise ValueError( - f"format should be one of ['dcm, 'zip', 'nii', 'nii.gz'], " - f"got '{file_format}' instead." - ) - - if file_format.lower() == 'zip': - url = f'{url}/archive' - elif file_format.lower() == 'dcm': - url = f'{url}/file' - elif file_format.lower() in ['nii', 'nii.gz']: - if not self._is_neuro_plugin_installed(): - raise PluginNotEnabledError( - 'Neuro plugin is not installed or enabled on Orthanc instance. More information on https://orthanc.uclouvain.be/book/plugins/neuro.html' - ) - url = f'{url}/nifti' - if file_format.lower() == 'nii.gz': - url += '?compress' - filepath = open(filepath, 'wb') elif hasattr(filepath, 'write') and hasattr(filepath, 'seek'): is_file_object = True From 626d5dc9c208a7f947722aff08a4d3dc78c8dfc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 23:41:13 +0200 Subject: [PATCH 43/45] add else condition --- pyorthanc/_resources/resource.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/pyorthanc/_resources/resource.py b/pyorthanc/_resources/resource.py index 0b0fe7d9..ed94535c 100644 --- a/pyorthanc/_resources/resource.py +++ b/pyorthanc/_resources/resource.py @@ -92,17 +92,11 @@ def _download_file( file_format: str = 'zip', params: Optional[QueryParamTypes] = None): - if file_format.lower() not in ['dcm', 'zip', 'nii', 'nii.gz']: - raise ValueError( - f"format should be one of ['dcm, 'zip', 'nii', 'nii.gz'], " - f"got '{file_format}' instead." - ) - if file_format.lower() == 'zip': url = f'{url}/archive' elif file_format.lower() == 'dcm': url = f'{url}/file' - elif file_format.lower() in ['nii', 'nii.gz']: + elif file_format.lower() == 'nii' or file_format.lower() == 'nii.gz': if not self._is_neuro_plugin_installed(): raise PluginNotEnabledError( 'Neuro plugin is not installed or enabled on Orthanc instance. More information on https://orthanc.uclouvain.be/book/plugins/neuro.html' @@ -110,6 +104,11 @@ def _download_file( url = f'{url}/nifti' if file_format.lower() == 'nii.gz': url += '?compress' + else: + raise ValueError( + f"format should be one of ['dcm, 'zip', 'nii', 'nii.gz'], " + f"got '{file_format}' instead." + ) # Check if filepath is a path or a file object. if isinstance(filepath, str): From 13a18c02ff08d4c31d18c9cbdb073ae3bc0cd544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 23:53:16 +0200 Subject: [PATCH 44/45] comment typo --- pyorthanc/_resources/instance.py | 2 +- pyorthanc/_resources/series.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pyorthanc/_resources/instance.py b/pyorthanc/_resources/instance.py index f54103f4..c8ac0444 100644 --- a/pyorthanc/_resources/instance.py +++ b/pyorthanc/_resources/instance.py @@ -49,7 +49,7 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, f The `.get_dicom_file_content()` method will pull all the data in a single GET call, while `.download()` stream the data to a file or a buffer. Favor the `.download()` method to avoid timeout and memory issues. - file_format option accepts 'zip', 'nii', 'nii.gz' + file_format option accepts 'dcm', 'nii', 'nii.gz' Examples diff --git a/pyorthanc/_resources/series.py b/pyorthanc/_resources/series.py index b5f2d147..998220ee 100644 --- a/pyorthanc/_resources/series.py +++ b/pyorthanc/_resources/series.py @@ -613,10 +613,9 @@ def download(self, filepath: Union[str, BinaryIO], with_progres: bool = False, f zip_bytes = buffer.read() # download series in nii.gz format - a_series.download('instance.nii.gz', file_format='nii.gz') + a_series.download('series.nii.gz', file_format='nii.gz') ``` """ - # self._download_file(f'{self.client.url}/series/{self.id_}/archive', filepath, with_progres) if file_format.lower() not in ['zip', 'nii', 'nii.gz']: raise ValueError( f"format should be one of ['zip', 'nii', 'nii.gz'], " From 64912cdbd0c2e82106028175865305581e12fdd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yannick=20Lemar=C3=A9chal?= <10884038+ylemarechal@users.noreply.github.com> Date: Mon, 4 Aug 2025 23:58:14 +0200 Subject: [PATCH 45/45] change to in condition --- pyorthanc/_resources/resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyorthanc/_resources/resource.py b/pyorthanc/_resources/resource.py index ed94535c..b14af928 100644 --- a/pyorthanc/_resources/resource.py +++ b/pyorthanc/_resources/resource.py @@ -96,7 +96,7 @@ def _download_file( url = f'{url}/archive' elif file_format.lower() == 'dcm': url = f'{url}/file' - elif file_format.lower() == 'nii' or file_format.lower() == 'nii.gz': + elif file_format.lower() in ['nii', 'nii.gz']: if not self._is_neuro_plugin_installed(): raise PluginNotEnabledError( 'Neuro plugin is not installed or enabled on Orthanc instance. More information on https://orthanc.uclouvain.be/book/plugins/neuro.html'