dcm_dict 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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