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/lib/dcm_dict.rb ADDED
@@ -0,0 +1,46 @@
1
+ #
2
+ # Copyright (C) 2014 Enrico Rivarola
3
+ #
4
+ # This file is part of DcmDict gem (dcm_dict).
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. 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.
23
+ #
24
+ require "dcm_dict/version"
25
+ require "dcm_dict/error/dictionary_error"
26
+ require "dcm_dict/ext/object_extension"
27
+ require "dcm_dict/refine/internal/string_refine_internal"
28
+ require "dcm_dict/refine/internal/array_refine_internal"
29
+ require "dcm_dict/refine/internal/hash_refine_internal"
30
+ require "dcm_dict/xml/constant"
31
+ require "dcm_dict/xml/field_data"
32
+ require "dcm_dict/xml/tag_field_data"
33
+ require "dcm_dict/xml/uid_field_data"
34
+ require "dcm_dict/encoder/data_to_code"
35
+ require "dcm_dict/source_data/data_elements_data"
36
+ require "dcm_dict/source_data/uid_values_data"
37
+ require "dcm_dict/source_data/detached_data"
38
+ require "dcm_dict/dictionary/data_element_record"
39
+ require "dcm_dict/dictionary/data_element_dictionary"
40
+ require "dcm_dict/dictionary/uid_record"
41
+ require "dcm_dict/dictionary/uid_dictionary"
42
+ require "dcm_dict/refine/data_element_refine"
43
+ require "dcm_dict/refine/uid_refine"
44
+ require "dcm_dict/refine/string_refine"
45
+ require "dcm_dict/refine/array_refine"
46
+ require "dcm_dict/refine/symbol_refine"
@@ -0,0 +1,47 @@
1
+ #
2
+ # Copyright (C) 2014 Enrico Rivarola
3
+ #
4
+ # This file is part of DcmDict gem (dcm_dict).
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. 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.
23
+ #
24
+ module DcmDict
25
+ module Dictionary
26
+
27
+ # Base class for specific dictionary
28
+ class BaseDictionary
29
+ def initialize
30
+ @semaphore = Mutex.new
31
+ map_source_data
32
+ freeze_source_data
33
+ end
34
+
35
+ # Find record data using +key+
36
+ def record_at(key)
37
+ @semaphore.synchronize { atomic_record_at(key) }
38
+ end
39
+
40
+ # Find single feature identified by +field+ for record indexed by +key+
41
+ def feature_at(key, field)
42
+ @semaphore.synchronize { atomic_feature_at(key, field) }
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,62 @@
1
+ #
2
+ # Copyright (C) 2014 Enrico Rivarola
3
+ #
4
+ # This file is part of DcmDict gem (dcm_dict).
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. 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.
23
+ #
24
+ module DcmDict
25
+ module Dictionary
26
+
27
+ # Base class for dictionary record element
28
+ class BaseRecord
29
+ def initialize(data)
30
+ @data = {}
31
+ initialize_data(data)
32
+ end
33
+
34
+ private
35
+ def method_missing(name, *args, &block)
36
+ name_as_sym = name.to_sym
37
+ return @data[method_map[name_as_sym]] if (method_map.has_key?(name_as_sym))
38
+ return @data[name_as_sym] if (@data.has_key?(name_as_sym))
39
+ super
40
+ end
41
+
42
+ def respond_to_missing?(name, include_priv)
43
+ method_map.has_key?(name) || @data.has_key?(name)
44
+ end
45
+
46
+ def initialize_data(data)
47
+ @data = data
48
+ freeze_data
49
+ end
50
+
51
+ def freeze_data
52
+ @data.each {|key, value| value.freeze }
53
+ @data.freeze
54
+ end
55
+
56
+ def record_data
57
+ @data
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,117 @@
1
+ #
2
+ # Copyright (C) 2014 Enrico Rivarola
3
+ #
4
+ # This file is part of DcmDict gem (dcm_dict).
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. 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.
23
+ #
24
+ require_relative 'base_dictionary'
25
+
26
+ module DcmDict
27
+ module Dictionary
28
+ DataElementIndexKey = [:tag_ps, :tag_name, :tag_key, :tag_str,
29
+ :tag_sym, :tag_ndm, :tag_ary]
30
+
31
+ # Main class to handle data element data as dictionary
32
+ class DataElementDictionary < BaseDictionary
33
+ using DcmDict::Refine::Internal::ArrayRefineInternal
34
+ using DcmDict::Refine::Internal::StringRefineInternal
35
+
36
+ def initialize
37
+ super
38
+ end
39
+
40
+ private
41
+ def map_source_data
42
+ @standard_dict = {}
43
+ @multi_dict = []
44
+ SourceData::DataElementsData.each do |data|
45
+ record = DataElementRecord.new(data).freeze
46
+ DataElementIndexKey.each { |key| @standard_dict[data[key]] = record }
47
+ @multi_dict << record if record.tag_multiple?
48
+ end
49
+ end
50
+
51
+ def freeze_source_data
52
+ @standard_dict.freeze
53
+ @multi_dict.freeze
54
+ end
55
+
56
+ def atomic_feature_at(tag, key)
57
+ try_to_find_feature(tag, key)
58
+ rescue Exception => ex
59
+ raise DictionaryError.new("Unable to find feature #{key.inspect} for tag '#{tag}' (#{ex.class}: #{ex.message.inspect})")
60
+
61
+ end
62
+
63
+ def try_to_find_feature(tag, key)
64
+ atomic_record_at(tag).send(key)
65
+ end
66
+
67
+ def atomic_record_at(tag)
68
+ try_to_find(tag)
69
+ rescue Exception => ex
70
+ raise DictionaryError.new("Unable to find reference for tag '#{tag}' as #{tag.class} (#{ex.class}: #{ex.message.inspect})")
71
+ end
72
+
73
+ def try_to_find(tag)
74
+ try_to_find_standard_tag(tag) ||
75
+ try_to_find_group_length_tag(tag) ||
76
+ try_to_find_multiple_tag(tag) ||
77
+ try_to_find_private_creator_tag(tag) ||
78
+ try_to_find_unknown_tag(tag)
79
+ end
80
+
81
+ def try_to_find_standard_tag(tag)
82
+ @standard_dict[tag]
83
+ end
84
+
85
+ def try_to_find_multiple_tag(tag)
86
+ @multi_dict.each do |record|
87
+ mrec = record.extract_multiple_tag_record(tag)
88
+ return mrec if mrec
89
+ end
90
+ nil
91
+ end
92
+
93
+ def try_to_find_group_length_tag(tag)
94
+ if (tag.group_length_tag?)
95
+ return DataElementRecord.new(
96
+ SourceData::DetachedData.make_group_length_data(tag))
97
+ end
98
+ end
99
+
100
+ def try_to_find_private_creator_tag(tag)
101
+ if ( tag.private_creator_tag? )
102
+ return DataElementRecord.new(
103
+ SourceData::DetachedData.make_private_creator_data(tag))
104
+ end
105
+ end
106
+
107
+ def try_to_find_unknown_tag(tag)
108
+ DataElementRecord.new(
109
+ SourceData::DetachedData.make_unknown_data(tag))
110
+ end
111
+
112
+ end
113
+
114
+ TheDataElementDictionary = DataElementDictionary.new.freeze
115
+
116
+ end
117
+ end
@@ -0,0 +1,93 @@
1
+ #
2
+ # Copyright (C) 2014 Enrico Rivarola
3
+ #
4
+ # This file is part of DcmDict gem (dcm_dict).
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. 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.
23
+ #
24
+ require_relative 'base_record'
25
+
26
+ module DcmDict
27
+ module Dictionary
28
+ DataElementMethodMap = { :tag_multiple? => :tag_multiple,
29
+ :tag_name => :tag_name,
30
+ :tag_keyword => :tag_key,
31
+ :tag_vr => :tag_vr,
32
+ :tag_vm => :tag_vm,
33
+ :tag_note => :tag_note,
34
+ :tag => :tag_ary,
35
+ :tag_ary => :tag_ary,
36
+ :tag_ps => :tag_ps,
37
+ :tag_sym => :tag_sym,
38
+ :tag_ndm => :tag_ndm,
39
+ :tag_str => :tag_str }.freeze
40
+
41
+ DataElementMethod = DataElementMethodMap.flatten.
42
+ concat([:tag_group, :tag_element]).uniq.freeze
43
+
44
+ # Class to handle data element record from source dictionary data
45
+ class DataElementRecord < BaseRecord
46
+ using DcmDict::Refine::Internal::StringRefineInternal
47
+ using DcmDict::Refine::Internal::ArrayRefineInternal
48
+
49
+ def initialize(data)
50
+ super
51
+ end
52
+
53
+ # Group of tag
54
+ def tag_group
55
+ record_data[:tag_ary].tag_group_num
56
+ end
57
+
58
+ # Element of tag
59
+ def tag_element
60
+ record_data[:tag_ary].tag_element_num
61
+ end
62
+
63
+ # Extract data from 'multiple tag' record using +tag+
64
+ def extract_multiple_tag_record(tag)
65
+ if ( record_data[:tag_multiple] && match_tag?(tag) )
66
+ DataElementRecord.new( record_data.merge( { tag_str: tag.to_tag_str,
67
+ tag_ndm: tag.to_tag_ndm,
68
+ tag_ary: tag.to_tag_ary } ))
69
+ end
70
+ end
71
+
72
+ private
73
+ def method_map
74
+ DataElementMethodMap
75
+ end
76
+
77
+ def match_tag?(tag)
78
+ tag_to_match = tag.to_tag_str
79
+ tag_pattern.each do |pattern|
80
+ re = Regexp.new(pattern)
81
+ return true if re.match(tag_to_match)
82
+ end
83
+ false
84
+ end
85
+
86
+ def tag_pattern
87
+ gs, es = self.tag_ps.gsub(/[\(|\)]/, '').gsub(/[xX]/,"[0-9A-Fa-f]").split(',')
88
+ ["^\\(#{gs}\\,#{es}\\)$", "^#{gs}#{es}$" ]
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,82 @@
1
+ #
2
+ # This file is part of DcmDict gem (dcm_dict).
3
+ #
4
+ # DcmDict is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # DcmDict is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with DcmDict. If not, see <http://www.gnu.org/licenses/>.
16
+ #
17
+ # This software has neither been tested nor approved for clinical use
18
+ # or for incorporation in a medical device.
19
+ # It is the redistributor's or user's responsibility to comply with any
20
+ # applicable local, state, national or international regulations.
21
+ #
22
+ require_relative 'base_dictionary'
23
+
24
+ module DcmDict
25
+ module Dictionary
26
+ using DcmDict::Refine::Internal::StringRefineInternal
27
+
28
+ UidIndexKey = [:uid_value, :uid_name]
29
+
30
+ # Main class to handle uid data as dictionary
31
+ class UidDictionary < BaseDictionary
32
+
33
+ def initialize
34
+ super
35
+ end
36
+
37
+ private
38
+ def map_source_data
39
+ @uid_dict={}
40
+ SourceData::UidValuesData.each do |data|
41
+ record = UidRecord.new(data).freeze
42
+ UidIndexKey.each { |key| @uid_dict[data[key]] = record }
43
+ end
44
+ end
45
+
46
+ def freeze_source_data
47
+ @uid_dict.freeze
48
+ end
49
+
50
+ def atomic_feature_at(uid, key)
51
+ try_to_find_feature(uid, key)
52
+ rescue Exception => ex
53
+ raise DictionaryError.new("Unable to find feature #{key.inspect} for uid '#{uid}' as #{uid.class} (#{ex.class}: #{ex.message.inspect})")
54
+ end
55
+
56
+ def try_to_find_feature(uid, key)
57
+ atomic_record_at(uid).send(key)
58
+ end
59
+
60
+ def atomic_record_at(uid)
61
+ try_to_find_uid(uid)
62
+ rescue Exception => ex
63
+ raise DictionaryError.new("Unable to find reference for uid '#{uid}' as #{uid.class} (#{ex.class}: #{ex.message.inspect})")
64
+ end
65
+
66
+ def try_to_find_uid(uid)
67
+ @uid_dict[uid] ||
68
+ try_to_find_unknown_uid(uid)
69
+ end
70
+
71
+ def try_to_find_unknown_uid(uid)
72
+ raise "Unknown UID value" unless uid.uid_value?
73
+ UidRecord.new({ uid_value: uid,
74
+ uid_name: 'Unknown UID',
75
+ uid_type: :unknown })
76
+ end
77
+ end
78
+
79
+ TheUidDictionary = UidDictionary.new.freeze
80
+
81
+ end
82
+ end