dcm_dict 0.1.0

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 (62) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +674 -0
  3. data/LICENSE +22 -0
  4. data/README.md +296 -0
  5. data/Rakefile +36 -0
  6. data/bin/dcm_dict_converter.rb +194 -0
  7. data/lib/dcm_dict.rb +46 -0
  8. data/lib/dcm_dict/dictionary/base_dictionary.rb +47 -0
  9. data/lib/dcm_dict/dictionary/base_record.rb +62 -0
  10. data/lib/dcm_dict/dictionary/data_element_dictionary.rb +117 -0
  11. data/lib/dcm_dict/dictionary/data_element_record.rb +93 -0
  12. data/lib/dcm_dict/dictionary/uid_dictionary.rb +82 -0
  13. data/lib/dcm_dict/dictionary/uid_record.rb +48 -0
  14. data/lib/dcm_dict/encoder/data_to_code.rb +79 -0
  15. data/lib/dcm_dict/error/dictionary_error.rb +30 -0
  16. data/lib/dcm_dict/ext/object_extension.rb +38 -0
  17. data/lib/dcm_dict/refine/array_refine.rb +34 -0
  18. data/lib/dcm_dict/refine/data_element_refine.rb +37 -0
  19. data/lib/dcm_dict/refine/internal/array_refine_internal.rb +97 -0
  20. data/lib/dcm_dict/refine/internal/hash_refine_internal.rb +71 -0
  21. data/lib/dcm_dict/refine/internal/string_refine_internal.rb +119 -0
  22. data/lib/dcm_dict/refine/string_refine.rb +35 -0
  23. data/lib/dcm_dict/refine/symbol_refine.rb +34 -0
  24. data/lib/dcm_dict/refine/uid_refine.rb +36 -0
  25. data/lib/dcm_dict/rubies/rb_ext.rb +32 -0
  26. data/lib/dcm_dict/source_data/data_elements_data.rb +3937 -0
  27. data/lib/dcm_dict/source_data/detached_data.rb +67 -0
  28. data/lib/dcm_dict/source_data/uid_values_data.rb +382 -0
  29. data/lib/dcm_dict/version.rb +27 -0
  30. data/lib/dcm_dict/xml/constant.rb +38 -0
  31. data/lib/dcm_dict/xml/field_data.rb +47 -0
  32. data/lib/dcm_dict/xml/nokogiri_tool.rb +108 -0
  33. data/lib/dcm_dict/xml/rexml_tool.rb +105 -0
  34. data/lib/dcm_dict/xml/tag_field_data.rb +96 -0
  35. data/lib/dcm_dict/xml/uid_field_data.rb +49 -0
  36. data/lib/dcm_dict/xml/xml_tool.rb +47 -0
  37. data/spec/data_element_sample_spec_helper.rb +110 -0
  38. data/spec/data_element_shared_example_spec_helper.rb +57 -0
  39. data/spec/dcm_dict/dictionary/data_element_dictionary_spec.rb +75 -0
  40. data/spec/dcm_dict/dictionary/data_element_record_spec.rb +117 -0
  41. data/spec/dcm_dict/dictionary/uid_dictionary_spec.rb +60 -0
  42. data/spec/dcm_dict/dictionary/uid_record_spec.rb +53 -0
  43. data/spec/dcm_dict/encoder/data_to_code_spec.rb +109 -0
  44. data/spec/dcm_dict/ext/object_extension_spec.rb +53 -0
  45. data/spec/dcm_dict/refine/array_refine_spec.rb +61 -0
  46. data/spec/dcm_dict/refine/internal/array_refine_internal_spec.rb +98 -0
  47. data/spec/dcm_dict/refine/internal/hash_refine_internal_spec.rb +64 -0
  48. data/spec/dcm_dict/refine/internal/string_refine_internal_spec.rb +214 -0
  49. data/spec/dcm_dict/refine/string_refine_spec.rb +87 -0
  50. data/spec/dcm_dict/refine/symbol_refine_spec.rb +41 -0
  51. data/spec/dcm_dict/rubies/rb_ext_spec.rb +46 -0
  52. data/spec/dcm_dict/source_data/data_elements_data_spec.rb +40 -0
  53. data/spec/dcm_dict/source_data/detached_data_spec.rb +55 -0
  54. data/spec/dcm_dict/source_data/uid_values_data_spec.rb +37 -0
  55. data/spec/dcm_dict/version_spec.rb +30 -0
  56. data/spec/dcm_dict/xml/tag_field_data_spec.rb +62 -0
  57. data/spec/dcm_dict/xml/uid_field_data_spec.rb +60 -0
  58. data/spec/dictionary_shared_example_spec_helper.rb +118 -0
  59. data/spec/refine_shared_example_spec_helper.rb +54 -0
  60. data/spec/spec_helper.rb +42 -0
  61. data/spec/xml_sample_spec_helper.rb +533 -0
  62. metadata +212 -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 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.
