DICOM Basics - General Troubleshooting Tips and Techniques
Introduction
This is part of my series of articles on the DICOM standard. In this article, we'll cover practical troubleshooting techniques for diagnosing and resolving common DICOM communication issues. Whether you're dealing with failed associations, missing images, or query problems, these techniques will help you identify and fix the root cause.
DICOM integration can be challenging due to the many configuration parameters and the variety of vendor implementations. A systematic troubleshooting approach will save time and frustration.
The Troubleshooting Mindset
Before diving into specific issues, adopt these principles:
- Start Simple: Verify basic connectivity before complex operations
- One Change at a Time: Make single changes and test
- Document Everything: Keep notes on what you've tried
- Check Both Ends: Problems can be on either side of the connection
- Read the Logs: DICOM systems usually have detailed logging
Common DICOM Issues
Most DICOM problems fall into these categories:
| Category | Symptoms |
|---|---|
| Network/Connectivity | Connection refused, timeouts |
| Association Negotiation | Association rejected, no matching contexts |
| Data Transfer | Missing images, corrupted data |
| Query/Retrieve | No results, incomplete results |
| Configuration | Wrong AE titles, ports, transfer syntaxes |
Step 1: Verify Network Connectivity
Before troubleshooting DICOM-specific issues, verify basic network connectivity:
Check if the port is reachable:
# Test TCP connection to DICOM port
telnet <host> <port>
# Or use netcat
nc -zv <host> <port>
# Windows PowerShell
Test-NetConnection -ComputerName <host> -Port <port>
Check if the service is listening:
# On the server, check listening ports
netstat -an | grep <port>
# Linux
ss -tlnp | grep <port>
Common network issues:
- Firewall blocking the DICOM port
- Wrong IP address or hostname
- VPN or network segmentation issues
- Service not running on the expected port
Step 2: Verify with C-ECHO
C-ECHO (DICOM Verification) is the simplest DICOM operation. If C-ECHO fails, more complex operations will also fail.
Using DCMTK:
echoscu -v <host> <port> -aet <local_ae> -aec <remote_ae>
Using fo-dicom (in code):
var client = new DicomClient();
client.AddRequest(new DicomCEchoRequest());
try
{
await client.SendAsync(host, port, false, localAe, remoteAe);
Console.WriteLine("C-ECHO successful!");
}
catch (Exception ex)
{
Console.WriteLine($"C-ECHO failed: {ex.Message}");
}
Interpreting C-ECHO results:
| Result | Meaning |
|---|---|
| Success (0000) | Basic connectivity works |
| Connection refused | Port not listening or firewall |
| Association rejected | AE title or configuration issue |
| Timeout | Network issue or server overloaded |
Step 3: Check AE Title Configuration
AE (Application Entity) title mismatches are one of the most common issues:
- AE titles are case-sensitive on most systems
- Maximum 16 characters
- Some systems require pre-registration of remote AE titles
- Spaces may cause issues
Checklist:
□ Called AE Title matches the server's configured AE title exactly
□ Calling AE Title is registered/allowed on the server
□ No leading/trailing spaces
□ Correct case (PACS vs pacs vs Pacs)
Step 4: Analyze Association Rejections
When an association is rejected, the rejection reason provides clues:
| Rejection Reason | Meaning | Solution |
|---|---|---|
| Called AE Title Not Recognized | Server doesn’t know the called AE | Check AE title spelling |
| Calling AE Title Not Recognized | Client not registered | Register client AE on server |
| No Reason Given | Configuration issue | Check server logs |
| Temporary Congestion | Server overloaded | Retry later |
| Limit of Associations Reached | Too many connections | Wait or increase server limit |
Step 5: Check Presentation Context Negotiation
Each SOP Class and transfer syntax combination forms a presentation context. Both sides must agree:
Common presentation context issues:
Problem: No acceptable Presentation Context
Cause: Server doesn't support the requested SOP Class
Problem: No matching transfer syntax
Cause: Client and server don't share any transfer syntaxes
Problem: Abstract Syntax Not Supported
Cause: Server doesn't implement the service you're requesting
Solution approach:
- Check the Conformance Statement for supported SOP Classes
- Verify transfer syntax compatibility
- Try Implicit VR Little Endian (always supported)
Step 6: Troubleshooting C-STORE Issues
Images not arriving:
□ Check C-STORE response status (should be 0000)
□ Verify storage path/disk space on receiver
□ Check for SOP Class compatibility
□ Verify transfer syntax is accepted
□ Check receiver logs for errors
Images arrive but can’t be viewed:
□ Check pixel data transfer syntax
□ Verify decompression codec is available
□ Check for corrupted data in transfer
□ Verify mandatory DICOM tags are present
Step 7: Troubleshooting Query Issues
No query results:
□ Verify Query/Retrieve SOP Class is supported
□ Check query level (PATIENT, STUDY, SERIES, IMAGE)
□ Verify query attributes are indexed by the server
□ Check wildcard syntax (* vs ?)
□ Verify date format (YYYYMMDD)
□ Check for empty result vs. error response
Query returns too many or too few results:
□ Check matching keys in your query
□ Verify case sensitivity settings
□ Check date range syntax (20250101-20250131)
□ Review server-side query limits
Step 8: Check DICOM Logs
Most DICOM systems provide detailed logging. Key information to look for:
Association Level:
- Association request received
- Presentation contexts proposed/accepted
- Association accepted/rejected with reason
Operation Level:
- C-STORE/C-FIND/C-MOVE requests received
- Status codes returned
- Error messages
Data Level:
- SOP Instance UIDs processed
- Transfer syntaxes used
- Data transfer completion status
Essential DICOM Testing Tools
DCMTK (DICOM Toolkit) is the most widely used open-source toolkit for DICOM troubleshooting. This section provides comprehensive examples for diagnosing and resolving DICOM issues.
DCMTK Installation
Before using DCMTK tools, you need to install the toolkit:
Linux (Debian/Ubuntu):
sudo apt-get install dcmtk
macOS (Homebrew):
brew install dcmtk
Windows:
Download pre-built binaries from the OFFIS DCMTK website or use package managers like Chocolatey:
choco install dcmtk
Verify installation:
dcmdump --version
echoscu - DICOM Verification (C-ECHO)
The echoscu command is the first tool to use when troubleshooting. It performs a DICOM C-ECHO, which is the simplest DICOM operation and verifies basic connectivity.
Basic usage:
echoscu <host> <port>
With AE titles (most common scenario):
echoscu -aet MY_SCU -aec PACS_SCP 192.168.1.100 104
| Parameter | Description |
|---|---|
-aet | Application Entity Title of the local application (calling AE) |
-aec | Application Entity Title of the remote application (called AE) |
Verbose output for troubleshooting:
echoscu -v -d 192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
| Flag | Description |
|---|---|
-v | Verbose mode - shows association details |
-d | Debug mode - shows PDU level details |
-ll | Set log level (fatal, error, warn, info, debug, trace) |
Example verbose output (successful):
I: Requesting Association
I: Association Accepted (Max Send PDV: 16372)
I: Sending Echo Request (MsgID 1)
I: Received Echo Response (Success)
I: Releasing Association
Example verbose output (failed - AE title not recognized):
I: Requesting Association
E: Association Rejected:
E: Result: Rejected Permanent
E: Source: Service User
E: Reason: Called AE Title Not Recognized
Timeout configuration:
# Set association timeout to 30 seconds
echoscu --timeout 30 192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# Set DIMSE timeout (time to wait for response)
echoscu --dimse-timeout 60 192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Testing with specific transfer syntax:
# Propose only Implicit VR Little Endian
echoscu -x= 192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Common echoscu error messages and solutions:
| Error Message | Likely Cause | Solution |
|---|---|---|
Association Rejected: Called AE Title Not Recognized | Server doesn’t recognize the called AE | Verify -aec matches server’s configured AE title exactly |
Association Rejected: Calling AE Title Not Recognized | Client AE not registered on server | Register your AE title on the server |
Connection refused | No service listening on port | Verify server is running and port is correct |
TCP Initialization Error | Network/firewall issue | Check network connectivity and firewall rules |
Association Aborted | Server terminated connection | Check server logs for reason |
storescu - Send DICOM Files (C-STORE)
The storescu command sends DICOM files to a DICOM server (SCP). It's essential for testing image storage workflows.
Basic usage - send a single file:
storescu 192.168.1.100 104 image.dcm -aet MY_SCU -aec PACS_SCP
Send multiple files:
storescu 192.168.1.100 104 *.dcm -aet MY_SCU -aec PACS_SCP
Send all files from a directory recursively:
storescu 192.168.1.100 104 --scan-directories --recurse /path/to/dicom/ -aet MY_SCU -aec PACS_SCP
Verbose output to see what’s happening:
storescu -v -d 192.168.1.100 104 image.dcm -aet MY_SCU -aec PACS_SCP
Example verbose output (successful):
I: Requesting Association
I: Association Accepted (Max Send PDV: 16372)
I: Sending file: image.dcm
I: Sending Store Request (MsgID 1, CT)
I: Received Store Response (Success)
I: Releasing Association
Propose specific transfer syntaxes:
# Send using JPEG Lossless compression
storescu -xs 192.168.1.100 104 image.dcm -aet MY_SCU -aec PACS_SCP
# Send using Explicit VR Little Endian only
storescu +x= 192.168.1.100 104 image.dcm -aet MY_SCU -aec PACS_SCP
# Send uncompressed (Implicit VR Little Endian)
storescu -x= 192.168.1.100 104 image.dcm -aet MY_SCU -aec PACS_SCP
Handle compressed images:
# Send compressed images as-is, preserving the original transfer syntax
# (the receiving SCP must support the compression scheme).
# Note: use dcmsend rather than storescu here — reliable on-the-fly
# decompression is a dcmsend feature; storescu's is experimental.
dcmsend --decompress-never 192.168.1.100 104 compressed.dcm -aet MY_SCU -aec PACS_SCP
# Alternatively, have DCMTK decompress on the fly and propose only
# uncompressed transfer syntaxes to the SCP.
dcmsend --decompress-lossy 192.168.1.100 104 compressed.dcm -aet MY_SCU -aec PACS_SCP
Test with different PDU sizes:
# Use smaller PDU size for problematic connections
storescu --max-pdu 16384 192.168.1.100 104 image.dcm -aet MY_SCU -aec PACS_SCP
Report detailed status:
storescu -v --report-file report.txt 192.168.1.100 104 *.dcm -aet MY_SCU -aec PACS_SCP
Common storescu issues and solutions:
| Issue | Symptoms | Solution |
|---|---|---|
| SOP Class not supported | No presentation context for: 1.2.840.10008.5.1.4.1.1.2 | Server doesn’t support this image type; check conformance statement |
| Transfer syntax mismatch | No acceptable Presentation Context | Try -x= to send uncompressed |
| File reading error | Cannot open DICOM file | Verify file exists and is valid DICOM |
| Storage failure | Status A700 (Out of Resources) | Server disk full or database issue |
findscu - Query DICOM Server (C-FIND)
The findscu command queries a DICOM server for patient, study, series, or image information. It's critical for troubleshooting query/retrieve workflows.
Query levels:
# Patient level query
findscu -P -k QueryRetrieveLevel=PATIENT -k PatientName="*" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# Study level query (most common)
findscu -S -k QueryRetrieveLevel=STUDY -k PatientName="" -k StudyDate="" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# Series level query
findscu -S -k QueryRetrieveLevel=SERIES -k StudyInstanceUID="1.2.3..." \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# Image level query
findscu -S -k QueryRetrieveLevel=IMAGE -k SeriesInstanceUID="1.2.3..." \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
| Flag | Description |
|---|---|
-P | Patient Root Query/Retrieve Information Model |
-S | Study Root Query/Retrieve Information Model |
-W | Modality Worklist Information Model - FIND |
Query by patient name with wildcards:
# Exact match
findscu -S -k QueryRetrieveLevel=STUDY -k PatientName="DOE^JOHN" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# Wildcard match (all patients starting with DOE)
findscu -S -k QueryRetrieveLevel=STUDY -k PatientName="DOE*" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# All patients (empty value = universal match)
findscu -S -k QueryRetrieveLevel=STUDY -k PatientName="" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Query by date range:
# Specific date (YYYYMMDD format)
findscu -S -k QueryRetrieveLevel=STUDY -k StudyDate="20250115" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# Date range
findscu -S -k QueryRetrieveLevel=STUDY -k StudyDate="20250101-20250131" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# From date onwards
findscu -S -k QueryRetrieveLevel=STUDY -k StudyDate="20250101-" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# Up to date
findscu -S -k QueryRetrieveLevel=STUDY -k StudyDate="-20250131" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Query by modality:
# Find all CT studies
findscu -S -k QueryRetrieveLevel=STUDY -k ModalitiesInStudy="CT" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
# Find MR studies
findscu -S -k QueryRetrieveLevel=STUDY -k ModalitiesInStudy="MR" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Query with specific return keys:
# Return specific attributes in results
findscu -S -k QueryRetrieveLevel=STUDY \
-k PatientName="" \
-k PatientID="" \
-k StudyDate="" \
-k StudyTime="" \
-k StudyDescription="" \
-k StudyInstanceUID="" \
-k NumberOfStudyRelatedSeries="" \
-k NumberOfStudyRelatedInstances="" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Save query results to files:
# Save each result as a separate DICOM file
findscu -S -k QueryRetrieveLevel=STUDY -k PatientName="*" \
-X --output-directory ./results \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Verbose output for troubleshooting:
findscu -v -d -S -k QueryRetrieveLevel=STUDY -k PatientName="DOE*" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Example query output:
I: ---------------------------
I: Find Response: 1 (Pending)
I:
I: # Dicom-Data-Set
I: # Used TransferSyntax: Little Endian Explicit
I: (0008,0052) CS [STUDY] # QueryRetrieveLevel
I: (0010,0010) PN [DOE^JOHN] # PatientName
I: (0010,0020) LO [12345678] # PatientID
I: (0008,0020) DA [20250115] # StudyDate
I: (0020,000d) UI [1.2.840.113619.2.55.3.123456] # StudyInstanceUID
I:
I: ---------------------------
I: Find Response: 2 (Success)
I:
Combined query examples:
# Find CT studies for patient DOE from January 2025
findscu -S -k QueryRetrieveLevel=STUDY \
-k PatientName="DOE*" \
-k StudyDate="20250101-20250131" \
-k ModalitiesInStudy="CT" \
-k PatientID="" \
-k StudyInstanceUID="" \
-k StudyDescription="" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Troubleshooting findscu issues:
| Problem | Possible Cause | Solution |
|---|---|---|
| No results | Wrong query level | Ensure QueryRetrieveLevel matches your query keys |
| No results | Attribute not indexed | Check if PACS indexes the attribute you’re querying |
| No results | Case sensitivity | Try different case or use wildcards |
No presentation context | Query model not supported | Try -S instead of -P or vice versa |
| Partial results | Server limit | Check server configuration for result limits |
movescu - Retrieve DICOM Studies (C-MOVE)
The movescu command retrieves DICOM objects from a server. Unlike C-GET, C-MOVE instructs the server to send images to a specified destination.
Important: For C-MOVE to work, the destination AE must be:
- Registered on the source server
- Running and accepting connections
- Reachable from the source server
Basic C-MOVE by Study Instance UID:
movescu -S -k QueryRetrieveLevel=STUDY \
-k StudyInstanceUID="1.2.840.113619.2.55.3.123456" \
-aet MY_SCU -aec PACS_SCP -aem DEST_SCP \
192.168.1.100 104
| Parameter | Description |
|---|---|
-aet | Calling AE title (your application) |
-aec | Called AE title (the PACS) |
-aem | Move destination AE title (where to send images) |
Retrieve at different levels:
# Retrieve entire study
movescu -S -k QueryRetrieveLevel=STUDY \
-k StudyInstanceUID="1.2.3..." \
-aet MY_SCU -aec PACS_SCP -aem DEST_SCP 192.168.1.100 104
# Retrieve specific series
movescu -S -k QueryRetrieveLevel=SERIES \
-k StudyInstanceUID="1.2.3..." \
-k SeriesInstanceUID="1.2.3.4..." \
-aet MY_SCU -aec PACS_SCP -aem DEST_SCP 192.168.1.100 104
# Retrieve specific image
movescu -S -k QueryRetrieveLevel=IMAGE \
-k StudyInstanceUID="1.2.3..." \
-k SeriesInstanceUID="1.2.3.4..." \
-k SOPInstanceUID="1.2.3.4.5..." \
-aet MY_SCU -aec PACS_SCP -aem DEST_SCP 192.168.1.100 104
Retrieve to local storage (using storescp):
First, start a local storage SCP:
# In terminal 1: Start receiving server
storescp -v --output-directory ./received 11112
# In terminal 2: Request the move
movescu -S -k QueryRetrieveLevel=STUDY \
-k StudyInstanceUID="1.2.3..." \
-aet MY_SCU -aec PACS_SCP -aem MY_SCU \
--port 11112 192.168.1.100 104
Verbose output for troubleshooting:
movescu -v -d -S -k QueryRetrieveLevel=STUDY \
-k StudyInstanceUID="1.2.3..." \
-aet MY_SCU -aec PACS_SCP -aem DEST_SCP \
192.168.1.100 104
Example successful output:
I: Requesting Association
I: Association Accepted (Max Send PDV: 16372)
I: Sending Move Request (MsgID 1)
I: Received Move Response 1 (Pending, 0 completed, 0 failed, 0 warning, 5 remaining)
I: Received Move Response 2 (Pending, 1 completed, 0 failed, 0 warning, 4 remaining)
...
I: Received Final Move Response (Success)
I: Releasing Association
Common movescu issues:
| Issue | Error Message | Solution |
|---|---|---|
| Unknown destination | Move Destination Unknown | Register destination AE on source server |
| Destination unreachable | Unable to connect to Move Destination | Verify destination SCP is running and network is accessible |
| No matching studies | Status 0000 (Success) with zero completed sub-operations | An empty result set is not an error; verify the StudyInstanceUID is correct |
| Partial failure | Status with failed count > 0 | Check sub-operation status codes |
getscu - Retrieve Using C-GET
Unlike C-MOVE, C-GET retrieves images directly to the requesting application. This is useful when you can't configure the server with your AE title.
getscu -v -S -k QueryRetrieveLevel=STUDY \
-k StudyInstanceUID="1.2.3..." \
--output-directory ./received \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
Note: Not all PACS servers support C-GET. If it fails, use C-MOVE instead.
storescp - DICOM Storage Server (SCP)
The storescp command creates a simple DICOM storage server for receiving images. Essential for testing C-STORE and C-MOVE operations.
Basic storage server:
storescp 11112
With verbose output:
storescp -v 11112
Save received files:
# Save to specific directory
storescp --output-directory ./received 11112
# Custom filename pattern
storescp --output-directory ./received \
--filename-extension .dcm \
--sort-conc-studies series \
11112
Set AE title:
storescp -aet MY_SCP 11112
Debug incoming associations:
storescp -v -d --debug 11112
Accept all transfer syntaxes:
storescp +xa 11112
Example output when receiving files:
I: Received Association Request
I: Calling Application Entity: SENDING_AE
I: Called Application Entity: MY_SCP
I: Accepting Association
I: Received Store Request (MsgID 1)
I: Storing DICOM file: ./received/CT.1.2.840.113619.dcm
I: Sending Store Response (Status: Success)
I: Received Release Request
dcmdump - Inspect DICOM Files
The dcmdump command displays the contents of a DICOM file in human-readable format. It's indispensable for understanding what's in a DICOM file.
Basic dump:
dcmdump image.dcm
Example output:
# Dicom-File-Format
# Dicom-Meta-Information-Header
# Used TransferSyntax: Little Endian Explicit
(0002,0000) UL 196 # 4, 1 FileMetaInformationGroupLength
(0002,0001) OB 00\01 # 2, 1 FileMetaInformationVersion
(0002,0002) UI =CTImageStorage # 26, 1 MediaStorageSOPClassUID
(0002,0003) UI [1.2.840.113619.2.55.3.123456] # 38, 1 MediaStorageSOPInstanceUID
(0002,0010) UI =LittleEndianExplicit # 20, 1 TransferSyntaxUID
# Dicom-Data-Set
# Used TransferSyntax: Little Endian Explicit
(0008,0016) UI =CTImageStorage # 26, 1 SOPClassUID
(0008,0018) UI [1.2.840.113619.2.55.3.123456] # 38, 1 SOPInstanceUID
(0008,0020) DA [20250115] # 8, 1 StudyDate
(0008,0060) CS [CT] # 2, 1 Modality
(0010,0010) PN [DOE^JOHN] # 8, 1 PatientName
(0010,0020) LO [12345678] # 8, 1 PatientID
...
Show specific tags only:
# Show only patient and study information
dcmdump +P 0010,0010 +P 0010,0020 +P 0020,000d image.dcm
# Using tag names
dcmdump +P PatientName +P PatientID +P StudyInstanceUID image.dcm
Show pixel data information:
dcmdump +P PixelData image.dcm
Search for a specific value:
dcmdump image.dcm | grep -i "patientname"
Dump to file:
dcmdump image.dcm > dump.txt
Show private tags:
dcmdump --print-all image.dcm
Short format (one line per tag):
dcmdump -M image.dcm
Dump sequence items expanded:
dcmdump +Ep image.dcm
dcmftest - Verify DICOM File Format
The dcmftest command quickly tests if a file is a valid DICOM file.
dcmftest image.dcm
# Output: yes (if valid DICOM)
# Output: no (if not valid DICOM)
Test multiple files:
for f in *.dcm; do echo -n "$f: "; dcmftest "$f"; done
dciodvfy - Validate DICOM IOD
The dciodvfy command (part of David Clunie's dicom3tools) validates DICOM files against the standard. It's excellent for checking compliance.
Note: This tool is from dicom3tools, not DCMTK, but is commonly used alongside DCMTK.
dciodvfy image.dcm
Example output:
Warning - Missing attribute Type 2 Required Element=<PatientBirthDate> Module=<Patient>
Warning - Value dubious for this VR - Retired Person Name form
Error - Missing attribute Type 1 Required Element=<Rows> Module=<ImagePixel>
dcmconv - Convert DICOM Transfer Syntax
The dcmconv command converts DICOM files between different transfer syntaxes.
Convert to Explicit VR Little Endian:
dcmconv +te input.dcm output.dcm
Convert to Implicit VR Little Endian:
dcmconv +ti input.dcm output.dcm
Convert to Big Endian (retired since 2011):
dcmconv +tb input.dcm output.dcm
Remove meta header:
dcmconv -f input.dcm output.dcm
Common transfer syntax conversions:
| Flag | Transfer Syntax |
|---|---|
+ti | Implicit VR Little Endian |
+te | Explicit VR Little Endian |
+tb | Explicit VR Big Endian (retired since 2011) |
dcmcjpeg / dcmdjpeg - JPEG Compression
Compress to JPEG:
dcmcjpeg input.dcm output.dcm
Decompress JPEG:
dcmdjpeg compressed.dcm uncompressed.dcm
Compress with specific quality:
# JPEG Baseline (lossy)
dcmcjpeg +eb input.dcm output.dcm
# JPEG Lossless
dcmcjpeg +el input.dcm output.dcm
dcmodify - Modify DICOM Tags
The dcmodify command modifies DICOM file attributes. Useful for anonymization and fixing incorrect data.
Modify a single tag:
dcmodify -m "PatientName=ANONYMOUS" image.dcm
Modify multiple tags:
dcmodify -m "PatientName=ANONYMOUS" -m "PatientID=00000" image.dcm
Delete a tag:
dcmodify -e "PatientBirthDate" image.dcm
Insert a new tag:
dcmodify -i "(0010,0040)=M" image.dcm # PatientSex
Modify without backup:
dcmodify -nb -m "PatientName=TEST" image.dcm
Generate new UIDs:
dcmodify --gen-all-new-uids image.dcm
Batch modify (use with caution):
for f in *.dcm; do
dcmodify -nb -m "PatientName=ANONYMOUS" "$f"
done
img2dcm - Create DICOM from Images
The img2dcm command converts standard images (JPEG, PNG, BMP) to DICOM format.
Basic conversion:
img2dcm input.jpg output.dcm
With patient/study information:
img2dcm -k "PatientName=DOE^JOHN" \
-k "PatientID=12345" \
-k "StudyDescription=Test Study" \
input.jpg output.dcm
DCMTK Troubleshooting Workflow
Here's a systematic workflow for DICOM troubleshooting using DCMTK:
1. Test basic connectivity:
# Simple echo test
echoscu -v 192.168.1.100 104 -aet MY_SCU -aec PACS_SCP
2. If echo fails, increase verbosity:
# Debug level output
echoscu -v -d 192.168.1.100 104 -aet MY_SCU -aec PACS_SCP 2>&1 | tee echo_debug.log
3. If sending files fails, check the file:
# Verify file is valid DICOM
dcmftest image.dcm
# Dump file contents
dcmdump image.dcm | head -100
# Check SOP Class
dcmdump +P SOPClassUID image.dcm
4. If query returns no results:
# Verbose query with wildcards
findscu -v -d -S -k QueryRetrieveLevel=STUDY -k PatientName="*" \
192.168.1.100 104 -aet MY_SCU -aec PACS_SCP 2>&1 | tee query_debug.log
5. If C-MOVE fails:
# Start local receiver
storescp -v --output-directory ./test 11112 &
# Test move with verbose output
movescu -v -d -S -k QueryRetrieveLevel=STUDY \
-k StudyInstanceUID="1.2.3..." \
-aet MY_SCU -aec PACS_SCP -aem MY_SCU \
--port 11112 192.168.1.100 104
Other Testing Tools
DVTk (GUI):
- Visual association testing
- Script-based validation
- Detailed message analysis
Orthanc:
- Use as a test PACS server
- Web interface for viewing stored images
- RESTful API for testing
Network Capture with Wireshark
For deep troubleshooting, capture network traffic:
1. Start Wireshark capture on DICOM port
2. Filter: tcp.port == 104 (or your DICOM port)
3. Reproduce the issue
4. Analyze the DICOM PDUs
Wireshark can decode DICOM protocol, showing:
- Association request/accept/reject PDUs
- Presentation contexts negotiated
- DIMSE messages (C-ECHO, C-STORE, etc.)
- Status codes and error information
Common Error Codes
| Status Code | Meaning | Typical Cause |
|---|---|---|
| 0000 | Success | Operation completed |
| FF00 | Pending | More results coming (C-FIND) |
| A700 | Out of Resources | Server storage/memory issue |
| A900 | Identifier Does Not Match | Query/move UID mismatch |
| C000 | Unable to Process | Malformed or unsupported request |
| FE00 | Cancel | Operation cancelled |
Troubleshooting Checklist
Network Layer:
□ Port is open and reachable
□ No firewall blocking traffic
□ DNS/hostname resolves correctly
Configuration Layer:
□ AE titles match exactly (case-sensitive)
□ Port numbers are correct
□ Remote AE is registered if required
DICOM Layer:
□ C-ECHO succeeds
□ SOP Classes are compatible
□ Transfer syntaxes are compatible
□ Query attributes are indexed
Application Layer:
□ Disk space available
□ Database connectivity
□ Required services running
Best Practices for Avoiding Issues
- Always test with C-ECHO first
- Keep Conformance Statements accessible
- Document all configuration settings
- Implement comprehensive logging
- Monitor disk space and database connections
- Use consistent naming conventions for AE titles
- Test after any software updates
Conclusion
DICOM troubleshooting requires a systematic approach, starting from basic network connectivity and working up through the DICOM protocol layers. The key is to isolate where the problem occurs - network, association negotiation, or data transfer - and then apply the appropriate diagnostic techniques.
Having the right tools (DCMTK, Wireshark, test servers) and understanding how to read logs and error codes will significantly speed up problem resolution. When in doubt, start with C-ECHO and work your way up to more complex operations.