dcmspec 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dcmspec/__init__.py +0 -0
- dcmspec/apps/__init__.py +1 -0
- dcmspec/apps/cli/__init__.py +0 -0
- dcmspec/apps/cli/dataelements.py +89 -0
- dcmspec/apps/cli/iodattributes.py +125 -0
- dcmspec/apps/cli/iodmodules.py +92 -0
- dcmspec/apps/cli/modattributes.py +265 -0
- dcmspec/apps/cli/tdwiicontent.py +365 -0
- dcmspec/apps/cli/uidvalues.py +84 -0
- dcmspec/apps/cli/upsdimseattributes.py +109 -0
- dcmspec/apps/cli/upsioddimseattributes.py +330 -0
- dcmspec/apps/ui/iod_explorer/README.md +33 -0
- dcmspec/apps/ui/iod_explorer/__init__.py +9 -0
- dcmspec/apps/ui/iod_explorer/config/README.md +171 -0
- dcmspec/apps/ui/iod_explorer/config/iod_explorer_config.json +4 -0
- dcmspec/apps/ui/iod_explorer/config/iod_explorer_config_debug.json +4 -0
- dcmspec/apps/ui/iod_explorer/config/iod_explorer_config_example.json +4 -0
- dcmspec/apps/ui/iod_explorer/config/iod_explorer_config_minimal_logging.json +4 -0
- dcmspec/apps/ui/iod_explorer/iod_explorer.py +989 -0
- dcmspec/config.py +90 -0
- dcmspec/csv_table_spec_parser.py +85 -0
- dcmspec/doc_handler.py +214 -0
- dcmspec/dom_table_spec_parser.py +831 -0
- dcmspec/dom_utils.py +116 -0
- dcmspec/iod_spec_builder.py +444 -0
- dcmspec/iod_spec_printer.py +59 -0
- dcmspec/json_spec_store.py +110 -0
- dcmspec/module_registry.py +51 -0
- dcmspec/pdf_doc_handler.py +451 -0
- dcmspec/progress.py +232 -0
- dcmspec/service_attribute_defaults.py +124 -0
- dcmspec/service_attribute_model.py +231 -0
- dcmspec/spec_factory.py +451 -0
- dcmspec/spec_merger.py +536 -0
- dcmspec/spec_model.py +461 -0
- dcmspec/spec_parser.py +37 -0
- dcmspec/spec_printer.py +131 -0
- dcmspec/spec_store.py +50 -0
- dcmspec/ups_xhtml_doc_handler.py +117 -0
- dcmspec/xhtml_doc_handler.py +182 -0
- dcmspec-0.2.1.dist-info/METADATA +139 -0
- dcmspec-0.2.1.dist-info/RECORD +45 -0
- dcmspec-0.2.1.dist-info/WHEEL +4 -0
- dcmspec-0.2.1.dist-info/entry_points.txt +11 -0
- dcmspec-0.2.1.dist-info/licenses/LICENSE +201 -0
dcmspec/__init__.py
ADDED
|
File without changes
|
dcmspec/apps/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Application interfaces for dcmspec."""
|
|
File without changes
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""CLI for extracting, caching, and printing DICOM Data Elements from Part 6.
|
|
2
|
+
|
|
3
|
+
Features:
|
|
4
|
+
- Download and parse DICOM Data Elements table from Part 6 of the DICOM standard.
|
|
5
|
+
- Cache the model as a JSON file for future runs and as a structured representation of the standard.
|
|
6
|
+
- Print the resulting Data Elements as a table.
|
|
7
|
+
- Supports caching, configuration files, and command-line options for flexible workflows.
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
poetry run python -m src.dcmspec.apps.cli.dataelements [options]
|
|
11
|
+
|
|
12
|
+
For more details, use the --help option.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import os
|
|
16
|
+
import argparse
|
|
17
|
+
from dcmspec.config import Config
|
|
18
|
+
|
|
19
|
+
from dcmspec.spec_factory import SpecFactory
|
|
20
|
+
from dcmspec.spec_printer import SpecPrinter
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def main():
|
|
24
|
+
"""CLI for parsing, caching, and printing DICOM Data Elements from Part 6.
|
|
25
|
+
|
|
26
|
+
This CLI downloads, caches, and prints the list of DICOM Data Elements from Part 6 of the DICOM standard.
|
|
27
|
+
|
|
28
|
+
The tool parses the Data Elements table to extract tags, names, keywords, VR (Value Representation),
|
|
29
|
+
VM (Value Multiplicity), and status for all DICOM data elements. The output can be printed as a table.
|
|
30
|
+
|
|
31
|
+
The resulting model is cached as a JSON file. The primary purpose of this cache file is to provide a structured,
|
|
32
|
+
machine-readable representation of the DICOM Data Elements, which can be used for further processing or integration
|
|
33
|
+
in other tools. As a secondary benefit, the cache file is also used to speed up subsequent runs of the CLI scripts.
|
|
34
|
+
|
|
35
|
+
Usage:
|
|
36
|
+
poetry run python -m src.dcmspec.apps.cli.dataelements [options]
|
|
37
|
+
|
|
38
|
+
Options:
|
|
39
|
+
--config (str): Path to the configuration file.
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
poetry run python -m src.dcmspec.apps.cli.dataelements
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
# Parse command-line arguments
|
|
46
|
+
parser = argparse.ArgumentParser()
|
|
47
|
+
parser.add_argument("--config", help="Path to the configuration file")
|
|
48
|
+
args = parser.parse_args()
|
|
49
|
+
|
|
50
|
+
# Determine config file location
|
|
51
|
+
config_file = args.config or os.getenv("DCMSPEC_CONFIG", None)
|
|
52
|
+
|
|
53
|
+
# Initialize configuration
|
|
54
|
+
config = Config(app_name="dcmspec", config_file=config_file)
|
|
55
|
+
|
|
56
|
+
url = "https://dicom.nema.org/medical/dicom/current/output/chtml/part06/chapter_6.html"
|
|
57
|
+
cache_file_name = "DataElements.xhtml"
|
|
58
|
+
json_cache_path = "DataElements.json"
|
|
59
|
+
table_id = "table_6-1"
|
|
60
|
+
|
|
61
|
+
# Create the factory
|
|
62
|
+
factory = SpecFactory(
|
|
63
|
+
column_to_attr={
|
|
64
|
+
0: "elem_tag",
|
|
65
|
+
1: "elem_name",
|
|
66
|
+
2: "elem_keyword",
|
|
67
|
+
3: "elem_vr",
|
|
68
|
+
4: "elem_vm",
|
|
69
|
+
5: "elem_status"
|
|
70
|
+
},
|
|
71
|
+
config=config
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Download, parse, and cache the model
|
|
75
|
+
model = factory.create_model(
|
|
76
|
+
url=url,
|
|
77
|
+
cache_file_name=cache_file_name,
|
|
78
|
+
table_id=table_id,
|
|
79
|
+
force_download=False,
|
|
80
|
+
json_file_name=json_cache_path,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Print the model as a table
|
|
84
|
+
printer = SpecPrinter(model)
|
|
85
|
+
printer.print_table(colorize=True)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
main()
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""CLI for extracting, caching, and printing the complete set of DICOM attributes for a given IOD from Part 3.
|
|
2
|
+
|
|
3
|
+
Features:
|
|
4
|
+
- Download and parse DICOM IOD tables from Part 3 of the DICOM standard.
|
|
5
|
+
- Automatically parse all referenced Module Attributes tables for the IOD.
|
|
6
|
+
- Cache the model as a JSON file for future runs and as a structured representation of the standard.
|
|
7
|
+
- Print the resulting attributes as a table or tree.
|
|
8
|
+
- Supports both Composite and Normalized IODs.
|
|
9
|
+
- Supports caching, configuration files, and command-line options for flexible workflows.
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
poetry run python -m src.dcmspec.apps.cli.iodattributes <table_id> [options]
|
|
13
|
+
|
|
14
|
+
For more details, use the --help option.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
import argparse
|
|
19
|
+
|
|
20
|
+
from dcmspec.config import Config
|
|
21
|
+
from dcmspec.iod_spec_builder import IODSpecBuilder
|
|
22
|
+
from dcmspec.iod_spec_printer import IODSpecPrinter
|
|
23
|
+
from dcmspec.spec_factory import SpecFactory
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def main():
|
|
27
|
+
"""CLI for parsing, caching, and printing DICOM IOD attribute models.
|
|
28
|
+
|
|
29
|
+
This CLI downloads, caches, and prints all attributes for a specified DICOM IOD (Information Object Definition)
|
|
30
|
+
from Part 3 of the DICOM standard, supporting both Composite and Normalized IODs.
|
|
31
|
+
|
|
32
|
+
When an IOD table is specified, the tool parses the IOD table to determine which modules are referenced, then
|
|
33
|
+
automatically parses each referenced Module Attributes table. The resulting model contains both the list of modules
|
|
34
|
+
and, for each module, all its attributes. The print output (table or tree) shows only the attributes, not the IOD
|
|
35
|
+
table or module structure itself.
|
|
36
|
+
|
|
37
|
+
The resulting model is cached as a JSON file. The primary purpose of this cache file is to provide a structured,
|
|
38
|
+
machine-readable representation of the IOD's attributes, which can be used for further processing or integration in
|
|
39
|
+
other tools. As a secondary benefit, the cache file is also used to speed up subsequent runs of the CLI scripts.
|
|
40
|
+
|
|
41
|
+
Usage:
|
|
42
|
+
poetry run python -m src.dcmspec.apps.cli.iodattributes <table_id> [options]
|
|
43
|
+
|
|
44
|
+
Options:
|
|
45
|
+
table (str): Table ID to extract (e.g., "table_A.3-1" or "table_B.26.2-1").
|
|
46
|
+
--config (str): Path to the configuration file.
|
|
47
|
+
--print-mode (str): Print as 'table' (default), 'tree', or 'none' to skip printing.
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
poetry run python -m src.dcmspec.apps.cli.iodattributes table_A.3-1 --print-mode tree
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
url = "https://dicom.nema.org/medical/dicom/current/output/html/part03.html"
|
|
54
|
+
|
|
55
|
+
# Parse command-line arguments
|
|
56
|
+
parser = argparse.ArgumentParser()
|
|
57
|
+
parser.add_argument("table", help="Table ID")
|
|
58
|
+
parser.add_argument("--config", help="Path to the configuration file")
|
|
59
|
+
parser.add_argument(
|
|
60
|
+
"--print-mode",
|
|
61
|
+
choices=["table", "tree", "none"],
|
|
62
|
+
default="table",
|
|
63
|
+
help="Print as 'table' (default), 'tree', or 'none' to skip printing"
|
|
64
|
+
)
|
|
65
|
+
args = parser.parse_args()
|
|
66
|
+
|
|
67
|
+
cache_file_name = "Part3.xhtml"
|
|
68
|
+
model_file_name = f"Part3_{args.table}_expanded.json"
|
|
69
|
+
table_id = args.table
|
|
70
|
+
|
|
71
|
+
# Determine config file location
|
|
72
|
+
config_file = args.config or os.getenv("DCMSPEC_CONFIG", None)
|
|
73
|
+
|
|
74
|
+
# Initialize configuration
|
|
75
|
+
config = Config(app_name="dcmspec", config_file=config_file)
|
|
76
|
+
|
|
77
|
+
# Check table_id belongs to either Composite or Normalized IODs annexes
|
|
78
|
+
if "table_A." in table_id:
|
|
79
|
+
composite_iod = True
|
|
80
|
+
elif "table_B." in table_id:
|
|
81
|
+
composite_iod = False
|
|
82
|
+
else:
|
|
83
|
+
parser.error(f"table {table_id} does not correspond to a Composite or Normalized IOD")
|
|
84
|
+
|
|
85
|
+
# Create the IOD specification factory
|
|
86
|
+
c_iod_columns_mapping = {0: "ie", 1: "module", 2: "ref", 3: "usage"}
|
|
87
|
+
n_iod_columns_mapping = {0: "module", 1: "ref", 2: "usage"}
|
|
88
|
+
iod_columns_mapping = c_iod_columns_mapping if composite_iod else n_iod_columns_mapping
|
|
89
|
+
iod_factory = SpecFactory(
|
|
90
|
+
column_to_attr=iod_columns_mapping,
|
|
91
|
+
name_attr="module",
|
|
92
|
+
config=config,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Create the modules specification factory
|
|
96
|
+
parser_kwargs=None if composite_iod else {"skip_columns": [2]}
|
|
97
|
+
module_factory = SpecFactory(
|
|
98
|
+
column_to_attr={0: "elem_name", 1: "elem_tag", 2: "elem_type", 3: "elem_description"},
|
|
99
|
+
name_attr="elem_name",
|
|
100
|
+
parser_kwargs=parser_kwargs,
|
|
101
|
+
config=config,
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Create the builder
|
|
105
|
+
builder = IODSpecBuilder(iod_factory=iod_factory, module_factory=module_factory)
|
|
106
|
+
|
|
107
|
+
# Download, parse, and cache the combined model
|
|
108
|
+
model, _ = builder.build_from_url(
|
|
109
|
+
url=url,
|
|
110
|
+
cache_file_name=cache_file_name,
|
|
111
|
+
json_file_name=model_file_name,
|
|
112
|
+
table_id=table_id,
|
|
113
|
+
force_download=False,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# Print the model
|
|
117
|
+
printer = IODSpecPrinter(model)
|
|
118
|
+
if args.print_mode == "tree":
|
|
119
|
+
printer.print_tree(colorize=True)
|
|
120
|
+
elif args.print_mode == "table":
|
|
121
|
+
printer.print_table(colorize=True)
|
|
122
|
+
# else: do not print anything if print_mode == "none"
|
|
123
|
+
|
|
124
|
+
if __name__ == "__main__":
|
|
125
|
+
main()
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""CLI for extracting, caching, and printing DICOM IOD Module tables from Part 3.
|
|
2
|
+
|
|
3
|
+
Features:
|
|
4
|
+
- Download and parse DICOM IOD tables from Part 3 of the DICOM standard.
|
|
5
|
+
- Extract and print the list of modules for a given IOD.
|
|
6
|
+
- Cache the model as a JSON file for future runs and as a structured representation of the standard.
|
|
7
|
+
- Print the resulting module list as a table.
|
|
8
|
+
- Supports caching, configuration files, and command-line options for flexible workflows.
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
poetry run python -m src.dcmspec.apps.cli.iodmodules <table_id> [options]
|
|
12
|
+
|
|
13
|
+
For more details, use the --help option.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import argparse
|
|
18
|
+
from dcmspec.config import Config
|
|
19
|
+
|
|
20
|
+
from dcmspec.spec_factory import SpecFactory
|
|
21
|
+
from dcmspec.spec_printer import SpecPrinter
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def main():
|
|
25
|
+
"""CLI for parsing, caching, and printing DICOM IOD Module tables.
|
|
26
|
+
|
|
27
|
+
This CLI downloads, caches, and prints the list of modules of a given DICOM IOD (Information Object Definition)
|
|
28
|
+
from Part 3 of the DICOM standard.
|
|
29
|
+
|
|
30
|
+
The tool parses only the specified IOD table to extract the list of referenced modules, including their Information
|
|
31
|
+
Entity (IE), reference, and usage. It does not parse or include the attributes of the referenced module tables.
|
|
32
|
+
The output is a table listing all modules for the specified IOD.
|
|
33
|
+
|
|
34
|
+
The resulting model is cached as a JSON file. The primary purpose of this cache file is to provide a structured,
|
|
35
|
+
machine-readable representation of the IOD's module composition, which can be used for further processing or
|
|
36
|
+
integration in other tools. As a secondary benefit, the cache file is also used to speed up subsequent runs of the
|
|
37
|
+
CLI scripts.
|
|
38
|
+
|
|
39
|
+
Usage:
|
|
40
|
+
poetry run python -m src.dcmspec.apps.cli.iodmodules <table_id> [options]
|
|
41
|
+
|
|
42
|
+
Options:
|
|
43
|
+
table (str): Table ID to extract (e.g., "table_A.1-1" or "table_B.1-1").
|
|
44
|
+
--config (str): Path to the configuration file.
|
|
45
|
+
|
|
46
|
+
Example:
|
|
47
|
+
poetry run python -m src.dcmspec.apps.cli.iodmodules table_A.1-1
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
url = "https://dicom.nema.org/medical/dicom/current/output/html/part03.html"
|
|
51
|
+
|
|
52
|
+
# Parse command-line arguments
|
|
53
|
+
parser = argparse.ArgumentParser()
|
|
54
|
+
# parser.add_argument("table", help="Table ID")
|
|
55
|
+
parser.add_argument("table", nargs="?", default="table_A.3-1", help="Table ID")
|
|
56
|
+
|
|
57
|
+
parser.add_argument("--config", help="Path to the configuration file")
|
|
58
|
+
args = parser.parse_args()
|
|
59
|
+
|
|
60
|
+
cache_file_name = "Part3.xhtml"
|
|
61
|
+
model_file_name = f"Part3_{args.table}.json"
|
|
62
|
+
table_id = args.table
|
|
63
|
+
|
|
64
|
+
# Determine config file location
|
|
65
|
+
config_file = args.config or os.getenv("DCMSPEC_CONFIG", None)
|
|
66
|
+
|
|
67
|
+
# Initialize configuration
|
|
68
|
+
config = Config(app_name="dcmspec", config_file=config_file)
|
|
69
|
+
|
|
70
|
+
# Create the factory
|
|
71
|
+
factory = SpecFactory(
|
|
72
|
+
column_to_attr={0: "ie", 1: "module", 2: "ref", 3: "usage"},
|
|
73
|
+
name_attr="module",
|
|
74
|
+
config=config,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Download, parse, and cache the model
|
|
78
|
+
model = factory.create_model(
|
|
79
|
+
url=url,
|
|
80
|
+
cache_file_name=cache_file_name,
|
|
81
|
+
json_file_name=model_file_name,
|
|
82
|
+
table_id=table_id,
|
|
83
|
+
force_download=False,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Print the model as a table
|
|
87
|
+
printer = SpecPrinter(model)
|
|
88
|
+
printer.print_table(colorize=True)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
main()
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"""CLI for extracting, caching, and printing DICOM Module Attributes tables from Part 3.
|
|
2
|
+
|
|
3
|
+
Features:
|
|
4
|
+
- Download and parse DICOM Module Attributes tables from Part 3 of the DICOM standard.
|
|
5
|
+
- Optionally merge additional information (VR, VM, Keyword, Status) from Part 6.
|
|
6
|
+
- Cache the resulting model as a JSON file for future runs and as a structured representation of the standard.
|
|
7
|
+
- Print the resulting model as a table or tree.
|
|
8
|
+
- Supports caching, configuration files, and command-line options for flexible workflows.
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
poetry run python -m src.dcmspec.apps.cli.modattributes <table_id> [options]
|
|
12
|
+
|
|
13
|
+
For more details, use the --help option.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import argparse
|
|
18
|
+
import logging
|
|
19
|
+
from dcmspec.config import Config
|
|
20
|
+
|
|
21
|
+
from dcmspec.spec_factory import SpecFactory
|
|
22
|
+
from dcmspec.spec_merger import SpecMerger
|
|
23
|
+
from dcmspec.spec_printer import SpecPrinter
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def create_module_model(config, table_id, force_parse, force_download, include_depth, logger=None):
|
|
27
|
+
"""Create a DICOM Module Attributes model from Part 3 of the DICOM standard.
|
|
28
|
+
|
|
29
|
+
Downloads and parses the specified module attributes table from the DICOM standard (Part 3),
|
|
30
|
+
or loads it from cache if available. The resulting model contains the attributes, tags, types,
|
|
31
|
+
and descriptions for the specified module.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
config (Config): The configuration object.
|
|
35
|
+
table_id (str): The table ID to extract (e.g., "table_C.7-1").
|
|
36
|
+
force_parse (bool): If True, force reparsing of the DOM and regeneration of the JSON model.
|
|
37
|
+
force_download (bool): If True, force download of the input file and regeneration of the model.
|
|
38
|
+
include_depth (int or None): Depth to which included tables should be parsed (None for unlimited).
|
|
39
|
+
logger (logging.Logger, optional): Logger instance for debug output.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
SpecModel: The parsed module attributes model.
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
url = "https://dicom.nema.org/medical/dicom/current/output/html/part03.html"
|
|
46
|
+
cache_file_name = "Part3.xhtml"
|
|
47
|
+
model_file_name = f"Part3_{table_id}.json"
|
|
48
|
+
factory = SpecFactory(
|
|
49
|
+
column_to_attr={0: "elem_name", 1: "elem_tag", 2: "elem_type", 3: "elem_description"},
|
|
50
|
+
name_attr="elem_name",
|
|
51
|
+
config=config,
|
|
52
|
+
logger=logger,
|
|
53
|
+
)
|
|
54
|
+
if logger:
|
|
55
|
+
logger.debug(f"Creating module model: cache_file_name={cache_file_name}, model_file_name={model_file_name}")
|
|
56
|
+
return factory.create_model(
|
|
57
|
+
url=url,
|
|
58
|
+
cache_file_name=cache_file_name,
|
|
59
|
+
json_file_name=model_file_name,
|
|
60
|
+
table_id=table_id,
|
|
61
|
+
force_parse=force_parse,
|
|
62
|
+
force_download=force_download,
|
|
63
|
+
include_depth=include_depth,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def create_part6_model(config, logger=None):
|
|
67
|
+
"""Create a DICOM Data Elements model from Part 6 of the DICOM standard.
|
|
68
|
+
|
|
69
|
+
Downloads and parses the Data Elements table from Part 6 of the DICOM standard,
|
|
70
|
+
or loads it from cache if available. The resulting model contains tags, names,
|
|
71
|
+
keywords, VR, VM, and status for all DICOM data elements.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
config (Config): The configuration object.
|
|
75
|
+
logger (logging.Logger, optional): Logger instance for debug output.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
SpecModel: The parsed Part 6 Data Elements model.
|
|
79
|
+
|
|
80
|
+
"""
|
|
81
|
+
url = "https://dicom.nema.org/medical/dicom/current/output/chtml/part06/chapter_6.html"
|
|
82
|
+
cache_file_name = "DataElements.xhtml"
|
|
83
|
+
json_file_name = "DataElements.json"
|
|
84
|
+
table_id = "table_6-1"
|
|
85
|
+
factory = SpecFactory(
|
|
86
|
+
column_to_attr={
|
|
87
|
+
0: "elem_tag",
|
|
88
|
+
1: "elem_name",
|
|
89
|
+
2: "elem_keyword",
|
|
90
|
+
3: "elem_vr",
|
|
91
|
+
4: "elem_vm",
|
|
92
|
+
5: "elem_status"
|
|
93
|
+
},
|
|
94
|
+
config=config,
|
|
95
|
+
logger=logger,
|
|
96
|
+
)
|
|
97
|
+
if logger:
|
|
98
|
+
logger.debug(f"Creating part6 model: cache_file_name={cache_file_name}, json_cache_path={json_file_name}")
|
|
99
|
+
return factory.create_model(
|
|
100
|
+
url=url,
|
|
101
|
+
cache_file_name=cache_file_name,
|
|
102
|
+
table_id=table_id,
|
|
103
|
+
force_download=False,
|
|
104
|
+
json_file_name=json_file_name,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def main():
|
|
108
|
+
"""CLI for parsing, caching, and printing DICOM Module Attributes tables.
|
|
109
|
+
|
|
110
|
+
This CLI extracts, caches, and prints the attributes of a given DICOM Module
|
|
111
|
+
from Part 3 of the DICOM standard. Optionally, it can enrich the module with VR, VM, Keyword,
|
|
112
|
+
or Status information from Part 6 (Data Elements dictionary).
|
|
113
|
+
|
|
114
|
+
The tool parses the specified Module Attributes table to extract all attributes, tags, types,
|
|
115
|
+
and descriptions for the module. Optionally, it can merge in VR, VM, Keyword, or Status information
|
|
116
|
+
from Part 6. The output can be printed as a table or tree.
|
|
117
|
+
|
|
118
|
+
The resulting model is cached as a JSON file. The primary purpose of this cache file is to provide
|
|
119
|
+
a structured, machine-readable representation of the module's attributes, which can be used for further processing
|
|
120
|
+
or integration in other tools. As a secondary benefit, the cache file is also used to speed up subsequent runs
|
|
121
|
+
of the CLI scripts.
|
|
122
|
+
|
|
123
|
+
Usage:
|
|
124
|
+
poetry run python -m src.dcmspec.apps.cli.modattributes <table_id> [options]
|
|
125
|
+
|
|
126
|
+
Options:
|
|
127
|
+
table (str): Table ID to extract (e.g., "table_C.7-1").
|
|
128
|
+
--config (str): Path to the configuration file.
|
|
129
|
+
--include-depth (int): Depth to which included tables should be parsed (default: unlimited).
|
|
130
|
+
--force-parse: Force reparsing of the DOM and regeneration of the JSON model.
|
|
131
|
+
--force-download: Force download of the input file and regeneration of the model.
|
|
132
|
+
--print-mode (str): Print as 'table' (default), 'tree', or 'none' to skip printing.
|
|
133
|
+
--add-part6 (list): Specification(s) to merge from Part 6 (e.g., --add-part6 VR VM).
|
|
134
|
+
--force-update: Force update of the specifications merged from part 6, even if cached.
|
|
135
|
+
-d, --debug: Enable debug logging to the console.
|
|
136
|
+
-v, --verbose: Enable verbose (info-level) logging to the console.
|
|
137
|
+
|
|
138
|
+
Example:
|
|
139
|
+
poetry run python -m src.dcmspec.apps.cli.modattributes table_C.7-1 --add-part6 VR VM
|
|
140
|
+
|
|
141
|
+
"""
|
|
142
|
+
# Parse command-line arguments
|
|
143
|
+
parser = argparse.ArgumentParser()
|
|
144
|
+
parser.add_argument("table", help="Table ID")
|
|
145
|
+
parser.add_argument("--config", help="Path to the configuration file")
|
|
146
|
+
parser.add_argument(
|
|
147
|
+
"--include-depth",
|
|
148
|
+
type=int,
|
|
149
|
+
default=None,
|
|
150
|
+
help="Depth to which included tables should be parsed (default: unlimited)"
|
|
151
|
+
)
|
|
152
|
+
parser.add_argument(
|
|
153
|
+
"--force-parse",
|
|
154
|
+
action="store_true",
|
|
155
|
+
help="Force reparsing of the DOM and regeneration of the JSON model, even if the JSON cache exists."
|
|
156
|
+
)
|
|
157
|
+
parser.add_argument(
|
|
158
|
+
"--force-download",
|
|
159
|
+
action="store_true",
|
|
160
|
+
help=(
|
|
161
|
+
"Force download of the input file and regeneration of the model, even if cached. "
|
|
162
|
+
"Implies --force-parse (the file will also be re-parsed)."
|
|
163
|
+
)
|
|
164
|
+
)
|
|
165
|
+
parser.add_argument(
|
|
166
|
+
"--print-mode",
|
|
167
|
+
choices=["table", "tree", "none"],
|
|
168
|
+
default="table",
|
|
169
|
+
help="Print as 'table' (default), 'tree', or 'none' to skip printing"
|
|
170
|
+
)
|
|
171
|
+
parser.add_argument(
|
|
172
|
+
"--add-part6",
|
|
173
|
+
nargs="+",
|
|
174
|
+
choices=["VR", "VM", "Keyword", "Status"],
|
|
175
|
+
help="Specification to merge from Part 6 (e.g. --add-part6 VR VM)"
|
|
176
|
+
)
|
|
177
|
+
parser.add_argument(
|
|
178
|
+
"--force-update",
|
|
179
|
+
action="store_true",
|
|
180
|
+
help="Force update of the specifications merged from part 6, even if cached"
|
|
181
|
+
)
|
|
182
|
+
parser.add_argument(
|
|
183
|
+
"-d", "--debug",
|
|
184
|
+
action="store_true",
|
|
185
|
+
help="Enable debug logging to the console (overrides --verbose)"
|
|
186
|
+
)
|
|
187
|
+
parser.add_argument(
|
|
188
|
+
"-v", "--verbose",
|
|
189
|
+
action="store_true",
|
|
190
|
+
help="Enable verbose (info-level) logging to the console"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
args = parser.parse_args()
|
|
194
|
+
|
|
195
|
+
# Set up logger
|
|
196
|
+
logger = logging.getLogger("modattributes")
|
|
197
|
+
handler = logging.StreamHandler()
|
|
198
|
+
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
|
|
199
|
+
handler.setFormatter(formatter)
|
|
200
|
+
if not logger.hasHandlers():
|
|
201
|
+
logger.addHandler(handler)
|
|
202
|
+
if args.debug:
|
|
203
|
+
logger.setLevel(logging.DEBUG)
|
|
204
|
+
handler.setLevel(logging.DEBUG)
|
|
205
|
+
elif args.verbose:
|
|
206
|
+
logger.setLevel(logging.INFO)
|
|
207
|
+
handler.setLevel(logging.INFO)
|
|
208
|
+
else:
|
|
209
|
+
logger.setLevel(logging.WARNING)
|
|
210
|
+
handler.setLevel(logging.WARNING)
|
|
211
|
+
|
|
212
|
+
# Determine config file location
|
|
213
|
+
config_file = args.config or os.getenv("DCMSPEC_CONFIG", None)
|
|
214
|
+
config = Config(app_name="modattributes", config_file=config_file)
|
|
215
|
+
|
|
216
|
+
logger.debug(f"Config file: {config_file}")
|
|
217
|
+
logger.debug(f"Cache dir: {config.get_param('cache_dir')}")
|
|
218
|
+
logger.debug(f"Table ID: {args.table}")
|
|
219
|
+
|
|
220
|
+
# Create the module model
|
|
221
|
+
module_model = create_module_model(
|
|
222
|
+
config=config,
|
|
223
|
+
table_id=args.table,
|
|
224
|
+
force_parse=args.force_parse,
|
|
225
|
+
force_download=args.force_download,
|
|
226
|
+
include_depth=args.include_depth,
|
|
227
|
+
logger=logger,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# Optionally enrich with Part 6
|
|
231
|
+
part6_attr_map = {
|
|
232
|
+
"VR": "elem_vr",
|
|
233
|
+
"VM": "elem_vm",
|
|
234
|
+
"Keyword": "elem_keyword",
|
|
235
|
+
"Status": "elem_status",
|
|
236
|
+
}
|
|
237
|
+
merge_attrs = [part6_attr_map[x] for x in (args.add_part6 or [])]
|
|
238
|
+
|
|
239
|
+
if merge_attrs:
|
|
240
|
+
model_file_name = f"Part3_{args.table}_enriched.json"
|
|
241
|
+
part6_model = create_part6_model(config, logger=logger)
|
|
242
|
+
logger.debug("Merging module model with part6 model.")
|
|
243
|
+
merger = SpecMerger(config=config, logger=logger)
|
|
244
|
+
model = merger.merge_node(
|
|
245
|
+
module_model,
|
|
246
|
+
part6_model,
|
|
247
|
+
match_by= "attribute",
|
|
248
|
+
attribute_name="elem_tag",
|
|
249
|
+
merge_attrs=merge_attrs,
|
|
250
|
+
json_file_name=model_file_name,
|
|
251
|
+
force_update=args.force_update or args.force_download or args.force_parse,
|
|
252
|
+
)
|
|
253
|
+
else:
|
|
254
|
+
model = module_model
|
|
255
|
+
|
|
256
|
+
logger.debug("Model ready for printing/output")
|
|
257
|
+
printer = SpecPrinter(model)
|
|
258
|
+
if args.print_mode == "tree":
|
|
259
|
+
printer.print_tree(colorize=True)
|
|
260
|
+
elif args.print_mode == "table":
|
|
261
|
+
printer.print_table(colorize=True)
|
|
262
|
+
# else: do not print anything if print_mode == "none"
|
|
263
|
+
|
|
264
|
+
if __name__ == "__main__":
|
|
265
|
+
main()
|