dcm_dict 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +156 -0
  3. data/COPYING +674 -0
  4. data/LICENSE +22 -0
  5. data/README.md +327 -0
  6. data/Rakefile +36 -0
  7. data/bin/dcm_dict_converter.rb +194 -0
  8. data/lib/dcm_dict.rb +46 -0
  9. data/lib/dcm_dict/dictionary/base_dictionary.rb +47 -0
  10. data/lib/dcm_dict/dictionary/base_record.rb +62 -0
  11. data/lib/dcm_dict/dictionary/data_element_dictionary.rb +117 -0
  12. data/lib/dcm_dict/dictionary/data_element_record.rb +93 -0
  13. data/lib/dcm_dict/dictionary/uid_dictionary.rb +82 -0
  14. data/lib/dcm_dict/dictionary/uid_record.rb +48 -0
  15. data/lib/dcm_dict/encoder/data_to_code.rb +79 -0
  16. data/lib/dcm_dict/error/dictionary_error.rb +30 -0
  17. data/lib/dcm_dict/ext/object_extension.rb +38 -0
  18. data/lib/dcm_dict/refine/array_refine.rb +34 -0
  19. data/lib/dcm_dict/refine/data_element_refine.rb +37 -0
  20. data/lib/dcm_dict/refine/internal/array_refine_internal.rb +97 -0
  21. data/lib/dcm_dict/refine/internal/hash_refine_internal.rb +71 -0
  22. data/lib/dcm_dict/refine/internal/string_refine_internal.rb +135 -0
  23. data/lib/dcm_dict/refine/string_refine.rb +35 -0
  24. data/lib/dcm_dict/refine/symbol_refine.rb +34 -0
  25. data/lib/dcm_dict/refine/uid_refine.rb +36 -0
  26. data/lib/dcm_dict/rubies/rb_ext.rb +32 -0
  27. data/lib/dcm_dict/source_data/data_elements_data.rb +4945 -0
  28. data/lib/dcm_dict/source_data/detached_data.rb +67 -0
  29. data/lib/dcm_dict/source_data/uid_values_data.rb +467 -0
  30. data/lib/dcm_dict/version.rb +27 -0
  31. data/lib/dcm_dict/xml/constant.rb +38 -0
  32. data/lib/dcm_dict/xml/field_data.rb +47 -0
  33. data/lib/dcm_dict/xml/nokogiri_tool.rb +108 -0
  34. data/lib/dcm_dict/xml/rexml_tool.rb +105 -0
  35. data/lib/dcm_dict/xml/tag_field_data.rb +96 -0
  36. data/lib/dcm_dict/xml/uid_field_data.rb +60 -0
  37. data/lib/dcm_dict/xml/xml_tool.rb +47 -0
  38. data/spec/data_element_sample_spec_helper.rb +203 -0
  39. data/spec/data_element_shared_example_spec_helper.rb +57 -0
  40. data/spec/dcm_dict/dictionary/data_element_dictionary_spec.rb +76 -0
  41. data/spec/dcm_dict/dictionary/data_element_record_spec.rb +138 -0
  42. data/spec/dcm_dict/dictionary/uid_dictionary_spec.rb +82 -0
  43. data/spec/dcm_dict/dictionary/uid_record_spec.rb +53 -0
  44. data/spec/dcm_dict/encoder/data_to_code_spec.rb +109 -0
  45. data/spec/dcm_dict/ext/object_extension_spec.rb +53 -0
  46. data/spec/dcm_dict/refine/array_refine_spec.rb +60 -0
  47. data/spec/dcm_dict/refine/internal/array_refine_internal_spec.rb +98 -0
  48. data/spec/dcm_dict/refine/internal/hash_refine_internal_spec.rb +64 -0
  49. data/spec/dcm_dict/refine/internal/string_refine_internal_spec.rb +228 -0
  50. data/spec/dcm_dict/refine/string_refine_spec.rb +87 -0
  51. data/spec/dcm_dict/refine/symbol_refine_spec.rb +41 -0
  52. data/spec/dcm_dict/rubies/rb_ext_spec.rb +46 -0
  53. data/spec/dcm_dict/source_data/data_elements_data_spec.rb +40 -0
  54. data/spec/dcm_dict/source_data/detached_data_spec.rb +55 -0
  55. data/spec/dcm_dict/source_data/uid_values_data_spec.rb +37 -0
  56. data/spec/dcm_dict/version_spec.rb +30 -0
  57. data/spec/dcm_dict/xml/tag_field_data_spec.rb +62 -0
  58. data/spec/dcm_dict/xml/uid_field_data_spec.rb +60 -0
  59. data/spec/dictionary_shared_example_spec_helper.rb +118 -0
  60. data/spec/refine_shared_example_spec_helper.rb +54 -0
  61. data/spec/spec_helper.rb +42 -0
  62. data/spec/xml_sample_spec_helper.rb +567 -0
  63. metadata +216 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ DcmDict is a Ruby gem (dcm_dict) to handle
