Skip to content

First steps

Installation

pip install pyorthanc

Getting started

Connect to Orthanc

Here are some quick how to examples to use pyorthanc

from pyorthanc import Orthanc

orthanc = Orthanc(url='http://localhost:8042/', username='orthanc', password='orthanc')

Upload DICOM files to Orthanc:

with open('A_DICOM_INSTANCE_PATH.dcm', 'rb') as file:
    orthanc.post_instances(file.read())

Getting list of connected remote modalities:

modalities = orthanc.get_modalities()

Query (C-Find) and Retrieve (C-Move) from remote modality:

from pyorthanc import Modality

modality = Modality(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)

# Retrieve (C-Move) results of query on a target modality (AET)
modality.move(query_response['ID'], {'TargetAet': 'target_modality'})

Find and download patients according to criteria:

from pyorthanc import find_patients, retrieve_and_write_patients

patients = find_patients(
    client=orthanc,
    query={'PatientName': '*Gabriel'},  # Filter on PatientName
    labels=['a-label']  # Filter on patients with the 'a-label'
)

Download the patients data as a zip file

from pyorthanc import retrieve_and_write_patients

for patient in patients:
    patient.download(f'./data/patient-{patient.patient_id}.zip', with_progres=False)

# As a directory tree DICOM files (patients -> studies -> series -> instances)
retrieve_and_write_patients(patients, './data/')

Or manipulates the Patient object

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

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=[...])

If you have the Patient ID, StudyInstanceUID, the SeriesInstanceUID and/or the SOPInstanceUID, you can generate the Orthanc IDs:

from pyorthanc import util, Patient

util.to_orthanc_patient_id('patient_id')  # '8dfa510b-b29ad31a-b2139fbf-b9929710-2edfa5c2'
util.to_orthanc_study_id('patient_id', 'study_uid')  # 'f9c33ef9-0bcdc38b-c216e9e8-8dbd62c1-28e4815c'
util.to_orthanc_series_id('patient_id', 'study_uid', 'series_uid')  # 'beceea8b-5424ff8c-3c76fe2e-edfed858-819fe6e1'
util.to_orthanc_instance_id('patient_id', 'study_uid', 'series_uid', 'instance_uid')  # '0e7848a0-4337f771-bda13733-150f651b-dfddd545'

patient = Patient('8dfa510b-b29ad31a-b2139fbf-b9929710-2edfa5c2', client)

Anonymize patient

Resources (Patient, Study, Series, Instance) can be easily anonymized.

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)

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

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)

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 children of the resources Patient/Study/Series/Instance are only query once and then filtered accordingly to the provided filters.

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.

Develop with the Orthanc's Python Plugin

The orthanc_sdk is useful when developing with the Orthanc's Python Plugin, it exposes orthanc module when available (i.e. used as an Orthanc script), or expose the functions/classes signatures when not for linting and autocomplete.

Use it the same way you would use the Python Plugin:

# Has the same signature as `import orthanc`
from pyorthanc import orthanc_sdk 

def on_get(output: orthanc_sdk.RestOutput, *_, **__):
    output.AnswerBuffer('ok', 'text/plain')

orthanc_sdk.RegisterRestCallback('/test', on_get)

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.

Access instance information

Get instance informations