ECGProcess 1.1.0__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 (33) hide show
  1. ecgprocess/__init__.py +1 -0
  2. ecgprocess/_version.py +1 -0
  3. ecgprocess/constants.py +170 -0
  4. ecgprocess/errors.py +380 -0
  5. ecgprocess/example_data/__init__.py +1 -0
  6. ecgprocess/example_data/example_datasets/.example-XML1.xml.un~ +0 -0
  7. ecgprocess/example_data/example_datasets/.example-XML1.xsd.un~ +0 -0
  8. ecgprocess/example_data/example_datasets/.example-XML1_a.xsd.un~ +0 -0
  9. ecgprocess/example_data/example_datasets/.example-XML1_d.xsd.un~ +0 -0
  10. ecgprocess/example_data/example_datasets/.example-XML1_wrong.xsd.un~ +0 -0
  11. ecgprocess/example_data/example_datasets/example-DICOM1.dcm +0 -0
  12. ecgprocess/example_data/example_datasets/example-DICOM2.dcm +0 -0
  13. ecgprocess/example_data/example_datasets/example-XML1.xml +675 -0
  14. ecgprocess/example_data/example_datasets/example-XML1.xsd +518 -0
  15. ecgprocess/example_data/example_datasets/example-XML1_error.xsd +519 -0
  16. ecgprocess/example_data/example_datasets/example-XML1_wrong.xsd +519 -0
  17. ecgprocess/example_data/example_datasets/string_data.txt +1 -0
  18. ecgprocess/example_data/examples.py +501 -0
  19. ecgprocess/plot_ecgs.py +921 -0
  20. ecgprocess/process_dicom.py +243 -0
  21. ecgprocess/process_xml.py +319 -0
  22. ecgprocess/tabular.py +1394 -0
  23. ecgprocess/utils/__init__.py +1 -0
  24. ecgprocess/utils/config_tools.py +581 -0
  25. ecgprocess/utils/ecg_tools.py +311 -0
  26. ecgprocess/utils/engineering_tools.py +385 -0
  27. ecgprocess/utils/general.py +399 -0
  28. ecgprocess/utils/reader_tools.py +508 -0
  29. ecgprocess-1.1.0.dist-info/METADATA +153 -0
  30. ecgprocess-1.1.0.dist-info/RECORD +33 -0
  31. ecgprocess-1.1.0.dist-info/WHEEL +5 -0
  32. ecgprocess-1.1.0.dist-info/licenses/LICENCE.txt +17 -0
  33. ecgprocess-1.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,501 @@
