Knowledge Base

Examples & Tutorials

Practical tutorials covering basic setup, DICOM operations, REST API usage, multi-PACS routing, and batch scripting.

Tutorial 1 — Basic setup and first DICOM echo

# 1. Extract and navigate
unzip DicomProxyRTWindows.zip -d C:\DicomProxy
cd C:\DicomProxy

appsettings.json:

{
  "DicomPort": 11112,
  "HttpPort": 8080,
  "StoragePath": "C:\\DicomStorage",
  "ThisModality": { "AE_Title": "DICOMPROXY", "Port": 11112, "IPAddress": "0.0.0.0" }
}
:: Start the service
DicomProxyRTWindows.exe

:: Test DICOM echo (DCMTK)
echoscu localhost 11112 -aet TESTCLIENT -aec DICOMPROXY
:: Expected: "Received Echo Response (Success)"

Tutorial 2 — Store your first DICOM image

# Store via DICOM protocol
storescu localhost 11112 -aet TESTCLIENT -aec DICOMPROXY sample.dcm

# Verify via HTTP API
curl http://localhost:8080/wado/studies

DICOM operations (DCMTK)

C-FIND

# All studies
findscu localhost 11112 -aet TESTCLIENT -aec DICOMPROXY \
  -k QueryRetrieveLevel=STUDY -k StudyInstanceUID

# By patient and date range
findscu localhost 11112 -aet TESTCLIENT -aec DICOMPROXY \
  -k QueryRetrieveLevel=STUDY \
  -k PatientName="DOE^JOHN" \
  -k StudyDate="20240101-20241231" \
  -k StudyInstanceUID=""

C-GET

getscu localhost 11112 -aet TESTCLIENT -aec DICOMPROXY \
  -k QueryRetrieveLevel=STUDY \
  -k StudyInstanceUID="1.2.3.4.5.6.7.8.9" \
  --output-directory ./retrieved

C-MOVE

movescu localhost 11112 -aet TESTCLIENT -aec DICOMPROXY \
  -aem DESTINATION_AE \
  -k QueryRetrieveLevel=STUDY \
  -k StudyInstanceUID="1.2.3.4.5.6.7.8.9"

REST API examples

QIDO-RS queries

# All studies
curl "http://localhost:8080/wado/studies"

# Filter by patient and date
curl "http://localhost:8080/wado/studies?PatientName=DOE*&StudyDate=20240101-20241231"

# Series for a study
curl "http://localhost:8080/wado/studies/1.2.3.4.5.6.7.8.9/series?Modality=CT"

WADO-RS retrieval

# Study metadata as JSON
curl -H "Accept: application/json" \
  "http://localhost:8080/wado/studies/1.2.3.4.5.6.7.8.9/metadata"

# Instance as DICOM file
curl -H "Accept: application/dicom" \
  "http://localhost:8080/wado/studies/.../instances/..." -o image.dcm

# Rendered JPEG thumbnail
curl -H "Accept: image/jpeg" \
  "http://localhost:8080/wado/studies/.../instances/.../rendered?viewport=512,512" \
  -o image.jpg

STOW-RS store

curl -X POST \
  -H "Content-Type: multipart/related; type=\"application/dicom\"" \
  --data-binary @image.dcm \
  "http://localhost:8080/wado/studies"

Multi-PACS routing configuration

servers.json:

{
  "servers": [
    {
      "id": "primary_pacs", "name": "Primary PACS", "ae_title": "PRIMARYPACS",
      "hostname": "192.168.1.100", "port": 11112, "enabled": true, "priority": 1,
      "supported_services": ["C-STORE", "C-FIND", "C-GET", "C-MOVE", "C-ECHO"]
    },
    {
      "id": "archive_pacs", "name": "Archive PACS", "ae_title": "ARCHIVEPACS",
      "hostname": "192.168.1.101", "port": 11112, "enabled": true, "priority": 2,
      "supported_services": ["C-STORE", "C-FIND", "C-GET", "C-ECHO"]
    },
    {
      "id": "cloud_pacs", "name": "Cloud PACS", "ae_title": "CLOUDPACS",
      "hostname": "cloud.pacs.example.com", "port": 11112, "enabled": true, "priority": 3,
      "supported_services": ["C-STORE", "C-FIND", "C-GET"]
    }
  ]
}
# Test each PACS
curl -X POST "http://localhost:8080/proxy/echo/primary_pacs"
curl -X POST "http://localhost:8080/proxy/echo/archive_pacs"

