User guide

The client can be used with any DICOMweb server, such as dcm4che, orthanc or DICOMcloud.

Application Programming Interface (API)

To interact with a publicly accessible server, you only need to provide the url for the server address.

from dicomweb_client.api import DICOMwebClient

client = DICOMwebClient("https://mydicomwebserver.com")

Some servers expose the different DICOMweb RESTful services using different path prefixes. For example, the publicly accessible DICOMcloud server uses the prefixes "qidors", "wadors", and "stowrs" for QIDO-RS, WADO-RS, and STOW-RS, respectively. You can specify these prefixes using qido_url_prefix, wado_url_prefix, and stow_url_prefix.

from dicomweb_client.api import DICOMwebClient

client = DICOMwebClient(
    url="https://dicomcloud.azurewebsites.net",
    qido_url_prefix="qidors",
    wado_url_prefix="wadors",
    stow_url_prefix="stowrs"
)

To interact with servers requiring authentication, DICOMwebClient accepts arbitrary authentication handlers derived from requests.auth.AuthBase (see here for details).

from requests.auth import HTTPBasicAuth
from dicomweb_client.api import DICOMwebClient

client = DICOMwebClient(
    url="https://mydicomwebserver.com",
    auth=HTTPBasicAuth('myusername', 'mypassword')
)

To simplify usage for HTTPBasicAuth, you may also directly provide a username and password using the corresponding arguments.

from dicomweb_client.api import DICOMwebClient

client = DICOMwebClient(
    url="https://mydicomwebserver.com",
    username="myusername",
    password="mypassword"
)

To interact with server requiring certificate-based authentication, you can provide the CA bundle and client certificate using the ca_bundle and cert arguments, respectively.

from dicomweb_client.api import DICOMwebClient

client = DICOMwebClient(
    url="https://mydicomwebserver.com",
    ca_bundle="/path/to/ca.crt",
    cert="/path/to/cert.pem"
)

STOW-RS StoreInstances

Store a single dataset obtained from a PS3.10 file:

from dicomweb_client.api import DICOMwebClient
import pydicom

filename = "/path/to/file.dcm"
dataset = pydicom.dcmread(filename)
client.store_instances(datasets=[dataset])

QIDO-RS SeachForStudies

Search for all studies:

studies = client.search_for_studies()

Search for studies filtering by PatientID:

studies = client.search_for_studies(search_filters={'PatientID': 'ABC123'})

Note that attributes can be specified in search_filters using either the keyword or the tag:

studies = client.search_for_studies(search_filters={'00100020': 'ABC123'})

Search for all studies but limit the number of returned results using the limit parameter.

studies_subset = client.search_for_studies(limit=100)

A server may also automatically limit the number of results that it returns per search request. In this case, the method can be called repeatedly to request remaining results using the offset parameter.

studies = []
offset = 0
while True:
    subset = client.search_for_studies(offset=offset)
    if len(subset) == 0:
        break
    studies.extend(subset)
    offset += len(subset)

QIDO-RS SeachForSeries

Search for all series:

series = client.search_for_series()

Search for series of a given study:

series = client.search_for_series('1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639')

Search for series filtering by AccessionNumber:

series = client.search_for_series(search_filters={'AccessionNumber': '123456'})

Search for series filtering by AccessionNumber (using wildcard ? to match a range of numbers):

series = client.search_for_series(search_filters={'AccessionNumber': '12345?'})

Search for series filtering by SeriesDescription:

series = client.search_for_series(search_filters={'SeriesDescription': 'T2 AXIAL'})

Search for series filtering by SeriesDescription (using wildcard * to match a range of descriptions):

series = client.search_for_series(search_filters={'SeriesDescription': 'T2 AX*'})

Search for series filtering by Modality:

series = client.search_for_series(search_filters={'Modality': 'CT'})

QIDO-RS SeachForInstances

Search for all instances:

instances = client.search_for_instances()

Search for instances of a given study and series:

instances = client.search_for_instances(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
)

Search for instances filtering by SOPClassUID:

instances = client.search_for_instances(search_filters={'SOPClassUID': '1.2.840.10008.5.1.4.1.1.2'})

WADO-RS RetrieveStudy

Retrieve instances of a given study:

instances = client.retrieve_study('1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639')

WADO-RS RetrieveSeries

Retrieve instances of a given series:

instances = client.retrieve_series(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
)

Retrieve full instances of a given series using specific JPEG 2000 transfer syntax for encoding of bulk data:

instance = client.retrieve_instance(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    media_types=(('application/dicom', '1.2.840.10008.1.2.4.90', ), )
)

Retrieve bulk data of instances of a given series using specific JPEG 2000 transfer syntax:

instance = client.retrieve_instance(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    media_types=(('image/jp2', '1.2.840.10008.1.2.4.90', ), )
)

WADO-RS RetrieveInstance

Retrieve full instance using default Explicit VR Little Endian transfer syntax for encoding of bulk data:

instance = client.retrieve_instance(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
)

Retrieve full instance using specific JPEG 2000 transfer syntax for encoding of bulk data:

instance = client.retrieve_instance(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534',
    media_types=(('application/dicom', '1.2.840.10008.1.2.4.90', ), )
)

Retrieve bulk data of instance using specific JPEG 2000 transfer syntax:

instance = client.retrieve_instance(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534',
    media_types=(('image/jp2', '1.2.840.10008.1.2.4.90', ), )
)

WADO-RS RetrieveMetadata

Retrieve metadata for instances of a given study:

metadata = client.retrieve_study_metadata('1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639')

Retrieve metadata for instances of a given series:

metadata = client.retrieve_series_metadata(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
)

Retrieve metadata for a particular instance:

metadata = client.retrieve_instance_metadata(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639',
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
)

Note

WADO-RS RetrieveMetadata always returns metadata at the instance-level, retrieve_study_metadata() and retrieve_series_metadata() return an array of metadata items for each instance belonging to a given study and series, respectively.

WADO-RS RetrieveFrames

Retrieve a set of frames with default transfer syntax (“application/octet-stream”):

frames = client.retrieve_instance_frames(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
    frame_numbers=[1, 2]
)

Retrieve a set of frames of a given instances as JPEG compressed image:

frames = client.retrieve_instance_frames(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
    frame_numbers=[1, 2],
    media_types=('image/jpeg', )
)

Retrieve a set of frames of a given instances as compressed image in any available format:

frames = client.retrieve_instance_frames(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
    frame_numbers=[1, 2],
    media_types=('image/*', )
)

Retrieve a set of frames of a given instances as either JPEG 2000 or JPEG-LS compressed image:

frames = client.retrieve_instance_frames(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
    frame_numbers=[1, 2],
    media_types=('image/jp2', 'image/x-jpls', )
)

Retrieve a set of frames of a given instances as either JPEG, JPEG 2000 or JPEG-LS lossless compressed image using specific transfer syntaxes:

frames = client.retrieve_instance_frames(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
    frame_numbers=[1, 2],
    media_types=(
        ('image/jpeg', '1.2.840.10008.1.2.4.57', ),
        ('image/jp2', '1.2.840.10008.1.2.4.90', ),
        ('image/x-jpls', '1.2.840.10008.1.2.4.80', ),
    )
)

WADO-RS RetrieveBulkdata

Retrieve bulk data given a URL:

data = client.retrieve_bulkdata('https://mydicomwebserver.com/studies/...')

WADO-RS RetrieveRenderedTransaction

Retrieve a single-frame image instance rendered as a PNG compressed image:

frames = client.retrieve_instance_rendered(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
    media_types=('image/png', )
)

Retrieve a single frame of a multi-frame image instance rendered as a high-quality JPEG compressed image that includes an ICC profile:

frames = client.retrieve_instance_frames_rendered(
    study_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639'
    series_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034'
    sop_instance_uid='1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534'
    frame_numbers=[1],
    media_types=('image/jpeg', ),
    params={'quality': 95, 'iccprofile': 'yes'}
)

When frames are retrieved in image format, they can be converted into a NumPy array using the PIL module:

from io import BytesIO

import numpy as np
from PIL import Image

image = Image.open(BytesIO(frames[0]))
array = np.array(image)

Warning

Retrieving images using lossy compression methods may lead to image recompression artifacts if the images have been stored lossy compressed.

Loading JSON Data To pydicom

Load metadata from JSON format into a pydicom.dataset.Dataset object. A common use for this is translating metadata received from a RetrieveMetadata or a SearchFor-style request:

from dicomweb_client.api import load_json_dataset

metadata = client.retrieve_study_metadata('1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639')
metadata_datasets = [load_json_dataset(ds) for ds in metadata]

Command Line Interface (CLI)

Search for studies:

dicomweb_client --url https://dicomcloud.azurewebsites.net/qidors search studies

Retrieve metadata for all instances of a given study:

dicomweb_client --url https://dicomcloud.azurewebsites.net/wadors \
    retrieve studies \
    --study 1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639 \
    metadata

The output can be dicomized for human interpretation:

dicomweb_client --url https://dicomcloud.azurewebsites.net/wadors \
    retrieve studies \
    --study 1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639 \
    metadata \
    --dicomize

Retrieve the full Part 3.10 files for all instances of a given study:

dicomweb_client --url https://dicomcloud.azurewebsites.net/wadors \
    retrieve studies \
    --study 1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639 \
    full

Retrieve a single frame of a given instances as JPEG compressed image:

dicomweb_client --url https://dicomcloud.azurewebsites.net/wadors \
    retrieve instances \
    --study 1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639 \
    --series 1.2.826.0.1.3680043.8.1055.1.20111103111208937.49685336.24517034 \
    --instance 1.2.826.0.1.3680043.8.1055.1.20111103111208937.40440871.13152534 \
    frames \
    --numbers 1 \
    --media-type image/jpeg