Skip to content

bobvmierlo/PACSAdminTool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

363 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PACS Admin Tool

A portable, self-contained DICOM/HL7 workstation for PACS administrators.

No installation required — just run PacsAdminTool.exe or PacsAdminToolWeb.exe. Can also be run locally with Python and pip, or deployed as a Docker container.

Note: This tool was built for my own professional use. The repository is not actively maintained and issues may not be addressed.


Features

Web UI Tabs

Tab Functionality
Dashboard AE connectivity health check (batch C-ECHO all presets at once), service status, recent audit activity
C-FIND / Q-R Patient/Study/Series/Image level C-FIND with query builder; multi-select results with checkboxes; bulk C-MOVE or C-GET retrieve
C-STORE Send single files or entire folder trees to any Storage SCP
DICOM Receiver Embedded DICOM SCP — receive C-STORE and C-ECHO; auto-saves files; inspect tags or delete files per-row; auto-purges files older than 24 h
DMWL Full Modality Worklist query with export to CSV
Storage Commit Send N-ACTION storage commitment requests; receive async N-EVENT-REPORT responses with committed/failed breakdown
IOCM Send Instance Availability Notifications (delete/change notifications)
Inspector & Editor Upload any .dcm file; browse all tags in a searchable tree; inline tag editor lets you change any value, then download the modified file or send it directly via C-STORE; Diff sub-tab compares two DICOM files tag-by-tag
DICOM Validator Upload any .dcm file for conformance checking; validates file meta (group 0002), core UIDs, mandatory patient/study tags, pixel data consistency, UID collisions, and retired SOP classes; findings categorised as Error / Warning / Info
SR Viewer Parse any DICOM Structured Report as an interactive collapsible tree; colour-coded type/relationship badges; DCM-coded concepts link to the NEMA PS3.16 standard; filter bar
KOS Creator Build a DICOM Key Object Selection document (XDS-I manifest) from existing DICOM files
DICOMize Convert non-DICOM files to DICOM: PDF → Encapsulated PDF, images (JPEG/PNG/BMP/TIFF/WebP) → Secondary Capture, video (MP4/MOV) → Encapsulated Video; download or send directly to a PACS via C-STORE
Anonymizer Strip PHI from one or more DICOM files using a Basic or Full profile; download result as a ZIP
UID Remapper Generate fresh Study / Series / Instance UIDs for a batch of DICOM files while preserving internal referential integrity; preview the old→new UID mapping before downloading as ZIP
DICOMDIR Read a DICOMDIR file and browse the Patient → Study → Series → Instance hierarchy; or generate a standards-compliant DICOMDIR from uploaded files/folder and download as ZIP
DICOMweb QIDO-RS study/series/instance queries, STOW-RS multi-file upload, WADO-RS retrieve (packaged as ZIP); preset-based server configuration with Basic Auth and Bearer Token support
HL7 Send/receive HL7 v2 messages over MLLP; built-in templates for ORM, ORU, ADT, SIU, OML, QBP
Settings Manage local AE title/port, remote AE presets, HL7 defaults, language, log level
Logs Live view of application logs from ~/.pacs_admin_tool/logs/

Automatic Update Notifications

Both the desktop GUI and the web UI check GitHub Releases on startup and show a styled notification banner when a newer version is available.

Web UI — a blue slide-in banner appears below the header bar:

  • Shows the new version number and a link to the release page
  • On .exe builds: a "Download Update" button downloads the new binary in the background; once ready it becomes "Install & Restart" — the swap and restart happen automatically

Desktop GUI — a matching blue banner appears between the header and tabs:

  • Same Download / Install & Restart / View Release buttons
  • Fires 3 seconds after startup in a background thread; the UI is never blocked

Auto-update details:

  • Works for frozen PyInstaller executables (PacsAdminTool.exe, PacsAdminToolWeb.exe)
  • Windows: a detached batch script performs the swap after the process exits, then relaunches
  • Linux/macOS: the binary is replaced in-place and os.execv() restarts the process
  • Docker and source-code installs: only the "View Release ↗" link is shown (no auto-update)
  • Uses only Python standard-library modules (urllib, json, threading) — no extra packages required
  • Results are cached for 1 hour; GitHub is never contacted more than once per hour

System Tray Icon

