pl-pacs_query is a ChRIS
ds plugin that queries a remote PACS using pfdcm and returns structured
metadata describing available DICOM studies or series.
The plugin communicates directly with a PACS using DICOM C-FIND through
pynetdicom. Queries are performed hierarchically: matching studies are
identified first, followed by a series-level query for each matching study.
The query results are written to the output directory as JSON files for downstream processing.
Querying a PACS for available imaging data is commonly the first step in automated DICOM retrieval and processing workflows.
pl-pacs_query provides this functionality within a ChRIS pipeline by
performing DICOM C-FIND operations against a configured remote PACS.
Because many PACS implementations do not support relational C-FIND queries, the plugin performs hierarchical Query/Retrieve:
StudyInstanceUID is collected from each matching study.StudyInstanceUID.pfdcm.autocomplete_directive() combines the original query directive with
the PACS response and calculates the expected number of DICOM instances.This hierarchical approach avoids relying on PACS support for relational queries and ensures that series queries are scoped to an exact parent study.
pl-pacs_query is a ChRIS plugin, meaning it can
run from either within ChRIS or the command-line.
| Argument | Description |
|---|---|
inputdir | Directory containing input files (read-only). May be empty. |
outputdir | Directory where query results will be written. |
| Option | Required | Description |
|---|---|---|
--src-aet | Yes | Called AE Title of the remote PACS. |
--src-ip | Yes | Hostname or IP address of the remote PACS. |
--src-port | Yes | DICOM port of the remote PACS. |
--dst-aet | Yes | Calling AE Title used by pl-pacs_query. This AE Title generally must be known/authorized by the PACS. |
| Option | Default | Description |
|---|---|---|
--PACSdirective | "" | JSON string containing the PACS query criteria. |
--reportName | "" | Name of the output report without the .json extension. If omitted, a deterministic hash-based report name is generated. |
--query-model | study | DICOM Query/Retrieve information model. Supported values are study and patient. |
-V, --version | — | Print the plugin version and exit. |
--PACSdirective accepts a JSON object describing the PACS query.
For example:
{
"PatientID": "TEST",
"StudyDate": "20251027"
}
When passed on the command line, quote the complete JSON string:
--PACSdirective '{"PatientID":"TEST","StudyDate":"20251027"}'
The directive is sanitized using pfdcm before being converted into a DICOM
query identifier.
The plugin uses a two-stage hierarchical C-FIND workflow.
The supplied PACS directive is converted into a STUDY-level DICOM identifier.
Conceptually:
PatientID = TEST
StudyDate = 20251027
QueryRetrieveLevel = STUDY
The remote PACS returns zero or more matching studies.
For every matching study, the plugin obtains its:
StudyInstanceUID
For every returned study, a second C-FIND is performed:
QueryRetrieveLevel = SERIES
StudyInstanceUID = <matching study UID>
This ensures that each SERIES query is scoped to a specific parent study.
The series responses are converted to dictionaries and collected into the
search response used by pfdcm.autocomplete_directive().
The plugin writes a JSON report to outputdir.
When --reportName is supplied:
--reportName search_results
the output is:
search_results.json
If --reportName is omitted, the plugin generates a deterministic MD5 hash
from the generated response:
search_results_<hash>.json
For example:
outgoing/
└── search_results_a2f4c80d20a74c42b79c47cf219cf15f.json
A result may contain fields such as:
[
{
"PatientID": "TEST",
"PatientName": "TEST",
"StudyDate": "20251027",
"StudyInstanceUID": "1.2.3.4.5",
"SeriesInstanceUID": "1.2.3.4.5.1",
"SeriesNumber": "1",
"SeriesDescription": "T1",
"Modality": "MR",
"NumberOfSeriesRelatedInstances": "100"
}
]
The exact fields returned depend on the remote PACS and the DICOM attributes included in its C-FIND responses.
To get started with local command-line usage, use Apptainer
(a.k.a. Singularity) to run pl-pacs_query as a container:
apptainer exec docker://fnndsc/pl-pacs_query pacs_query [--args values...] input/ output/
To print its available options, run:
apptainer exec docker://fnndsc/pl-pacs_query pacs_query --help
pacs_query requires two positional arguments: a directory containing
input data, and a directory where to create output data.
First, create the input directory and move input data into it.
mkdir incoming/ outgoing/
mv some.dat other.dat incoming/
apptainer exec docker://fnndsc/pl-pacs_query:latest \
pacs_query \
--src-aet TEST_PACS \
--src-ip 127.0.0.1 \
--src-port 104 \
--dst-aet TEST_CLIENT \
--PACSdirective '{"PatientID":"TEST","StudyDate":"20251027"}' \
--reportName search_results \
incoming/ outgoing/
Instructions for developers.
Build a local container image:
docker build -t localhost/fnndsc/pl-pacs_query .
Mount the source code pacs_query.py into a container to try out changes without rebuild.
docker run --rm \
-v "$PWD/incoming:/incoming:ro" \
-v "$PWD/outgoing:/outgoing:rw" \
local/pl-pacs_query \
pacs_query \
--src-aet TEST_PACS \
--src-ip PACS_HOST \
--src-port 104 \
--dst-aet TEST_CLIENT \
--PACSdirective '{"PatientID":"TEST","StudyDate":"20251027"}' \
--reportName search_results \
/incoming /outgoing
After a successful query:
outgoing/
└── search_results.json
Note: The PACS must be reachable from inside the container. The calling AE Title supplied with
--dst-aetmay also need to be registered or authorized by the remote PACS.
Run unit tests using pytest.
It's recommended to rebuild the image to ensure that sources are up-to-date.
Use the option --build-arg extras_require=dev to install extra dependencies for testing.
docker build -t localhost/fnndsc/pl-pacs_query:dev --build-arg extras_require=dev .
docker run --rm -it localhost/fnndsc/pl-pacs_query:dev pytest
Steps for release can be automated by Github Actions. This section is about how to do those steps manually.
Increase the version number in setup.py and commit this file.
Build and push an image tagged by the version. For example, for version 1.2.3:
docker build -t docker.io/fnndsc/pl-pacs_query:1.2.3 .
docker push docker.io/fnndsc/pl-pacs_query:1.2.3
Run chris_plugin_info
to produce a JSON description of this plugin, which can be uploaded to ChRIS.
docker run --rm docker.io/fnndsc/pl-pacs_query:1.2.3 chris_plugin_info -d docker.io/fnndsc/pl-pacs_query:1.2.3 > chris_plugin_info.json
Intructions on how to upload the plugin to ChRIS can be found here: https://chrisproject.org/docs/tutorials/upload_plugin
Content type
Image
Digest
sha256:b2f1ca9cc…
Size
57.5 MB
Last updated
19 days ago
docker pull fnndsc/pl-pacs_query