data/README.md ADDED
@@ -0,0 +1,296 @@
1
+ # What's *DcmDict*
2
+ **DcmDict** is a Ruby gem (*dcm\_dict*) to handle in a simple way the Data defined within the [DICOM(r)][1] Standard such as DICOM Data Elements or DICOM Unique Identifiers.
3
+
4
+ # Why *DcmDict*
5
+ With the latest releases in this year (2014) DICOM documents are available in different format including one particularly interesting, the *DocBook* XML version.
6
+ As written by D. Clunie on [its web site][2]:
7
+ > "... other formats (such as DocBook, HTML, Word and ODT) are also made available for the convenience of implementors who may need to extract machine-readable content, ..."
8
+
9
+ This is great news for anyone involved in the study of the standard !
10
+
11
+ 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.
12
+
13
+ # *DcmDict* features
14
+ The library involve *String*, *Array* and *Symbol* class as *refinements* to access to DICOM information. In this way is possible to *play* with the 'Patient's Birth Date' tag defined as (0010,0030) by:
15
+ ```ruby
16
+ > "(0010,0030)".tag_name
17
+ => "Patient's Birth Date"
18
+ > 'PatientBirthDate'.tag_vr
19
+ => [:DA]
20
+ > "Patient's Birth Date".tag_vm
21
+ => ["1"]
22
+ > :patient_birth_date.tag
23
+ => [16, 48]
24
+ > [16,48].tag_key
25
+ => "PatientBirthDate"
26
+ > [16, 48].tag_group
27
+ => 16
28
+ > '00100030'.tag_element
29
+ => 48
30
+ > :patient_birth_date.tag_group
31
+ => 16
32
+ > "Patient's Birth Date".tag_element
33
+ => 48
34
+ ```
35
+ as well for UIDs
36
+ ```ruby
37
+ > '1.2.840.10008.1.2'.uid_name
38
+ => "Implicit VR Little Endian: Default Transfer Syntax for DICOM"
39
+ > '1.2.840.10008.1.2'.uid_type
40
+ => :transfer_syntax
41
+ > "Implicit VR Little Endian: Default Transfer Syntax for DICOM".uid_value
42
+ => "1.2.840.10008.1.2"
43
+ ```
44
+
45
+ let see all features in detail:
46
+
47
+ ## Library usage
48
+ The library involve **Ruby Refinements** so use it is simple, it is necessary to include the specific *using directive*:
49
+
50
+ ```ruby
51
+ using DcmDict::Refine::StringRefine
52
+ ```
53
+ for the String object,
54
+ ```ruby
55
+ using DcmDict::Refine::ArrayRefine
56
+ ```
57
+ for the Array object and
58
+
59
+ ```ruby
60
+ using DcmDict::Refine::SymbolRefine
61
+ ```
62
+ for the Symbol object.
63
+
64
+ That's it.
65
+
66
+ **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* into the class you want to use as "keyword": there are two base modules *DcmDict::Refine::DataElementRefine* and *DcmDict::Refine::UidRefine*.
67
+
68
+ For example in the String class will have the code:
69
+ ```ruby
70
+ class String
71
+ include DcmDict::Refine::DataElementRefine
72
+ include DcmDict::Refine::UidRefine
73
+ end
74
+ ```
75
+ *The main way remains **Ruby Refinements***.
76
+
77
+ **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 through [refine gem][5] and add the required *bit_length* method to *Fixnum* class through [backports gem][6].
78
+ 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.
79
+
80
+ ## Data Element data in detail
81
+ Any Data Element features can be accessed from a *String*, *Array* or *Symbol* objects.
82
+
83
+ 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.
84
+
85
+ The main methods supported are:
86
+
87
+ |Method | Note| Type||
88
+ |:------|:------------:|:---:|:---:|
89
+ |**tag** | tag as Array| Array of two Fixnum|(alias of *tag_ary*)|
90
+ |**tag_name** | name of tag| String|
91
+ |**tag_keyword** | keyword| String|
92
+ |**tag_key** | keyword| String|
93
+ |**tag_vr** | Value Representation| Array of Symbol|
94
+ |**tag_vm** | Value Multiplicity| Array of Symbol|
95
+ |**tag_ps** | tag as string (as standard doc)| String|
96
+ |**tag_ary** | tag as Array|Array of two Fixnum|
97
+ |**tag_sym** | tag as Symbol|Symbol|
98
+ |**tag_ndm** | tag as in Native DICOM Model|String|
99
+ |**tag_str** | tag as string (similar to tag_ps)|String|
100
+ |**tag_note** | tag note|String|
101
+ |**tag_multiple?** | is a multiple tag ? |boolean|
102
+ ||useful for 'multi tag' attribute|
103
+
104
+ each data element is indexed by these fields:
105
+
106
+ |Field|Type|
107
+ |:----|:-----:|
108
+ |**tag_key** | String|
109
+ |**tag_ps** | String|
110
+ |**tag_ary** | Array|
111
+ |**tag_sym** | Symbol|
112
+ |**tag_ndm** | String|
113
+ |**tag_str** | String|
114
+ |**tag_name** | String|
115
+
116
+ Through these fields is possible to access to data element informations.
117
+ Consider the case of the tag (0010,1005) (*Patient's Birth Name*), the primary fields are:
118
+ **'(0010,1005)'**, **"Patient's Birth Name"**, **'PatientBirthName'**, **:patient_birth_name**, **'00101005'** and **[0x0010,0x1005]**
119
+
120
+ - 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'**
121
+ - As Array key you may use the numeric array **[0x0010,0x1005]**
122
+ - As Symbol key you may use **:patient_birth_name**
123
+
124
+ ### example:
125
+ Consider the previous case of tag (0010,1005), the code:
126
+
127
+ ```ruby
128
+ puts "Patient's Birth Name".tag_ps.inspect
129
+ puts [0x0010,0x1005].tag_name.inspect
130
+ puts '(0010,1005)'.tag_key.inspect
131
+ puts :patient_birth_name.tag_vr.inspect
132
+ puts 'PatientBirthName'.tag_vm.inspect
133
+ puts '00101005'.tag.inspect
134
+ puts '(0010,1005)'.tag_ary.inspect
135
+ puts '00101005'.tag_sym.inspect
136
+ puts 'PatientBirthName'.tag_ndm.inspect
137
+ puts "Patient's Birth Name".tag_str.inspect
138
+ puts [0x0010,0x1005].tag_note.inspect
139
+ puts [0x0010,0x1005].tag_group.inspect
140
+ puts :patient_birth_name.tag_element.inspect
141
+ ```
142
+
143
+ will produce
144
+
145
+
146
+ ```ruby
147
+ "(0010,1005)"
148
+ "Patient's Birth Name"
149
+ "PatientBirthName"
150
+ [:PN]
151
+ ["1"]
152
+ [16, 4101]
153
+ [16, 4101]
154
+ :patient_birth_name
155
+ "00101005"
156
+ "(0010,1005)"
157
+ ""
158
+ 16
159
+ 4101
160
+ ```
161
+
162
+ ### Multiple Tag
163
+ The library also manage 'multiple tags' such as *(0020,31XX)* (*Source Image IDs*).
164
+ As an example for this data element the default tag in array form is [0x0020,0x3122] and all fields are expressed as:
165
+
166
+ |Method/field | Value|
167
+ |:------|:------------:|
168
+ |**tag** | [0x0020,0x3122]|
169
+ |**tag_name** | "Source Image IDs"|
170
+ |**tag_keyword** | 'SourceImageIDs'|
171
+ |**tag_key** | 'SourceImageIDs'|
172
+ |**tag_vr** | [:CS]|
173
+ |**tag_vm** | ["1-n"]|
174
+ |**tag_ps** | '(0020,31XX)'|
175
+ |**tag_ary** | [0x0020,0x3122]|
176
+ |**tag_sym** | :source_image_ids|
177
+ |**tag_ndm** | '00203122'
178
+ |**tag_str** | '(0020,3122)'|
179
+ |**tag_note** | 'RET'|
180
+ |**tag_multiple?** | true|
181
+
182
+ [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:
183
+
184
+ ```ruby
185
+ > '(0020,31XX)'.tag_name
186
+ => "Source Image IDs"
187
+ > '(0020,31XX)'.tag_ndm
188
+ => "00203122"
189
+ > "SourceImageIDs".tag_ary
190
+ => [32, 12578]
191
+ > '(0020,3178)'.tag_name
192
+ => "Source Image IDs"
193
+ [0x0020,0x3146].tag_sym
194
+ => :source_image_ids
195
+ > '00203120'.tag_key
196
+ => "SourceImageIDs"
197
+ > [0x0020,0x3138].tag_vr
198
+ => [:CS]
199
+ > '(0020,3144)'.tag_note
200
+ => "RET"
201
+ ```
202
+ and so on.
203
+
204
+ ## UID data in detail
205
+ Any UID features can be accessed from a *String* object.
206
+
207
+ ### UID Values
208
+ For these objects is possible to access to value, name and type values for any single uid.
209
+ Main methods supported are:
210
+
211
+ |Method | Note| Type||
212
+ |:------|:------------:|:---:|:---:|
213
+ |**uid** | value of uid| String|(alias of *uid_value*)|
214
+ |**uid_value** | value of uid| String|
215
+ |**uid_name** | name of uid| String|
216
+ |**uid_type** | type of uid| Symbol|
217
+
218
+ each uid is indexed by:
219
+
220
+ |Field|Type|
221
+ |:----|:-----|
222
+ |**uid_value** | String|
223
+ |**uid_name** | String|
224
+
225
+ From these fields is possible to access to all uid informations.
226
+ 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"**.
227
+ - As String key you may use the standard value **'1.2.840.10008.1.1'** and the uid name **"Verification SOP Class"**
228
+
229
+ For this uid all fields are expressed as:
230
+
231
+ |Method/field | Value|
232
+ |:------|:------------:|
233
+ |**uid** | '1.2.840.10008.1.1'|
234
+ |**uid_value** | '1.2.840.10008.1.1'|
235
+ |**uid_name** | "Verification SOP Class"|
236
+ |**uid_type** | :sop_class|
237
+
238
+ ### example:
239
+ ```ruby
240
+ > "Verification SOP Class".uid_value
241
+ => "1.2.840.10008.1.1"
242
+ > "1.2.840.10008.1.1".uid_type
243
+ => :sop_class
244
+ > "1.2.840.10008.1.1".uid_name
245
+ => "Verification SOP Class"
246
+ > "Verification SOP Class".uid
247
+ => "1.2.840.10008.1.1"
248
+ ```
249
+
250
+ ## How data is extracted
251
+ The library also contains a script (*dcm_dict_converter.rb* into *bin* folder) able to download the xml documents and extracts the source data in a *Ruby compatible format*.
252
+ The script produces the conversion in the *stdout* so for example is possible to extract the Tag Values by:
253
+
254
+ ```ruby
255
+ dcm_dict_converter.rb tag > /tmp/tag-dict.rb
256
+ ```
257
+
258
+ Note: the script use the [Nokogiri][3] as XML parser if installed as gem, otherwise the standard *REXML*.
259
+
260
+ Check the file for other details.
261
+
262
+ ## Install
263
+
264
+ $ gem install dcm_dict
265
+
266
+ *Note for Windows users*: may be that it is installed a previous version of Ruby 2.1, at the moment [RubyInstaller][7] does not provide the official release for this version. It is still possible to make it manually by clone/download the ['git' version of RubyInstaller][8] and execute the rake command ```rake ruby21``` (see RubyInstaller doc for details).
267
+
268
+ ## What's next
269
+ 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.
270
+ There are many possible *candidates* for inclusion in the *dictionary*, here are some *"ideas"*:
271
+ - Directory Record type data
272
+ - Well-known Frames of Reference UID Values
273
+ - Context Group UID Values
274
+ - Standard Color Palettes UID Values
275
+ - IOD definition data
276
+ - ...
277
+
278
+ ## Contributing
279
+ TBD
280
+
281
+ ## License
282
+ Copyright (C) 2014 Enrico Rivarola.
283
+ See the `LICENSE` and `COPYING` files for license details.
284
+
285
+ ## Source Code
286
+ Main source code repository on github at [henrythebuilder/dcm_dict](https://github.com/henrythebuilder/dcm_dict)
287
+
288
+
289
+ [1]: http://medical.nema.org/dicom/ "DICOM Homepage"
290
+ [2]: http://www.dclunie.com/dicom-status/status.html "DICOM Standard Status"
291
+ [3]: http://nokogiri.org/ "Nokogiri"
292
+ [4]: http://rubini.us/ "Rubinius"
293
+ [5]: https://rubygems.org/gems/refine "Refine gem at RubyGems.org"
294
+ [6]: https://rubygems.org/gems/backports "Backports gem at RubyGems.org"
295
+ [7]: http://rubyinstaller.org/ "The easy way to install Ruby on Windows"
296
+ [8]: https://github.com/oneclick/rubyinstaller "RubyInstaller for Windows"
data/Rakefile ADDED
@@ -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 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 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/2014a/source/docbook/part06/part06.xml"
58
+ Part7XmlUrl="http://dicom.nema.org/medical/dicom/2014a/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
+ 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