Both the desktop GUI and the web server can show a system tray icon (notification area, bottom-right on Windows) when pystray and Pillow are installed. The app works without them, but system tray functionality will be disabled.

Desktop GUI:

  • Closing the window (X button) minimises the app to the tray instead of quitting
  • Double-click the tray icon or use the right-click menu to restore the window
  • Right-click menu: Show Window, Open Data Folder, Exit

Web Server:

  • The tray icon is the only visual indicator that the server is running (no console window)
  • Right-click menu: Open in Browser, Open Data Folder, Exit
  • No need to use Task Manager to stop the server — just click Exit in the tray menu

Quick Start (Desktop GUI)

# 1. Install dependencies
pip install pydicom pynetdicom hl7

# 2. (Optional) Install system tray support
pip install pystray Pillow

# 3. Run
python main.py

Quick Start (Web Version)

# 1. Install dependencies
pip install pydicom pynetdicom hl7 flask flask-socketio simple-websocket

# 2. (Optional) Install system tray support
pip install pystray Pillow

# 3. Run the web server
python webmain.py

# 4. Open in your browser
#    http://localhost:5000

To allow other PCs on your network to connect:

python webmain.py --host 0.0.0.0
# Others can reach it at http://<your-ip>:5000

To use a different port:

python webmain.py --port 8080

To enable debug mode with auto-reload:

python webmain.py --debug

Quick Start (Docker)

The web server is available as a pre-built Docker image on the GitHub Container Registry. No Python installation required — Docker is all you need.

Using docker-compose (recommended)

Copy the docker-compose.yml from this repository and run:

docker compose up -d

Then open http://localhost:5000 in your browser.

Config and logs are stored in a named Docker volume (pacs_data) so they survive container restarts and upgrades.

To upgrade to a newer version:

docker compose pull
docker compose up -d

docker-compose.yml options explained

services:
  pacsadmintool:
    image: ghcr.io/bobvmierlo/pacsadmintool:latest
    container_name: pacsadmintool
    restart: unless-stopped

    ports:
      - "5000:5000"       # Web UI — change the left number to use a different host port
                          # e.g. "8080:5000" to reach the UI at http://your-server:8080

      # Uncomment these if you want the built-in listeners to accept traffic
      # from outside the container. The left (host) port must match what you
      # configure in the Settings tab inside the app.
      #- "11112:11112"    # DICOM Storage SCP (C-STORE / C-ECHO receiver)
      #- "2575:2575"      # HL7 MLLP listener

    volumes:
      - pacs_data:/data   # Named volume — stores config.json and log files.
                          # Replace with a bind-mount if you prefer a specific path
                          # on the host, e.g.: - /opt/pacsadmin:/data

    environment:
      # PACS_DATA_DIR is already set to /data inside the image.
      # Only override this if you change the volume mount point above.
      # - PACS_DATA_DIR=/data

volumes:
  pacs_data:

Key settings at a glance:

Option What it does
"5000:5000" Maps host port → container port. Change the left number to expose the UI on a different host port.
"11112:11112" Required if you want to receive DICOM via C-STORE from external systems. Must match the SCP port in Settings.
"2575:2575" Required if you want to receive HL7 messages from external systems. Must match the HL7 listener port in Settings.
pacs_data:/data Named volume for persistent storage. Swap for a bind-mount (e.g. /opt/pacsadmin:/data) if you need direct host-filesystem access to your config or logs.
restart: unless-stopped The container restarts automatically after a reboot or crash. Use no to disable, or always to restart even after a manual docker stop.

Running without docker-compose

docker run -d \
  --name pacsadmintool \
  --restart unless-stopped \
  -p 5000:5000 \
  -v pacs_data:/data \
  ghcr.io/bobvmierlo/pacsadmintool:latest

Build a Portable .exe (Windows)

# One command:
build.bat

This produces dist\PacsAdminTool.exe — a single executable with no external dependencies.

Manual build steps:

pip install -r requirements.txt
pyinstaller pacs_tool.spec --clean --noconfirm

Build on Linux / macOS

chmod +x build.sh
./build.sh
# Output: dist/PacsAdminTool

Configuration

Settings are saved to ~/.pacs_admin_tool/config.json automatically. Logs are written to ~/.pacs_admin_tool/logs/ with automatic 7-day rotation.

