Skip to main content

PACS/ChRIS core tools and utils

Project description

https://badge.fury.io/py/pypx.svg

1. Overview

pypx is a complete client-side PACS (Picture Archive and Communications System) Query/Retrieve/Storage solution that operates in stand-alone script mode in addition to providing a set of python modules for use in other packages. The modules/API provide a simple mechanism for a python program to interact with an appropriately configured remote PACS, while the stand alone scripts offer a convenient ability to directly Query/Retrieve/Store images from the command line.

pypx was mostly developed for use in the ChRIS system as part of the pfdcm microservice; however the CLI scripts of pypx and the provided docker image offer a quick and powerful means of accessing a PACS without any additional overhead.

1.1 Complete Client Side

This solution is client-side and cannot operate fully independently of an appropriately configured PACS. Unfortunately, simply downloading this repo/tools and pointing the scripts at some PACS is insufficient. The PACS itself (which is NOT part of this repo) needs to be configured to service communications and requests from these tools. See below for more information.

1.1.1 Quick PACS Primer

A PACS exists as a separate service on a network, and pypx communicates with a pre-configured PACS when asking for Query data and when Retrieving images. Importantly, from the client perspective, data is PUSHED from the PACS, and not PULLED from the client. This means that client software in essence “asks” the PACS for images and the PACS obliges by transmitting the images over the network to a pre-configured location.

Communications with a PACS are for the most insecure and reflected a circa 1990s view/model of internetworking. When a client communicates with a PACS, it sends along with every request string identifiers unique to the client and configured in the PACS. Typical identifiers are the AETitle and sometimes additionally the CalledAETitle. The PACS examines these strings on receipt to identify/authenticate the client and also to identify a destination network IP:port to which data can be transmitted.

1.1.2 Configuring a PACS

In order to be fully complete, a destination PACS with which pypx modules wish to communicate needs to be configured with appropriate AETitle, CalledAETitle, as well as the network address IP and port of the pypx hosting machine. Configuring a PACS is obviously outside of the scope of this documentation. Consult your PACS for information on this configuration.

As a brief note, if the opensource orthanc PACS server is being used, the orthanc.json can be edited to include

{
    "DicomAet" : "CHRISV3T"
}

and

{
   "CHRIS" : [ "CHRIS", "10.72.76.39", 10402 ],
   "CHRISLOCAL" : ["CHRISLOCAL", "192.168.1.189", 11113 ]
}

where CHRISLOCAL for example defines a DICOM storescp service on the host 192.168.1.189 and port 11113 while CHRIS defines another destination storescp service .

1.1.3 Configuring pypx

Locally, however, some configuration is required and conveniently located in the script PACS_QR.sh. In the

function institution_set
{
    ...
}

simply add another block reflecting the variables appropriate to your remote PACS service.

1.2 Components

1.2.1 Environment

pypx can be thought of as a bridge connecting a PACS to a ChRIS instance. In between these services is a filesystem. A retrieve operation will request files from a PACS which arrive over the network and a separately configured listening service repacks these files in a specially configured location called the BASEMOUNT. Once these files are received, they can be push -ed to special ChRIS friendly storage called swift, and once there they can be register -ed to ChRIS/CUBE. Each of these services (swift and CUBE) have network locations and login details which are stored in the BASEMOUNT in <BASEMOUNT>/services/[swift,cube].json. Many different swift and CUBE configurations can in theory exist in these json files. Each configuration is identified by a key – the SWIFTKEY for the swift service and the CUBEKEY for the CUBE service. Using these keys makes for a convenient way to push and register files without very verbose CLI.

See PACS_QR.sh -x for some in-line help on setting these keys.

1.2.2 Tools