# Query specific PACS
curl "http://localhost:8080/proxy/wado/primary_pacs/rs/studies?PatientName=DOE*"

Batch upload (PowerShell)

# batch_upload.ps1
param(
    [string]$SourceFolder,
    [string]$ProxyUrl = "http://localhost:8080",
    [int]$ConcurrentUploads = 5
)

function Upload-DicomFile($FilePath, $Url) {
    try {
        Invoke-RestMethod -Uri "$Url/wado/studies" -Method Post `
          -ContentType "application/dicom" -InFile $FilePath -TimeoutSec 300
        return @{ Success = $true; File = $FilePath }
    }
    catch {
        return @{ Success = $false; File = $FilePath; Error = $_.Exception.Message }
    }
}

$files = Get-ChildItem -Path $SourceFolder -Filter "*.dcm" -Recurse
$total = $files.Count; $ok = 0; $fail = 0

for ($i = 0; $i -lt $total; $i += $ConcurrentUploads) {
    $batch = $files[$i..([Math]::Min($i + $ConcurrentUploads - 1, $total - 1))]
    $jobs = $batch | ForEach-Object { Start-Job -ScriptBlock ${function:Upload-DicomFile} -ArgumentList $_.FullName, $ProxyUrl }
    $jobs | Wait-Job | Receive-Job | ForEach-Object {
        if ($_.Success) { $ok++; Write-Host "OK  $($_.File)" -ForegroundColor Green }
        else            { $fail++; Write-Host "ERR $($_.File): $($_.Error)" -ForegroundColor Red }
    }
    $jobs | Remove-Job
}

Write-Host "Done. Success: $ok  Failures: $fail"

Monitoring (Python)

import requests, time, logging

class DicomProxyMonitor:
    def __init__(self, url="http://localhost:8080"):
        self.url = url
        logging.basicConfig(level=logging.INFO)
        self.log = logging.getLogger(__name__)

    def check_status(self):
        r = requests.get(f"{self.url}/api/status", timeout=10)
        if r.ok:
            self.log.info(f"Studies: {r.json().get('studies_count')}")
            return True
        return False

    def check_pacs(self):
        r = requests.get(f"{self.url}/api/connections", timeout=10)
        if r.ok:
            for s in r.json().get('configured_servers', []):
                level = logging.INFO if s['status'] == 'Connected' else logging.WARNING
                self.log.log(level, f"PACS {s['id']}: {s['status']}")

    def monitor(self, interval=300):
        while True:
            if self.check_status():
                self.check_pacs()
            time.sleep(interval)

Troubleshooting common issues

Connection timeout

curl http://localhost:8080/api/status
curl -X POST http://localhost:8080/proxy/echo/pacs1

Increase timeout_seconds and retry_count in servers.json for that server.

Storage full

Use the automated cleanup configuration or run POST /api/database/cleanup, and increase MaxStorageSizeGB in appsettings.json.

SSL certificate setup

# ssl_setup.ps1
param([string]$CertPath = "C:\DicomProxy\certificate.pfx", [string]$Password = "Secure!")

$cert = New-SelfSignedCertificate -DnsName "localhost" `
  -CertStoreLocation "cert:\LocalMachine\My" `
  -KeyUsage DigitalSignature,KeyEncipherment

Export-PfxCertificate -Cert $cert -FilePath $CertPath `
  -Password (ConvertTo-SecureString $Password -AsPlainText -Force)

$config = Get-Content "appsettings.json" | ConvertFrom-Json
$config.Security.EnableTLS = $true
$config.Security.CertificatePath = "certificate.pfx"
$config.Security.CertificatePassword = $Password
$config | ConvertTo-Json -Depth 10 | Set-Content "appsettings.json"

See also: Configuration Reference | API Reference