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.
Files changed (45) hide show
  1. dcmspec/__init__.py +0 -0
  2. dcmspec/apps/__init__.py +1 -0
  3. dcmspec/apps/cli/__init__.py +0 -0
  4. dcmspec/apps/cli/dataelements.py +89 -0
  5. dcmspec/apps/cli/iodattributes.py +125 -0
  6. dcmspec/apps/cli/iodmodules.py +92 -0
  7. dcmspec/apps/cli/modattributes.py +265 -0
  8. dcmspec/apps/cli/tdwiicontent.py +365 -0
  9. dcmspec/apps/cli/uidvalues.py +84 -0
  10. dcmspec/apps/cli/upsdimseattributes.py +109 -0
  11. dcmspec/apps/cli/upsioddimseattributes.py +330 -0
  12. dcmspec/apps/ui/iod_explorer/README.md +33 -0
  13. dcmspec/apps/ui/iod_explorer/__init__.py +9 -0
  14. dcmspec/apps/ui/iod_explorer/config/README.md +171 -0
  15. dcmspec/apps/ui/iod_explorer/config/iod_explorer_config.json +4 -0
  16. dcmspec/apps/ui/iod_explorer/config/iod_explorer_config_debug.json +4 -0
  17. dcmspec/apps/ui/iod_explorer/config/iod_explorer_config_example.json +4 -0
  18. dcmspec/apps/ui/iod_explorer/config/iod_explorer_config_minimal_logging.json +4 -0
  19. dcmspec/apps/ui/iod_explorer/iod_explorer.py +989 -0
  20. dcmspec/config.py +90 -0
  21. dcmspec/csv_table_spec_parser.py +85 -0
  22. dcmspec/doc_handler.py +214 -0
  23. dcmspec/dom_table_spec_parser.py +831 -0
  24. dcmspec/dom_utils.py +116 -0
  25. dcmspec/iod_spec_builder.py +444 -0
  26. dcmspec/iod_spec_printer.py +59 -0
  27. dcmspec/json_spec_store.py +110 -0
  28. dcmspec/module_registry.py +51 -0
  29. dcmspec/pdf_doc_handler.py +451 -0
  30. dcmspec/progress.py +232 -0
  31. dcmspec/service_attribute_defaults.py +124 -0
  32. dcmspec/service_attribute_model.py +231 -0
  33. dcmspec/spec_factory.py +451 -0
  34. dcmspec/spec_merger.py +536 -0
  35. dcmspec/spec_model.py +461 -0
  36. dcmspec/spec_parser.py +37 -0
  37. dcmspec/spec_printer.py +131 -0
  38. dcmspec/spec_store.py +50 -0
  39. dcmspec/ups_xhtml_doc_handler.py +117 -0
  40. dcmspec/xhtml_doc_handler.py +182 -0
  41. dcmspec-0.2.1.dist-info/METADATA +139 -0
  42. dcmspec-0.2.1.dist-info/RECORD +45 -0
  43. dcmspec-0.2.1.dist-info/WHEEL +4 -0
  44. dcmspec-0.2.1.dist-info/entry_points.txt +11 -0
  45. dcmspec-0.2.1.dist-info/licenses/LICENSE +201 -0
dcmspec/__init__.py ADDED
File without changes
@@ -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()