Internally, the code wraps around DCMTK utilies as well as the PyDicom module. The following modules/scripts are provided:

  • pfstorage: Query / put files/objects into swift storage.

  • px-do: Perform various downstream utility functions once a px-find has completed.

  • px-echo: Ping the PACS to make sure it is online (echoscu).

  • px-find: Find (Query) a PACS in a variety of ways. The start point of almost all other workflows which are constructed as find _then_ do.

  • px-listen: Deprecated listening service wrapper.

  • px-move: Move data from the PACS (movescu).

  • px-push: Push DICOM data to a remote node (either a PACS or a ChRIS swift object storage container).

  • px-register: A companion to px-push that registers files in ChRIS swift storage to the ChRIS CUBE backend.

  • px-repack: Read and repack DICOM files, organizing the destination in a human-friendly tree based layout.

  • px-report: Consume the JSON outputs of many of the tools (esp the px-find and generate various console-based reports).

  • px-status: Report on the status of query results in the BASEMOUNT.

  • px-smdb: A simple file-system based database that provides tracking and query for processed DICOM files.

2. Installation

2.1 Prerequisites

For all installation solutions, make sure that the machine receiving images from a PACS has approporate listening and repacking services and that the PACS itself has been configured to recognize this machine. While out of scope of this document, the simplest way to set this up is to use the pfdcm service (provided separately).

2.2 Using docker

Using the dockerized container is the recommended installation vector as the image contains all tools (dcmtk) that can interact both with a PACS as well as swift storage and CUBE without any additional software on the host system.

docker pull fnndsc/pypx

Alternatively, you can build a local image with

# If behing a proxy
PROXY=http://some.proxy.com
export UID=$(id -u)
DOCKER_BUILDKIT=1 docker build --build-arg http_proxy=${PROXY} --build-arg UID=$UID -t local/pypx .

# otherwise...
export UID=$(id -u)
DOCKER_BUILDKIT=1 docker build --build-arg UID=$UID -t local/pypx .

2.3 PyPI

For convenience, a PyPI installation is also available. This assumes additional non-python requirements such as dcmtk have been installed. This is recommended only for advanced users.

apt-get update                                   \
&& apt-get install -y dcmtk                      \
&& apt-get install -y python3-pip python3-dev    \
&& pip3 install --upgrade pip                    \
&& pip install pypx

3. Configuring the containerized version

If using the container tool images directly, take care to assure that the machine receiving PACS transmissions is available and has a listener service accessible on an exposed port. This port should be accessible to the remote PACS. Our strong recommendation is to use the companion pfdcm container/repo to receive PACS data. Note that pfdcm itself contains pypx and will handle the reception and repacking of DICOM files using the correct pypx tools.

4 Usage

4.1 PACS_QR.sh and workflow.sh

For the most complete example, please consult the workflow.sh script in the source repository. This provides a Jupyter-notebook-shell-eque overview of most if not all the possible methods to call and use these tools.

For the most convenient example, use the PACS_QR.sh script – consult its internal help with

PACS_QR.sh -x

4.2 PACS_QR.sh quick-n-dirty

The PACS_QR.sh has several implicit assumptions and values that can/should be set by approprate CLI. The entire scope is beyond this simple README, however, assuming these values are set (either by using the defaults or an appropriate/custom institution_set function), the workflow is rather simple. Assuming an MRN of say 7654321,

# Query
PACS_QR.sh -- "--PatientID 7654321"

# More "low level" -- in fact `PACS_QR.sh` is mostly a convenience wrapper
# around these low level functions. For completeness sake the low level
# `Query` is shown here. Note that passing `PACS_QR.sh -v 1 ...` will
# instruct `PACS_QR.sh` to show the actual commands it uses.
px-find \
     --aec CHRIS \
     --aet CHRISV3 \
     --serverIP 134.174.12.21 \
     --serverPort 104 \
     --db /home/dicom/log \
     --verbosity 1 \
     --PatientID 7654321

# A similar call using the
#    --then report --withFeedBack
# (note if --then <something> is specified, then a --withFeedBack needs to be added
# for console ouput)
# Also, this report shows the SeriesInstanceUIDs in the report body
px-find \
     --aec CHRIS \
     --aet CHRISV3 \
     --serverIP 134.174.12.21 \
     --serverPort 104 \
     --db /home/dicom/log \
     --verbosity 1 \
     --PatientID 7654321 --then report --withFeedBack

