dicom 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/CHANGELOG.md +390 -376
- data/COPYING +674 -674
- data/Gemfile +2 -2
- data/Gemfile.lock +30 -28
- data/README.md +154 -152
- data/dicom.gemspec +30 -30
- data/lib/dicom/anonymizer.rb +677 -654
- data/lib/dicom/audit_trail.rb +109 -109
- data/lib/dicom/d_library.rb +269 -265
- data/lib/dicom/d_object.rb +465 -465
- data/lib/dicom/d_read.rb +21 -8
- data/lib/dicom/d_server.rb +329 -329
- data/lib/dicom/d_write.rb +355 -355
- data/lib/dicom/dictionary/elements.tsv +597 -86
- data/lib/dicom/dictionary/uids.tsv +4 -2
- data/lib/dicom/elemental_parent.rb +63 -63
- data/lib/dicom/extensions/array.rb +56 -56
- data/lib/dicom/extensions/hash.rb +30 -30
- data/lib/dicom/extensions/string.rb +125 -125
- data/lib/dicom/file_handler.rb +121 -121
- data/lib/dicom/general/constants.rb +210 -210
- data/lib/dicom/general/deprecated.rb +0 -320
- data/lib/dicom/general/logging.rb +155 -155
- data/lib/dicom/general/methods.rb +98 -82
- data/lib/dicom/general/variables.rb +28 -28
- data/lib/dicom/general/version.rb +5 -5
- data/lib/dicom/image_item.rb +836 -836
- data/lib/dicom/image_processor.rb +79 -79
- data/lib/dicom/image_processor_mini_magick.rb +71 -71
- data/lib/dicom/image_processor_r_magick.rb +106 -106
- data/lib/dicom/link.rb +1529 -1528
- data/rakefile.rb +29 -30
- metadata +43 -49
data/lib/dicom/audit_trail.rb
CHANGED
@@ -1,110 +1,110 @@
|
|
1
|
-
module DICOM
|
2
|
-
|
3
|
-
# The AuditTrail class handles key/value storage for the Anonymizer.
|
4
|
-
# When using the advanced Anonymization options such as enumeration
|
5
|
-
# and UID replacement, the AuditTrail class keeps track of key/value
|
6
|
-
# pairs and dumps this information to a text file using the json format.
|
7
|
-
# This enables us to ensure a unique relationship between the anonymized
|
8
|
-
# values and the original values, as well as preserving this relationship
|
9
|
-
# for later restoration of original values.
|
10
|
-
#
|
11
|
-
class AuditTrail
|
12
|
-
|
13
|
-
# The hash used for storing the key/value pairs of this instace.
|
14
|
-
attr_reader :dictionary
|
15
|
-
|
16
|
-
# Creates a new AuditTrail instance by loading the information stored
|
17
|
-
# in the specified file.
|
18
|
-
#
|
19
|
-
# @param [String] file_name the path to a file containing a previously stored audit trail
|
20
|
-
# @return [AuditTrail] the created AuditTrail instance
|
21
|
-
#
|
22
|
-
def self.read(file_name)
|
23
|
-
audit_trail = AuditTrail.new
|
24
|
-
audit_trail.load(file_name)
|
25
|
-
return audit_trail
|
26
|
-
end
|
27
|
-
|
28
|
-
# Creates a new AuditTrail instance.
|
29
|
-
#
|
30
|
-
def initialize
|
31
|
-
# Define the key/value hash used for tag records:
|
32
|
-
@dictionary = Hash.new
|
33
|
-
end
|
34
|
-
|
35
|
-
# Adds a tag record to the log.
|
36
|
-
#
|
37
|
-
# @param [String] tag the tag string (e.q. '0010,0010')
|
38
|
-
# @param [String, Integer, Float] original the original value (e.q. 'John Doe')
|
39
|
-
# @param [String, Integer, Float] replacement the replacement value (e.q. 'Patient1')
|
40
|
-
#
|
41
|
-
def add_record(tag, original, replacement)
|
42
|
-
@dictionary[tag] = Hash.new unless @dictionary.key?(tag)
|
43
|
-
@dictionary[tag][original] = replacement
|
44
|
-
end
|
45
|
-
|
46
|
-
# Loads the key/value dictionary hash from a specified file.
|
47
|
-
#
|
48
|
-
# @param [String] file_name the path to a file containing a previously stored audit trail
|
49
|
-
#
|
50
|
-
def load(file_name)
|
51
|
-
@dictionary = JSON.load(File.new(file_name, "r:UTF-8"))
|
52
|
-
end
|
53
|
-
|
54
|
-
# Retrieves the original value used for the given combination of tag & replacement value.
|
55
|
-
#
|
56
|
-
# @param [String] tag the tag string (e.q. '0010,0010')
|
57
|
-
# @param [String, Integer, Float] replacement the replacement value (e.q. 'Patient1')
|
58
|
-
# @return [String, Integer, Float] the original value of the given tag
|
59
|
-
#
|
60
|
-
def original(tag, replacement)
|
61
|
-
original = nil
|
62
|
-
if @dictionary.key?(tag)
|
63
|
-
original = @dictionary[tag].key(replacement)
|
64
|
-
end
|
65
|
-
return original
|
66
|
-
end
|
67
|
-
|
68
|
-
# Gives the key/value pairs for a specific tag.
|
69
|
-
#
|
70
|
-
# @param [String] tag the tag string (e.q. '0010,0010')
|
71
|
-
# @return [Hash] the key/value pairs of a specific tag
|
72
|
-
#
|
73
|
-
def records(tag)
|
74
|
-
if @dictionary.key?(tag)
|
75
|
-
return @dictionary[tag]
|
76
|
-
else
|
77
|
-
return Hash.new
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Retrieves the replacement value used for the given combination of tag & original value.
|
82
|
-
#
|
83
|
-
# @param [String] tag the tag string (e.q. '0010,0010')
|
84
|
-
# @param [String, Integer, Float] original the original value (e.q. 'John Doe')
|
85
|
-
# @return [String, Integer, Float] the replacement value of the given tag
|
86
|
-
#
|
87
|
-
def replacement(tag, original)
|
88
|
-
replacement = nil
|
89
|
-
replacement = @dictionary[tag][original] if @dictionary.key?(tag)
|
90
|
-
return replacement
|
91
|
-
end
|
92
|
-
|
93
|
-
# Dumps the key/value pairs to a json string which is written to the specified file.
|
94
|
-
#
|
95
|
-
# @param [String] file_name the path to be used for storing key/value pairs on disk
|
96
|
-
#
|
97
|
-
def write(file_name)
|
98
|
-
# Encode json string:
|
99
|
-
str = JSON.pretty_generate(@dictionary)
|
100
|
-
# Create directory if needed:
|
101
|
-
unless File.directory?(File.dirname(file_name))
|
102
|
-
require 'fileutils'
|
103
|
-
FileUtils.mkdir_p(File.dirname(file_name))
|
104
|
-
end
|
105
|
-
# Write to file:
|
106
|
-
File.open(file_name, 'w') {|f| f.write(str) }
|
107
|
-
end
|
108
|
-
|
109
|
-
end
|
1
|
+
module DICOM
|
2
|
+
|
3
|
+
# The AuditTrail class handles key/value storage for the Anonymizer.
|
4
|
+
# When using the advanced Anonymization options such as enumeration
|
5
|
+
# and UID replacement, the AuditTrail class keeps track of key/value
|
6
|
+
# pairs and dumps this information to a text file using the json format.
|
7
|
+
# This enables us to ensure a unique relationship between the anonymized
|
8
|
+
# values and the original values, as well as preserving this relationship
|
9
|
+
# for later restoration of original values.
|
10
|
+
#
|
11
|
+
class AuditTrail
|
12
|
+
|
13
|
+
# The hash used for storing the key/value pairs of this instace.
|
14
|
+
attr_reader :dictionary
|
15
|
+
|
16
|
+
# Creates a new AuditTrail instance by loading the information stored
|
17
|
+
# in the specified file.
|
18
|
+
#
|
19
|
+
# @param [String] file_name the path to a file containing a previously stored audit trail
|
20
|
+
# @return [AuditTrail] the created AuditTrail instance
|
21
|
+
#
|
22
|
+
def self.read(file_name)
|
23
|
+
audit_trail = AuditTrail.new
|
24
|
+
audit_trail.load(file_name)
|
25
|
+
return audit_trail
|
26
|
+
end
|
27
|
+
|
28
|
+
# Creates a new AuditTrail instance.
|
29
|
+
#
|
30
|
+
def initialize
|
31
|
+
# Define the key/value hash used for tag records:
|
32
|
+
@dictionary = Hash.new
|
33
|
+
end
|
34
|
+
|
35
|
+
# Adds a tag record to the log.
|
36
|
+
#
|
37
|
+
# @param [String] tag the tag string (e.q. '0010,0010')
|
38
|
+
# @param [String, Integer, Float] original the original value (e.q. 'John Doe')
|
39
|
+
# @param [String, Integer, Float] replacement the replacement value (e.q. 'Patient1')
|
40
|
+
#
|
41
|
+
def add_record(tag, original, replacement)
|
42
|
+
@dictionary[tag] = Hash.new unless @dictionary.key?(tag)
|
43
|
+
@dictionary[tag][original] = replacement
|
44
|
+
end
|
45
|
+
|
46
|
+
# Loads the key/value dictionary hash from a specified file.
|
47
|
+
#
|
48
|
+
# @param [String] file_name the path to a file containing a previously stored audit trail
|
49
|
+
#
|
50
|
+
def load(file_name)
|
51
|
+
@dictionary = JSON.load(File.new(file_name, "r:UTF-8"))
|
52
|
+
end
|
53
|
+
|
54
|
+
# Retrieves the original value used for the given combination of tag & replacement value.
|
55
|
+
#
|
56
|
+
# @param [String] tag the tag string (e.q. '0010,0010')
|
57
|
+
# @param [String, Integer, Float] replacement the replacement value (e.q. 'Patient1')
|
58
|
+
# @return [String, Integer, Float] the original value of the given tag
|
59
|
+
#
|
60
|
+
def original(tag, replacement)
|
61
|
+
original = nil
|
62
|
+
if @dictionary.key?(tag)
|
63
|
+
original = @dictionary[tag].key(replacement)
|
64
|
+
end
|
65
|
+
return original
|
66
|
+
end
|
67
|
+
|
68
|
+
# Gives the key/value pairs for a specific tag.
|
69
|
+
#
|
70
|
+
# @param [String] tag the tag string (e.q. '0010,0010')
|
71
|
+
# @return [Hash] the key/value pairs of a specific tag
|
72
|
+
#
|
73
|
+
def records(tag)
|
74
|
+
if @dictionary.key?(tag)
|
75
|
+
return @dictionary[tag]
|
76
|
+
else
|
77
|
+
return Hash.new
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Retrieves the replacement value used for the given combination of tag & original value.
|
82
|
+
#
|
83
|
+
# @param [String] tag the tag string (e.q. '0010,0010')
|
84
|
+
# @param [String, Integer, Float] original the original value (e.q. 'John Doe')
|
85
|
+
# @return [String, Integer, Float] the replacement value of the given tag
|
86
|
+
#
|
87
|
+
def replacement(tag, original)
|
88
|
+
replacement = nil
|
89
|
+
replacement = @dictionary[tag][original] if @dictionary.key?(tag)
|
90
|
+
return replacement
|
91
|
+
end
|
92
|
+
|
93
|
+
# Dumps the key/value pairs to a json string which is written to the specified file.
|
94
|
+
#
|
95
|
+
# @param [String] file_name the path to be used for storing key/value pairs on disk
|
96
|
+
#
|
97
|
+
def write(file_name)
|
98
|
+
# Encode json string:
|
99
|
+
str = JSON.pretty_generate(@dictionary)
|
100
|
+
# Create directory if needed:
|
101
|
+
unless File.directory?(File.dirname(file_name))
|
102
|
+
require 'fileutils'
|
103
|
+
FileUtils.mkdir_p(File.dirname(file_name))
|
104
|
+
end
|
105
|
+
# Write to file:
|
106
|
+
File.open(file_name, 'w') {|f| f.write(str) }
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
110
|
end
|
data/lib/dicom/d_library.rb
CHANGED
@@ -1,265 +1,269 @@
|
|
1
|
-
module DICOM
|
2
|
-
|
3
|
-
# The DLibrary class contains methods for interacting with ruby-dicom's dictionary data.
|
4
|
-
#
|
5
|
-
# In practice, the library is for internal use and not accessed by the user. However, a
|
6
|
-
# a library instance is available through the DICOM::LIBRARY constant.
|
7
|
-
#
|
8
|
-
# @example Get a dictionary element corresponding to the given tag
|
9
|
-
# element = DICOM::LIBRARY.element('0010,0010')
|
10
|
-
#
|
11
|
-
class DLibrary
|
12
|
-
|
13
|
-
# A hash with element
|
14
|
-
attr_reader :
|
15
|
-
# A hash with element
|
16
|
-
attr_reader :
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
#
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
when value.
|
97
|
-
@
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
#
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
when value.
|
115
|
-
|
116
|
-
|
117
|
-
nil
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
#
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
when value.
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
#
|
144
|
-
#
|
145
|
-
# @return
|
146
|
-
#
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
#
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
# @
|
207
|
-
#
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
#
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
#
|
231
|
-
# in
|
232
|
-
#
|
233
|
-
#
|
234
|
-
#
|
235
|
-
#
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
#
|
250
|
-
#
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
end
|
1
|
+
module DICOM
|
2
|
+
|
3
|
+
# The DLibrary class contains methods for interacting with ruby-dicom's dictionary data.
|
4
|
+
#
|
5
|
+
# In practice, the library is for internal use and not accessed by the user. However, a
|
6
|
+
# a library instance is available through the DICOM::LIBRARY constant.
|
7
|
+
#
|
8
|
+
# @example Get a dictionary element corresponding to the given tag
|
9
|
+
# element = DICOM::LIBRARY.element('0010,0010')
|
10
|
+
#
|
11
|
+
class DLibrary
|
12
|
+
|
13
|
+
# A hash with element tag strings as keys and DicitonaryElement instances as values.
|
14
|
+
attr_reader :elements
|
15
|
+
# A hash with element name strings as key and method name symbols as value.
|
16
|
+
attr_reader :methods_from_names
|
17
|
+
# A hash with element method name symbols as key and name strings as value.
|
18
|
+
attr_reader :names_from_methods
|
19
|
+
# A hash with uid strings as keys and UID instances as values.
|
20
|
+
attr_reader :uids
|
21
|
+
|
22
|
+
# Creates a DLibrary instance.
|
23
|
+
#
|
24
|
+
def initialize
|
25
|
+
# Create instance hashes used for dictionary data and method conversion:
|
26
|
+
@elements = Hash.new
|
27
|
+
@uids = Hash.new
|
28
|
+
@methods_from_names = Hash.new
|
29
|
+
@names_from_methods = Hash.new
|
30
|
+
# Load the elements dictionary:
|
31
|
+
add_element_dictionary("#{ROOT_DIR}/dictionary/elements.tsv")
|
32
|
+
# Load the unique identifiers dictionary:
|
33
|
+
add_uid_dictionary("#{ROOT_DIR}/dictionary/uids.tsv")
|
34
|
+
end
|
35
|
+
|
36
|
+
# Adds a custom DictionaryElement to the ruby-dicom element dictionary.
|
37
|
+
#
|
38
|
+
# @param [DictionaryElement] element the custom dictionary element to be added
|
39
|
+
#
|
40
|
+
def add_element(element)
|
41
|
+
raise ArgumentError, "Invalid argument 'element'. Expected DictionaryElement, got #{element.class}" unless element.is_a?(DictionaryElement)
|
42
|
+
# We store the elements in a hash with tag as key and the element instance as value:
|
43
|
+
@elements[element.tag] = element
|
44
|
+
# Populate the method conversion hashes with element data:
|
45
|
+
method = element.name.to_element_method
|
46
|
+
@methods_from_names[element.name] = method
|
47
|
+
@names_from_methods[method] = element.name
|
48
|
+
end
|
49
|
+
|
50
|
+
# Adds a custom dictionary file to the ruby-dicom element dictionary.
|
51
|
+
#
|
52
|
+
# @note The format of the dictionary is a tab-separated text file with 5 columns:
|
53
|
+
# * Tag, Name, VR, VM & Retired status
|
54
|
+
# * For samples check out ruby-dicom's element dictionaries in the git repository
|
55
|
+
# @param [String] file the path to the dictionary file to be added
|
56
|
+
#
|
57
|
+
def add_element_dictionary(file)
|
58
|
+
File.open(file, :encoding => 'utf-8').each do |record|
|
59
|
+
fields = record.split("\t")
|
60
|
+
add_element(DictionaryElement.new(fields[0], fields[1], fields[2].split(","), fields[3].rstrip, fields[4].rstrip))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Adds a custom uid (e.g. SOP Class, Transfer Syntax) to the ruby-dicom uid dictionary.
|
65
|
+
#
|
66
|
+
# @param [UID] uid the custom uid instance to be added
|
67
|
+
#
|
68
|
+
def add_uid(uid)
|
69
|
+
raise ArgumentError, "Invalid argument 'uid'. Expected UID, got #{uid.class}" unless uid.is_a?(UID)
|
70
|
+
# We store the uids in a hash with uid-value as key and the uid instance as value:
|
71
|
+
@uids[uid.value] = uid
|
72
|
+
end
|
73
|
+
|
74
|
+
# Adds a custom dictionary file to the ruby-dicom uid dictionary.
|
75
|
+
#
|
76
|
+
# @note The format of the dictionary is a tab-separated text file with 4 columns:
|
77
|
+
# * Value, Name, Type & Retired status
|
78
|
+
# * For samples check out ruby-dicom's uid dictionaries in the git repository
|
79
|
+
# @param [String] file the path to the dictionary file to be added
|
80
|
+
#
|
81
|
+
def add_uid_dictionary(file)
|
82
|
+
File.open(file, :encoding => 'utf-8').each do |record|
|
83
|
+
fields = record.split("\t")
|
84
|
+
add_uid(UID.new(fields[0], fields[1], fields[2].rstrip, fields[3].rstrip))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
# Gives the method (symbol) corresponding to the specified element string value.
|
90
|
+
#
|
91
|
+
# @param [String] value an element tag, element name or an element's method name
|
92
|
+
# @return [Symbol, NilClass] the matched element method, or nil if no match is made
|
93
|
+
#
|
94
|
+
def as_method(value)
|
95
|
+
case true
|
96
|
+
when value.tag?
|
97
|
+
@methods_from_names[element(value).name]
|
98
|
+
when value.dicom_name?
|
99
|
+
@methods_from_names[value]
|
100
|
+
when value.dicom_method?
|
101
|
+
@names_from_methods.has_key?(value.to_sym) ? value.to_sym : nil
|
102
|
+
else
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Gives the name corresponding to the specified element string value.
|
108
|
+
#
|
109
|
+
# @param [String] value an element tag, element name or an element's method name
|
110
|
+
# @return [String, NilClass] the matched element name, or nil if no match is made
|
111
|
+
#
|
112
|
+
def as_name(value)
|
113
|
+
case true
|
114
|
+
when value.tag?
|
115
|
+
element(value).name
|
116
|
+
when value.dicom_name?
|
117
|
+
@methods_from_names.has_key?(value) ? value.to_s : nil
|
118
|
+
when value.dicom_method?
|
119
|
+
@names_from_methods[value.to_sym]
|
120
|
+
else
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Gives the tag corresponding to the specified element string value.
|
126
|
+
#
|
127
|
+
# @param [String] value an element tag, element name or an element's method name
|
128
|
+
# @return [String, NilClass] the matched element tag, or nil if no match is made
|
129
|
+
#
|
130
|
+
def as_tag(value)
|
131
|
+
case true
|
132
|
+
when value.tag?
|
133
|
+
element(value) ? value : nil
|
134
|
+
when value.dicom_name?
|
135
|
+
get_tag(value)
|
136
|
+
when value.dicom_method?
|
137
|
+
get_tag(@names_from_methods[value.to_sym])
|
138
|
+
else
|
139
|
+
nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Identifies the DictionaryElement that corresponds to the given tag.
|
144
|
+
#
|
145
|
+
# @note If a given tag doesn't return a dictionary match, a new DictionaryElement is created.
|
146
|
+
# * For private tags, a name 'Private' and VR 'UN' is assigned
|
147
|
+
# * For unknown tags, a name 'Unknown' and VR 'UN' is assigned
|
148
|
+
# @param [String] tag the tag of the element
|
149
|
+
# @return [DictionaryElement] a corresponding DictionaryElement
|
150
|
+
#
|
151
|
+
def element(tag)
|
152
|
+
element = @elements[tag]
|
153
|
+
unless element
|
154
|
+
if tag.group_length?
|
155
|
+
element = DictionaryElement.new(tag, 'Group Length', ['UL'], '1', '')
|
156
|
+
else
|
157
|
+
if tag.private?
|
158
|
+
element = DictionaryElement.new(tag, 'Private', ['UN'], '1', '')
|
159
|
+
else
|
160
|
+
element = unknown_or_range_element(tag)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
element
|
165
|
+
end
|
166
|
+
|
167
|
+
# Extracts, and returns, all transfer syntaxes and SOP Classes from the dictionary.
|
168
|
+
#
|
169
|
+
# @return [Array<Hash, Hash>] transfer syntax and sop class hashes, each with uid as key and name as value
|
170
|
+
#
|
171
|
+
def extract_transfer_syntaxes_and_sop_classes
|
172
|
+
transfer_syntaxes = Hash.new
|
173
|
+
sop_classes = Hash.new
|
174
|
+
@uids.each_value do |uid|
|
175
|
+
if uid.transfer_syntax?
|
176
|
+
transfer_syntaxes[uid.value] = uid.name
|
177
|
+
elsif uid.sop_class?
|
178
|
+
sop_classes[uid.value] = uid.name
|
179
|
+
end
|
180
|
+
end
|
181
|
+
return transfer_syntaxes, sop_classes
|
182
|
+
end
|
183
|
+
|
184
|
+
# Gives the tag that matches the supplied data element name, by searching the element dictionary.
|
185
|
+
#
|
186
|
+
# @param [String] name a data element name
|
187
|
+
# @return [String, NilClass] the corresponding element tag, or nil if no match is made
|
188
|
+
#
|
189
|
+
def get_tag(name)
|
190
|
+
tag = nil
|
191
|
+
name = name.to_s.downcase
|
192
|
+
@tag_name_pairs_cache ||= Hash.new
|
193
|
+
return @tag_name_pairs_cache[name] unless @tag_name_pairs_cache[name].nil?
|
194
|
+
@elements.each_value do |element|
|
195
|
+
next unless element.name.downcase == name
|
196
|
+
tag = element.tag
|
197
|
+
break
|
198
|
+
end
|
199
|
+
@tag_name_pairs_cache[name]=tag
|
200
|
+
return tag
|
201
|
+
end
|
202
|
+
|
203
|
+
# Determines the name and vr of the element which the specified tag belongs to,
|
204
|
+
# based on a lookup in the element data dictionary.
|
205
|
+
#
|
206
|
+
# @note If a given tag doesn't return a dictionary match, the following values are assigned:
|
207
|
+
# * For private tags: name 'Private' and VR 'UN'
|
208
|
+
# * For unknown (non-private) tags: name 'Unknown' and VR 'UN'
|
209
|
+
# @param [String] tag an element's tag
|
210
|
+
# @return [Array<String, String>] the name and value representation corresponding to the given tag
|
211
|
+
#
|
212
|
+
def name_and_vr(tag)
|
213
|
+
de = element(tag)
|
214
|
+
return de.name, de.vr
|
215
|
+
end
|
216
|
+
|
217
|
+
# Identifies the UID that corresponds to the given value.
|
218
|
+
#
|
219
|
+
# @param [String] value the unique identifier value
|
220
|
+
# @return [UID, NilClass] a corresponding UID instance, or nil (if no match is made)
|
221
|
+
#
|
222
|
+
def uid(value)
|
223
|
+
@uids[value]
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
private
|
228
|
+
|
229
|
+
|
230
|
+
# Creates a list of possible 'range' tag candidates based on the given tag.
|
231
|
+
# Usually tags are uniquely defined in the DICOM dictionary, and the given
|
232
|
+
# tag can be matched directly. However, for a small set of known tags, the
|
233
|
+
# dictionary allows a range of tags to be associated with a specific
|
234
|
+
# entry. This method creates an array of candidate tags which are processed
|
235
|
+
# in order to match against these ranges.
|
236
|
+
#
|
237
|
+
# @param [String] tag the element tag
|
238
|
+
# @return [Array<String>] processed candidate tags
|
239
|
+
#
|
240
|
+
def range_candidates(tag)
|
241
|
+
[
|
242
|
+
"#{tag[0..3]},xxx#{tag[8]}", # 1000,xxxh
|
243
|
+
"#{tag[0..3]},xxxx", # 1010,xxxx
|
244
|
+
"#{tag[0..1]}xx,#{tag[5..8]}", # hhxx,hhhh
|
245
|
+
"#{tag[0..6]}x#{tag[8]}" # 0028,hhxh
|
246
|
+
]
|
247
|
+
end
|
248
|
+
|
249
|
+
# Matches a tag against the possible range tag candidates, and if no match
|
250
|
+
# is found, returns a dictionary element representing an unknown tag.
|
251
|
+
#
|
252
|
+
# @param [String] tag the element tag
|
253
|
+
# @return [DictionaryElement] a matched range element or an unknown element
|
254
|
+
#
|
255
|
+
def unknown_or_range_element(tag)
|
256
|
+
element = nil
|
257
|
+
range_candidates(tag).each do |range_candidate_tag|
|
258
|
+
if de = @elements[range_candidate_tag]
|
259
|
+
element = DictionaryElement.new(tag, de.name, de.vrs, de.vm, de.retired)
|
260
|
+
break
|
261
|
+
end
|
262
|
+
end
|
263
|
+
# If nothing was matched, we are facing an unknown (but not private) tag:
|
264
|
+
element ||= DictionaryElement.new(tag, 'Unknown', ['UN'], '1', '')
|
265
|
+
end
|
266
|
+
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|