dicom 0.8 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/{CHANGELOG → CHANGELOG.rdoc} +100 -52
- data/README.rdoc +126 -0
- data/lib/dicom.rb +13 -7
- data/lib/dicom/anonymizer.rb +129 -111
- data/lib/dicom/constants.rb +60 -10
- data/lib/dicom/d_client.rb +230 -157
- data/lib/dicom/d_library.rb +88 -8
- data/lib/dicom/d_object.rb +141 -149
- data/lib/dicom/d_read.rb +42 -36
- data/lib/dicom/d_server.rb +8 -10
- data/lib/dicom/d_write.rb +25 -46
- data/lib/dicom/dictionary.rb +1 -3
- data/lib/dicom/{data_element.rb → element.rb} +61 -49
- data/lib/dicom/elemental.rb +126 -0
- data/lib/dicom/file_handler.rb +18 -17
- data/lib/dicom/image_item.rb +844 -0
- data/lib/dicom/image_processor.rb +69 -0
- data/lib/dicom/image_processor_mini_magick.rb +74 -0
- data/lib/dicom/image_processor_r_magick.rb +102 -0
- data/lib/dicom/item.rb +21 -19
- data/lib/dicom/link.rb +64 -82
- data/lib/dicom/{super_parent.rb → parent.rb} +270 -39
- data/lib/dicom/ruby_extensions.rb +175 -3
- data/lib/dicom/sequence.rb +5 -6
- data/lib/dicom/stream.rb +37 -25
- data/lib/dicom/variables.rb +51 -0
- data/lib/dicom/version.rb +6 -0
- metadata +97 -29
- data/README +0 -100
- data/init.rb +0 -1
- data/lib/dicom/elements.rb +0 -82
- data/lib/dicom/super_item.rb +0 -696
@@ -1,17 +1,15 @@
|
|
1
|
-
# Copyright 2008-2010 Christoffer Lervag
|
2
|
-
|
3
1
|
module DICOM
|
4
2
|
|
5
3
|
# Super class which contains common code for all parent elements.
|
6
4
|
#
|
7
5
|
# === Inheritance
|
8
6
|
#
|
9
|
-
# Since all
|
7
|
+
# Since all parents inherit from this class, these methods are available to instances of the following classes:
|
10
8
|
# * DObject
|
11
9
|
# * Item
|
12
10
|
# * Sequence
|
13
11
|
#
|
14
|
-
class
|
12
|
+
class Parent
|
15
13
|
|
16
14
|
# Returns the specified child element.
|
17
15
|
# If the requested data element isn't found, nil is returned.
|
@@ -35,7 +33,7 @@ module DICOM
|
|
35
33
|
return @tags[tag]
|
36
34
|
end
|
37
35
|
|
38
|
-
# Adds a
|
36
|
+
# Adds a Element or Sequence instance to self (where self can be either a DObject or an Item).
|
39
37
|
#
|
40
38
|
# === Restrictions
|
41
39
|
#
|
@@ -43,28 +41,37 @@ module DICOM
|
|
43
41
|
#
|
44
42
|
# === Parameters
|
45
43
|
#
|
46
|
-
# * <tt>element</tt> -- An element (
|
44
|
+
# * <tt>element</tt> -- An element (Element or Sequence).
|
45
|
+
# * <tt>options</tt> -- A hash of parameters.
|
46
|
+
#
|
47
|
+
# === Options
|
48
|
+
#
|
49
|
+
# * <tt>:no_follow</tt> -- Boolean. If true, the method does not update the parent attribute of the child that is added.
|
47
50
|
#
|
48
51
|
# === Examples
|
49
52
|
#
|
50
53
|
# # Set a new patient's name to the DICOM object:
|
51
|
-
# obj.add(
|
54
|
+
# obj.add(Element.new("0010,0010", "John_Doe"))
|
52
55
|
# # Add a previously defined element roi_name to the first item in the following sequence:
|
53
|
-
# obj["3006,0020"][
|
56
|
+
# obj["3006,0020"][0].add(roi_name)
|
54
57
|
#
|
55
|
-
def add(element)
|
58
|
+
def add(element, options={})
|
56
59
|
unless element.is_a?(Item)
|
57
60
|
unless self.is_a?(Sequence)
|
61
|
+
# Does the element's binary value need to be reencoded?
|
62
|
+
reencode = true if element.is_a?(Element) && element.endian != stream.str_endian
|
58
63
|
# If we are replacing an existing Element, we need to make sure that this Element's parent value is erased before proceeding.
|
59
64
|
self[element.tag].parent = nil if exists?(element.tag)
|
60
65
|
# Add the element, and set its parent attribute:
|
61
66
|
@tags[element.tag] = element
|
62
|
-
element.parent = self
|
67
|
+
element.parent = self unless options[:no_follow]
|
68
|
+
# As the element has been moved in place, perform re-encode if indicated:
|
69
|
+
element.value = element.value if reencode
|
63
70
|
else
|
64
|
-
raise "A Sequence is
|
71
|
+
raise "A Sequence is only allowed to have Item elements added to it. Use add_item() instead if the intention is to add an Item."
|
65
72
|
end
|
66
73
|
else
|
67
|
-
raise "An Item is not allowed as a parameter to the add() method. Use add_item() instead."
|
74
|
+
raise ArgumentError, "An Item is not allowed as a parameter to the add() method. Use add_item() instead."
|
68
75
|
end
|
69
76
|
end
|
70
77
|
|
@@ -72,7 +79,8 @@ module DICOM
|
|
72
79
|
# If no existing Item is specified, an empty item will be added.
|
73
80
|
#
|
74
81
|
# === Notes
|
75
|
-
#
|
82
|
+
#
|
83
|
+
# * Items are specified by index (starting at 0) instead of a tag string!
|
76
84
|
#
|
77
85
|
# === Parameters
|
78
86
|
#
|
@@ -82,6 +90,7 @@ module DICOM
|
|
82
90
|
# === Options
|
83
91
|
#
|
84
92
|
# * <tt>:index</tt> -- Fixnum. If the Item is to be inserted at a specific index (Item number), this option parameter needs to set.
|
93
|
+
# * <tt>:no_follow</tt> -- Boolean. If true, the method does not update the parent attribute of the child that is added.
|
85
94
|
#
|
86
95
|
# === Examples
|
87
96
|
#
|
@@ -97,9 +106,9 @@ module DICOM
|
|
97
106
|
if options[:index]
|
98
107
|
# This Item will take a specific index, and all existing Items with index higher or equal to this number will have their index increased by one.
|
99
108
|
# Check if index is valid (must be an existing index):
|
100
|
-
if options[:index] >=
|
109
|
+
if options[:index] >= 0
|
101
110
|
# If the index value is larger than the max index present, we dont need to modify the existing items.
|
102
|
-
|
111
|
+
if options[:index] < @tags.length
|
103
112
|
# Extract existing Hash entries to an array:
|
104
113
|
pairs = @tags.sort
|
105
114
|
@tags = Hash.new
|
@@ -114,27 +123,29 @@ module DICOM
|
|
114
123
|
end
|
115
124
|
else
|
116
125
|
# Set the index value one higher than the already existing max value:
|
117
|
-
options[:index] = @tags.length
|
126
|
+
options[:index] = @tags.length
|
118
127
|
end
|
119
128
|
#,Add the new Item and set its index:
|
120
129
|
@tags[options[:index]] = item
|
121
130
|
item.index = options[:index]
|
122
131
|
else
|
123
|
-
raise "The specified index (#{options[:index]}) is out of range (
|
132
|
+
raise ArgumentError, "The specified index (#{options[:index]}) is out of range (Must be a positive integer)."
|
124
133
|
end
|
125
134
|
else
|
126
135
|
# Add the existing Item to this Sequence:
|
127
|
-
index = @tags.length
|
136
|
+
index = @tags.length
|
128
137
|
@tags[index] = item
|
129
138
|
# Let the Item know what index key it's got in it's parent's Hash:
|
130
139
|
item.index = index
|
131
140
|
end
|
141
|
+
# Set ourself as this item's new parent:
|
142
|
+
item.set_parent(self) unless options[:no_follow]
|
132
143
|
else
|
133
|
-
raise "The specified parameter is not an Item. Only Items are allowed to be added to a Sequence."
|
144
|
+
raise ArgumentError, "The specified parameter is not an Item. Only Items are allowed to be added to a Sequence."
|
134
145
|
end
|
135
146
|
else
|
136
147
|
# Create an empty Item with self as parent.
|
137
|
-
index = @tags.length
|
148
|
+
index = @tags.length
|
138
149
|
item = Item.new(:parent => self)
|
139
150
|
end
|
140
151
|
else
|
@@ -193,7 +204,50 @@ module DICOM
|
|
193
204
|
return total_count
|
194
205
|
end
|
195
206
|
|
196
|
-
#
|
207
|
+
# Iterates the children of this parent, calling <tt>block</tt> for each child.
|
208
|
+
#
|
209
|
+
def each(&block)
|
210
|
+
children.each_with_index(&block)
|
211
|
+
end
|
212
|
+
|
213
|
+
# Iterates the child elements of this parent, calling <tt>block</tt> for each element.
|
214
|
+
#
|
215
|
+
def each_element(&block)
|
216
|
+
elements.each_with_index(&block) if children?
|
217
|
+
end
|
218
|
+
|
219
|
+
# Iterates the child items of this parent, calling <tt>block</tt> for each item.
|
220
|
+
#
|
221
|
+
def each_item(&block)
|
222
|
+
items.each_with_index(&block) if children?
|
223
|
+
end
|
224
|
+
|
225
|
+
# Iterates the child sequences of this parent, calling <tt>block</tt> for each sequence.
|
226
|
+
#
|
227
|
+
def each_sequence(&block)
|
228
|
+
sequences.each_with_index(&block) if children?
|
229
|
+
end
|
230
|
+
|
231
|
+
# Iterates the child tags of this parent, calling <tt>block</tt> for each tag.
|
232
|
+
#
|
233
|
+
def each_tag(&block)
|
234
|
+
@tags.each_key(&block)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Returns all child elements of this parent in an array.
|
238
|
+
# If no child elements exists, returns an empty array.
|
239
|
+
#
|
240
|
+
def elements
|
241
|
+
children.select { |child| child.is_a?(Element)}
|
242
|
+
end
|
243
|
+
|
244
|
+
# A boolean which indicates whether the parent has any child elements.
|
245
|
+
#
|
246
|
+
def elements?
|
247
|
+
elements.any?
|
248
|
+
end
|
249
|
+
|
250
|
+
# Re-encodes the binary data strings of all child Element instances.
|
197
251
|
# This also includes all the elements contained in any possible child elements.
|
198
252
|
#
|
199
253
|
# === Notes
|
@@ -210,7 +264,7 @@ module DICOM
|
|
210
264
|
children.each do |element|
|
211
265
|
if element.children?
|
212
266
|
element.encode_children(old_endian)
|
213
|
-
elsif element.is_a?(
|
267
|
+
elsif element.is_a?(Element)
|
214
268
|
encode_child(element, old_endian)
|
215
269
|
end
|
216
270
|
end
|
@@ -221,7 +275,7 @@ module DICOM
|
|
221
275
|
#
|
222
276
|
# === Parameters
|
223
277
|
#
|
224
|
-
# * <tt>tag</tt> -- A tag string which identifies the data element that is queried (Exception: In the case of an Item query, an index
|
278
|
+
# * <tt>tag</tt> -- A tag string which identifies the data element that is queried (Exception: In the case of an Item query, an index integer is used instead).
|
225
279
|
#
|
226
280
|
# === Examples
|
227
281
|
#
|
@@ -243,6 +297,7 @@ module DICOM
|
|
243
297
|
# * <tt>group_string</tt> -- A group string (the first 4 characters of a tag string).
|
244
298
|
#
|
245
299
|
def group(group_string)
|
300
|
+
raise ArgumentError, "Expected String, got #{group_string.class}." unless group_string.is_a?(String)
|
246
301
|
found = Array.new
|
247
302
|
children.each do |child|
|
248
303
|
found << child if child.tag.group == group_string
|
@@ -290,7 +345,7 @@ module DICOM
|
|
290
345
|
# Formatting: Name (and Tag)
|
291
346
|
if element.tag == ITEM_TAG
|
292
347
|
# Add index numbers to the Item names:
|
293
|
-
name = "#{element.name} (\##{i
|
348
|
+
name = "#{element.name} (\##{i})"
|
294
349
|
else
|
295
350
|
name = element.name
|
296
351
|
end
|
@@ -301,7 +356,7 @@ module DICOM
|
|
301
356
|
# Formatting: Length
|
302
357
|
l_s = s*(max_length-element.length.to_s.length)
|
303
358
|
# Formatting Value:
|
304
|
-
if element.is_a?(
|
359
|
+
if element.is_a?(Element)
|
305
360
|
value = element.value.to_s
|
306
361
|
else
|
307
362
|
value = ""
|
@@ -344,6 +399,12 @@ module DICOM
|
|
344
399
|
return elements.flatten, index
|
345
400
|
end
|
346
401
|
|
402
|
+
# Returns a string containing a human-readable hash representation of the element.
|
403
|
+
#
|
404
|
+
def inspect
|
405
|
+
to_hash.inspect
|
406
|
+
end
|
407
|
+
|
347
408
|
# Checks if an element is a parent.
|
348
409
|
# Returns true for all parent elements.
|
349
410
|
#
|
@@ -351,8 +412,74 @@ module DICOM
|
|
351
412
|
return true
|
352
413
|
end
|
353
414
|
|
415
|
+
# Returns all child items of this parent in an array.
|
416
|
+
# If no child items exists, returns an empty array.
|
417
|
+
#
|
418
|
+
def items
|
419
|
+
children.select { |child| child.is_a?(Item)}
|
420
|
+
end
|
421
|
+
|
422
|
+
# A boolean which indicates whether the parent has any child items.
|
423
|
+
#
|
424
|
+
def items?
|
425
|
+
items.any?
|
426
|
+
end
|
427
|
+
|
428
|
+
# Handles missing methods, which in our case is intended to be dynamic
|
429
|
+
# method names matching DICOM elements in the dictionary.
|
430
|
+
#
|
431
|
+
# === Notes
|
432
|
+
#
|
433
|
+
# * When a dynamic method name is matched against a DICOM element, this method:
|
434
|
+
# * Returns the element if the method name suggests an element retrieval, and the element exists.
|
435
|
+
# * Returns nil if the method name suggests an element retrieval, but the element doesn't exist.
|
436
|
+
# * Returns a boolean, if the method name suggests a query (?), based on whether the matched element exists or not.
|
437
|
+
# * When the method name suggests assignment (=), an element is created with the supplied arguments, or if the argument is nil, the element is removed.
|
438
|
+
#
|
439
|
+
# * When a dynamic method name is not matched against a DICOM element, and the method is not defined by the parent, a NoMethodError is raised.
|
440
|
+
#
|
441
|
+
# === Parameters
|
442
|
+
#
|
443
|
+
# * <tt>sym</tt> -- Symbol. A method name.
|
444
|
+
#
|
445
|
+
def method_missing(sym, *args, &block)
|
446
|
+
# Try to match the method against a tag from the dictionary:
|
447
|
+
tag = LIBRARY.as_tag(sym.to_s) || LIBRARY.as_tag(sym.to_s[0..-2])
|
448
|
+
if tag
|
449
|
+
if sym.to_s[-1..-1] == '?'
|
450
|
+
# Query:
|
451
|
+
return self.exists?(tag)
|
452
|
+
elsif sym.to_s[-1..-1] == '='
|
453
|
+
# Assignment:
|
454
|
+
unless args.length==0 || args[0].nil?
|
455
|
+
# What kind of element to create?
|
456
|
+
if tag == "FFFE,E000"
|
457
|
+
return self.add_item
|
458
|
+
elsif LIBRARY.tags[tag][0][0] == "SQ"
|
459
|
+
return self.add(Sequence.new(tag))
|
460
|
+
else
|
461
|
+
return self.add(Element.new(tag, *args))
|
462
|
+
end
|
463
|
+
else
|
464
|
+
return self.remove(tag)
|
465
|
+
end
|
466
|
+
else
|
467
|
+
# Retrieval:
|
468
|
+
return self[tag] rescue nil
|
469
|
+
end
|
470
|
+
end
|
471
|
+
# Forward to Object#method_missing:
|
472
|
+
super
|
473
|
+
end
|
474
|
+
|
354
475
|
# Sets the length of a Sequence or Item.
|
355
476
|
#
|
477
|
+
# === Notes
|
478
|
+
#
|
479
|
+
# Currently, Ruby DICOM does not use sequence/item lengths when writing DICOM files
|
480
|
+
# (it sets the length to -1, which means UNDEFINED). Therefore, in practice, it isn't
|
481
|
+
# necessary to use this method, at least as far as writing (valid) DICOM files is concerned.
|
482
|
+
#
|
356
483
|
# === Parameters
|
357
484
|
#
|
358
485
|
# * <tt>new_length</tt> -- Fixnum. The new length to assign to the Sequence/Item.
|
@@ -368,6 +495,7 @@ module DICOM
|
|
368
495
|
# Prints all child elements of this particular parent.
|
369
496
|
# Information such as tag, parent-child relationship, name, vr, length and value is gathered for each data element
|
370
497
|
# and processed to produce a nicely formatted output.
|
498
|
+
# Returns an array of formatted data elements.
|
371
499
|
#
|
372
500
|
# === Parameters
|
373
501
|
#
|
@@ -392,6 +520,7 @@ module DICOM
|
|
392
520
|
# FIXME: Speed. The new print algorithm may seem to be slower than the old one (observed on complex, hiearchical DICOM files). Perhaps it can be optimized?
|
393
521
|
#
|
394
522
|
def print(options={})
|
523
|
+
elements = Array.new
|
395
524
|
# We first gather some properties that is necessary to produce a nicely formatted printout (max_lengths, count_all),
|
396
525
|
# then the actual information is gathered (handle_print),
|
397
526
|
# and lastly, we pass this information on to the methods which print the output (print_file or print_screen).
|
@@ -408,6 +537,7 @@ module DICOM
|
|
408
537
|
else
|
409
538
|
puts "Notice: Object #{self} is empty (contains no data elements)!"
|
410
539
|
end
|
540
|
+
return elements
|
411
541
|
end
|
412
542
|
|
413
543
|
# Finds and returns the maximum character lengths of name and length which occurs for any child element,
|
@@ -446,23 +576,42 @@ module DICOM
|
|
446
576
|
# === Parameters
|
447
577
|
#
|
448
578
|
# * <tt>tag</tt> -- A tag string which specifies the element to be removed (Exception: In the case of an Item removal, an index (Fixnum) is used instead).
|
579
|
+
# * <tt>options</tt> -- A hash of parameters.
|
580
|
+
#
|
581
|
+
# === Options
|
582
|
+
#
|
583
|
+
# * <tt>:no_follow</tt> -- Boolean. If true, the method does not update the parent attribute of the child that is removed.
|
449
584
|
#
|
450
585
|
# === Examples
|
451
586
|
#
|
452
|
-
# # Remove a
|
587
|
+
# # Remove a Element from a DObject instance:
|
453
588
|
# obj.remove("0008,0090")
|
454
589
|
# # Remove Item 1 from a specific Sequence:
|
455
590
|
# obj["3006,0020"].remove(1)
|
456
591
|
#
|
457
|
-
def remove(tag)
|
592
|
+
def remove(tag, options={})
|
593
|
+
if tag.is_a?(String) or tag.is_a?(Integer)
|
594
|
+
raise ArgumentError, "Argument (#{tag}) is not a valid tag string." if tag.is_a?(String) && !tag.tag?
|
595
|
+
raise ArgumentError, "Negative Integer argument (#{tag}) is not allowed." if tag.is_a?(Integer) && tag < 0
|
596
|
+
else
|
597
|
+
raise ArgumentError, "Expected String or Integer, got #{tag.class}."
|
598
|
+
end
|
458
599
|
# We need to delete the specified child element's parent reference in addition to removing it from the tag Hash.
|
459
600
|
element = @tags[tag]
|
460
601
|
if element
|
461
|
-
element.parent = nil
|
602
|
+
element.parent = nil unless options[:no_follow]
|
462
603
|
@tags.delete(tag)
|
463
604
|
end
|
464
605
|
end
|
465
606
|
|
607
|
+
# Removes all child elements from this parent.
|
608
|
+
#
|
609
|
+
def remove_children
|
610
|
+
@tags.each_key do |tag|
|
611
|
+
remove(tag)
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
466
615
|
# Removes all data elements of the specified group from this parent.
|
467
616
|
#
|
468
617
|
# === Parameters
|
@@ -509,29 +658,112 @@ module DICOM
|
|
509
658
|
end
|
510
659
|
end
|
511
660
|
|
512
|
-
# Returns the
|
661
|
+
# Returns true if the parent responds to the given method (symbol) (method is defined).
|
662
|
+
# Returns false if the method is not defined.
|
663
|
+
#
|
664
|
+
# === Parameters
|
665
|
+
#
|
666
|
+
# * <tt>method</tt> -- Symbol. A method name who's response is tested.
|
667
|
+
# * <tt>include_private</tt> -- (Not used by ruby-dicom) Boolean. If true, private methods are included in the search.
|
668
|
+
#
|
669
|
+
def respond_to?(method, include_private=false)
|
670
|
+
# Check the library for a tag corresponding to the given method name symbol:
|
671
|
+
return true unless LIBRARY.as_tag(method.to_s).nil?
|
672
|
+
# In case of a query (xxx?) or assign (xxx=), remove last character and try again:
|
673
|
+
return true unless LIBRARY.as_tag(method.to_s[0..-2]).nil?
|
674
|
+
# Forward to Object#respond_to?:
|
675
|
+
super
|
676
|
+
end
|
677
|
+
|
678
|
+
# Returns all child sequences of this parent in an array.
|
679
|
+
# If no child sequences exists, returns an empty array.
|
680
|
+
#
|
681
|
+
def sequences
|
682
|
+
children.select { |child| child.is_a?(Sequence) }
|
683
|
+
end
|
684
|
+
|
685
|
+
# A boolean which indicates whether the parent has any child sequences.
|
686
|
+
#
|
687
|
+
def sequences?
|
688
|
+
sequences.any?
|
689
|
+
end
|
690
|
+
|
691
|
+
# Builds and returns a nested hash containing all children of this parent.
|
692
|
+
# Keys are determined by the key_representation attribute, and data element values are used as values.
|
693
|
+
#
|
694
|
+
# === Notes
|
695
|
+
#
|
696
|
+
# * For private elements, the tag is used for key instead of the key representation, as private tags lacks names.
|
697
|
+
# * For child-less parents, the key_representation attribute is used as value.
|
698
|
+
#
|
699
|
+
def to_hash
|
700
|
+
as_hash = Hash.new
|
701
|
+
unless children?
|
702
|
+
if self.is_a?(DObject)
|
703
|
+
as_hash = {}
|
704
|
+
else
|
705
|
+
as_hash[(self.tag.private?) ? self.tag : self.send(DICOM.key_representation)] = nil
|
706
|
+
end
|
707
|
+
else
|
708
|
+
children.each do |child|
|
709
|
+
if child.tag.private?
|
710
|
+
hash_key = child.tag
|
711
|
+
elsif child.is_a?(Item)
|
712
|
+
hash_key = "Item #{child.index}"
|
713
|
+
else
|
714
|
+
hash_key = child.send(DICOM.key_representation)
|
715
|
+
end
|
716
|
+
if child.is_a?(Element)
|
717
|
+
as_hash[hash_key] = child.to_hash[hash_key]
|
718
|
+
else
|
719
|
+
as_hash[hash_key] = child.to_hash
|
720
|
+
end
|
721
|
+
end
|
722
|
+
end
|
723
|
+
return as_hash
|
724
|
+
end
|
725
|
+
|
726
|
+
# Returns a json string containing a human-readable representation of the element.
|
727
|
+
#
|
728
|
+
def to_json
|
729
|
+
to_hash.to_json
|
730
|
+
end
|
731
|
+
|
732
|
+
# Returns a yaml string containing a human-readable representation of the element.
|
733
|
+
#
|
734
|
+
def to_yaml
|
735
|
+
to_hash.to_yaml
|
736
|
+
end
|
737
|
+
|
738
|
+
# Returns the value of a specific Element child of this parent.
|
513
739
|
# Returns nil if the child element does not exist.
|
514
740
|
#
|
515
741
|
# === Notes
|
516
742
|
#
|
517
|
-
# * Only
|
743
|
+
# * Only Element instances have values. Parent elements like Sequence and Item have no value themselves.
|
518
744
|
# If the specified <tt>tag</tt> is that of a parent element, <tt>value()</tt> will raise an exception.
|
519
745
|
#
|
520
746
|
# === Parameters
|
521
747
|
#
|
522
|
-
# * <tt>tag</tt> -- A tag string which identifies the child
|
748
|
+
# * <tt>tag</tt> -- A tag string which identifies the child Element.
|
523
749
|
#
|
524
750
|
# === Examples
|
525
751
|
#
|
526
752
|
# # Get the patient's name value:
|
527
753
|
# name = obj.value("0010,0010")
|
528
754
|
# # Get the Frame of Reference UID from the first item in the Referenced Frame of Reference Sequence:
|
529
|
-
# uid = obj["3006,0010"][
|
755
|
+
# uid = obj["3006,0010"][0].value("0020,0052")
|
530
756
|
#
|
531
757
|
def value(tag)
|
758
|
+
if tag.is_a?(String) or tag.is_a?(Integer)
|
759
|
+
raise ArgumentError, "Argument (#{tag}) is not a valid tag string." if tag.is_a?(String) && !tag.tag?
|
760
|
+
raise ArgumentError, "Negative Integer argument (#{tag}) is not allowed." if tag.is_a?(Integer) && tag < 0
|
761
|
+
else
|
762
|
+
raise ArgumentError, "Expected String or Integer, got #{tag.class}."
|
763
|
+
end
|
532
764
|
if exists?(tag)
|
533
765
|
if @tags[tag].is_parent?
|
534
|
-
raise "Illegal parameter '#{tag}'. Parent elements, like the referenced '#{@tags[tag].class}', have no value. Only
|
766
|
+
raise ArgumentError, "Illegal parameter '#{tag}'. Parent elements, like the referenced '#{@tags[tag].class}', have no value. Only Element tags are valid."
|
535
767
|
else
|
536
768
|
return @tags[tag].value
|
537
769
|
end
|
@@ -545,12 +777,12 @@ module DICOM
|
|
545
777
|
private
|
546
778
|
|
547
779
|
|
548
|
-
# Re-encodes the value of a child
|
780
|
+
# Re-encodes the value of a child Element (but only if the Element encoding is
|
549
781
|
# influenced by a shift in endianness).
|
550
782
|
#
|
551
783
|
# === Parameters
|
552
784
|
#
|
553
|
-
# * <tt>element</tt> -- The
|
785
|
+
# * <tt>element</tt> -- The Element who's value will be re-encoded.
|
554
786
|
# * <tt>old_endian</tt> -- The previous endianness of the element binary (used for decoding the value).
|
555
787
|
#
|
556
788
|
#--
|
@@ -565,14 +797,13 @@ module DICOM
|
|
565
797
|
else
|
566
798
|
# Not all types of tags needs to be reencoded when switching endianness:
|
567
799
|
case element.vr
|
568
|
-
when "US", "SS", "UL", "SL", "FL", "FD", "OF", "OW" # Numbers
|
800
|
+
when "US", "SS", "UL", "SL", "FL", "FD", "OF", "OW", "AT" # Numbers or tag reference
|
569
801
|
# Re-encode, as long as it is not a group 0002 element (which must always be little endian):
|
570
802
|
unless element.tag.group == "0002"
|
571
803
|
stream_old_endian = Stream.new(element.bin, old_endian)
|
572
|
-
|
573
|
-
element.value =
|
804
|
+
formatted_value = stream_old_endian.decode(element.length, element.vr)
|
805
|
+
element.value = formatted_value # (the value=() method also encodes a new binary for the element)
|
574
806
|
end
|
575
|
-
#when "AT" # Tag reference
|
576
807
|
end
|
577
808
|
end
|
578
809
|
end
|