Query/Retrieve (Find) Service Examples¶
The DICOM Query/Retrieve Service provides a mechanism for a service user to query the SOP Instances managed by a QR SCP. The QR (Find) SOP classes allow an SCU to receive a list of attributes matching the requested query. This is accomplished through the DIMSE C-FIND service.
Query/Retrieve (Find) SCU¶
Associate with a peer DICOM Application Entity and request the SCP search for
SOP Instances with a Patient Name matching CITIZEN^Jan using Patient
Root Query/Retrieve Information Model - Find at the 'PATIENT' level.
from pydicom.dataset import Dataset
from pynetdicom import AE, debug_logger
from pynetdicom.sop_class import PatientRootQueryRetrieveInformationModelFind
debug_logger()
ae = AE()
ae.add_requested_context(PatientRootQueryRetrieveInformationModelFind)
# Create our Identifier (query) dataset
ds = Dataset()
ds.PatientName = 'CITIZEN^Jan'
ds.QueryRetrieveLevel = 'PATIENT'
# Associate with the peer AE at IP 127.0.0.1 and port 11112
assoc = ae.associate('127.0.0.1', 11112)
if assoc.is_established:
    # Send the C-FIND request
    responses = assoc.send_c_find(ds, PatientRootQueryRetrieveInformationModelFind)
    for (status, identifier) in responses:
        if status:
            print('C-FIND query status: 0x{0:04X}'.format(status.Status))
        else:
            print('Connection timed out, was aborted or received invalid response')
    # Release the association
    assoc.release()
else:
    print('Association rejected, aborted or never connected')
The responses received from the SCP are dependent on the Identifier dataset
keys and values, the Query/Retrieve level and the information model. For
example, provided the optional attribute SOP Classes in Study is supported,
the following query dataset should yield C-FIND responses containing
the various SOP Class UIDs that make are in each study for a patient with
Patient ID 1234567.
ds = Dataset()
ds.SOPClassesInStudy = ''
ds.PatientID = '1234567'
ds.StudyInstanceUID = ''
ds.QueryRetrieveLevel = 'STUDY'
Query/Retrieve (Find) SCP¶
The following represents a toy implementation of a Query/Retrieve (Find) SCP where the SCU has sent the following Identifier dataset under the Patient Root Query Retrieve Information Model - Find context.
ds = Dataset()
ds.PatientName = 'CITIZEN^Jan'
ds.QueryRetrieveLevel = 'PATIENT'
This is a very bad way of managing stored SOP Instances, in reality its probably best to store the instance attributes in a database and run the query against that, which is the approach taken by the qrscp application.
Check the
handler implementation documentation
to see the requirements for the evt.EVT_C_FIND handler.
 import os
 from pydicom import dcmread
 from pydicom.dataset import Dataset
 from pynetdicom import AE, evt
 from pynetdicom.sop_class import PatientRootQueryRetrieveInformationModelFind
 # Implement the handler for evt.EVT_C_FIND
 def handle_find(event):
     """Handle a C-FIND request event."""
     ds = event.identifier
     # Import stored SOP Instances
     instances = []
     fdir = '/path/to/directory'
     for fpath in os.listdir(fdir):
         instances.append(dcmread(os.path.join(fdir, fpath)))
     if 'QueryRetrieveLevel' not in ds:
         # Failure
         yield 0xC000, None
         return
     if ds.QueryRetrieveLevel == 'PATIENT':
         if 'PatientName' in ds:
             if ds.PatientName not in ['*', '', '?']:
                 matching = [
                     inst for inst in instances if inst.PatientName == ds.PatientName
                 ]
             # Skip the other possibile values...
         # Skip the other possible attributes...
     # Skip the other QR levels...
     for instance in matching:
         # Check if C-CANCEL has been received
         if event.is_cancelled:
             yield (0xFE00, None)
             return
         identifier = Dataset()
         identifier.PatientName = instance.PatientName
         identifier.QueryRetrieveLevel = ds.QueryRetrieveLevel
         # Pending
         yield (0xFF00, identifier)
handlers = [(evt.EVT_C_FIND, handle_find)]
# Initialise the Application Entity and specify the listen port
ae = AE()
# Add the supported presentation context
ae.add_supported_context(PatientRootQueryRetrieveInformationModelFind)
# Start listening for incoming association requests
ae.start_server(('', 11112), evt_handlers=handlers)