From fba9ad66ad7edeea0ec0cf554f7961e1dd840657 Mon Sep 17 00:00:00 2001 From: mrbean-bremen Date: Mon, 9 Sep 2024 19:56:54 +0200 Subject: [PATCH] Replace removed pydicom API - makes it compatible to pydicom 3 - also promote to beta state --- CHANGES.md | 1 + README.md | 45 ++++++++++++------- .../validator/test_dicom_file_validator.py | 8 ++-- pyproject.toml | 2 +- 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fecc8d6..623cc8e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ The released versions correspond to PyPi releases. ### Infrastructure * use the current DICOM standard (2024c) for testing +* make the package compatible to `pydicom` 3.0 ## [Version 0.6.2](https://pypi.python.org/pypi/dicom-validator/0.6.2) (2024-08-09) Fixes a regression in version 0.6.1. diff --git a/README.md b/README.md index 495d08e..cc008dd 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ DICOM standard. *Disclaimer:* No guarantees are given for the correctness of the results. -This is alpha-stage software and mostly thought as a proof of concept. +This is beta-stage software which is mostly developed as a proof of concept. Also check the limitations for `validate_iods` described below. *Note:* @@ -40,18 +40,18 @@ pip install dicom-validator ## Usage ``` -validate_iods.py [-h] [--standard-path STANDARD_PATH] - [--revision REVISION] [--force-read] [--recreate-json] - [--verbose] - dicomfiles [dicomfiles ...] - -dump_dcm_info.py [-h] [--standard-path STANDARD_PATH] - [--revision REVISION] [--max-value-len MAX_VALUE_LEN] - [--show-tags [SHOW_TAGS [SHOW_TAGS ...]]] - [--show-image-data] [--recreate-json] - dicomfiles [dicomfiles ...] +validate_iods [-h] [--standard-path STANDARD_PATH] + [--revision REVISION] [--force-read] [--recreate-json] + [--suppress-vr-warnings] [--verbose] + dicomfiles [dicomfiles ...] + +dump_dcm_info [-h] [--standard-path STANDARD_PATH] + [--revision REVISION] [--max-value-len MAX_VALUE_LEN] + [--show-tags [SHOW_TAGS [SHOW_TAGS ...]]] + [--show-image-data] [--recreate-json] + dicomfiles [dicomfiles ...] ``` -Use the `--help` option for each script do get usage info. +Use the `--help` option for each script do get more specific usage info. ## Access to the DICOM standard @@ -128,17 +128,24 @@ Process finished with exit code 6 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 contained in the DICOM file (e.g. verbose - descriptions like "if the Patient is an animal") +- 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 -Also note that only the given standard is used to evaluate the files. If +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 `--revision` 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. #### Unsupported cases (support may be added in future versions) - SOP classes not in the table in PS3.3 such as Presentation States are not @@ -188,7 +195,9 @@ c:\dev\DICOM Data\SR\image12.dcm ## Build executable on Windows -Here is a sample workflow: +A self-contained Windows executable is contained in the release artifacts. + +Here is a sample workflow to build such an executable yourself: ```powershell # Clone the repository git clone git@github.com:pydicom/dicom-validator.git @@ -204,3 +213,7 @@ pip install -r requirements-dev.txt # Build executables. They will be placed in the `dist` subfolder. pyinstaller dicom-validator.spec -y ``` + +## Contributing +Contributions are very welcome. If you submit a pull request for a bugfix +or a new feature, please make sure to also write respective tests. diff --git a/dicom_validator/tests/validator/test_dicom_file_validator.py b/dicom_validator/tests/validator/test_dicom_file_validator.py index 176ab71..9e6d07e 100644 --- a/dicom_validator/tests/validator/test_dicom_file_validator.py +++ b/dicom_validator/tests/validator/test_dicom_file_validator.py @@ -2,7 +2,7 @@ from pathlib import Path import pytest -from pydicom import write_file +from pydicom import dcmwrite from pydicom.dataset import Dataset, FileDataset, FileMetaDataset from dicom_validator.validator.dicom_file_validator import DicomFileValidator @@ -51,14 +51,14 @@ def test_missing_sop_class(self, validator): file_dataset = FileDataset( filename, Dataset(), file_meta=self.create_metadata() ) - write_file(filename, file_dataset, write_like_original=False) + dcmwrite(filename, file_dataset, write_like_original=False) self.assert_fatal_error(validator, filename, "Missing SOPClassUID") def test_unknown_sop_class(self, validator): dataset = Dataset() dataset.SOPClassUID = "Unknown" file_dataset = FileDataset("test", dataset, file_meta=self.create_metadata()) - write_file("test", file_dataset, write_like_original=False) + dcmwrite("test", file_dataset, write_like_original=False) self.assert_fatal_error( validator, "test", "Unknown SOPClassUID (probably retired): Unknown" ) @@ -79,7 +79,7 @@ def test_non_fatal_errors(self, validator): dataset = Dataset() dataset.SOPClassUID = "1.2.840.10008.5.1.4.1.1.2" # CT Image Storage file_dataset = FileDataset("test", dataset, file_meta=self.create_metadata()) - write_file("test", file_dataset, write_like_original=False) + dcmwrite("test", file_dataset, write_like_original=False) error_dict = validator.validate("test") assert len(error_dict) == 1 errors = error_dict["test"] diff --git a/pyproject.toml b/pyproject.toml index d727b8c..56f3941 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Intended Audience :: Developers", "Intended Audience :: Healthcare Industry", - "Development Status :: 3 - Alpha", + "Development Status :: 4 - Beta", "Environment :: Console", "Programming Language :: Python", "Programming Language :: Python :: 3.8",