2
+ in a simple way the Data defined within the DICOM Standard.
3
+
4
+ Copyright (C) 2014-2020 Enrico Rivarola
5
+
6
+ DcmDict is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ DcmDict is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with DcmDict (file 'COPYING'). If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ This software has neither been tested nor approved for clinical use
20
+ or for incorporation in a medical device.
21
+ It is the redistributor's or user's responsibility to comply with any
22
+ applicable local, state, national or international regulations.
@@ -0,0 +1,327 @@
1
+ # What's *DcmDict*
2
+ **DcmDict** is a Ruby gem [(*dcm\_dict*)][12] to handle in a simple way the *Data Dictionary* defined within the DICOM<sup>®</sup> Standard <sup id='fn-dcm-trademark'>[1]</sup> such as DICOM Data Elements or DICOM Unique Identifiers.
3
+
4
+ # Why *DcmDict*
5
+ With the new releases from year 2014 DICOM documents are available in different format including one particularly interesting, the *DocBook* XML version.
6
+
7
+ As confirmed in the DICOM<sup>®</sup> Standard [web site][10] where each part is published in [multiple formats][11] and XML format is defined by:
8
+ >"... XML – good for machine readability, e.g. self-updating validators ..."
9
+
10
+ This is great news for anyone involved in the study of the standard !
11
+
12
+ Starting from this thing was born the idea of trying to automate the extraction of data from XML documents to make available the information in a simple way that simplifies the study of the DICOM standard, in the hope this idea will be useful and inspiration.
13
+
14
+ # *DcmDict* features
15
+ The library involve *String*, *Array* and *Symbol* class as *refinements* to access to DICOM information.
16
+
17
+ In this way is possible to *play* with the 'Patient's Birth Date' tag defined as (0010,0030) by:
18
+
19
+ ```ruby
20
+ > "(0010,0030)".tag_name
21
+ => "Patient's Birth Date"
22
+ > 'PatientBirthDate'.tag_vr
23
+ => [:DA]
24
+ > "Patient's Birth Date".tag_vm
25
+ => ["1"]
26
+ > :patient_birth_date.tag
27
+ => [16, 48]
28
+ > [16,48].tag_key
29
+ => "PatientBirthDate"
30
+ > [16, 48].tag_group
31
+ => 16
32
+ > '00100030'.tag_element
33
+ => 48
34
+ > :patient_birth_date.tag_group
35
+ => 16
36
+ > "Patient's Birth Date".tag_element
37
+ => 48
38
+ ```
39
+
40
+ as well for UIDs
41
+
42
+ ```ruby
43
+ > '1.2.840.10008.1.2'.uid_name
44
+ => "Implicit VR Little Endian: Default Transfer Syntax for DICOM"
45
+ > '1.2.840.10008.1.2'.uid_type
46
+ => :transfer_syntax
47
+ > "Implicit VR Little Endian: Default Transfer Syntax for DICOM".uid_value
48
+ => "1.2.840.10008.1.2"
49
+ ```
50
+
51
+ let see all features in detail:
52
+
53
+ ## Library usage
54
+ The library involve **Ruby Refinements** so use it is simple, it is necessary to include the specific *using directive*:
55
+
56
+ ```ruby
57
+ using DcmDict::Refine::StringRefine
58
+ ```
59
+ for the String object,
60
+ ```ruby
61
+ using DcmDict::Refine::ArrayRefine
62
+ ```
63
+ for the Array object and
64
+
65
+ ```ruby
66
+ using DcmDict::Refine::SymbolRefine
67
+ ```
68
+ for the Symbol object.
69
+
70
+ That's it.
71
+
72
+ **Note**: It is possible to use also the the *monkey patching* way, this is a *deprecated* utilization but possible, and, may be, useful technique in certain contexts or for some particular test. For the *monkey patching* is possible to include some specific *common modules* in the class you want to use as "keyword": there are two base modules *DcmDict::Refine::DataElementRefine* and *DcmDict::Refine::UidRefine*.
73
+
74
+ For example in the String class will have the code:
75
+
76
+ ```ruby
77
+ class String
78
+ include DcmDict::Refine::DataElementRefine
79
+ include DcmDict::Refine::UidRefine
80
+ end
81
+ ```
82
+
83
+ *The main way remains **Ruby Refinements***.
84
+
85
+ **Rubies compatibility**: at this moment the other considered rubies is only [Rubinius][4] (>= v2.2.10). In order to try to ensure a minimum compatibility there is a file under *lib/dcm_dict/rubies/* called *rb_ext.rb* able to *mask*/*simulates* the refinements by [refine gem][5] and add the required *bit_length* method to *Fixnum* class by [backports gem][6].
86
+ This sort of extension is not loaded by default but only into *spec files* for the *'rbx' Ruby Engine*. See *spec_helper.rb* and *rb_ext.rb* for details.
87
+
88
+ ## Data Element data in detail
89
+ Any Data Element feature can be accessed from a *String*, *Array* or *Symbol* objects.
90
+
91
+ For these objects is possible to access to Tag (group/element), Name, Keyword, Value Representation (VR) and Value Multiplicity (VM) for any single Data Element.
92
+
93
+ The main methods supported are:
94
+
95
+ |Method | Note| Type||
96
+ |:------|:------------:|:---:|:---:|
97
+ |**tag** | tag as Array| Array of two Fixnum|(alias of *tag_ary*)|
98
+ |**tag_name** | name of tag| String|
99
+ |**tag_keyword** | keyword| String|
100
+ |**tag_key** | keyword| String|
101
+ |**tag_vr** | Value Representation| Array of Symbol|
102
+ |**tag_vm** | Value Multiplicity| Array of Symbol|
103
+ |**tag_ps** | tag as string (as standard doc)| String|
104
+ |**tag_ary** | tag as Array|Array of two Fixnum|
105
+ |**tag_sym** | tag as Symbol|Symbol|
106
+ |**tag_ndm** | tag as in Native DICOM Model|String|
107
+ |**tag_str** | tag as string (similar to tag_ps)|String|
108
+ |**tag_note** | tag note|String|
109
+ |**tag_multiple?** | is a multiple tag ? |boolean|(useful for 'multi tag' attribute)|
110
+
111
+ each data element is indexed by these fields:
112
+
113
+ |Field|Type|
114
+ |:----|:-----:|
115
+ |**tag_key** | String|
116
+ |**tag_ps** | String|
117
+ |**tag_ary** | Array|
118
+ |**tag_sym** | Symbol|
119
+ |**tag_ndm** | String|
120
+ |**tag_str** | String|
121
+ |**tag_name** | String|
122
+
123
+ By these fields is possible to access to data element informations.
124
+ Consider the case of the tag (0010,1005) (*Patient's Birth Name*), the primary fields are:
125
+ **'(0010,1005)'**, **"Patient's Birth Name"**, **'PatientBirthName'**, **:patient_birth_name**, **'00101005'** and **[0x0010,0x1005]**
126
+
127
+ - As String key you may use the standard tag format **'(0010,1005)'**, the tag name **'Patient's Birth Name'**, the tag keyword **'PatientBirthName'** or the Native DICOM Format tag **'00101005'**
128
+ - As Array key you may use the numeric array **[0x0010,0x1005]**
129
+ - As Symbol key you may use **:patient_birth_name**
130
+
131
+ ### example:
132
+ Consider the previous case of tag (0010,1005), the code:
133
+
134
+ ```ruby
135
+ puts "Patient's Birth Name".tag_ps.inspect
136
+ puts [0x0010,0x1005].tag_name.inspect
137
+ puts '(0010,1005)'.tag_key.inspect
138
+ puts :patient_birth_name.tag_vr.inspect
139
+ puts 'PatientBirthName'.tag_vm.inspect
140
+ puts '00101005'.tag.inspect
141
+ puts '(0010,1005)'.tag_ary.inspect
142
+ puts '00101005'.tag_sym.inspect
143
+ puts 'PatientBirthName'.tag_ndm.inspect
144
+ puts "Patient's Birth Name".tag_str.inspect
145
+ puts [0x0010,0x1005].tag_note.inspect
146
+ puts [0x0010,0x1005].tag_group.inspect
147
+ puts :patient_birth_name.tag_element.inspect
148
+ ```
149
+
150
+ will produce
151
+
152
+
153
+ ```ruby
154
+ "(0010,1005)"
155
+ "Patient's Birth Name"
156
+ "PatientBirthName"
157
+ [:PN]
158
+ ["1"]
159
+ [16, 4101]
160
+ [16, 4101]
161
+ :patient_birth_name
162
+ "00101005"
163
+ "(0010,1005)"
164
+ ""
165
+ 16
166
+ 4101
167
+ ```
168
+
169
+ ### Multiple Tag
170
+ The library also manage 'multiple tags' such as *(0020,31XX)* (*Source Image IDs*).
171
+ As an example for this data element the default tag in array form is [0x0020,0x3122] and all fields are expressed as:
172
+
173
+ |Method/field | Value|
174
+ |:------|:------------:|
175
+ |**tag** | [0x0020,0x3122]|
176
+ |**tag_name** | "Source Image IDs"|
177
+ |**tag_keyword** | 'SourceImageIDs'|
178
+ |**tag_key** | 'SourceImageIDs'|
179
+ |**tag_vr** | [:CS]|
180
+ |**tag_vm** | ["1-n"]|
181
+ |**tag_ps** | '(0020,31XX)'|
182
+ |**tag_ary** | [0x0020,0x3122]|
183
+ |**tag_sym** | :source_image_ids|
184
+ |**tag_ndm** | '00203122'
185
+ |**tag_str** | '(0020,3122)'|
186
+ |**tag_note** | 'RET'|
187
+ |**tag_multiple?** | true|
188
+
189
+ [0x0020,0x3122] is the default value for group/element pair (*[32, 12578]*), but any valid pair of numbers for this tag will be refers that information:
190
+
191
+ ```ruby
192
+ > '(0020,31XX)'.tag_name
193
+ => "Source Image IDs"
194
+ > '(0020,31XX)'.tag_ndm
195
+ => "00203122"
196
+ > "SourceImageIDs".tag_ary
197
+ => [32, 12578]
198
+ > '(0020,3178)'.tag_name
199
+ => "Source Image IDs"
200
+ [0x0020,0x3146].tag_sym
201
+ => :source_image_ids
202
+ > '00203120'.tag_key
203
+ => "SourceImageIDs"
204
+ > [0x0020,0x3138].tag_vr
205
+ => [:CS]
206
+ > '(0020,3144)'.tag_note
207
+ => "RET"
208
+ ```
209
+
210
+ and so on.
211
+
212
+ ## UID data in detail
213
+ Any UID features can be accessed from a *String* object.
214
+
215
+ ### UID Values
216
+ For these objects is possible to access to value, name and type values for any single uid.
217
+ Main methods supported are:
218
+
219
+ |Method | Note| Type||
220
+ |:------|:------------:|:---:|:---:|
221
+ |**uid** | value of uid| String|(alias of *uid_value*)|
222
+ |**uid_value** | value of uid| String|
223
+ |**uid_name** | name of uid| String|
224
+ |**uid_type** | type of uid| Symbol|
225
+
226
+ each uid is indexed by:
227
+
228
+ |Field|Type|
229
+ |:----|:-----|
230
+ |**uid_value** | String|
231
+ |**uid_name** | String|
232
+
233
+ From these fields is possible to access to all uid informations.
234
+ Consider the case of the uid *1.2.840.10008.1.1* (*Verification SOP Class*), the primary fields are the strings **'1.2.840.10008.1.1'** and **"Verification SOP Class"**.
235
+ - As String key you may use the standard value **'1.2.840.10008.1.1'** and the uid name **"Verification SOP Class"**
236
+
237
+ For this uid all fields are expressed as:
238
+
239
+ |Method/field | Value|
240
+ |:------|:------------:|
241
+ |**uid** | '1.2.840.10008.1.1'|
242
+ |**uid_value** | '1.2.840.10008.1.1'|
243
+ |**uid_name** | "Verification SOP Class"|
244
+ |**uid_type** | :sop_class|
245
+
246
+ ### example:
247
+
248
+ ```ruby
249
+ > "Verification SOP Class".uid_value
250
+ => "1.2.840.10008.1.1"
251
+ > "1.2.840.10008.1.1".uid_type
252
+ => :sop_class
253
+ > "1.2.840.10008.1.1".uid_name
254
+ => "Verification SOP Class"
255
+ > "Verification SOP Class".uid
256
+ => "1.2.840.10008.1.1"
257
+ ```
258
+
259
+ ## How data is extracted
260
+ The library also contains a script (*dcm_dict_converter.rb* in the *bin* folder) able to download the xml documents and extracts the source data in a *Ruby compatible format*.
261
+ The script produces the conversion in the *stdout* so for example is possible to extract the Tag Values by:
262
+
263
+ ```ruby
264
+ dcm_dict_converter.rb tag > /tmp/tag-dict.rb
265
+ ```
266
+
267
+ Note: the script use the [Nokogiri][3] as XML parser if installed as gem, otherwise the standard *REXML*.
268
+
269
+ Check the file for other details.
270
+
271
+ ## Note
272
+ Current library version is aligned to *DICOM Base Standard* **2020c**
273
+
274
+ ## Install
275
+
276
+ $ gem install dcm_dict
277
+
278
+ *Note for Windows users*: may be that it is installed a previous version of Ruby 2.1, if [RubyInstaller][7] does not provide the official release for the supported version it's still possible to make it manually by clone/download the ['git' version of RubyInstaller][8] and execute the rake command ```rake ruby21``` or equivalent (see RubyInstaller doc for details).
279
+
280
+ ## What's next
281
+ The main idea is that *dictionary* should include only fixed data defined in the DICOM standard to encode and then make it available in easy way.
282
+ There are many possible *candidates* for inclusion in the *dictionary*, here are some *"ideas"*:
283
+
284
+ - Directory Record type data
285
+ - Well-known Frames of Reference UID Values
286
+ - Context Group UID Values
287
+ - Standard Color Palettes UID Values
288
+ - IOD definition data
289
+ - ...
290
+
291
+ ## Contributing
292
+ TBD
293
+
294
+ ## License
295
+ Copyright (C) 2014-2020 Enrico Rivarola.
296
+ See the `LICENSE` and `COPYING` files for license details.
297
+
298
+ ## Ruby Gem
299
+ Ruby gem **dcm\_dict** on [RubyGems][9] at [rubygems.org/gems/dcm_dict](https://rubygems.org/gems/dcm_dict)
300
+
301
+ ## Source Code
302
+ Main source code repository on github at [henrythebuilder/dcm_dict](https://github.com/henrythebuilder/dcm_dict)
303
+
304
+ <div class="footnotes">
305
+ <hr />
306
+ <ol>
307
+ <li id="fn1-dcm-trademark">
308
+ <p><a href="http://www.dicomstandard.org/" title="DICOM Standard">DICOM<sup>®</sup></a> is the registered trademark of the National Electrical Manufacturers Association for its standards publications relating to digital communications of medical information.
309
+ <a href="#fn-dcm-trademark" class='footnoteBackLink' title="Jump back to footnote 1 in the text.">&#x21A9;&#xFE0E;</a></p>
310
+ </li>
311
+ </ol>
312
+ </div>
313
+
314
+ [1]: #fn1-dcm-trademark
315
+
316
+ [dcm1]: http://medical.nema.org/dicom/ "DICOM Homepage"
317
+ [2]: http://www.dclunie.com/dicom-status/status.html "DICOM Standard Status"
318
+ [3]: http://nokogiri.org/ "Nokogiri"
319
+ [4]: http://rubini.us/ "Rubinius"
320
+ [5]: https://rubygems.org/gems/refine "Refine gem at RubyGems.org"
321
+ [6]: https://rubygems.org/gems/backports "Backports gem at RubyGems.org"
322
+ [7]: http://rubyinstaller.org/ "The easy way to install Ruby on Windows"
323
+ [8]: https://github.com/oneclick/rubyinstaller "RubyInstaller for Windows"
324
+ [9]: https://rubygems.org/
325
+ [10]: http://www.dicomstandard.org/
326
+ [11]: http://www.dicomstandard.org/current/
327
+ [12]: https://rubygems.org/gems/dcm_dict
@@ -0,0 +1,36 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "dcm_dict/version"
3
+ require 'rake'
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc "Check all spec"
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.pattern = 'spec/**/*_spec.rb'
9
+ t.ruby_opts = "-w"
10
+ t.rspec_opts = '--color --format documentation'
11
+ end
12
+
13
+ desc "Check all spec with code coverage"
14
+ task :coverage do
15
+ ENV['COVERAGE'] = "true"
16
+ Rake::Task["spec"].execute
17
+ end
18
+
19
+ desc(task(:coverage).comment)
20
+ task :default => :coverage
21
+
22
+ desc "Build dcm_dict v#{DcmDict::VERSION} gem"
23
+ task :build do
24
+ system "gem build dcm_dict.gemspec"
25
+ FileUtils.mkdir_p "pkg"
26
+ FileUtils.mv "dcm_dict-#{DcmDict::VERSION}.gem", "pkg"
27
+ end
28
+
29
+ desc "Open IRB with DcmDict support"
30
+ task :console do
31
+ require 'irb'
32
+ require 'irb/completion'
33
+ require 'dcm_dict'
34
+ ARGV.clear
35
+ IRB.start
36
+ end
@@ -0,0 +1,194 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- ruby -*-
3
+ #
4
+ # Copyright (C) 2014-2020 Enrico Rivarola
5
+ #
6
+ # This file is part of DcmDict gem (dcm_dict).
7
+ #
8
+ # DcmDict is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # DcmDict is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with DcmDict. If not, see <http://www.gnu.org/licenses/>.
20
+ #
21
+ # This software has neither been tested nor approved for clinical use
22
+ # or for incorporation in a medical device.
23
+ # It is the redistributor's or user's responsibility to comply with any
24
+ # applicable local, state, national or international regulations.
25
+ #
26
+ require 'open-uri'
27
+ require 'tempfile'
28
+ require 'dcm_dict'
29
+ require 'dcm_dict/xml/xml_tool'
30
+
31
+ LICENSE_TEXT=<<END_LICENSE
32
+ Copyright (C) 2014-2020 Enrico Rivarola
33
+
34
+ This file is part of DcmDict gem (dcm_dict).
35
+
36
+ DcmDict is free software: you can redistribute it and/or modify
37
+ it under the terms of the GNU General Public License as published by
38
+ the Free Software Foundation, either version 3 of the License, or
39
+ (at your option) any later version.
40
+
41
+ DcmDict is distributed in the hope that it will be useful,
42
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
43
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44
+ GNU General Public License for more details.
45
+
46
+ You should have received a copy of the GNU General Public License
47
+ along with DcmDict. If not, see <http://www.gnu.org/licenses/>.
48
+
49
+ This software has neither been tested nor approved for clinical use
50
+ or for incorporation in a medical device.
51
+ It is the redistributor's or user's responsibility to comply with any
52
+ applicable local, state, national or international regulations
53
+
54
+ END_LICENSE
55
+
56
+ class DcmDictConverter
57
+ Part6XmlUrl="http://dicom.nema.org/medical/dicom/current/source/docbook/part06/part06.xml"
58
+ Part7XmlUrl="http://dicom.nema.org/medical/dicom/current/source/docbook/part07/part07.xml"
59
+ DataElementSource={
60
+ Part7XmlUrl => ["table_E.1-1", "table_E.2-1"],
61
+ Part6XmlUrl => ["table_7-1", "table_8-1", "table_6-1"]
62
+ }
63
+
64
+ UidSource={
65
+ Part6XmlUrl => ["table_A-1"]
66
+ }
67
+
68
+ DataElementFix = {
69
+ "table_E.2-1" => {:tag_note => 'RET'}
70
+ }
71
+
72
+ def initialize
73
+
74
+ end
75
+
76
+ def print_out_tag
77
+ trace("Print out data to stdout\n")
78
+ print_out_data_elements()
79
+ trace("Print out done.\n")
80
+ end
81
+
82
+ def print_out_uid
83
+ trace("Print out data to stdout\n")
84
+ print_out_uid_data()
85
+ trace("Print out done.\n")
86
+ end
87
+
88
+ private
89
+ def pull_standard_draft(url, output)
90
+ buffer_size = 256 * 1_024
91
+ trace("Downloading #{url}\n")
92
+ URI.open(url, "r",
93
+ :content_length_proc => lambda {|content_length| trace("Content Length: #{content_length} bytes\n.") },
94
+ :progress_proc => lambda { |size| trace(".") }) do |src|
95
+ while (buffer = src.read(buffer_size))
96
+ output.write(buffer)
97
+ end
98
+ end
99
+ trace("Done.\n")
100
+ output.flush
101
+ output.rewind
102
+ end
103
+
104
+ def extract_node_set(xml_file, table_to_map)
105
+ xml_doc = DcmDict::XML::XmlTool.create_xml_doc(File.read(xml_file))
106
+ table_to_map.each do |table|
107
+ trace("Extracting data from '#{table}':")
108
+ xpath="//xmlns:table[@xml:id=\"#{table}\"]//xmlns:tbody/xmlns:tr"
109
+ DcmDict::XML::XmlTool.each_tr_set(xml_doc, xpath) do |tdset|
110
+ yield(table, tdset)
111
+ end
112
+ trace("Done.\n")
113
+ end
114
+ end
115
+
116
+ def extract_data_element(xml_file, table_to_map)
117
+ extract_node_set(xml_file, table_to_map) do |table, td|
118
+ data = DcmDict::XML::XmlTool.extract_data_element_field_from_tr_set(td)
119
+ check_data_element_data(data, table)
120
+ yield(data) if block_given?
121
+ end
122
+ end
123
+
124
+ def check_data_element_data(data, table)
125
+ if (DataElementFix.has_key?(table))
126
+ DataElementFix[table].each{|key, val| data[key]=val if data[key].empty?}
127
+ end
128
+ end
129
+
130
+ def print_out_data_elements()
131
+ print_out(DcmDict::Encoder::DataToCode.data_element_header)
132
+ DataElementSource.each do |url, table_to_map|
133
+ Tempfile.create('dcmps') do |xml_file|
134
+ pull_standard_draft(url, xml_file)
135
+ extract_data_element(xml_file, table_to_map) do |data|
136
+ print_out(DcmDict::Encoder::DataToCode.data_element_data_to_code(data, 6))
137
+ print_out("\r\n")
138
+ trace('.')
139
+ end
140
+ end
141
+ end
142
+ print_out(DcmDict::Encoder::DataToCode.data_element_footer)
143
+ end
144
+
145
+ def extract_uid(xml_file, table_to_map)
146
+ extract_node_set(xml_file, table_to_map) do |table, td|
147
+ data = DcmDict::XML::XmlTool.extract_uid_field_from_tr_set(td)
148
+ yield(data) if block_given?
149
+ end
150
+ end
151
+
152
+ def print_out_uid_data()
153
+ print_out(DcmDict::Encoder::DataToCode.uid_header)
154
+ UidSource.each do |url, table_to_map|
155
+ Tempfile.create('dcmps') do |xml_file|
156
+ pull_standard_draft(url, xml_file)
157
+ extract_uid(xml_file, table_to_map) do |data|
158
+ print_out(DcmDict::Encoder::DataToCode.uid_data_to_code(data, 6))
159
+ print_out("\r\n")
160
+ trace('.')
161
+ end
162
+ end
163
+ end
164
+ print_out(DcmDict::Encoder::DataToCode.uid_footer)
165
+ end
166
+
167
+ def print_out(string)
168
+ $stdout.print(string)
169
+ end
170
+
171
+ def trace(msg)
172
+ $stderr.print(msg)
173
+ end
174
+
175
+ end
176
+
177
+ STDERR << LICENSE_TEXT
178
+ STDERR << "\nAny key to continue or Ctrl-C to break.\n"
179
+ STDIN.getc
180
+
181
+ if (DcmDict::XML.nokogiri_enable?)
182
+ STDERR << "Parsing XML data with Nokogiri.\n\n"
183
+ else
184
+ STDERR << "Parsing XML data with REXML.\n\n"
185
+ end
186
+
187
+ case ARGV[0]
188
+ when "tag"
189
+ DcmDictConverter.new.print_out_tag
190
+ when "uid"
191
+ DcmDictConverter.new.print_out_uid
192
+ else
193
+ STDERR << "\nwrong option: use 'tag' or 'uid' (ie dcm_dict_converter.rb tag > uid_values.rb)\n"
194
+ end