1
+ """Provides centralised access to example data sets that can be used in tests
2
+ and also in example code and/or jupyter notebooks.
3
+
4
+ Notes
5
+ -----
6
+ Data can be "added" either through functions that generate the data on the fly
7
+ or via functions that load the data from a static file located in the
8
+ ``example_data`` directory. The data files being added should be as small as
9
+ possible (i.e. kilobyte/megabyte range). The dataset functions should be
10
+ decorated with the ``@dataset`` decorator, so the example module knows about
11
+ them. If the function is loading a dataset from a file in the package, it
12
+ should look for the path in ``_ROOT_DATASETS_DIR``.
13
+
14
+ Examples
15
+ --------
16
+
17
+ Registering a function as a dataset providing function:
18
+
19
+ >>> @dataset
20
+ >>> def dummy_data(*args, **kwargs):
21
+ >>> \"\"\"A dummy dataset function that returns a small list.
22
+ >>>
23
+ >>> Returns
24
+ >>> -------
25
+ >>> data : `list`
26
+ >>> A list of length 3 with ``['A', 'B', 'C']``
27
+ >>>
28
+ >>> Notes
29
+ >>> -----
30
+ >>> This function is called ``dummy_data`` and has been decorated with a
31
+ >>> ``@dataset`` decorator which makes it available with the
32
+ >>> `example_data.get_data(<NAME>)` function and also
33
+ >>> `example_data.help(<NAME>)` functions.
34
+ >>> \"\"\"
35
+ >>> return ['A', 'B', 'C']
36
+
37
+ The dataset can then be used as follows:
38
+
39
+ >>> from ecgprocess.example_data import examples
40
+ >>> examples.get_data('dummy_data')
41
+ >>> ['A', 'B', 'C']
42
+
43
+ A dataset function that loads a dataset from file, these functions should load
44
+ from the ``_ROOT_DATASETS_DIR``:
45
+
46
+ >>> @dataset
47
+ >>> def dummy_load_data(*args, **kwargs):
48
+ >>> \"\"\"A dummy dataset function that loads a string from a file.
49
+ >>>
50
+ >>> Returns
51
+ >>> -------
52
+ >>> str_data : `str`
53
+ >>> A string of data loaded from an example data file.
54
+ >>>
55
+ >>> Notes
56
+ >>> -----
57
+ >>> This function is called ``dummy_data`` and has been decorated with a
58
+ >>> ``@dataset`` decorator which makes it available with the
59
+ >>> `example_data.get_data(<NAME>)` function and also
60
+ >>> `example_data.help(<NAME>)` functions. The path to this dataset is
61
+ >>> built from ``_ROOT_DATASETS_DIR``.
62
+ >>> \"\"\"
63
+ >>> load_path = os.path.join(_ROOT_DATASETS_DIR, "string_data.txt")
64
+ >>> with open(load_path) as data_file:
65
+ >>> return data_file.read().strip()
66
+
67
+ The dataset can then be used as follows:
68
+
69
+ >>> from ecgprocess.example_data import examples
70
+ >>> examples.get_data('dummy_load_data')
71
+ >>> 'an example data string'
72
+ """
73
+ import os
74
+ import re
75
+ import pandas as pd
76
+ import numpy as np
77
+ import ecgprocess.utils.config_tools as config_utils
78
+ from tempfile import NamedTemporaryFile
79
+ from ecgprocess.constants import CoreData as Core
80
+ CLeads = Core.Leads
81
+ # The name of the example datasets directory
82
+ _EXAMPLE_DATASETS = "example_datasets"
83
+ """The example dataset directory name (`str`)
84
+ """
85
+
86
+ _ROOT_DATASETS_DIR = os.path.join(os.path.dirname(__file__), _EXAMPLE_DATASETS)
87
+ """The root path to the dataset files that are available (`str`)
88
+ """
89
+
90
+ _DATASETS = dict()
91
+ """This will hold the registered dataset functions (`dict`)
92
+ """
93
+
94
+
95
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
96
+ def dataset(func):
97
+ """Register a dataset generating function. This function should be used as
98
+ a decorator.
99
+
100
+ Parameters
101
+ ----------
102
+ func : `function`
103
+ The function to register as a dataset. It is registered as under the
104
+ function name.
105
+
106
+ Returns
107
+ -------
108
+ func : `function`
109
+ The function that has been registered.
110
+
111
+ Raises
112
+ ------
113
+ KeyError
114
+ If a function of the same name has already been registered.
115
+
116
+ Notes
117
+ -----
118
+ The dataset function should accept ``*args`` and ``**kwargs`` and should be
119
+ decorated with the ``@dataset`` decorator.
120
+
121
+ Examples
122
+ --------
123
+ Create a dataset function that returns a dictionary.
124
+
125
+ >>> @dataset
126
+ >>> def get_dict(*args, **kwargs):
127
+ >>> \"\"\"A dictionary to test or use as an example.
128
+ >>>
129
+ >>> Returns
130
+ >>> -------
131
+ >>> test_dict : `dict`
132
+ >>> A small dictionary of string keys and numeric values
133
+ >>> \"\"\"
134
+ >>> return {'A': 1, 'B': 2, 'C': 3}
135
+ >>>
136
+
137
+ The dataset can then be used as follows:
138
+
139
+ >>> from ecgprocess.example_data import examples
140
+ >>> examples.get_data('get_dict')
141
+ >>> {'A': 1, 'B': 2, 'C': 3}
142
+
143
+ """
144
+ try:
145
+ _DATASETS[func.__name__]
146
+ raise KeyError("function already registered")
147
+ except KeyError:
148
+ pass
149
+
150
+ _DATASETS[func.__name__] = func
151
+ return func
152
+
153
+
154
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
155
+ def get_data(name, *args, **kwargs):
156
+ """Central point to get the datasets.
157
+
158
+ Parameters
159
+ ----------
160
+ name : `str`
161
+ A name for the dataset that should correspond to a registered
162
+ dataset function.
163
+ *args
164
+ Arguments to the data generating functions
165
+ **kwargs
166
+ Keyword arguments to the data generating functions
167
+
168
+ Returns
169
+ -------
170
+ dataset : `Any`
171
+ The requested datasets
172
+ """
173
+ try:
174
+ return _DATASETS[name](*args, **kwargs)
175
+ except KeyError as e:
176
+ raise KeyError("dataset not available: {0}".format(name)) from e
177
+
178
+
179
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
180
+ def list_datasets():
181
+ """List all the registered datasets.
182
+
183
+ Returns
184
+ -------
185
+ datasets : `list` of `tuple`
186
+ The registered datasets. Element [0] for each tuple is the dataset name
187
+ and element [1] is a short description captured from the docstring.
188
+ """
189
+ datasets = []
190
+ for d in _DATASETS.keys():
191
+ desc = re.sub(
192
+ r'(Parameters|Returns).*$', '', _DATASETS[d].__doc__.replace(
193
+ '\n', ' '
194
+ )
195
+ ).strip()
196
+ datasets.append((d, desc))
197
+ return datasets
198
+
199
+
200
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
201
+ def help(name):
202
+ """Central point to get help for the datasets.
203
+
204
+ Parameters
205
+ ----------
206
+ name : `str`
207
+ A name for the dataset that should correspond to a unique key in the
208
+ DATASETS module level dictionary.
209
+
210
+ Returns
211
+ -------
212
+ help : `str`
213
+ The docstring for the function
214
+ """
215
+ docs = ["Dataset: {0}\n{1}\n\n".format(name, "-" * (len(name) + 9))]
216
+ try:
217
+ docs.extend(
218
+ ["{0}\n".format(re.sub(r"^\s{4}", "", i))
219
+ for i in _DATASETS[name].__doc__.split("\n")]
220
+ )
221
+ return "".join(docs)
222
+ except KeyError as e:
223
+ raise KeyError("dataset not available: {0}".format(name)) from e
224
+
225
+
226
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227
+ @dataset
228
+ def dummy_data():
229
+ """A dummy dataset function that returns a small list.
230
+
231
+ Returns
232
+ -------
233
+ data : `list`
234
+ A list of length 3 with ``['A', 'B', 'C']``
235
+
236
+ Notes
237
+ -----
238
+ This function is called ``dummy_data`` and has been decorated with a
239
+ ``@dataset`` decorator which makes it available with the
240
+ `example_data.get_data(<NAME>)` function and also
241
+ `example_data.help(<NAME>)` functions.
242
+ """
243
+ return ['A', 'B', 'C']
244
+
245
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
246
+ @dataset
247
+ def dummy_load_data():
248
+ """A dummy dataset function that loads a string from a file.
249
+
250
+ Returns
251
+ -------
252
+ str_data : `str`
253
+ A string of data loaded from an example data file.
254
+
255
+ Notes
256
+ -----
257
+ This function is called ``dummy_data`` and has been decorated with a
258
+ ``@dataset`` decorator which makes it available with the
259
+ `example_data.get_data(<NAME>)` function and also
260
+ `example_data.help(<NAME>)` functions. The path to this dataset is built
261
+ from ``_ROOT_DATASETS_DIR``.
262
+ """
263
+ load_path = os.path.join(_ROOT_DATASETS_DIR, "string_data.txt")
264
+ with open(load_path) as data_file:
265
+ return data_file.read().strip()
266
+
267
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
268
+ @dataset
269
+ def list_dicom_paths():
270
+ """
271
+ Returns the paths to the available DICOM example datasets.
272
+
273
+ Returns
274
+ -------
275
+ paths: dict
276
+ The data names (keys) and paths (values) available in ECGProcess.
277
+ """
278
+ # paths dictionary
279
+ paths_dict = {
280
+ 'example_dicom_1': os.path.join(
281
+ _ROOT_DATASETS_DIR, 'example-DICOM1.dcm'),
282
+ 'example_dicom_2': os.path.join(
283
+ _ROOT_DATASETS_DIR, 'example-DICOM2.dcm'),
284
+ }
285
+ # return
286
+ return paths_dict
287
+
288
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
289
+ @dataset
290
+ def list_xml_paths():
291
+ """
292
+ Returns the paths to available XML and XSD schema paths.
293
+
294
+ Returns
295
+ -------
296
+ paths: dict
297
+ The data names (keys) and paths (values) available in ECGProcess.
298
+ """
299
+ FILENAME='example-XML1'
300
+ # paths dictionary
301
+ paths_dict = {
302
+ 'example_1': os.path.join(
303
+ _ROOT_DATASETS_DIR, FILENAME+'.xml'),
304
+ 'example_1_schema': os.path.join(
305
+ _ROOT_DATASETS_DIR, FILENAME+'.xsd'),
306
+ 'example_1_schema_error': os.path.join(
307
+ _ROOT_DATASETS_DIR, FILENAME+'_error.xsd'),
308
+ }
309
+ # return
310
+ return paths_dict
311
+
312
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
313
+ @dataset
314
+ def config_file(path=None, text:None | dict[str, list[str]]=None) -> str:
315
+ """
316
+ Returns a toy example of a data configuration file as a string or uses
317
+ user-supplied text if provided in dictionary format.
318
+
319
+ Parameters
320
+ ----------
321
+ path : `str`, default None
322
+ An optional path to write the text to disk. Uses utf-8 file encoding.
323
+ user_text : `dict` [`str`, `list` [`str`]], default None
324
+ Configuration content specified as a dictionary. Each key represents a
325
+ header (enclosed in square brackets in the output), and the
326
+ corresponding value is a list of attributes or entries. Tab characters
327
+ in list items are preserved, enabling target-source assignments in the
328
+ generated file.
329
+
330
+ Returns
331
+ -------
332
+ str
333
+ The formatted configuration file.
334
+
335
+ Examples
336
+ --------
337
+ >>> custom_text = {
338
+ ... "CustomSection1": ["CustomAttribute1", "CustomAttribute2"],
339
+ ... "MetaData": ["CustomData\tCustomValue"],
340
+ ... "AdditionalInfo": ["Info1", "Info2"],
341
+ ... }
342
+ >>> print(data_configuration(user_text=custom_text))
343
+ [CustomSection1]
344
+ CustomAttribute1
345
+ CustomAttribute2
346
+ [MetaData]
347
+ CustomData CustomValue
348
+ [AdditionalInfo]
349
+ Info1
350
+ Info2
351
+ """
352
+ # Default configuration
353
+ default_text = {
354
+ "WaveForms": [
355
+ "I\tLead_I_name",
356
+ "aVF\tLead_aVF_name",
357
+ ],
358
+ "MedianBeats": [
359
+ "II\tLead_II_name",
360
+ ],
361
+ "MetaData": [
362
+ "sampling frequency (original)\tSamplingFrequency",
363
+ "sampling number (waveforms)\tNumberOfWaveformSamples",
364
+ "Birthdate\tPatientBirthDate",
365
+ ],
366
+ "OtherData": [
367
+ "ChannelSampleSkew\tChannelSampleSkew",
368
+ ],
369
+ }
370
+ # Use default text if user_text is not provided
371
+ config = text or default_text
372
+ # Generate the formatted text
373
+ text_lines = []
374
+ for header, attributes in config.items():
375
+ text_lines.append(f"[{header}]")
376
+ text_lines.extend(attributes)
377
+ text = "\n".join(text_lines)
378
+ # If a file path is provided, write the text to the file
379
+ if path:
380
+ with open(path, "w", encoding="utf-8") as file:
381
+ file.write(text)
382
+ return text
383
+
384
+
385
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
386
+ @dataset
387
+ def parsed_config():
388
+ """
389
+ Returns a dict of parsed and mapped config files.
390
+ """
391
+ # #### XML config file
392
+ config_xml = {
393
+ "WaveForms": [
394
+ "I\tStripData.WaveformData_0.#text",
395
+ "II\tStripData.WaveformData_1.#text",
396
+ ],
397
+ "MetaData": [
398
+ "unique identifier\tUID.DICOMStudyUID",
399
+ "number of leads\tRestingECGMeasurements.MedianSamples.NumberOfLeads",
400
+ "resolution unit (waveforms)\tStripData.Resolution.@units",
401
+ "resolution (waveforms)\tStripData.Resolution.#text",
402
+ "resolution unit (medianbeats)\tRestingECGMeasurements.MedianSamples.Resolution.@units",
403
+ "resolution (medianbeats)\tRestingECGMeasurements.MedianSamples.Resolution.#text",
404
+ "sampling frequency (original)\tRestingECGMeasurements.MedianSamples.SampleRate.#text",
405
+ "sampling frequency unit\tRestingECGMeasurements.MedianSamples.SampleRate.@units",
406
+ "sampling number (waveforms)\tStripData.ChannelSampleCountTotal",
407
+ "sampling number (medianbeats)\tRestingECGMeasurements.MedianSamples.ChannelSampleCountTotal",
408
+ "age\tPatientInfo.Age.#text",
409
+ "gender\tPatientInfo.Gender",
410
+ "birthday day\tPatientInfo.BirthDateTime.Day",
411
+ "birthday month\tPatientInfo.BirthDateTime.Month",
412
+ "birthday year\tPatientInfo.BirthDateTime.Year",
413
+ "sysbp unit\tPatientVisit.SysBP.@units",
414
+ "diabpb unit\tPatientVisit.DiaBP.@units",
415
+ "sysbp\tPatientVisit.SysBP.@text",
416
+ "diabpb\tPatientVisit.DiaBP.@text",
417
+ "pacemaker\tPatientInfo.PaceMaker",
418
+ ]
419
+ }
420
+ with NamedTemporaryFile("w") as tmp_file:
421
+ _ = config_file(path=tmp_file.name, text=config_xml)
422
+ parser_xml = config_utils.ConfigParser(tmp_file.name)()
423
+ # adding the mapper
424
+ parser_xml.map(mapper=config_utils.DataMap())
425
+
426
+ # #### XML config file 2
427
+ config_xml2 = {
428
+ "WaveForms": [
429
+ "I\tStripData.WaveformData_0.#text",
430
+ "II\tStripData.WaveformData_1.#text",
431
+ ],
432
+ "MetaData": [
433
+ "number of leads\tRestingECGMeasurements.MedianSamples.NumberOfLeads",
434
+ "resolution unit (waveforms)\tStripData.Resolution.@units",
435
+ "resolution (waveforms)\tStripData.Resolution.#text",
436
+ "resolution unit (medianbeats)\tRestingECGMeasurements.MedianSamples.Resolution.@units",
437
+ "resolution (medianbeats)\tRestingECGMeasurements.MedianSamples.Resolution.#text",
438
+ "sampling frequency (original)\tRestingECGMeasurements.MedianSamples.SampleRate.#text",
439
+ "sampling frequency unit\tRestingECGMeasurements.MedianSamples.SampleRate.@units",
440
+ "sampling number (waveforms)\tStripData.ChannelSampleCountTotal",
441
+ "sampling number (medianbeats)\tRestingECGMeasurements.MedianSamples.ChannelSampleCountTotal",
442
+ "age\tPatientInfo.Age.#text",
443
+ "gender\tPatientInfo.Gender",
444
+ "birthday day\tPatientInfo.BirthDateTime.Day",
445
+ "birthday month\tPatientInfo.BirthDateTime.Month",
446
+ "birthday year\tPatientInfo.BirthDateTime.Year",
447
+ "sysbp unit\tPatientVisit.SysBP.@units",
448
+ "diabpb unit\tPatientVisit.DiaBP.@units",
449
+ "sysbp\tPatientVisit.SysBP.@text",
450
+ "diabpb\tPatientVisit.DiaBP.@text",
451
+ "pacemaker\tPatientInfo.PaceMaker",
452
+ ]
453
+ }
454
+ with NamedTemporaryFile("w") as tmp_file:
455
+ _ = config_file(path=tmp_file.name, text=config_xml2)
456
+ parser_xml2 = config_utils.ConfigParser(tmp_file.name)()
457
+ # adding the mapper
458
+ parser_xml2.map(mapper=config_utils.DataMap())
459
+
460
+ # #### DICOM config file
461
+ leads = [attr for attr in dir(CLeads) if not attr.startswith("__")]
462
+ config_dicom = {
463
+ "WaveForms": [
464
+ f"{getattr(CLeads, lead)}\tWaveformData.ECG_Leads_{idx}"
465
+ for idx, lead in enumerate(leads)],
466
+ "MedianBeats": [
467
+ f"{getattr(CLeads, lead)}\tWaveformData.Median_Beats_{idx}"
468
+ for idx, lead in enumerate(leads)],
469
+ "MetaData": [
470
+ "unique identifier\tSOP Instance UID",
471
+ "number of leads\tWaveform Sequence_0.Number of Waveform Channels",
472
+ "resolution unit (waveforms)\tWaveform Sequence_0.Channel Definition Sequence_0.Channel Sensitivity Units Sequence_0.Code Value",
473
+ "resolution (waveforms)\tWaveform Sequence_0.Channel Definition Sequence_0.Channel Sensitivity",
474
+ "resolution unit (medianbeats)\tWaveform Sequence_1.Channel Definition Sequence_0.Channel Sensitivity Units Sequence_0.Code Value",
475
+ "resolution (medianbeats)\tWaveform Sequence_1.Channel Definition Sequence_0.Channel Sensitivity",
476
+ "sampling frequency (original)\tWaveform Sequence_0.Sampling Frequency",
477
+ "sampling number (waveforms)\tWaveform Sequence_0.Number of Waveform Samples",
478
+ "sampling number (medianbeats)\tWaveform Sequence_1.Number of Waveform Samples",
479
+ "Softwave version\tSoftware Versions",
480
+ "Manufacturer\tManufacturer",
481
+ "Model name\tManufacturer's Model Name",
482
+ ] +\
483
+ [
484
+ f"wave_channel_sens_{idx}\tWaveform Sequence_0.Channel Definition Sequence_{idx}.Channel Sensitivity" for idx, _ in enumerate(leads)] +\
485
+ [
486
+ f"wave_channel_correctionfactor_{idx}\tWaveform Sequence_0.Channel Definition Sequence_{idx}.Channel Sensitivity Correction Factor" for idx, _ in enumerate(leads)] +\
487
+ [
488
+ f"wave_channel_baseline_{idx}\tWaveform Sequence_0.Channel Definition Sequence_{idx}.Channel Baseline" for idx, _ in enumerate(leads)]
489
+ }
490
+ with NamedTemporaryFile("w") as tmp_file:
491
+ _ = config_file(path=tmp_file.name, text=config_dicom)
492
+ parser_dicom = config_utils.ConfigParser(tmp_file.name)()
493
+ # adding the mapper
494
+ parser_dicom.map(mapper=config_utils.DataMap())
495
+
496
+ # return
497
+ return {'parsed_dicom1': parser_dicom,
498
+ 'parsed_xml1' : parser_xml,
499
+ 'parsed_xml2' : parser_xml2,
500
+ }
501
+