User guide
The client can be used with any DICOMweb server, such as dcm4che, orthanc or DICOMcloud.
Application Programming Interface (API)
Interacting with a remote DICOMweb server
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(url="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"
)
Accessing local DICOM Part10 files
The package provides the dicomweb_client.api.DICOMfileClient
class for accessing data stored as DICOM Part10 files on a file system.
The class exposes the same dicomweb_client.api.DICOMClient
interface as the dicomweb_client.api.DICOMwebClient
and can be used as a drop-in replacement.
To create a dicomweb_client.api.DICOMfileClient
instance, you should pass the location of the desired data store on the file system. Note that the file:// scheme
designator is required.
from dicomweb_client.api import DICOMfileClient
client = DICOMfileClient("file:///path/to/directory")
STOW-RS StoreInstances
Store a single dataset obtained from a PS3.10 file:
import pydicom
filename = "/path/to/file.dcm"
dataset = pydicom.dcmread(filename)
client.store_instances(datasets=[dataset])
QIDO-RS SeachForStudies
Search for all studies (up to server-defined maximum set per call - see below to iteratively get 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)
The same can be achieved more conveniently using the get_remaining
parameter.
studies = client.search_for_studies(get_remaining=True)
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': 'SM'})
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/jls', )
)
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/jls', '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 pydicom.dataset import Dataset
metadata = client.retrieve_study_metadata('1.2.826.0.1.3680043.8.1055.1.20111103111148288.98361414.79379639')
metadata_datasets = [Dataset.from_json(ds) for ds in metadata]
Note that the metadata may include references to BulkData elements.
By default, BulkData elements will not be handled and the values not be automatically retrieved.
To handle BulkData elements and retrieve their values, one has to provide a bulk_data_uri_handler
callable to the pydicom.dataset.Dataset.from_json() method.
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
Store instances to a Google DICOMweb store:
dicomweb_client --url https://healthcare.googleapis.com/v1beta1/projects/MYPROJECT/locations/us-central1/datasets/MYDATASET/dicomStores/MYDICOMSTORE/dicomWeb \
--token $(gcloud auth print-access-token) \
store instances \
dicomfiles/*