Source code for dicom_validator.validator.dicom_file_validator
import logging
import os
from os import PathLike
from pydicom import config, dcmread
from pydicom.errors import InvalidDicomError
from dicom_validator.validator.dicom_info import DicomInfo
from dicom_validator.validator.error_handler import (
ValidationResultHandler,
default_error_handler,
)
from dicom_validator.validator.iod_validator import IODValidator
from dicom_validator.validator.validation_result import ValidationResult, Status
[docs]
class DicomFileValidator:
"""Validates a single DICOM file or all DICOM files in a directory."""
[docs]
def __init__(
self,
dicom_info: DicomInfo,
log_level: int = logging.INFO,
force_read: bool = False,
suppress_vr_warnings: bool = False,
error_handler: ValidationResultHandler | None = None,
) -> None:
"""Initializes a DicomFileValidator object.
Parameters
----------
dicom_info : DicomInfo
DICOM information as read from the JSON files created from the standard
log_level : int
The log level to use with the default error handler
force_read: bool
If `True`, the DICOM file is tried to read even if it may not be valid
suppress_vr_warnings: bool
By default, values not valid for the given VR are reported, using the
`pydicom` validation. If set to `True`, this validation is not performed.
error_handler: ValidationResultHandler or None
If set, this handler will be used to handle the validation result,
otherwise the default handler is used that logs errors to the console.
"""
self._dicom_info = dicom_info
self.log_level = log_level
self._force_read = force_read
self._suppress_vr_warnings = suppress_vr_warnings
self._error_handler = error_handler
[docs]
def validate(self, path: str | PathLike) -> dict[str, ValidationResult]:
"""Validate a single DICOM file or all files under a directory.
Parameters
----------
path : str | os.PathLike
Path to a DICOM file or a directory containing DICOM files.
Returns
-------
dict[str, ValidationResult]
A mapping from file path to its validation result.
"""
results: dict[str, ValidationResult] = {}
path = os.fspath(path)
if not os.path.exists(path):
results[path] = ValidationResult(
file_path=path, status=Status.MissingFile, errors=1
)
self.handle_error(results[path])
else:
if os.path.isdir(path):
results.update(self.validate_dir(path))
else:
results.update(self.validate_file(path))
return results
[docs]
def validate_dir(self, dir_path: str) -> dict[str, ValidationResult]:
"""Validate all DICOM files contained in a directory tree.
Parameters
----------
dir_path : str
Path to a directory that will be traversed recursively.
Returns
-------
dict[str, ValidationResult]
A mapping from file path to its validation result for all files found.
"""
results: dict[str, ValidationResult] = {}
for root, _, names in os.walk(dir_path):
for name in names:
results.update(self.validate(os.path.join(root, name)))
return results
[docs]
def validate_file(self, file_path: str) -> dict[str, ValidationResult]:
"""Validate a single DICOM file.
Parameters
----------
file_path : str
Path to a DICOM file.
Returns
-------
dict[str, ValidationResult]
A mapping containing exactly one entry for the given file.
"""
try:
# dcmread calls validate_value by default. If values don't match
# required VR (value representation), it emits a warning but
# does not provide the tag and value that caused the warning.
# We will handle it later (optionally) by calling validate_value
# directly.
config.settings.reading_validation_mode = config.IGNORE
data_set = dcmread(file_path, defer_size=1024, force=self._force_read)
except InvalidDicomError:
result = ValidationResult(file_path=file_path, status=Status.InvalidFile)
self.handle_error(result)
return {
file_path: result,
}
return {
file_path: IODValidator(
data_set,
self._dicom_info,
log_level=self.log_level,
suppress_vr_warnings=self._suppress_vr_warnings,
error_handler=self._error_handler,
file_path=file_path,
).validate()
}
def handle_error(self, result: ValidationResult) -> None:
handler = self._error_handler or default_error_handler(
self._dicom_info, self.log_level
)
handler.handle_validation_result(result)