The tool validate_iods

This is a command line tool that allows to check one or more DICOM files for compliance with the DICOM standard with regard to the required and optional modules for a given SOP class (as defined by the SOP Class UID), and to the required and optional tags in each of these modules.

Validating a single DICOM file

Validating a single file produces an output like this:

$validate_iods.py -r 2022a c:\DICOM\data\ACRNEMA\WG02\Enhanced-XA\ENHXA

Using DICOM edition 2022a
Validating DICOM file c:\DICOM\data\ACRNEMA\WG02\Enhanced-XA\ENHXA
SOP class is "1.2.840.10008.5.1.4.1.1.12.1.1" (Enhanced XA Image IOD)

Errors
======

Module "Enhanced XA/XRF Image":
Tag (0018,9410) (Planes in Acquisition) is missing

Module "Mask":
Tag (0028,6100) (Mask Subtraction Sequence) is missing

Module "X-Ray Frame Acquisition":
(5200,9230) (Per-frame Functional Groups Sequence) / (0018,9417) (Frame Acquisition Sequence):
  Tag (0018,9328) (Exposure Time in ms) is unexpected
  Tag (0018,9332) (Exposure in mAs) is unexpected

Module "X-Ray Frame Pixel Data Properties":
(5200,9229) (Shared Functional Groups Sequence) / (0028,9443) (Frame Pixel Data Properties Sequence):
  Tag (0018,1164) (Imager Pixel Spacing) is missing

Module "XA/XRF Multi-frame Presentation":
(0008,9458) (Frame Display Sequence):
  Tag (0028,1090) (Recommended Viewing Mode) is missing
  Tag (0028,9411) (Display Filter Percentage) is missing

Module "General":
Tag (0008,0022) (Acquisition Date) is unexpected
Tag (0008,0032) (Acquisition Time) is unexpected
Tag (0018,1164) (Imager Pixel Spacing) is unexpected
Tag (0028,9411) (Display Filter Percentage) is unexpected

======

Process finished with exit code 11

As you can see, each module with errors is listed separately, and for each error a separate entry is created that contains the tag name (and the parent tags if the tag is inside a sequence) and the kind of error. In this case, validation errors have been encountered in 5 different modules, and 4 tags not belonging to an allowed module have been found (which are grouped under “General”). The exit code is the number of errors encountered. See validation logic and errors for more information on these errors.

Validating several DICOM files

Several DICOM files can be given as the last arguments in the command line and will be checked in the order they are given:

validate_iods a.dcm b.dcm

will first check a.dcm, then b.dcm and generates output like:

Using DICOM edition 2025d
Validating DICOM file a.dcm
SOP class is "1.2.840.10008.5.1.4.1.1.481.2" (RT Dose IOD)

Validating DICOM file b.dcm
SOP class is "1.2.840.10008.5.1.4.1.1.4" (MR Image IOD)

Errors
======

Module "Patient":
Tag (0010,2298) (Responsible Person Role) is missing

Module "General":
Tag (0028,1052) (Rescale Intercept) is unexpected
Tag (0028,1053) (Rescale Slope) is unexpected
Tag (0028,1054) (Rescale Type) is unexpected

======

Process finished with exit code 4

In this case, the first file had no errors, while the second file had 4 errors. As can be seen here, the returned error code is the number of found validation errors.

It is also possible to provide one or more directories, which will recursively be searched for contained files, and each file be checked consecutively. Mixing DICOM file names and directories is also allowed.

Any non-DICOM files are by default just listed in the output and ignored - the error count is not affected by them:

validate_iods path/to/dicom/files

Provided a valid DICOM file and a text file are located in this path, this results in something like:

Using DICOM edition 2025d
Validating DICOM file mr.dcm
SOP class is "1.2.840.10008.5.1.4.1.1.4" (MR Image IOD)

Not a DICOM File: path/to/dicom/files/readme.txt - ignoring

Process finished with exit code 0

This changes if the option –force-read is used: in this case each file is handled as a DICOM file, and non-DICOM files may generate different errors generated by pydicom, and will be handled as invalid DICOM, increasing the error count. The option –force-read is usually not needed and shall only be used if handling very old DICOM files without a DICOM header.

Used DICOM standard edition

Per default, the latest locally available edition of the DICOM standard is used for validation. If no edition is available, or if a newer version is available (this is checked once a month), the relevant parts of the newest version of the standard are downloaded and processed. If the –src parameter is not provided, <user home>/dicom-validator/ is used to store the files locally. It is also possible to use a specific version of the standard via the command line option –edition or -e. This allows to define a specific version (e.g., “2025e”), or a year (e.g., “2022”), in which case the latest version for that year is used.

VR violations

Per default, values are also checked for validity for the given VR, e.g. an error is issued if the value is too long for the VR, has illegal characters or the wrong format. This VR validation is done directly by pydicom - the tool only collects the results. If these are not wanted, as they are not strictly IOD violations, they can be switched off by using the command line option –suppress-vr-warnings.

Limitations

Condition evaluation

As mentioned, if the evaluation of conditions fails, the related module or tag is considered optional, which may hide some non-conformity. Condition evaluation may fail if:

  • the needed information is not directly contained in the DICOM file (e.g. verbose descriptions like “if the Patient is an animal”, “if the image has been calibrated” etc.)

  • the information is related to other DICOM files (e.g. referenced images)

  • the parsing failed because the condition is too complicated, unexpected, or due to a bug (please write an issue if you encounter such a problem)

Retired tags

Only the given standard is used to evaluate the files. If the DICOM file has been written using an older standard, it may conform to that standard, but not to the newest one. Tags that are retired in the version of the standard used for parsing are not considered at all. You can always check against an older standard by using the –edition option.

Enumerated values and defined terms

Most enumerated values are checked against, but some are ignored due to parsing issues. Support for more cases may be added in the future. Defined terms are not checked, because they are allowed to be user-defined, which means that any value may be valid.