When running in Docker the data directory is /data inside the container (controlled by the PACS_DATA_DIR environment variable). Mount a volume there to keep your config and logs across restarts — see the Docker section above.

Remote AE Presets

Add your PACS, RIS, and modality AE entries in the Settings tab. They become available as a dropdown in every other tab.

Language

The UI supports English and Dutch. Switch languages in the Settings tab.


DICOM Operations Reference

C-FIND

  • Supports Patient Root and Study Root query models
  • Query levels: PATIENT, STUDY, SERIES, IMAGE
  • Wildcard matching supported (e.g. SMITH* for patient name)
  • Results shown in a table with checkboxes for bulk selection

C-MOVE

  • Retrieve one or more C-FIND results to a destination AE
  • Destination must have your local AE registered as a known source
  • Bulk mode: select multiple rows and retrieve sequentially

C-GET

  • Alternative to C-MOVE — pulls files directly into the application without requiring an inbound port on the destination
  • Not supported by all PACS systems (optional per DICOM standard)
  • See the Help tab for a full C-MOVE vs C-GET comparison

C-STORE

  • Sends files using all common Storage SOP classes
  • Recursive folder scanning supported

DMWL

  • Queries ModalityWorklistInformationFind SOP
  • Filters: patient, date, modality, AE title, accession
  • CSV export of results

Storage Commitment

  • Sends N-ACTION with a list of SOP Class/Instance UID pairs
  • Async N-EVENT-REPORT arrives on a separate inbound association (requires the DICOM Receiver to be running)
  • Displays committed/failed counts and per-UID failure reason codes

IOCM

  • Sends Instance Availability Notification (N-CREATE)
  • Marks instances as UNAVAILABLE for delete notifications
  • Per PS3.4 Annex KK

DICOM Receiver (SCP Listener)

  • Runs a DICOM SCP in the background
  • Accepts C-STORE (all common modalities), C-ECHO, and Storage Commitment N-EVENT-REPORT callbacks
  • Saves received files to a configurable directory
  • Per-file Inspect (full tag browser) and Delete actions in the Files on Disk table
  • Auto-purge: files older than 24 hours are deleted on startup and nightly at 01:00 to prevent patient data from lingering

Inspector & Editor

Two sub-tabs in one panel — no PACS connection required.

Inspect & Edit sub-tab:

  • Upload any .dcm file and browse all tags in a searchable, collapsible tree
  • Sequence (SQ) elements expand inline; binary data shown as byte-length summary
  • Click Edit Tags… to open the inline Tag Editor: change any tag value in-place, track pending changes, then Download Modified File or Send to PACS via C-STORE

Diff sub-tab:

  • Select two .dcm files (File A and File B) and click Compare
  • Results table shows every tag with its status: Changed / Only in A / Only in B / Identical
  • Toggle "Show differences only" to filter out identical tags
  • Colour-coded rows: yellow = changed, red-tint = only in A, green-tint = only in B

DICOM Validator

Performs a DICOM conformance check on any .dcm file without sending it to a PACS.

Check categories:

Category What is verified
File Meta Group 0002 present, MediaStorageSOPClassUID matches SOPClassUID, transfer syntax present
Core UIDs SOPClassUID, SOPInstanceUID, StudyInstanceUID, SeriesInstanceUID — all present, valid UID format
Patient module Type 2 tags PatientName, PatientID, PatientBirthDate, PatientSex present (blank is allowed)
Study module StudyDate, StudyTime, AccessionNumber, ReferringPhysicianName — presence and format
Pixel data PixelData present for image SOP classes; consistency of Rows, Columns, BitsAllocated, SamplesPerPixel
UID collisions Detects Study/Series/Instance UIDs that are identical (copy-paste errors)
SOP class Flags retired SOP classes
Private tags Reports the number of private (odd-group) tags present

Severity levels:

  • Error — non-conformant; likely to cause import/routing failures in a PACS
  • Warning — technically valid but unusual; may cause interoperability issues
  • Info — informational only; no action required

Requirements: Only pydicom (already bundled) — no extra packages.

UID Remapper

Generates fresh Study / Series / Instance UIDs for a batch of DICOM files while preserving internal referential integrity.

Why you need this: Most PACS systems reject a C-STORE when the StudyInstanceUID already exists in their database. The UID Remapper creates brand-new UIDs so the study can be re-imported as a fresh study.

Remap levels:

Level Tags replaced
Study only StudyInstanceUID (0020,000D)
Study + Series StudyInstanceUID + SeriesInstanceUID (0020,000E)
Study + Series + Instance All three + SOPInstanceUID (0008,0018) + file meta MediaStorageSOPInstanceUID

Workflow:

  1. Select one or more DICOM files
  2. Choose a remap level (default: all UIDs)
  3. Optionally set a custom UID prefix (default 2.25. — UUID-based, globally unique without a registered root)
  4. Click Preview to inspect the old→new UID mapping before committing
  5. Click Download Remapped ZIP to get the modified files
  6. C-STORE via the C-STORE tab or upload via DICOMweb STOW-RS

All files from the same original study receive the same new StudyInstanceUID, maintaining referential integrity across a multi-file set.

Anonymizer

  • Upload one or more DICOM files
  • Basic profile: removes patient identifiers and institution details
  • Full profile: additionally removes study/series descriptions and other potentially identifying fields
  • Replacement patient name and ID can be specified
  • Output downloaded as a ZIP archive

DICOMDIR

  • Reader: upload a DICOMDIR file to browse the Patient → Study → Series → Instance hierarchy
  • Generator: upload individual DICOM files or an entire folder; a standards-compliant DICOM File Set (DICOMDIR + organised instance files) is generated using pydicom.FileSet and returned as a downloadable ZIP

DICOMweb (QIDO-RS / STOW-RS / WADO-RS)

Implements all three DICOMweb services defined in DICOM PS3.18 as an HTTP-based alternative to the traditional C-FIND / C-STORE / C-MOVE workflow.

Server configuration:

  • Base URL, authentication type (None / Basic / Bearer Token), and credentials are entered once per session or loaded from a named preset
  • Presets are saved in config.json under dicomweb_presets and are available in the dropdown on every session start

Sub-tabs:

Sub-tab Service What it does
QIDO-RS Query based on ID for DICOM Objects Queries studies, series, or instances using standard DICOM attributes as URL parameters; results rendered in a sortable table
STOW-RS Store Over the Web Uploads one or more local .dcm files to the server using a multipart/related; type=application/dicom POST
WADO-RS Web Access to DICOM Objects Retrieves one or more DICOM instances from the server; the server packages the multipart/related response into a .zip file for convenient download

Authentication:

  • None — plain HTTP/HTTPS, no credentials
  • Basic — HTTP Basic Auth (username + password encoded as Base64)
  • Bearer TokenAuthorization: Bearer <token> header (OAuth 2.0 / API keys)

Requirements: requests library (pip install requests); already included in requirements.txt and requirements-web.txt.

SR Viewer

Parses any DICOM Structured Report and renders it as an interactive collapsible tree.

Supported SR SOP classes:

  • Basic Text SR, Enhanced SR, Comprehensive SR, Comprehensive 3D SR
  • X-Ray Radiation Dose SR, Patient Radiation Dose SR, Enhanced X-Ray Radiation Dose SR
  • Mammography CAD SR, Chest CAD SR, Colon CAD SR
  • Simplified Adult Echo SR
  • Acquisition Context SR, Implantation Plan SR
  • Key Object Selection (KOS)
  • And any other SR SOP class (generic fallback)

Supported content item types: CONTAINER, NUM (with units), TEXT, CODE, IMAGE, UIDREF, PNAME, DATE, TIME, DATETIME, SCOORD, SCOORD3D, TCOORD, COMPOSITE, WAVEFORM

Tree viewer features:

  • CONTAINER items render as collapsible sections with a ▼/▶ toggle; click to expand/collapse
  • Colour-coded type badges (amber for NUM, purple for CODE, green for TEXT, …)
  • Relationship badges (CONTAINS, HAS OBS CONTEXT, INFERRED FROM, …)
  • Concept names coded in the DCM scheme are clickable links to NEMA PS3.16 (opens in a new tab)
  • Filter bar — live search across concept names and values; results shown as a flat table
  • Expand all / Collapse all controls
  • "View Raw DICOM Tags" button opens the full attribute list for low-level inspection

DICOMize

Converts non-DICOM files into valid DICOM objects using only the libraries already bundled in the tool (pydicom + Pillow — no extra packages required).

Sub-tabs:

