[](https://github.com/gacou54/pyorthanc/actions?query=workflow%3ATest)
[](https://gacou54.github.io/pyorthanc/)


[](https://joss.theoj.org/papers/73f4c5a5e026aa4ef0e7ed9ed471a9a7)
# PyOrthanc
**PyOrthanc** is a comprehensive Python client for [Orthanc](https://www.orthanc-server.com/), providing:
- Complete wrapping of the Orthanc REST API methods
- High-level utilities for common DICOM operations
- Asynchronous client support
- Helper functions for working with DICOM data
- Integration with the [Orthanc Python plugin](https://orthanc.uclouvain.be/book/plugins/python.html)
## Why PyOrthanc?
PyOrthanc makes it easy to work with DICOM medical images stored on Orthanc servers using Python - instead
of dealing with the DICOM protocol directly or creating complex code to interact with Orthanc's REST API.
Researchers and clinicians can make simple Python script to access and manage their medical imaging data.
Advanced users can use PyOrthanc to make Orthanc query a hospital PACS (Picture Archiving and Communication System).
This allows to find and retrieve images produced in the clinic for research or quality control purposes.
Additionally, since PyOrthanc simplifies Orthanc's anonymization operations,
an entire medical image management workflow can be implemented in Python.
## PyOrthanc or python-orthanc-api-client?
Another project [`python-orthanc-api-client`](https://github.com/orthanc-team/python-orthanc-api-client)
from [orthanc-team](https://github.com/orthanc-team) is quite similar to `pyorthanc`.
If you are wondering which one to use, please refer to this [discussion](https://github.com/gacou54/pyorthanc/issues/80).
## Quick Install
```bash
pip install pyorthanc # Basic installation
pip install pyorthanc[all] # Install all optional dependencies
```
## Basic Usage
Assuming an Orthanc server running locally at `http://localhost:8042`:
```python
from pyorthanc import Orthanc, upload
# Connect to Orthanc server
client = Orthanc('http://localhost:8042')
# Or with authentication:
client = Orthanc('http://localhost:8042', username='orthanc', password='orthanc')
# Basic operations
patient_ids = client.get_patients()
studies = client.get_studies()
# Upload DICOM files
upload(client, 'image.dcm') # From a file
upload(client, 'dicom_files.zip') # From a zip
upload(client, 'path/to/directory') # Upload all dicom files in a directory
upload(client, 'path/to/directory', recursive=True) # Upload all dicom files in a directory recursively
# Check if dicom is in Orthanc before upload
upload(client, 'path/to/directory', recursive=True, check_before_upload=True)
```
## Working with DICOM Modalities
```python
from pyorthanc import Modality
# Create modality connection
modality = Modality(client, 'REMOTE_PACS')
# Test connection with C-ECHO
if modality.echo():
print("Successfully connected to PACS")
# Query studies with C-FIND
response = modality.find({
'Level': 'Study',
'Query': {
'PatientID': '12345*',
'StudyDate': '20230101-20231231'
}
})
# Matches (i.e. answers in Orthanc nomenclature) can be reviewed before retrieving results
response['answers']
# Retrieve results with C-MOVE to a target AET
modality.move(response['ID'], {'TargetAet': 'ORTHANC'})
```
## Finding and Processing DICOM Data
```python
from pyorthanc import find_patients, find_studies, find_series, find_instances
# Search for patients
patients = find_patients(
client,
query={'PatientName': '*Gabriel'},
labels=['research'] # It is also possible to filter by labels
)
# Process patient data
for patient in patients:
print(f"Patient: {patient.name} (ID: {patient.patient_id})")
print(f"Birth Date: {patient.birth_date}")
print(f"Labels: {patient.labels}")
# Access studies
for study in patient.studies:
print(f"\nStudy Date: {study.date}")
print(f"Description: {study.description}")
# Access series
for series in study.series:
print(f"\nModality: {series.modality}")
print(f"Series Description: {series.description}")
# Access individual DICOM instances
for instance in series.instances:
# Convert to pydicom dataset
ds = instance.get_pydicom()
# Process DICOM data...
# Note the existing function to query Orthanc
find_studies(client, query={...})
find_series(client, query={...})
find_instances(client, query={...})
```
## Using pyorthanc within Orthanc's Python plugin
Use the `orthanc_sdk` module when using [Orthanc's Python plugin](https://orthanc.uclouvain.be/book/plugins/python.html).
`orthanc_sdk` acts as the same as `orthanc`, but it provides type hints and autocompletion.
For example:
```python
from pyorthanc import orthanc_sdk
# Register a new REST endpoint
def handle_api(output: orthanc_sdk.RestOutput, uri: str, **request):
"""Handle REST API request"""
if request['method'] == 'GET':
output.AnswerBuffer('Hello from plugin!', 'text/plain')
else:
output.SendMethodNotAllowed('GET')
orthanc_sdk.RegisterRestCallback('/hello-world', handle_api)
# Handle incoming DICOM
def on_store(dicom: orthanc_sdk.DicomInstance, instance_id: str):
"""Process stored DICOM instances"""
print(f'Received instance {instance_id}')
print(f'Size: {dicom.GetInstanceSize()} bytes')
print(f'Transfer Syntax: {dicom.GetInstanceTransferSyntaxUid()}')
orthanc_sdk.RegisterOnStoredInstanceCallback(on_store)
```
## Examples
Typical example can be found in these notebooks.
- This [notebook](https://github.com/gacou54/pyorthanc/blob/main/examples/find_data.ipynb) shows
how a user can query image data from an Orthanc server
- This [notebook](https://github.com/gacou54/pyorthanc/blob/main/examples/modalities.ipynb) shows
how a user can query and pull data from other modality (such as a CT scan or a PACS) connected to an Orthanc Server.
## Notes on versioning
The `Orthanc` and `AsyncOrthanc` classes are generated from https://orthanc.uclouvain.be/api/.
Compatibility of versions between PyOrthanc and the Orthanc REST API are the following.
Note that recent PyOrthanc versions will likely support older Orthanc version.
| PyOrthanc version | Generated from |
|-------------------|-----------------------------------------------|
| \>= 1.20.0 | Orthanc API 1.12.6 with Python Plugin 4.2 |
| 1.19.0, 1.19.1 | Orthanc API 1.12.5 with Python Plugin 4.2 |
| 1.18.0 | Orthanc API 1.12.4 with Python Plugin 4.2 |
| 1.17.0 | Orthanc API 1.12.3 with Python Plugin 4.2 |
| 1.13.2 to 1.16.1 | Orthanc API 1.12.1 with Python Plugin 4.1 |
| 1.13.0, 1.13.1 | Orthanc API 1.12.1 with Python Plugin 4.0 |
| 1.12.* | Orthanc API 1.12.1 |
| 1.11.* | Orthanc API 1.11.3 |
| 0.2.* | Provided Google sheet from Orthanc maintainer |
## Running tests
The tests are run in a docker image launched with docker compose.
```shell
docker compose run test
```
This command starts 3 containers :
1. A Python image with the PyOrthanc source code and launches pytest
2. An instance of Orthanc (`orthanc1`) on which the PyOrthanc client is connected
3. A second Orthanc instance (`orthanc2`) which acts as a modality connected to `orthanc1`
## [Cheat sheet](docs/cheat_sheet.md)
## [First steps](docs/tutorial/quickstart.md#first-steps)
### [Getting started](docs/tutorial/quickstart.md#getting-started)
* [Connect to Orthanc](docs/tutorial/quickstart.md#connect-to-orthanc)
* [Upload DICOM files to Orthanc](docs/tutorial/quickstart.md#upload-dicom-files-to-orthanc)
* [Handle connected DICOM modalities](docs/tutorial/quickstart.md#getting-list-of-connected-remote-modalities)
* [Find and download patients according to criteria](docs/tutorial/quickstart.md#find-and-download-patients-according-to-criteria)
* [Query (C-Find) and Retrieve (C-Move) from remote modality](docs/tutorial/quickstart.md#query-c-find-and-retrieve-c-move-from-remote-modality)
### [Advanced examples](docs/tutorial/advanced.md)
### [Releases](https://github.com/gacou54/pyorthanc/releases)
### [Community guidelines](docs/contributing.md)
* [Report an issue](docs/contributing.md#report-an-issue)
* [Support](docs/contributing.md#seeking-support)
* [Contribute](docs/contributing.md#contribute)
## [Contacts](docs/contacts.md#contacts)
* [Maintainers Team](docs/contacts.md#maintainers-team)
* [Useful links](docs/contacts.md#useful-links)
## [Citation](docs/citation.md#citation)
Raw data
{
"_id": null,
"home_page": "https://gacou54.github.io/pyorthanc/",
"name": "pyorthanc",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.8",
"maintainer_email": null,
"keywords": "Orthanc, DICOM, Medical-Imaging",
"author": "Gabriel Couture",
"author_email": "gacou54@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/79/5f/5dda73a71bab2c718f05ff640225b61cf05d161b01bfa43a87500d2098c7/pyorthanc-1.22.1.tar.gz",
"platform": null,
"description": "[](https://github.com/gacou54/pyorthanc/actions?query=workflow%3ATest)\n[](https://gacou54.github.io/pyorthanc/)\n\n\n[](https://joss.theoj.org/papers/73f4c5a5e026aa4ef0e7ed9ed471a9a7)\n\n# PyOrthanc\n\n**PyOrthanc** is a comprehensive Python client for [Orthanc](https://www.orthanc-server.com/), providing:\n\n- Complete wrapping of the Orthanc REST API methods\n- High-level utilities for common DICOM operations \n- Asynchronous client support\n- Helper functions for working with DICOM data\n- Integration with the [Orthanc Python plugin](https://orthanc.uclouvain.be/book/plugins/python.html)\n\n\n## Why PyOrthanc?\nPyOrthanc makes it easy to work with DICOM medical images stored on Orthanc servers using Python - instead\nof dealing with the DICOM protocol directly or creating complex code to interact with Orthanc's REST API.\n\nResearchers and clinicians can make simple Python script to access and manage their medical imaging data.\n\nAdvanced users can use PyOrthanc to make Orthanc query a hospital PACS (Picture Archiving and Communication System).\nThis allows to find and retrieve images produced in the clinic for research or quality control purposes.\nAdditionally, since PyOrthanc simplifies Orthanc's anonymization operations,\nan entire medical image management workflow can be implemented in Python.\n\n## PyOrthanc or python-orthanc-api-client? \n\nAnother project [`python-orthanc-api-client`](https://github.com/orthanc-team/python-orthanc-api-client) \nfrom [orthanc-team](https://github.com/orthanc-team) is quite similar to `pyorthanc`. \n\nIf you are wondering which one to use, please refer to this [discussion](https://github.com/gacou54/pyorthanc/issues/80).\n\n## Quick Install\n```bash\npip install pyorthanc # Basic installation\npip install pyorthanc[all] # Install all optional dependencies\n```\n\n## Basic Usage\nAssuming an Orthanc server running locally at `http://localhost:8042`:\n```python\nfrom pyorthanc import Orthanc, upload\n\n# Connect to Orthanc server\nclient = Orthanc('http://localhost:8042')\n# Or with authentication:\nclient = Orthanc('http://localhost:8042', username='orthanc', password='orthanc')\n\n# Basic operations\npatient_ids = client.get_patients()\nstudies = client.get_studies() \n\n# Upload DICOM files\nupload(client, 'image.dcm') # From a file\nupload(client, 'dicom_files.zip') # From a zip\nupload(client, 'path/to/directory') # Upload all dicom files in a directory\nupload(client, 'path/to/directory', recursive=True) # Upload all dicom files in a directory recursively\n# Check if dicom is in Orthanc before upload\nupload(client, 'path/to/directory', recursive=True, check_before_upload=True)\n```\n\n## Working with DICOM Modalities\n\n```python\nfrom pyorthanc import Modality\n\n# Create modality connection\nmodality = Modality(client, 'REMOTE_PACS')\n\n# Test connection with C-ECHO\nif modality.echo():\n print(\"Successfully connected to PACS\")\n\n# Query studies with C-FIND\nresponse = modality.find({\n 'Level': 'Study',\n 'Query': {\n 'PatientID': '12345*',\n 'StudyDate': '20230101-20231231'\n }\n})\n\n# Matches (i.e. answers in Orthanc nomenclature) can be reviewed before retrieving results\nresponse['answers']\n\n# Retrieve results with C-MOVE to a target AET\nmodality.move(response['ID'], {'TargetAet': 'ORTHANC'})\n```\n\n## Finding and Processing DICOM Data\n\n```python\nfrom pyorthanc import find_patients, find_studies, find_series, find_instances\n\n# Search for patients\npatients = find_patients(\n client,\n query={'PatientName': '*Gabriel'},\n labels=['research'] # It is also possible to filter by labels\n)\n\n# Process patient data\nfor patient in patients:\n print(f\"Patient: {patient.name} (ID: {patient.patient_id})\")\n print(f\"Birth Date: {patient.birth_date}\")\n print(f\"Labels: {patient.labels}\")\n \n # Access studies\n for study in patient.studies:\n print(f\"\\nStudy Date: {study.date}\")\n print(f\"Description: {study.description}\")\n \n # Access series\n for series in study.series:\n print(f\"\\nModality: {series.modality}\")\n print(f\"Series Description: {series.description}\")\n \n # Access individual DICOM instances\n for instance in series.instances:\n # Convert to pydicom dataset\n ds = instance.get_pydicom()\n # Process DICOM data...\n\n# Note the existing function to query Orthanc\nfind_studies(client, query={...})\nfind_series(client, query={...})\nfind_instances(client, query={...})\n```\n\n## Using pyorthanc within Orthanc's Python plugin\n\nUse the `orthanc_sdk` module when using [Orthanc's Python plugin](https://orthanc.uclouvain.be/book/plugins/python.html).\n`orthanc_sdk` acts as the same as `orthanc`, but it provides type hints and autocompletion. \nFor example:\n\n```python\nfrom pyorthanc import orthanc_sdk\n\n# Register a new REST endpoint\ndef handle_api(output: orthanc_sdk.RestOutput, uri: str, **request):\n \"\"\"Handle REST API request\"\"\"\n if request['method'] == 'GET':\n output.AnswerBuffer('Hello from plugin!', 'text/plain')\n else:\n output.SendMethodNotAllowed('GET')\n\northanc_sdk.RegisterRestCallback('/hello-world', handle_api)\n\n# Handle incoming DICOM\ndef on_store(dicom: orthanc_sdk.DicomInstance, instance_id: str):\n \"\"\"Process stored DICOM instances\"\"\"\n print(f'Received instance {instance_id}')\n print(f'Size: {dicom.GetInstanceSize()} bytes')\n print(f'Transfer Syntax: {dicom.GetInstanceTransferSyntaxUid()}')\n\northanc_sdk.RegisterOnStoredInstanceCallback(on_store)\n```\n\n## Examples\nTypical example can be found in these notebooks.\n- This [notebook](https://github.com/gacou54/pyorthanc/blob/main/examples/find_data.ipynb) shows\n how a user can query image data from an Orthanc server\n- This [notebook](https://github.com/gacou54/pyorthanc/blob/main/examples/modalities.ipynb) shows\n how a user can query and pull data from other modality (such as a CT scan or a PACS) connected to an Orthanc Server. \n\n\n## Notes on versioning\n\nThe `Orthanc` and `AsyncOrthanc` classes are generated from https://orthanc.uclouvain.be/api/.\n\nCompatibility of versions between PyOrthanc and the Orthanc REST API are the following.\nNote that recent PyOrthanc versions will likely support older Orthanc version.\n\n| PyOrthanc version | Generated from |\n|-------------------|-----------------------------------------------|\n| \\>= 1.20.0 | Orthanc API 1.12.6 with Python Plugin 4.2 |\n| 1.19.0, 1.19.1 | Orthanc API 1.12.5 with Python Plugin 4.2 |\n| 1.18.0 | Orthanc API 1.12.4 with Python Plugin 4.2 |\n| 1.17.0 | Orthanc API 1.12.3 with Python Plugin 4.2 |\n| 1.13.2 to 1.16.1 | Orthanc API 1.12.1 with Python Plugin 4.1 |\n| 1.13.0, 1.13.1 | Orthanc API 1.12.1 with Python Plugin 4.0 |\n| 1.12.* | Orthanc API 1.12.1 |\n| 1.11.* | Orthanc API 1.11.3 |\n| 0.2.* | Provided Google sheet from Orthanc maintainer |\n\n\n## Running tests\nThe tests are run in a docker image launched with docker compose.\n\n```shell\ndocker compose run test\n```\nThis command starts 3 containers :\n1. A Python image with the PyOrthanc source code and launches pytest\n2. An instance of Orthanc (`orthanc1`) on which the PyOrthanc client is connected\n3. A second Orthanc instance (`orthanc2`) which acts as a modality connected to `orthanc1`\n\n## [Cheat sheet](docs/cheat_sheet.md)\n## [First steps](docs/tutorial/quickstart.md#first-steps)\n### [Getting started](docs/tutorial/quickstart.md#getting-started)\n* [Connect to Orthanc](docs/tutorial/quickstart.md#connect-to-orthanc)\n* [Upload DICOM files to Orthanc](docs/tutorial/quickstart.md#upload-dicom-files-to-orthanc)\n* [Handle connected DICOM modalities](docs/tutorial/quickstart.md#getting-list-of-connected-remote-modalities)\n* [Find and download patients according to criteria](docs/tutorial/quickstart.md#find-and-download-patients-according-to-criteria)\n* [Query (C-Find) and Retrieve (C-Move) from remote modality](docs/tutorial/quickstart.md#query-c-find-and-retrieve-c-move-from-remote-modality)\n### [Advanced examples](docs/tutorial/advanced.md)\n### [Releases](https://github.com/gacou54/pyorthanc/releases)\n### [Community guidelines](docs/contributing.md)\n* [Report an issue](docs/contributing.md#report-an-issue)\n* [Support](docs/contributing.md#seeking-support)\n* [Contribute](docs/contributing.md#contribute)\n## [Contacts](docs/contacts.md#contacts)\n* [Maintainers Team](docs/contacts.md#maintainers-team)\n* [Useful links](docs/contacts.md#useful-links)\n## [Citation](docs/citation.md#citation)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Orthanc REST API python wrapper with additional utilities",
"version": "1.22.1",
"project_urls": {
"Homepage": "https://gacou54.github.io/pyorthanc/",
"Repository": "https://github.com/gacou54/pyorthanc"
},
"split_keywords": [
"orthanc",
" dicom",
" medical-imaging"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "72b69cd2b48407088546ccb6d280be4448c2a3402879d85267a4ed4614924bcc",
"md5": "2df14737246e9387d5d4d96600db47ee",
"sha256": "4fcadb30aa84af57c0535ea1c5bbf1f27d3c5c215c212fc823dacff157dec4c0"
},
"downloads": -1,
"filename": "pyorthanc-1.22.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2df14737246e9387d5d4d96600db47ee",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.8",
"size": 123711,
"upload_time": "2025-07-14T15:12:49",
"upload_time_iso_8601": "2025-07-14T15:12:49.550157Z",
"url": "https://files.pythonhosted.org/packages/72/b6/9cd2b48407088546ccb6d280be4448c2a3402879d85267a4ed4614924bcc/pyorthanc-1.22.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "795f5dda73a71bab2c718f05ff640225b61cf05d161b01bfa43a87500d2098c7",
"md5": "689ade5dd47f019a77095ae4e726e13c",
"sha256": "a7b9a8e7f9a78f36cd2ca5e13f734b99ede5f94deb27ed0ab04fda0a55a5cc68"
},
"downloads": -1,
"filename": "pyorthanc-1.22.1.tar.gz",
"has_sig": false,
"md5_digest": "689ade5dd47f019a77095ae4e726e13c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.8",
"size": 110222,
"upload_time": "2025-07-14T15:12:50",
"upload_time_iso_8601": "2025-07-14T15:12:50.942782Z",
"url": "https://files.pythonhosted.org/packages/79/5f/5dda73a71bab2c718f05ff640225b61cf05d161b01bfa43a87500d2098c7/pyorthanc-1.22.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-14 15:12:50",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "gacou54",
"github_project": "pyorthanc",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pyorthanc"
}