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
@@ -0,0 +1,46 @@
1
+ #
2
+ # Copyright (C) 2014-2020 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-2020 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-2020 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-2020 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-2020 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