Sub-tab Input Output DICOM SOP Class Notes
PDF Any PDF file Encapsulated PDF Storage (1.2.840.10008.5.1.4.1.1.104.1) PDF bytes stored verbatim
Images JPEG, PNG, BMP, TIFF, WebP, JFIF … Secondary Capture Image Storage (1.2.840.10008.5.1.4.1.1.7) Converted to 8-bit RGB; one .dcm per image
Video MP4, MOV … Video Photographic Image Storage (1.2.840.10008.5.1.4.1.1.77.1.2.1) MPEG-4 AVC/H.264 transfer syntax; video stored verbatim

Shared patient & study data card sits above the sub-tabs and is shared across all three. Fill it in once per session. Click the header to collapse it after filling.

  • Study Instance UID — enter to link to an existing study, or click Generate (RFC 4122 / 2.25.… style UID)
  • Download DICOM — converts and triggers a browser download (.dcm or .zip for multiple images)
  • Send to PACS — converts then immediately C-STOREs to the specified remote AE; supports presets from Settings

KOS Creator

Builds a DICOM Key Object Selection document (SOP 1.2.840.10008.5.1.4.1.1.88.59) that can be used as an XDS-I manifest when publishing a study to an IHE XDS domain.

Workflow:

  1. Load one or more DICOM files — the tool extracts patient, study, series, and instance metadata automatically.
  2. Review and edit the study/patient fields and the referenced instance list if needed.
  3. Choose a document title (Of Interest, For Referring Provider, XDS-I Manifest, etc.).
  4. Create & Save the KOS as a .dcm file, or Create & Send it directly via C-STORE.

Instance list format (one line per instance, # lines are comments):

# SeriesUID | SOPClassUID | SOPInstanceUID
1.2.3.4.5|1.2.840.10008.5.1.4.1.1.2|1.2.3.4.5.6.7

The generated KOS includes:

  • ContentSequence with IMAGE items and observer context
  • CurrentRequestedProcedureEvidenceSequence (required by DICOM PS3.3 C.17.6)
  • Proper file meta with Explicit VR Little Endian transfer syntax
  • All nine CID 7010 document titles, including XDS-I Manifest (DCM:113500)

HL7 Message Templates

Template Description
ORM^O01 Radiology order
OML^O21 Lab order
ORU^R01 Observation/report result
ADT^A04 Patient registration
ADT^A08 Patient update
ADT^A23 Delete visit
SIU^S12 Schedule appointment
SIU^S15 Cancel appointment
QBP^Q22 Patient demographics query (PDQ)

All templates are editable before sending. Raw HL7 text can also be pasted directly.


Requirements

Desktop version:

  • Python 3.10+
  • pynetdicom
  • pydicom
  • hl7

Optional:

  • pystray (system tray icon)
  • Pillow (icon rendering for tray)
  • PyInstaller (build only)

Web version (additional):

  • flask
  • flask-socketio
  • simple-websocket
  • requests (DICOMweb tab)

The compiled .exe has no runtime requirements.


Network Ports

Service Default Port
Local DICOM SCP 11112
HL7 MLLP Listener 2575
Web UI 5000

Configure in Settings tab or ~/.pacs_admin_tool/config.json.


Open-source credits

The web UI bundles the following JavaScript libraries (all served locally, no CDN):

Library Version Author / Project License Link
dwv (DICOM Web Viewer) 0.33 Yves Martelli GPL-3.0 github.com/ivmartel/dwv
Konva 8.4.2 Anton Lavrenov MIT github.com/konvajs/konva
JSZip 3.10.1 Stuart Knightley MIT / GPL-3.0 github.com/Stuk/jszip
magic-wand-tool 1.1.7 Ryasnoy Paul MIT github.com/Tamersoul/magic-wand-js
Socket.IO (client) 4.7.2 Guillermo Rauch MIT github.com/socketio/socket.io

The DICOM decoder Web Worker scripts bundled under web/static/decoders/ originate from the dwv project and its upstream sources:

  • decoders/pdfjs/ — JPEG 2000 / JPEG Baseline decoders adapted from Mozilla PDF.js (Apache-2.0)
  • decoders/rii-mango/ — JPEG Lossless decoder from rii-mango/jpeg-lossless-decoder-js (MIT)
  • decoders/dwv/ — RLE decoder from the dwv project (GPL-3.0)

About

All-in-one PACS Administrator tool

Resources

License

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors