Source code for dicom_validator.validator.validation_result

import enum
from dataclasses import dataclass

from pydicom.tag import BaseTag


[docs] class ErrorCode(enum.Enum): """Defines the kind of error found for a DICOM tag in a module.""" NoError = 0 TagMissing = 1 # tag is missing from a module TagEmpty = 2 # type 1 tag is empty TagUnexpected = 3 # tag is not in any allowed module TagNotAllowed = 4 # tag not allowed by a condition EnumValueNotAllowed = 5 # value not in the list of allowed enum values InvalidValue = 6 # the value failed the VR validation
[docs] class ErrorScope(enum.Enum): """Defines the scope of an error found for a DICOM tag in a module. Some errors are specific to functional groups while having the same error code as errors unrelated to functional groups.""" General = 0 SharedFuncGroup = 1 PerFrameFuncGroup = 2 BothFuncGroups = 3
[docs] class TagType(str, enum.Enum): """The DICOM tag type used in a specific module.""" Undefined = "Undefined" # tag not in an expected module Type1 = "1" Type1C = "1C" Type2 = "2" Type2C = "2C" Type3 = "3"
[docs] class Status(enum.Enum): """The result state after validation.""" Passed = 0 # no errors found in validation Failed = 1 # some violations found in validation MissingFile = 2 # file to be validated is missing InvalidFile = 3 # file to be validated is invalid DICOM MissingSOPClassUID = 4 # file to be validated has no SOP Class UID UnknownSOPClassUID = 5 # the SOP Class UID in the file to be validated is unknown
[docs] @dataclass class DicomTag: """Represents a DICOM tag together with parent sequences, if any.""" tag: BaseTag parents: list[BaseTag] | None = None def __init__(self, tag: int, parents: list[int] | None = None): self.tag = BaseTag(tag) self.parents = [BaseTag(p) for p in parents] if parents else None def __hash__(self): return hash(self.tag + (sum(self.parents) if self.parents else 0)) def __str__(self): """String representation for easier debugging.""" if self.parents: s = " / ".join(str(tag) for tag in self.parents) + " / " else: s = "" return s + str(self.tag) def __lt__(self, other): """Comparison operator. Makes sure that tags with the same parent sequences are ordered adjacently.""" if self.parents: if other.parents: if self.parents == other.parents: return self.tag < other.tag return self.parents < other.parents return self.parents[0] < other.tag if other.parents: return self.tag < other.parents[0] return self.tag < other.tag
[docs] @dataclass class TagError: """Represents error found for a specific DICOM tag.""" type: TagType = TagType.Undefined code: ErrorCode = ErrorCode.NoError scope: ErrorScope = ErrorScope.General context: dict | None = None def is_error(self): return self.code != ErrorCode.NoError
TagErrors = dict[DicomTag, TagError] ModuleErrors = dict[str, TagErrors]
[docs] @dataclass class ValidationResult: """The validation result for a specific DICOM dataset.""" sop_class_uid: str = "" file_path: str = "" status: Status = Status.Passed errors: int = 0 module_errors: ModuleErrors | None = None def reset(self): self.status = Status.Passed self.errors = 0 self.module_errors = ModuleErrors() def add_tag_errors(self, module_name: str, tag_errors: TagErrors) -> None: self.module_errors = self.module_errors or ModuleErrors() nr_module_errors = len(self.module_errors.get(module_name, [])) self.module_errors.setdefault(module_name, {}).update(tag_errors) self.errors += len(tag_errors) - nr_module_errors