# For the most flexibility in reporting, set find results to be JSON
# and pipe the json into the `px-report` app.
px-find \
     --aec CHRIS \
     --aet CHRISV3 \
     --serverIP 134.174.12.21 \
     --serverPort 104 \
     --db /home/dicom/log \
     --verbosity 1 --json \
     --PatientID 7654321 |\
px-report \
     --colorize dark \
     --printReport tabular

# Retrieve
PACS_QR.sh --do retrieve -- "--PatientID 7654321"

# Status
PACS_QR.sh --do status -- "--PatientID 7654321"

# Push to CUBE swift storage
PACS_QR.sh --do push -- "--PatientID 7654321"

# Register to CUBE internal DB
PACS_QR.sh --do register -- "--PatientID 7654321"

Note carefully the syntax of the above PACS_QR.sh commands! A -- string separates script <key>/<value> pairs from a string defining the search parameters. Note that most valid DICOM tags can be used for this string. More tags can also make a search more specific, for instance

"--PatientID 7654321 --StudyDate 19990909"

will limit returns only to hits performed on given StudyDate.

5. Development and debugging

The recommended development/debug approach is to mount source directories into the container and thus debug the containerized code from the host. Assuming you are in the source code repo root, and assuming you want to debug px-push:

# Make sure that all env variables below are set appropriately!
docker run --rm -ti -v $PWD/pypx:/usr/local/lib/python3.8/dist-packages/pypx \
    -v $PWD/bin/px-push:/usr/local/bin/px-push                               \
    -v $LOCALDICOMDIR:$LOCALDICOMDIR -v $BASEMOUNT:$BASEMOUNT $PYPX          \
    --px-push                                                                \
              --swiftIP $SWIFTHOST                                           \
              --swiftPort $SWIFTPORT                                         \
              --swiftLogin $SWIFTLOGIN                                       \
              --swiftServicesPACS $SWIFTSERVICEPACS                          \
              --db $DB                                                       \
              --swiftPackEachDICOM                                           \
              --xcrdir $LOCALDICOMDIR                                        \
              --parseAllFilesWithSubStr dcm                                  \
              --verbosity 1                                                  \
              --json

7. Additional support (incomplete)

Please see the relevant wiki pages for usage instructions (some are still under construction):

7. Credits

PyDicom

DCMTK

  • Author(s): Dicom @ OFFIS Team

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pypx-3.12.6.tar.gz (91.1 kB view details)

Uploaded Source

Built Distribution

pypx-3.12.6-py3-none-any.whl (114.7 kB view details)

Uploaded Python 3

File details

Details for the file pypx-3.12.6.tar.gz.

File metadata

  • Download URL: pypx-3.12.6.tar.gz
  • Upload date:
  • Size: 91.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for pypx-3.12.6.tar.gz
Algorithm Hash digest
SHA256 6e98465366a0b53cfd8cacb675f4b16e72be63f6f55f9237a1026a700949f741
MD5 78be8ceb5ec0c0e55786c1dba5a52f83
BLAKE2b-256 7e6cef0d9d59e14c376452a9a7faacc2c5c4e24b5663544e93614074ab08427f

See more details on using hashes here.

File details

Details for the file pypx-3.12.6-py3-none-any.whl.

File metadata

  • Download URL: pypx-3.12.6-py3-none-any.whl
  • Upload date:
  • Size: 114.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.0.0 CPython/3.12.3

File hashes

Hashes for pypx-3.12.6-py3-none-any.whl
Algorithm Hash digest
SHA256 b8a47cd22edd1f09bbe56cc7db4423d4bdbb9a541ac411b862bd481fefa8ffcd
MD5 1abf4127ed28e5f99bfe7ebdf9b38ea2
BLAKE2b-256 7db593e2b5072131f75af74e955edf3b3574e5c160c4f8d054d3ba0245912523

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page