Skip to content

Commit

Permalink
Add handling of conditional includes
Browse files Browse the repository at this point in the history
- needed for validation of SR Document Content
- closes #39
  • Loading branch information
mrbean-bremen committed Aug 20, 2023
1 parent c6ef9f4 commit c71b85a
Show file tree
Hide file tree
Showing 9 changed files with 4,945 additions and 306 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The released versions correspond to PyPi releases.
### Changes
* removed official support for Python 3.7 which has reached end of life

### Features
* added handling of conditional includes (needed for SR documents)
(see [#39](../.. /issues/39))
### Infrastructure
* use `pyproject.toml` instead of `setup.py`

Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@ 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.py [-h] [--standard-path STANDARD_PATH]
[--revision REVISION] [--force-read] [--recreate-json]
[--verbose]
dicomfiles [dicomfiles ...]
```
Use the `--help` option for each script do get usage info.

Expand Down
23 changes: 15 additions & 8 deletions dicom_validator/spec_reader/part3_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,13 +183,15 @@ def _parse_module_description(self, parent_node):
columns, current_descriptions, last_tag_id, tag_name
)
elif tag_name.startswith("Include"):
self._handle_included_attributes(columns, current_descriptions)
self._handle_included_attributes(
tag_name, columns, current_descriptions
)
else:
# todo: other entries
pass
return current_descriptions[0]

def _handle_included_attributes(self, columns, current_descriptions):
def _handle_included_attributes(self, text, columns, current_descriptions):
include_node = self._find(columns[0], ["para", "emphasis", "xref"])
if include_node is None:
description = self._find_text(columns[0])
Expand All @@ -199,7 +201,9 @@ def _handle_included_attributes(self, columns, current_descriptions):
)
if is_func_group:
# add a placeholder - has to be evaluated at validation time
current_descriptions[-1].setdefault("include", []).append("FuncGroup")
current_descriptions[-1].setdefault("include", []).append(
{"ref": "FuncGroup"}
)
return
include_ref = include_node.attrib["linkend"]
if self._current_refs and include_ref == self._current_refs[-1]:
Expand All @@ -216,7 +220,14 @@ def _handle_included_attributes(self, columns, current_descriptions):
# it is allowed to have no attributes (example: Raw Data)
ref_description = self._parse_module_description(ref_node) or {}
self._module_descriptions[label] = ref_description
current_descriptions[-1].setdefault("include", []).append(label)
include_attr = {"ref": label}
# this is currently the only occurring condition for includes
cond_prefix = "if and only if "
cond_index = text.find(cond_prefix)
if cond_index > 0:
cond_text = text[cond_index:].replace(cond_prefix, "required if ")
include_attr["cond"] = self._condition_parser.parse(cond_text)
current_descriptions[-1].setdefault("include", []).append(include_attr)
self._current_refs.pop()

def _handle_regular_attribute(
Expand All @@ -230,10 +241,6 @@ def _handle_regular_attribute(
"type": tag_type,
}
if tag_type in ("1C", "2C"):
# cond = self._find_all_text(columns[3])
# index = cond.find('Required if ')
# if index >= 0:
# current_descriptions[-1][tag_id]['desc'] = cond[index:]
current_descriptions[-1][tag_id]["cond"] = self._condition_parser.parse(
self._find_all_text(columns[3])
)
Expand Down
3,049 changes: 3,049 additions & 0 deletions dicom_validator/tests/fixtures/2021d/docbook/part03.xml

Large diffs are not rendered by default.

61 changes: 61 additions & 0 deletions dicom_validator/tests/fixtures/2021d/json/iod_info.json
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,67 @@
},
"title": "VL Whole Slide Microscopy Image IOD"
},
"1.2.840.10008.5.1.4.1.1.88.67": {
"group_macros": {},
"modules": {
"Clinical Trial Series": {
"ref": "C.7.3.2",
"use": "U"
},
"Clinical Trial Study": {
"ref": "C.7.2.3",
"use": "U"
},
"Clinical Trial Subject": {
"ref": "C.7.1.3",
"use": "U"
},
"Enhanced General Equipment": {
"ref": "C.7.5.2",
"use": "M"
},
"General Equipment": {
"ref": "C.7.5.1",
"use": "M"
},
"General Study": {
"ref": "C.7.2.1",
"use": "M"
},
"Patient": {
"ref": "C.7.1.1",
"use": "M"
},
"Patient Study": {
"ref": "C.7.2.2",
"use": "U"
},
"SOP Common": {
"ref": "C.12.1",
"use": "M"
},
"SR Document Content": {
"ref": "C.17.3",
"use": "M"
},
"SR Document General": {
"ref": "C.17.2",
"use": "M"
},
"SR Document Series": {
"ref": "C.17.1",
"use": "M"
},
"Synchronization": {
"cond": {
"type": "U"
},
"ref": "C.7.4.2",
"use": "C - shall be present if system time is synchronized to an external reference. May be present otherwise."
}
},
"title": "X-Ray Radiation Dose SR IOD"
},
"1.2.840.10008.5.1.4.1.1.481.2": {
"group_macros": {},
"modules": {
Expand Down
Loading

0 comments on commit c71b85a

Please sign in to comment.