dicom 0.8 → 0.9
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.
- 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
|