dicom 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,8 +2,10 @@ module DICOM
2
2
  # Class for reading the data from a DICOM file:
3
3
  class DRead
4
4
 
5
+ attr_reader :success
6
+
5
7
  # Initialize the DRead instance.
6
- def initialize(file_name)
8
+ def initialize(file_name=nil, lib=nil)
7
9
  # Variables that hold data that will be returned to the person/procedure using this class:
8
10
  # Arrays that will hold information from the DICOM file:
9
11
  @names = Array.new()
@@ -12,6 +14,8 @@ module DICOM
12
14
  @lengths = Array.new()
13
15
  @values = Array.new()
14
16
  @raw = Array.new()
17
+ # Array that will holde any messages generated while reading the DICOM file:
18
+ @msg = Array.new()
15
19
  # Explicitness (explicit (true) by default):
16
20
  @explicit = true
17
21
  # Explicitness of the remaining groups after the first group:
@@ -40,12 +44,26 @@ module DICOM
40
44
  else
41
45
  @endian = false
42
46
  end
47
+ # A length variable will be used at the end to check whether the last tag was read correctly, or whether the file endend unexpectedly:
48
+ @data_length = 0
49
+ # Variable used to tell whether file was read succesfully or not:
50
+ @success = false
43
51
 
44
52
  # Open file for binary reading:
45
- @file = File.new(file_name, "rb")
53
+ begin
54
+ @file = File.new(file_name, "rb")
55
+ rescue
56
+ @msg += ["Error! Could not open file: "+ file_name + " Returning."]
57
+ return
58
+ end
46
59
 
47
- # Establish relationship between tag adress and name:
48
- load_library()
60
+ # Load the library class (DICOM dictionary):
61
+ if lib != nil
62
+ # Library already specified by user:
63
+ @lib = lib
64
+ else
65
+ @lib = DLibrary.new()
66
+ end
49
67
 
50
68
  # Read the initial header of the file:
51
69
  header=check_header()
@@ -69,18 +87,25 @@ module DICOM
69
87
  @raw+=[tag[5]]
70
88
  end
71
89
  end
90
+ @success = true
72
91
  # Check the status of the pixel data:
73
92
  check_pixel_status()
74
93
  # Index of last element in tag arrays:
75
94
  @lastIndex=@names.length-1
76
95
  # Close the file as we are finished reading it:
77
96
  @file.close()
97
+ # Check if the last tag was read out correctly (that the length of its data corresponds to that expected by the length specified in the DICOM file):
98
+ if @data_length != @lengths[@lastIndex]
99
+ @msg += ["Error! The data content read from file does not match the length specified for the tag "+ @labels[@lastIndex] + ". It seems this is not a valid DICOM file. Returning."]
100
+ @success = false
101
+ return
102
+ end
78
103
  end
79
104
 
80
105
 
81
106
  # Returns the relevant information gathered from the read dicom procedure.
82
107
  def return_data()
83
- return [@names,@labels,@types,@lengths,@values,@raw,@compression,@color,@explicit, @file_endian]
108
+ return [@names,@labels,@types,@lengths,@values,@raw,@compression,@color,@explicit, @file_endian, @msg]
84
109
  end
85
110
 
86
111
 
@@ -97,8 +122,8 @@ module DICOM
97
122
  str_header2=bin2.unpack('a' * 4).to_s
98
123
  # If we dont have this expected header, we will still try to read it is a DICOM file.
99
124
  if str_header2 != 'DICM' then
100
- puts "Warning: The specified file does not contain the official DICOM header."
101
- puts "Will try to read the file anyway, as some sources are known to skip the formal DICOM header."
125
+ @msg+=["Warning: The specified file does not contain the official DICOM header."]
126
+ @msg+=["Will try to read the file anyway, as some sources are known to skip the formal DICOM header."]
102
127
  # Some DICOM files skips group 2, which defines the structure of the DICOM file.
103
128
  # This has only been observed in files that also skips the above part of the DICOM header.
104
129
  # Check for skipped group 0002:
@@ -119,7 +144,7 @@ module DICOM
119
144
  @file_endian = false
120
145
  @rest_endian = false
121
146
  @compression = false
122
- puts "Warning: Group '0002' Transfer Syntax does not exist. Assuming Implicit, Little Endian."
147
+ @msg+=["Warning: Group '0002' Transfer Syntax does not exist. Assuming Implicit VR, Little Endian."]
123
148
  end
124
149
  return false
125
150
  else
@@ -132,13 +157,13 @@ module DICOM
132
157
  # Modifies instance variable @color if color image is detected and instance variable @compression if no pixel data is detected.
133
158
  def check_pixel_status()
134
159
  # Check if pixel data is present:
135
- pixel_pos = @labels.index("7FE0.0010")
160
+ pixel_pos = @labels.index("7FE0,0010")
136
161
  if pixel_pos == nil
137
162
  @compression = nil
138
163
  return
139
164
  end
140
165
  # Check for color image:
141
- col_string = get_value("0028.0004")
166
+ col_string = get_value("0028,0004")
142
167
  if col_string != false
143
168
  if (col_string.include? "RGB") or (col_string.include? "COLOR") or (col_string.include? "COLOUR")
144
169
  @color = true
@@ -149,24 +174,30 @@ module DICOM
149
174
 
150
175
  # Governs the process of reading tags in the DICOM file.
151
176
  def process_tag()
152
- #STEP 1:
153
- # Read the tag label, but do stop reading if indicated by this method.
177
+ #STEP 1: ------------------------------------------------------
178
+ # Read the tag label, but exit if the method signals that we have reached end of file:
154
179
  @content = true
155
- res=read_label()
156
- if res == false
180
+ label=read_label()
181
+ if label == false
157
182
  return false
158
183
  end
159
- if @content == false
184
+ if @content == false # PS: @content switch is not active atm it seems!
160
185
  return
161
186
  end
162
- # As we have a valid tag, extract the two pieces of information:
163
- label=res[0]
164
- pos=res[1]
165
- # STEP 2:
187
+ # Retrieve the tag name and type based on the label we have read from file:
188
+ lib_data = @lib.get_name_vr(label)
189
+ name = lib_data[0]
190
+ vr = lib_data[1]
191
+ if vr == "UN"
192
+ @unknown = true
193
+ else
194
+ @unknown = false
195
+ end
196
+ # STEP 2: ----------------------------------------------------
166
197
  # Continue reading the tag information: Byte type and length.
167
- res=read_type_length(pos,label)
168
- type=res[0]
169
- length=res[1]
198
+ tag_info = read_type_length(vr,label)
199
+ type = tag_info[0]
200
+ length = tag_info[1]
170
201
  # For sequence type tag, check if the tag have length specified:
171
202
  if type == "SQ"
172
203
  if length == "UNDEFINED" or length.to_i == 0
@@ -177,7 +208,7 @@ module DICOM
177
208
  end
178
209
  # If length is undefined, do not continue to read tag data:
179
210
  if length == "UNDEFINED"
180
- if label == "7FE0.0010"
211
+ if label == "7FE0,0010"
181
212
  data = "(Encapsulated pixel data)"
182
213
  name = "Encapsulated image"
183
214
  else
@@ -186,39 +217,40 @@ module DICOM
186
217
  end
187
218
  return [name,label,type,length,data]
188
219
  end
189
- # Item related tags:
220
+ # Some special handling for item related tags:
190
221
  if type == "()"
191
- # Get name ("Item"):
192
- name = get_name(pos)
193
222
  # If length is zero, just return:
194
223
  if length == 0
195
224
  type = ""
196
225
  data = nil
226
+ @data_length = 0
197
227
  return [name,label,type,length,data]
198
228
  else
199
229
  # If there is content, this may, in the case of an image, be the image data.
200
230
  # Must insert the image's type here.
201
231
  # Some times when this tag has a length, it does not have content in itself, but instead
202
232
  # have content in a number of subtags.
203
- if @sq_length == true
204
- # Do nothing (keep the type as "()")
205
- else
233
+ if @sq_length != true
206
234
  # Treat the item as containing image data:
207
235
  type = "OW" # A more general approach should be implemented here.
208
236
  end
209
237
  end
210
238
  end
211
- # STEP 3:
239
+ # STEP 3: ----------------------------------------
212
240
  # Finally read the tag data.
213
241
  if @content == true
214
- res=read_data(type,length,pos)
215
- value = res[0]
216
- raw = res[1]
217
- name=get_name(pos)
242
+ tag_data = read_data(type,length)
243
+ value = tag_data[0]
244
+ raw = tag_data[1]
218
245
  # Check for the Transfer Syntax UID tag, and process it:
219
- if label == "0002.0010"
246
+ if label == "0002,0010"
220
247
  process_syntax(value)
221
248
  end
249
+ if type == "SQ" or type == "()"
250
+ @data_length = length # To avoid false errors. In time perhaps a better way of handling this will be found.
251
+ else
252
+ @data_length = raw.length
253
+ end
222
254
  return [name,label,type,length,value,raw]
223
255
  end
224
256
  end
@@ -263,36 +295,24 @@ module DICOM
263
295
  end
264
296
  end
265
297
  # Join the label group and label element together to the final string:
266
- label=label1+'.'+label2
267
- # Find the position of this label in the array of library labels:
268
- pos=@lib_labels.index(label)
269
- # If no match found, this is an unknown header type. Inform the user:
270
- if pos == nil
271
- @unknown = true
272
- # For identifying additions needed in the library:
273
- #puts "Unknown header element: "+label
274
- else
275
- @unknown = false
276
- end
277
- # Return the label as well as the position of this label in the library:
278
- return [label,pos]
298
+ label=label1+","+label2
299
+ # Return the label:
300
+ return label
279
301
  end
280
302
  # END TAG LABEL
281
303
 
282
304
 
283
305
  # Reads and returns TAG TYPE (2 bytes) and TAG LENGTH (Varying length).
284
- def read_type_length(pos,label)
306
+ def read_type_length(type,label)
285
307
  # Structure will differ, dependent on whether we have explicit or implicit type of file:
286
- # Explicit:
308
+ # EXPLICIT:
287
309
  if @explicit == true
288
- # Unfortunately, it seems we need to have a special case for item labels in the explicit scenario:
289
- if label == "FFFE.E000" or label == "FFFE.E00D" or label == "FFFE.E0DD"
290
- # For the item related tag, get the special type from library, then read the 4 byte length:
291
- type = @lib_types[pos]
310
+ # It seems we need to have a special case for item labels in the explicit scenario:
311
+ if label == "FFFE,E000" or label == "FFFE,E00D" or label == "FFFE,E0DD"
292
312
  bin=@file.read(4)
293
313
  length = get_SL(bin)
294
314
  else
295
- # Read tag type field (2 bytes), as long as we are not dealing with an item related tag:
315
+ # Read tag type field (2 bytes - since we are not dealing with an item related tag):
296
316
  bin=@file.read(2)
297
317
  type=bin.unpack('a*').to_s
298
318
  end
@@ -301,32 +321,18 @@ module DICOM
301
321
  when "OB","OW","SQ","UN"
302
322
  # Two empty bytes should occur here, according to the standard:
303
323
  bin=@file.read(2)
304
- #length=bin.unpack('S*')[0]
305
- # However, it may occur (??) that the length appears in this slot, and subsequently,
306
- # the following 4 byte slot is not utilized:
307
- #if length != 0
308
324
  # Read value length (4 bytes):
309
325
  bin=@file.read(4)
310
326
  length=get_SL(bin)
311
- #end
312
327
  when "()"
313
328
  #An empty entry for the item related tags (As it has already been processed).
314
- # Do nothing.
315
- # For all the other tag types:
316
329
  else
317
- # Read value length (2 bytes):
330
+ # For all the other tag types: Read value length (2 bytes):
318
331
  bin=@file.read(2)
319
332
  length=get_US(bin)
320
333
  end
321
334
  else
322
- #Implicit:
323
- # If it is unknown, use the identifier "UN":
324
- if pos == nil
325
- type = "UN"
326
- else
327
- # Tag type is not specified in the file, try to retrieve it from the library:
328
- type = @lib_types[pos]
329
- end
335
+ #IMPLICIT:
330
336
  # Read value length (4 bytes):
331
337
  bin=@file.read(4)
332
338
  length = get_SL(bin)
@@ -337,8 +343,8 @@ module DICOM
337
343
  length = "UNDEFINED"
338
344
  elsif length%2 >0
339
345
  # According to the DICOM standard, all tag lengths should be an even number.
340
- # If it is not, there has probably been an error in the readout:
341
- puts "Warning: Odd number of bytes occured. This is a violation of the DICOM standard."
346
+ # If it is not, it may indicate a file that is not standards compliant or it might even not be a DICOM file.
347
+ @msg+=["Warning: Odd number of bytes in tag length occured. This is a violation of the DICOM standard, but program will attempt to continue reading the rest of the file."]
342
348
  end
343
349
  return [type,length]
344
350
  end
@@ -346,7 +352,7 @@ module DICOM
346
352
 
347
353
 
348
354
  # Reads and returns TAG DATA (Varying length - determined at an earlier stage).
349
- def read_data(type, length, pos)
355
+ def read_data(type, length)
350
356
  # Treatment dependent on what type of information we are dealing with.
351
357
  case type
352
358
 
@@ -355,69 +361,69 @@ module DICOM
355
361
  # them all in a string separated by "/".
356
362
  # Unsigned long: (4 bytes)
357
363
  when "UL"
364
+ bin = @file.read(length)
358
365
  if length <= 4
359
- bin = @file.read(length)
360
366
  data = get_UL(bin)
361
367
  else
362
- data = process_numbers(length, type, 4)
368
+ data = process_numbers(length, type, bin)
363
369
  end
364
370
 
365
371
  # Signed long: (4 bytes)
366
372
  when "SL"
373
+ bin = @file.read(length)
367
374
  if length <= 4
368
- bin = @file.read(length)
369
375
  data = get_SL(bin)
370
376
  else
371
- data = process_numbers(length, type, 4)
377
+ data = process_numbers(length, type, bin)
372
378
  end
373
379
 
374
380
  # Unsigned short: (2 bytes)
375
- when 'US'
381
+ when "US"
382
+ bin = @file.read(length)
376
383
  if length <= 2
377
- bin = @file.read(length)
378
384
  data = get_US(bin)
379
385
  else
380
- data = process_numbers(length, type, 2)
386
+ data = process_numbers(length, type, bin)
381
387
  end
382
388
 
383
389
  # Signed short: (2 bytes)
384
- when 'SS'
390
+ when "SS"
391
+ bin = @file.read(length)
385
392
  if length <= 2
386
- bin = @file.read(length)
387
393
  data = get_SS(bin)
388
394
  else
389
- data = process_numbers(length, type, 2)
395
+ data = process_numbers(length, type, bin)
390
396
  end
391
397
 
392
398
  # Floating point double: (8 bytes)
393
399
  when "FD"
400
+ bin = @file.read(length)
394
401
  if length <= 8
395
- bin = @file.read(length)
396
402
  data = get_FD(bin)
397
403
  else
398
- data = process_numbers(length, type, 8)
404
+ data = process_numbers(length, type, bin)
399
405
  end
400
406
 
401
407
  # Unknown information, header element is not recognised from local database:
402
- when 'UN'
408
+ when "UN"
403
409
  bin=@file.read(length)
404
410
  data=bin.unpack('H*')[0]
405
411
 
406
412
  # A tag that contains items/elements (sequence of elements):
407
- when 'SQ'
413
+ when "SQ"
408
414
  # The tag has no content in itself, the file starts directly on a new tag adress.
409
- data="(sequence of elements)"
415
+ data="(Sequence of Elements)"
410
416
 
411
417
  # Item tag:
412
- when '()'
418
+ when "()"
413
419
  # Tag may have a length, but no content belonging to this tag itself. They are to be read
414
420
  # for this item's subtags.
415
- data = "(Sequence of tags)"
421
+ data = "(Sequence of Tags)"
416
422
 
417
423
  # The tag contains a tag adress (4 bytes):
418
- when 'AT'
424
+ when "AT"
419
425
  if length != 4
420
- puts "warning: Unexpected tag length, expected 4 bytes for tag type 'AT'!"
426
+ @msg+=["Warning: Unexpected tag length, expected 4 bytes for tag type 'AT'!"]
421
427
  end
422
428
  temp=Array.new(4)
423
429
  4.times do |i|
@@ -428,18 +434,18 @@ module DICOM
428
434
  data=temp[1].to_s+temp[0].to_s+"."+temp[3].to_s+temp[2].to_s
429
435
  # This has not been tested with other than Little endian system/file:
430
436
  if @file_endian or @system_endian
431
- puts "Warning: Handling for tag type 'AT' has not been verified for other than default endianness."
437
+ @msg+=["Warning: Handling for tag type 'AT' has not been verified for other than default endianness."]
432
438
  end
433
439
 
434
440
  # Binary data, used sometimes when we have encapsulated images:
435
- when 'OB'
441
+ when "OB"
436
442
  bin=@file.read(length)
437
443
  data=bin.unpack('H*')[0]
438
444
 
439
445
  # Image data:
440
- when 'OW'
446
+ when "OW"
441
447
  # We need to know what kind of bith depth the pixel data is saved with:
442
- bit_depth=get_value('0028.0100')
448
+ bit_depth=get_value('0028,0100')
443
449
  # Proceed to read the image binary data:
444
450
  bin=@file.read(length)
445
451
  # Number of bytes used per pixel will determine how to unpack this:
@@ -451,8 +457,8 @@ module DICOM
451
457
  when 12
452
458
  # 12 BIT SIMPLY NOT WORKING YET!
453
459
  # This one is a bit more tricky to extract.
454
- # Unknown if really working.
455
- puts "Warning: Bit depth 12 is not working correctly at this time!"
460
+ # I havent really given this priority so far as 12 bit image data is rather rare.
461
+ @msg+=["Warning: Bit depth 12 is not working correctly at this time!"]
456
462
  data=Array.new(length)
457
463
  (length).times do |i|
458
464
  hex=bin.unpack('H3')
@@ -469,26 +475,17 @@ module DICOM
469
475
  bin=@file.read(length)
470
476
  data=bin.unpack('a*').to_s
471
477
  else
472
- puts "Warning: Tag type "+type+" does not have a reading method assigned to it. Please update the source code."
478
+ @msg+=["Warning: Tag type "+type+" does not have a reading method assigned to it. Please update the source code."]
473
479
  bin=@file.read(length)
474
480
  data=bin.unpack('H*')[0]
475
481
  end
482
+
483
+ # Return the data:
476
484
  return [data,bin]
477
485
  end
478
486
  # END TAG DATA
479
487
 
480
488
 
481
- # Returns tag name from library if tag is recognised, else returns 'Unknown Name'.
482
- def get_name(pos)
483
- if not @unknown
484
- str_name=@lib_names[pos]
485
- else
486
- str_name='Unknown Name'
487
- end
488
- return str_name
489
- end
490
-
491
-
492
489
  # Returns the (processed) value of a DICOM tag based on an input tag label, category name or array index.
493
490
  def get_value(id)
494
491
  # Assume we have been fed a tag label:
@@ -516,450 +513,9 @@ module DICOM
516
513
  end
517
514
 
518
515
 
519
- # Loads the library which links tag label with tag name and tag type.
520
- # (Note that this library is not complete, it is based on information from the DICOM files I have available.)
521
- # (TNV means type not verified with external source for the particular tag that these letters appear behind)
522
- def load_library()
523
- a=Array.new()
524
- b=Array.new()
525
- c=Array.new()
526
- a+=['0002.0000'] and b+=['UL'] and c+=['Group Length']
527
- a+=['0002.0001'] and b+=['OB'] and c+=['File Meta Information']
528
- a+=['0002.0002'] and b+=['UI'] and c+=['Media Storage SOP Class UID']
529
- a+=['0002.0003'] and b+=['UI'] and c+=['Media Storage SOP Instance UID']
530
- a+=['0002.0010'] and b+=['UI'] and c+=['Transfer Syntax UID']
531
- a+=['0002.0012'] and b+=['UI'] and c+=['Implementation Class UID']
532
- a+=['0002.0013'] and b+=['SH'] and c+=['Implementation Version Name']
533
- a+=['0002.0016'] and b+=['AE'] and c+=['Source Application Entity Title']
534
- a+=['0008.0000'] and b+=['UL'] and c+=['Group Length']
535
- a+=['0008.0005'] and b+=['CS'] and c+=['Specific Character Set']
536
- a+=['0008.0008'] and b+=['CS'] and c+=['Image Type']
537
- a+=['0008.0010'] and b+=['LO'] and c+=['Recognition Code'] #TNV
538
- a+=['0008.0012'] and b+=['DA'] and c+=['Instance Creation Date']
539
- a+=['0008.0013'] and b+=['TM'] and c+=['Instance Creation Time']
540
- a+=['0008.0014'] and b+=['UI'] and c+=['Instance Creator UID']
541
- a+=['0008.0016'] and b+=['UI'] and c+=['SOP Class UID']
542
- a+=['0008.0018'] and b+=['UI'] and c+=['SOP Instance UID']
543
- a+=['0008.0020'] and b+=['DA'] and c+=['Study Date']
544
- a+=['0008.0021'] and b+=['DA'] and c+=['Series Date']
545
- a+=['0008.0022'] and b+=['DA'] and c+=['Acquisition Date']
546
- a+=['0008.0023'] and b+=['DA'] and c+=['Image Date']
547
- a+=['0008.0030'] and b+=['TM'] and c+=['Study Time']
548
- a+=['0008.0031'] and b+=['TM'] and c+=['Series Time']
549
- a+=['0008.0032'] and b+=['TM'] and c+=['Acquisition Time']
550
- a+=['0008.0033'] and b+=['TM'] and c+=['Image Time']
551
- a+=['0008.0040'] and b+=['US'] and c+=['Data Set Type'] #TNV
552
- a+=['0008.0041'] and b+=['LO'] and c+=['Data Set Subtype'] #TNV
553
- a+=['0008.0050'] and b+=['SH'] and c+=['Accession Number']
554
- a+=['0008.0060'] and b+=['CS'] and c+=['Modality']
555
- a+=['0008.0064'] and b+=['CS'] and c+=['Conversion Type']
556
- a+=['0008.0070'] and b+=['LO'] and c+=['Manufacturer']
557
- a+=['0008.0080'] and b+=['LO'] and c+=['Institution Name']
558
- a+=['0008.0081'] and b+=['ST'] and c+=['Institution Address']
559
- a+=['0008.0090'] and b+=['PN'] and c+=['Referring Physician`s name']
560
- a+=['0008.0201'] and b+=['SH'] and c+=['Timezone Offset From UTC']
561
- a+=['0008.1010'] and b+=['SH'] and c+=['Station Name']
562
- a+=['0008.1030'] and b+=['LO'] and c+=['Study Description']
563
- a+=['0008.103E'] and b+=['LO'] and c+=['Series Description']
564
- a+=['0008.1040'] and b+=['LO'] and c+=['Institutional Department Name']
565
- a+=['0008.1050'] and b+=['PN'] and c+=['Performing Physician`s Name']
566
- a+=['0008.1060'] and b+=['PN'] and c+=['Name of Physician(s) Reading Study']
567
- a+=['0008.1070'] and b+=['PN'] and c+=['Operator`s name']
568
- a+=['0008.1080'] and b+=['LO'] and c+=['Admitting Diagnoses Description']
569
- a+=['0008.1090'] and b+=['LO'] and c+=['Manufacturer`s Model Name']
570
- a+=['0008.1140'] and b+=['SQ'] and c+=['Referenced Image Sequence']
571
- a+=['0008.1150'] and b+=['UI'] and c+=['Referenced SOP Class UID']
572
- a+=['0008.1155'] and b+=['UI'] and c+=['Referenced SOP Instance UID']
573
- a+=['0008.2120'] and b+=['SH'] and c+=['Stage Name']
574
- a+=['0008.2122'] and b+=['IS'] and c+=['Stage Number']
575
- a+=['0008.2124'] and b+=['IS'] and c+=['Number of Stages']
576
- a+=['0008.2128'] and b+=['IS'] and c+=['View Number']
577
- a+=['0008.212A'] and b+=['IS'] and c+=['Number of Views in Stage']
578
- a+=['0008.2204'] and b+=['CS'] and c+=['Transducer Orientation']
579
- a+=['0009.0000'] and b+=['UL'] and c+=['Group Length']
580
- a+=['0010.0000'] and b+=['UL'] and c+=['Group Length']
581
- a+=['0010.0010'] and b+=['PN'] and c+=['Patient`s Name']
582
- a+=['0010.0020'] and b+=['LO'] and c+=['Patient ID']
583
- a+=['0010.0030'] and b+=['DA'] and c+=['Patient`s Birth Date']
584
- a+=['0010.0040'] and b+=['CS'] and c+=['Patient`s Sex']
585
- a+=['0010.1000'] and b+=['LO'] and c+=['Other Patient IDs']
586
- a+=['0010.1005'] and b+=['PN'] and c+=['Patient`s Birth Name']
587
- a+=['0010.1010'] and b+=['AS'] and c+=['Patient`s Age']
588
- a+=['0010.1020'] and b+=['DS'] and c+=['Patient`s Size']
589
- a+=['0010.1030'] and b+=['DS'] and c+=['Patient`s Weight']
590
- a+=['0010.2160'] and b+=['SH'] and c+=['Ethnic Group']
591
- a+=['0010.21B0'] and b+=['LT'] and c+=['Additional Patient History']
592
- a+=['0010.4000'] and b+=['LT'] and c+=['Patient Comments']
593
- a+=['0018.0000'] and b+=['UL'] and c+=['Group Length']
594
- a+=['0018.0010'] and b+=['LO'] and c+=['Contrast/Bolus Agent']
595
- a+=['0018.0015'] and b+=['CS'] and c+=['Body Part Examined']
596
- a+=['0018.0020'] and b+=['CS'] and c+=['Scanning Sequence']
597
- a+=['0018.0021'] and b+=['CS'] and c+=['Sequence Variant']
598
- a+=['0018.0022'] and b+=['CS'] and c+=['Scan Options']
599
- a+=['0018.0023'] and b+=['CS'] and c+=['MR Acquisition Type']
600
- a+=['0018.0024'] and b+=['SH'] and c+=['Sequence Name']
601
- a+=['0018.0025'] and b+=['CS'] and c+=['Angio Flag']
602
- a+=['0018.0050'] and b+=['DS'] and c+=['Slice Thickness']
603
- a+=['0018.0060'] and b+=['DS'] and c+=['KVP']
604
- a+=['0018.0070'] and b+=['IS'] and c+=['Counts Accumulated']
605
- a+=['0018.0071'] and b+=['CS'] and c+=['Acquisition Termination Condition']
606
- a+=['0018.0080'] and b+=['DS'] and c+=['Repetition Time']
607
- a+=['0018.0081'] and b+=['DS'] and c+=['Echo Time']
608
- a+=['0018.0082'] and b+=['DS'] and c+=['Inversion Time']
609
- a+=['0018.0083'] and b+=['DS'] and c+=['Number of Averages']
610
- a+=['0018.0084'] and b+=['DS'] and c+=['Imaging Frequency']
611
- a+=['0018.0085'] and b+=['SH'] and c+=['Imaged Nucleus']
612
- a+=['0018.0086'] and b+=['IS'] and c+=['Echo Number(s)']
613
- a+=['0018.0087'] and b+=['DS'] and c+=['Magnetic Field Strength']
614
- a+=['0018.0088'] and b+=['DS'] and c+=['Spacing Between Slices']
615
- a+=['0018.0089'] and b+=['IS'] and c+=['Number of Phase Encoding Steps']
616
- a+=['0018.0090'] and b+=['DS'] and c+=['Data Collection Diameter']
617
- a+=['0018.0091'] and b+=['IS'] and c+=['Echo Train Length']
618
- a+=['0018.0093'] and b+=['DS'] and c+=['Percent Sampling']
619
- a+=['0018.0094'] and b+=['DS'] and c+=['Percent Phase Field of View']
620
- a+=['0018.0095'] and b+=['DS'] and c+=['Pixel Bandwidth']
621
- a+=['0018.1000'] and b+=['LO'] and c+=['Device Serial Number']
622
- a+=['0018.1004'] and b+=['LO'] and c+=['Plate ID']
623
- a+=['0018.1010'] and b+=['LO'] and c+=['Secondary Capture Device ID']
624
- a+=['0018.1012'] and b+=['DA'] and c+=['Date of Secondary Capture']
625
- a+=['0018.1014'] and b+=['TM'] and c+=['Time of Secondary Capture']
626
- a+=['0018.1018'] and b+=['LO'] and c+=['Secondary Capture Device Manufacturer`s Model Name']
627
- a+=['0018.1019'] and b+=['LO'] and c+=['Secondary Capture Device Software Version(s)']
628
- a+=['0018.1020'] and b+=['LO'] and c+=['Software Version(s)']
629
- a+=['0018.1030'] and b+=['LO'] and c+=['Protocol Name']
630
- a+=['0018.1041'] and b+=['DS'] and c+=['Contrast/Bolus Volume']
631
- a+=['0018.1044'] and b+=['DS'] and c+=['Contrast/Bolus Total Dose']
632
- a+=['0018.1050'] and b+=['DS'] and c+=['Spatial Resolution']
633
- a+=['0018.1062'] and b+=['IS'] and c+=['Nominal Interval']
634
- a+=['0018.1063'] and b+=['DS'] and c+=['Frame Time']
635
- a+=['0018.1081'] and b+=['IS'] and c+=['Low R-R Value']
636
- a+=['0018.1082'] and b+=['IS'] and c+=['High R-R Value']
637
- a+=['0018.1083'] and b+=['IS'] and c+=['Intervals Acquired']
638
- a+=['0018.1084'] and b+=['IS'] and c+=['Intervals Rejected']
639
- a+=['0018.1088'] and b+=['IS'] and c+=['Heart Rate']
640
- a+=['0018.1090'] and b+=['IS'] and c+=['Cardiac Number of Images']
641
- a+=['0018.1094'] and b+=['IS'] and c+=['Trigger Window']
642
- a+=['0018.1100'] and b+=['DS'] and c+=['Reconstruction Diameter']
643
- a+=['0018.1110'] and b+=['DS'] and c+=['Distance Source to Detector']
644
- a+=['0018.1111'] and b+=['DS'] and c+=['Distance Source to Patient']
645
- a+=['0018.1120'] and b+=['DS'] and c+=['Gantry/Detector Tilt']
646
- a+=['0018.1130'] and b+=['DS'] and c+=['Table Height']
647
- a+=['0018.1140'] and b+=['CS'] and c+=['Rotation Direction']
648
- a+=['0018.1149'] and b+=['IS'] and c+=['Field of View Dimension(s)']
649
- a+=['0018.1150'] and b+=['IS'] and c+=['Exposure Time']
650
- a+=['0018.1151'] and b+=['IS'] and c+=['X-ray Tube Current']
651
- a+=['0018.1152'] and b+=['IS'] and c+=['Exposure']
652
- a+=['0018.1155'] and b+=['CS'] and c+=['Radiation Setting']
653
- a+=['0018.1160'] and b+=['SH'] and c+=['Filter Type']
654
- a+=['0018.1164'] and b+=['DS'] and c+=['Image Pixel Spacing']
655
- a+=['0018.1170'] and b+=['IS'] and c+=['Generator Power']
656
- a+=['0018.1190'] and b+=['DS'] and c+=['Focal Spot(s)']
657
- a+=['0018.1200'] and b+=['DA'] and c+=['Date of Last Calibration']
658
- a+=['0018.1201'] and b+=['TM'] and c+=['Time of Last Calibration']
659
- a+=['0018.1210'] and b+=['SH'] and c+=['Convolution Kernel']
660
- a+=['0018.1250'] and b+=['SH'] and c+=['Receiving Coil']
661
- a+=['0018.1251'] and b+=['SH'] and c+=['Transmitting Coil']
662
- a+=['0018.1260'] and b+=['SH'] and c+=['Plate Type']
663
- a+=['0018.1261'] and b+=['LO'] and c+=['Phosphor Type']
664
- a+=['0018.1310'] and b+=['US'] and c+=['Acquisition Matrix']
665
- a+=['0018.1312'] and b+=['CS'] and c+=['Phase Encoding Direction']
666
- a+=['0018.1314'] and b+=['DS'] and c+=['Flip Angle']
667
- a+=['0018.1315'] and b+=['CS'] and c+=['Variable Flip Angle Flag']
668
- a+=['0018.1316'] and b+=['DS'] and c+=['SAR']
669
- a+=['0018.1318'] and b+=['DS'] and c+=['dB/dt']
670
- a+=['0018.1400'] and b+=['LO'] and c+=['Acquisition Device Processing Description']
671
- a+=['0018.1401'] and b+=['LO'] and c+=['Acquisition Device Processing Code']
672
- a+=['0018.1402'] and b+=['CS'] and c+=['Cassette Orientation']
673
- a+=['0018.1403'] and b+=['CS'] and c+=['Cassette Size']
674
- a+=['0018.1404'] and b+=['CS'] and c+=['Exposures on Plate']
675
- a+=['0018.1500'] and b+=['CS'] and c+=['Positioner Motion']
676
- a+=['0018.1510'] and b+=['DS'] and c+=['Positioner Primary Angle']
677
- a+=['0018.1511'] and b+=['DS'] and c+=['Positioner Secondary Angle']
678
- a+=['0018.5020'] and b+=['LO'] and c+=['Processing Function']
679
- a+=['0018.5100'] and b+=['CS'] and c+=['Patient Position']
680
- a+=['0018.5101'] and b+=['CS'] and c+=['View Position']
681
- a+=['0018.6000'] and b+=['DS'] and c+=['Sensitivity']
682
- a+=['0019.0000'] and b+=['UL'] and c+=['Group Length']
683
- a+=['0020.0000'] and b+=['UL'] and c+=['Group Length']
684
- a+=['0020.000D'] and b+=['UI'] and c+=['Study Instance UID']
685
- a+=['0020.000E'] and b+=['UI'] and c+=['Series Instance UID']
686
- a+=['0020.0010'] and b+=['SH'] and c+=['Study ID']
687
- a+=['0020.0011'] and b+=['IS'] and c+=['Series Number']
688
- a+=['0020.0012'] and b+=['IS'] and c+=['Acquisition Number']
689
- a+=['0020.0013'] and b+=['IS'] and c+=['Instance Number']
690
- a+=['0020.0020'] and b+=['CS'] and c+=['Patient Orientation']
691
- a+=['0020.0030'] and b+=['LO'] and c+=['Image Position'] #TNV
692
- a+=['0020.0035'] and b+=['LO'] and c+=['Image Orientation'] #TNV
693
- a+=['0020.0032'] and b+=['DS'] and c+=['Image Position (Patient)']
694
- a+=['0020.0037'] and b+=['DS'] and c+=['Image Orientation (Patient)']
695
- a+=['0020.0050'] and b+=['LO'] and c+=['Location'] #TNV
696
- a+=['0020.0052'] and b+=['UI'] and c+=['Frame of Reference UID']
697
- a+=['0020.0060'] and b+=['CS'] and c+=['Laterality']
698
- a+=['0020.0070'] and b+=['LO'] and c+=['Image Geometry Type'] #TNV
699
- a+=['0020.1001'] and b+=['LO'] and c+=['Acquisitions in Series'] #TNV
700
- a+=['0020.1002'] and b+=['IS'] and c+=['Images in Acquisition']
701
- a+=['0020.1020'] and b+=['LO'] and c+=['Reference'] #TNV
702
- a+=['0020.1040'] and b+=['LO'] and c+=['Position Reference Indicator']
703
- a+=['0020.1041'] and b+=['DS'] and c+=['Slice Location']
704
- a+=['0020.4000'] and b+=['LT'] and c+=['Image Comments']
705
- a+=['0020.5000'] and b+=['UL'] and c+=['Original Image Identification'] #TNV
706
- a+=['0020.5002'] and b+=['LO'] and c+=['Original Image Identification Nomenclature'] #TNV
707
- a+=['0021.0000'] and b+=['UL'] and c+=['Group Length']
708
- a+=['0023.0000'] and b+=['UL'] and c+=['Group Length']
709
- a+=['0027.0000'] and b+=['UL'] and c+=['Group Length']
710
- a+=['0028.0000'] and b+=['UL'] and c+=['Group Length']
711
- a+=['0028.0002'] and b+=['US'] and c+=['Samples per Pixel']
712
- a+=['0028.0004'] and b+=['CS'] and c+=['Photometric Interpretation']
713
- a+=['0028.0006'] and b+=['US'] and c+=['Planar Configuration']
714
- a+=['0028.0005'] and b+=['US'] and c+=['Image Dimensions'] #TNV
715
- a+=['0028.0008'] and b+=['IS'] and c+=['Number of Frames']
716
- a+=['0028.0009'] and b+=['AT'] and c+=['Frame Increment Pointer']
717
- a+=['0028.0010'] and b+=['US'] and c+=['Rows']
718
- a+=['0028.0011'] and b+=['US'] and c+=['Columns']
719
- a+=['0028.0030'] and b+=['DS'] and c+=['Pixel Spacing']
720
- a+=['0028.0034'] and b+=['IS'] and c+=['Pixel Aspect Ratio']
721
- a+=['0028.0040'] and b+=['LO'] and c+=['Image Format'] #TNV
722
- a+=['0028.0060'] and b+=['LO'] and c+=['Compression Code'] #TNV
723
- a+=['0028.0100'] and b+=['US'] and c+=['Bits Allocated']
724
- a+=['0028.0101'] and b+=['US'] and c+=['Bits Stored']
725
- a+=['0028.0102'] and b+=['US'] and c+=['High Bit']
726
- a+=['0028.0103'] and b+=['US'] and c+=['Pixel Representation']
727
- a+=['0028.0104'] and b+=['US'] and c+=['Smallest Valid Pixel Value'] #TNV
728
- a+=['0028.0105'] and b+=['US'] and c+=['Largest Valid Pixel Value'] #TNV
729
- a+=['0028.0106'] and b+=['US'] and c+=['Smallest Image Pixel Value'] # 'SS' also possible
730
- a+=['0028.0107'] and b+=['US'] and c+=['Largest Image Pixel Value'] # 'SS' also possible
731
- a+=['0028.0108'] and b+=['US'] and c+=['Smallest Pixel Value in Series']
732
- a+=['0028.0109'] and b+=['US'] and c+=['Largest Pixel Value in Series']
733
- a+=['0028.0120'] and b+=['US'] and c+=['Pixel Padding Value'] # 'SS' also possible
734
- a+=['0028.0200'] and b+=['US'] and c+=['Image Location'] #TNV
735
- a+=['0028.0300'] and b+=['CS'] and c+=['Quality Control Image']
736
- a+=['0028.0301'] and b+=['CS'] and c+=['Burned In Annotation']
737
- a+=['0028.1040'] and b+=['CS'] and c+=['Pixel Intensity Relationship']
738
- a+=['0028.1050'] and b+=['DS'] and c+=['Window Center']
739
- a+=['0028.1051'] and b+=['DS'] and c+=['Window Width']
740
- a+=['0028.1052'] and b+=['DS'] and c+=['Rescale Intercept']
741
- a+=['0028.1053'] and b+=['US'] and c+=['Rescale Slope']
742
- a+=['0028.1054'] and b+=['LO'] and c+=['Rescale Type']
743
- a+=['0028.1055'] and b+=['LO'] and c+=['Window Center & Width Explanation']
744
- a+=['0028.1101'] and b+=['US'] and c+=['Red Palette Color Lookup Table Descriptor']
745
- a+=['0028.1102'] and b+=['US'] and c+=['Green Palette Color Lookup Table Descriptor']
746
- a+=['0028.1103'] and b+=['US'] and c+=['Blue Palette Color Lookup Table Descriptor']
747
- a+=['0028.1199'] and b+=['UI'] and c+=['Palette Color Lookup Table UID']
748
- a+=['0028.1201'] and b+=['US'] and c+=['Red Palette Color Lookup Table Data']
749
- a+=['0028.1202'] and b+=['US'] and c+=['Green Palette Color Lookup Table Data']
750
- a+=['0028.1203'] and b+=['US'] and c+=['Blue Palette Color Lookup Table Data']
751
- a+=['0028.2110'] and b+=['CS'] and c+=['Lossy Image Compression']
752
- a+=['0028.3003'] and b+=['LO'] and c+=['LUT Explanation']
753
- a+=['0029.0000'] and b+=['UL'] and c+=['Group Length']
754
- a+=['0032.0000'] and b+=['UL'] and c+=['Group Length']
755
- a+=['0032.1060'] and b+=['LO'] and c+=['Requested Procedure Description']
756
- a+=['0040.0000'] and b+=['UL'] and c+=['Group Length']
757
- a+=['0040.0244'] and b+=['DA'] and c+=['Performed Procedure Step Start Date']
758
- a+=['0040.0245'] and b+=['TM'] and c+=['Performed Procedure Step Start Time']
759
- a+=['0040.0253'] and b+=['SH'] and c+=['Performed Procedure Step ID']
760
- a+=['0040.0254'] and b+=['LO'] and c+=['Performed Procedure Step Description']
761
- a+=['0043.0000'] and b+=['UL'] and c+=['Group Length']
762
- a+=['0045.0000'] and b+=['UL'] and c+=['Group Length']
763
- a+=['0051.0000'] and b+=['UL'] and c+=['Group Length']
764
- a+=['0054.0000'] and b+=['UL'] and c+=['Group Length']
765
- a+=['0054.0011'] and b+=['US'] and c+=['Number of Energy Windows']
766
- a+=['0054.0021'] and b+=['US'] and c+=['Number of Detectors']
767
- a+=['0054.0051'] and b+=['US'] and c+=['Number of Rotations']
768
- a+=['0054.0080'] and b+=['US'] and c+=['Slice Vector']
769
- a+=['0054.0081'] and b+=['US'] and c+=['Number of Slices']
770
- a+=['0054.0202'] and b+=['CS'] and c+=['Type of Detector Motion']
771
- a+=['0054.0400'] and b+=['SH'] and c+=['Image ID']
772
- a+=['0088.0000'] and b+=['UL'] and c+=['Group Length']
773
- a+=['0088.0140'] and b+=['UI'] and c+=['Storage Media File-set UID']
774
- a+=['0088.0200'] and b+=['SQ'] and c+=['Icon Image Sequence']
775
- a+=['2010.0000'] and b+=['UL'] and c+=['Group Length']
776
- a+=['2010.0100'] and b+=['CS'] and c+=['Border Density']
777
- a+=['2020.0000'] and b+=['UL'] and c+=['Group Length']
778
- a+=['2020.0020'] and b+=['CS'] and c+=['Polarity']
779
- a+=['3002.0000'] and b+=['UL'] and c+=['Group Length']
780
- a+=['3002.0002'] and b+=['SH'] and c+=['RT Image Label']
781
- a+=['3002.0003'] and b+=['LO'] and c+=['RT Image Name']
782
- a+=['3002.0004'] and b+=['ST'] and c+=['RT Image Description']
783
- a+=['3002.000A'] and b+=['CS'] and c+=['Reported Values Origin']
784
- a+=['3002.000C'] and b+=['CS'] and c+=['RT Image Plane']
785
- a+=['3002.000D'] and b+=['DS'] and c+=['X-Ray Image Receptor Translation']
786
- a+=['3002.000E'] and b+=['DS'] and c+=['X-Ray Image Receptor Angle']
787
- a+=['3002.0011'] and b+=['DS'] and c+=['Image Plane Pixel Spacing']
788
- a+=['3002.0012'] and b+=['DS'] and c+=['RT Image Position']
789
- a+=['3002.0020'] and b+=['SH'] and c+=['Radiation Machine Name']
790
- a+=['3002.0022'] and b+=['DS'] and c+=['Radiation Machine SAD']
791
- a+=['3002.0026'] and b+=['DS'] and c+=['RT Image SID']
792
- a+=['3002.0030'] and b+=['SQ'] and c+=['Exposure Sequence']
793
- a+=['3002.0032'] and b+=['DS'] and c+=['Meterset Exposure']
794
- a+=['3002.0034'] and b+=['DS'] and c+=['Diaphragm Position']
795
- a+=['3004.0000'] and b+=['UL'] and c+=['Group Length']
796
- a+=['3004.0002'] and b+=['CS'] and c+=['Dose Units']
797
- a+=['3004.0004'] and b+=['CS'] and c+=['Dose Type']
798
- a+=['3004.0006'] and b+=['LO'] and c+=['Dose Comment']
799
- a+=['3004.000A'] and b+=['CS'] and c+=['Dose Summation Type']
800
- a+=['3004.000C'] and b+=['DS'] and c+=['Grid Frame Offset Vector']
801
- a+=['3004.000E'] and b+=['DS'] and c+=['Dose Grid Scaling']
802
- a+=['3004.0010'] and b+=['SQ'] and c+=['RT Dose ROI Sequence']
803
- a+=['3004.0012'] and b+=['DS'] and c+=['Dose Value']
804
- a+=['3005.0000'] and b+=['UL'] and c+=['Group Length']
805
- a+=['3006.0000'] and b+=['UL'] and c+=['Group Length']
806
- a+=['3006.0002'] and b+=['SH'] and c+=['Structure Set Label']
807
- a+=['3006.0004'] and b+=['LO'] and c+=['Structure Set Name']
808
- a+=['3006.0008'] and b+=['DA'] and c+=['Structure Set Date']
809
- a+=['3006.0009'] and b+=['TM'] and c+=['Structure Set Time']
810
- a+=['3006.0010'] and b+=['SQ'] and c+=['Referenced Frame of Reference Sequence']
811
- a+=['3006.0012'] and b+=['SQ'] and c+=['RT Referenced Study Sequence']
812
- a+=['3006.0014'] and b+=['SQ'] and c+=['RT Referenced Series Sequence']
813
- a+=['3006.0020'] and b+=['SQ'] and c+=['Structure Set ROI Sequence']
814
- a+=['3006.0022'] and b+=['IS'] and c+=['ROI Number']
815
- a+=['3006.0024'] and b+=['UI'] and c+=['Referenced Frame of Reference UID']
816
- a+=['3006.0026'] and b+=['LO'] and c+=['ROI Name']
817
- a+=['3006.002A'] and b+=['IS'] and c+=['ROI Display Color']
818
- a+=['3006.0016'] and b+=['SQ'] and c+=['Contour Image Sequence']
819
- a+=['3006.0036'] and b+=['CS'] and c+=['ROI Generation Algorithm']
820
- a+=['3006.0039'] and b+=['SQ'] and c+=['ROI Contour Sequence']
821
- a+=['3006.0040'] and b+=['SQ'] and c+=['Contour Sequence']
822
- a+=['3006.0042'] and b+=['CS'] and c+=['Contour Geometric Type']
823
- a+=['3006.0046'] and b+=['IS'] and c+=['Number of Contour Points']
824
- a+=['3006.0048'] and b+=['IS'] and c+=['Contour Number']
825
- a+=['3006.0050'] and b+=['DS'] and c+=['Contour Data']
826
- a+=['3006.0080'] and b+=['SQ'] and c+=['RT ROI Observations Sequence']
827
- a+=['3006.0082'] and b+=['IS'] and c+=['Observation Number']
828
- a+=['3006.0084'] and b+=['IS'] and c+=['Referenced ROI Number']
829
- a+=['3006.00A4'] and b+=['CS'] and c+=['RT ROI Interpreted Type']
830
- a+=['3006.00A6'] and b+=['PN'] and c+=['ROI Interpreter']
831
- a+=['3006.00C0'] and b+=['SQ'] and c+=['Frame of Reference Relationship Sequence']
832
- a+=['3006.00C2'] and b+=['UI'] and c+=['Related Frame of Reference UID']
833
- a+=['3006.00C4'] and b+=['CS'] and c+=['Frame of Reference Transformation Type']
834
- a+=['3006.00C6'] and b+=['DS'] and c+=['Frame of Reference Transformation Matrix']
835
- a+=['3006.00C8'] and b+=['LO'] and c+=['Frame of Reference Transformation Comment']
836
- a+=['3007.0000'] and b+=['UL'] and c+=['Group Length']
837
- a+=['300A.0000'] and b+=['UL'] and c+=['Group Length']
838
- a+=['300A.0002'] and b+=['SH'] and c+=['RT Plan Label']
839
- a+=['300A.0003'] and b+=['LO'] and c+=['RT Plan Name']
840
- a+=['300A.0004'] and b+=['ST'] and c+=['RT Plan Description']
841
- a+=['300A.0006'] and b+=['DA'] and c+=['RT Plan Date']
842
- a+=['300A.0007'] and b+=['TM'] and c+=['RT Plan Time']
843
- a+=['300A.000C'] and b+=['CS'] and c+=['RT Plan Geometry']
844
- a+=['300A.0070'] and b+=['SQ'] and c+=['Fraction Group Sequence']
845
- a+=['300A.0071'] and b+=['IS'] and c+=['Fraction Group Number']
846
- a+=['300A.0078'] and b+=['IS'] and c+=['Number of Fractions Planned']
847
- a+=['300A.0080'] and b+=['IS'] and c+=['Number of Beams']
848
- a+=['300A.0086'] and b+=['DS'] and c+=['Beam Meterset']
849
- a+=['300A.00A0'] and b+=['IS'] and c+=['Number of Brachy Application Setups']
850
- a+=['300A.00B0'] and b+=['SQ'] and c+=['Beam Sequence']
851
- a+=['300A.00B2'] and b+=['SH'] and c+=['Treatment Machine Name']
852
- a+=['300A.00B3'] and b+=['CS'] and c+=['Primary Dosimeter Unit']
853
- a+=['300A.00B4'] and b+=['DS'] and c+=['Source-Axis Distance']
854
- a+=['300A.00B6'] and b+=['SQ'] and c+=['Beam Limiting Device Sequence']
855
- a+=['300A.00B8'] and b+=['CS'] and c+=['RT Beam Limiting Device Type']
856
- a+=['300A.00BC'] and b+=['IS'] and c+=['Number of Leaf/Jaw Pairs']
857
- a+=['300A.00BE'] and b+=['DS'] and c+=['Leaf Position Boundaries']
858
- a+=['300A.00C0'] and b+=['IS'] and c+=['Beam Number']
859
- a+=['300A.00C2'] and b+=['LO'] and c+=['Beam Name']
860
- a+=['300A.00C3'] and b+=['ST'] and c+=['Beam Description']
861
- a+=['300A.00C4'] and b+=['CS'] and c+=['Beam Type']
862
- a+=['300A.00C6'] and b+=['CS'] and c+=['Radiation Type']
863
- a+=['300A.00C8'] and b+=['IS'] and c+=['Reference Image Number']
864
- a+=['300A.00CE'] and b+=['CS'] and c+=['Treatment Delivery Type']
865
- a+=['300A.00D0'] and b+=['IS'] and c+=['Number of Wedges']
866
- a+=['300A.00D1'] and b+=['SQ'] and c+=['Wedge Sequence']
867
- a+=['300A.00D2'] and b+=['IS'] and c+=['Wedge Number']
868
- a+=['300A.00D3'] and b+=['CS'] and c+=['Wedge Type']
869
- a+=['300A.00D4'] and b+=['SH'] and c+=['Wedge Id']
870
- a+=['300A.00D5'] and b+=['IS'] and c+=['Wedge Angle']
871
- a+=['300A.00D6'] and b+=['DS'] and c+=['Wedge Factor']
872
- a+=['300A.00D8'] and b+=['DS'] and c+=['Wedge Orientation']
873
- a+=['300A.00E0'] and b+=['IS'] and c+=['Number of Compensators']
874
- a+=['300A.00E1'] and b+=['SH'] and c+=['Material Id']
875
- a+=['300A.00ED'] and b+=['IS'] and c+=['Number of Boli']
876
- a+=['300A.00F0'] and b+=['IS'] and c+=['Number of Blocks']
877
- a+=['300A.00F2'] and b+=['DS'] and c+=['Total Block Tray Factor']
878
- a+=['300A.00F4'] and b+=['SQ'] and c+=['Block Sequence']
879
- a+=['300A.00F5'] and b+=['SH'] and c+=['Block Tray Id']
880
- a+=['300A.00F6'] and b+=['DS'] and c+=['Source to Block Tray Distance']
881
- a+=['300A.00F8'] and b+=['CS'] and c+=['Block Type']
882
- a+=['300A.00FA'] and b+=['CS'] and c+=['Block Divergence']
883
- a+=['300A.00FC'] and b+=['IS'] and c+=['Block Number']
884
- a+=['300A.00FE'] and b+=['LO'] and c+=['Block Name']
885
- a+=['300A.0100'] and b+=['DS'] and c+=['Block Thickness']
886
- a+=['300A.0102'] and b+=['DS'] and c+=['Block Transmission']
887
- a+=['300A.0104'] and b+=['IS'] and c+=['Block Number of Points']
888
- a+=['300A.0106'] and b+=['DS'] and c+=['Block Data']
889
- a+=['300A.010E'] and b+=['DS'] and c+=['Final Cumulative Meterset Weight']
890
- a+=['300A.0110'] and b+=['IS'] and c+=['Number of Control Points']
891
- a+=['300A.0111'] and b+=['SQ'] and c+=['Control Point Sequence']
892
- a+=['300A.0112'] and b+=['IS'] and c+=['Control Point Index']
893
- a+=['300A.0114'] and b+=['DS'] and c+=['Nominal Beam Energy']
894
- a+=['300A.011A'] and b+=['SQ'] and c+=['Beam Limiting Device Position Sequence']
895
- a+=['300A.011C'] and b+=['DS'] and c+=['Leaf/Jaw Positions']
896
- a+=['300A.011E'] and b+=['DS'] and c+=['Gantry Angle']
897
- a+=['300A.011F'] and b+=['CS'] and c+=['Gantry Rotation Direction']
898
- a+=['300A.0120'] and b+=['DS'] and c+=['Beam Limiting Device Angle']
899
- a+=['300A.0121'] and b+=['CS'] and c+=['Beam Limiting Device Rotation Direction']
900
- a+=['300A.0122'] and b+=['DS'] and c+=['Patient Support Angle']
901
- a+=['300A.0123'] and b+=['CS'] and c+=['Patient Support Rotation Direction']
902
- a+=['300A.0125'] and b+=['DS'] and c+=['Table Top Eccentric Angle']
903
- a+=['300A.0126'] and b+=['CS'] and c+=['Table Top Eccentric Rotation Direction']
904
- a+=['300A.0128'] and b+=['DS'] and c+=['Table Top Vertical Position']
905
- a+=['300A.0129'] and b+=['DS'] and c+=['Table Top Longitudinal Position']
906
- a+=['300A.012A'] and b+=['DS'] and c+=['Table Top Lateral Position']
907
- a+=['300A.012C'] and b+=['DS'] and c+=['Isocenter Position']
908
- a+=['300A.0130'] and b+=['DS'] and c+=['Source to Surface Distance']
909
- a+=['300A.0134'] and b+=['DS'] and c+=['Cumulative Meterset Weight']
910
- a+=['300A.0180'] and b+=['SQ'] and c+=['Patient Setup Sequence']
911
- a+=['300A.0182'] and b+=['IS'] and c+=['Patient Setup Number']
912
- a+=['300A.01D2'] and b+=['DS'] and c+=['Table Top Vertical Setup Displacement']
913
- a+=['300A.01D4'] and b+=['DS'] and c+=['Table Top Longitudinal Setup Displacement']
914
- a+=['300A.01D6'] and b+=['DS'] and c+=['Table Top Lateral Setup Displacement']
915
- a+=['300A.0212'] and b+=['IS'] and c+=['Source Number']
916
- a+=['300A.0214'] and b+=['CS'] and c+=['Source Type']
917
- a+=['300C.0000'] and b+=['UL'] and c+=['Group Length']
918
- a+=['300C.0002'] and b+=['SQ'] and c+=['Referenced RT Plan Sequence']
919
- a+=['300C.0004'] and b+=['SQ'] and c+=['Referenced Beam Sequence']
920
- a+=['300C.0006'] and b+=['IS'] and c+=['Referenced Beam Number']
921
- a+=['300C.0020'] and b+=['SQ'] and c+=['Referenced Fraction Group Sequence']
922
- a+=['300C.0022'] and b+=['IS'] and c+=['Referenced Fraction Group Number']
923
- a+=['300C.0042'] and b+=['SQ'] and c+=['Referenced Reference Image Sequence']
924
- a+=['300C.0060'] and b+=['SQ'] and c+=['Referenced Structure Set Sequence']
925
- a+=['300C.006A'] and b+=['IS'] and c+=['Referenced Patient Setup Number']
926
- a+=['300C.0080'] and b+=['SQ'] and c+=['Referenced Dose Sequence']
927
- a+=['300E.0000'] and b+=['UL'] and c+=['Group Length']
928
- a+=['300E.0002'] and b+=['CS'] and c+=['Approval Status']
929
- a+=['3241.0000'] and b+=['UL'] and c+=['Group Length']
930
- a+=['5000.0000'] and b+=['UL'] and c+=['Group Length']
931
- a+=['5000.0005'] and b+=['US'] and c+=['Curve Dimensions']
932
- a+=['5000.0010'] and b+=['US'] and c+=['Number of Points']
933
- a+=['5000.0020'] and b+=['CS'] and c+=['Type of Data']
934
- a+=['5000.0030'] and b+=['SH'] and c+=['Axis Units']
935
- a+=['5000.0103'] and b+=['US'] and c+=['Data Value Representation']
936
- a+=['5000.3000'] and b+=['OB'] and c+=['Curve Data']
937
- a+=['5001.0000'] and b+=['UL'] and c+=['Group Length']
938
- a+=['5001.0010'] and b+=['US'] and c+=['Number of Points'] # ?? check with other sources
939
- a+=['5002.0000'] and b+=['UL'] and c+=['Group Length']
940
- a+=['5002.0005'] and b+=['US'] and c+=['Curve Dimensions']
941
- a+=['5002.0010'] and b+=['US'] and c+=['Number of Points']
942
- a+=['5002.0020'] and b+=['CS'] and c+=['Type of Data']
943
- a+=['5002.0030'] and b+=['SH'] and c+=['Axis Units']
944
- a+=['5002.0103'] and b+=['US'] and c+=['Data Value Representation']
945
- a+=['5002.3000'] and b+=['OB'] and c+=['Curve Data']
946
- a+=['7FE0.0000'] and b+=['UL'] and c+=['Group Length']
947
- a+=['7FE0.0010'] and b+=['OW'] and c+=['Pixel Data']
948
- a+=['FFFC.FFFC'] and b+=['OB'] and c+=['Data Set Trailing Padding']
949
- a+=['FFFE.E000'] and b+=['()'] and c+=['Item']
950
- a+=['FFFE.E00D'] and b+=['()'] and c+=['Sequence Delimitation Item']
951
- a+=['FFFE.E0DD'] and b+=['()'] and c+=['Sequence Delimitation Item']
952
- a+=['dumm.dumm'] and b+=['SS'] and c+=['Dummy entry 1'] # To get the 'SS' type in the list.
953
-
954
- @lib_labels=a
955
- @lib_types=b
956
- @lib_names=c
957
- end
958
-
959
-
960
516
  # Process a series of numbers to return a string containing all the numbers separated with the separator "/" between the numbers.
961
- def process_numbers(length, type, size)
962
- bin = @file.read(size)
517
+ def process_numbers(length, type, bin)
518
+ size = bin.length
963
519
  data=""
964
520
  case type
965
521
  when "UL"
@@ -973,7 +529,7 @@ module DICOM
973
529
  when "FD"
974
530
  temp1 = get_FD(bin)
975
531
  else
976
- puts "Warning: Type "+type+"not supported in method process_numbers()."
532
+ @msg+=["Warning: Type "+type+"not supported in method process_numbers()."]
977
533
  end
978
534
  remain = (length-size)/size
979
535
  remain.times do
@@ -990,7 +546,7 @@ module DICOM
990
546
  when "FD"
991
547
  temp2 = get_FD(bin)
992
548
  else
993
- puts "Warning: Type "+type+"not supported in method process_numbers()."
549
+ @msg+=["Warning: Type "+type+"not supported in method process_numbers()."]
994
550
  end
995
551
  data = temp1.to_s+"/"+temp2.to_s
996
552
  temp1 = data
@@ -1011,7 +567,7 @@ module DICOM
1011
567
  end
1012
568
  else
1013
569
  # Network byte order: (Unknown what to use here)
1014
- puts "Warning: Method get_BYTE not tested with this endian yet!"
570
+ @msg+=["Warning: Method get_BYTE not tested with this endian yet!"]
1015
571
  if elements > 1
1016
572
  num=bin.unpack('C*')
1017
573
  else
@@ -1063,7 +619,7 @@ module DICOM
1063
619
  else
1064
620
  num=bin.unpack('s*')[0]
1065
621
  end
1066
- puts "Warning: Oppositve endian for signed short is not working yet!"
622
+ @msg+=["Warning: Oppositve endian for signed short is not working yet!"]
1067
623
  end
1068
624
  return num
1069
625
  end
@@ -1104,7 +660,7 @@ module DICOM
1104
660
  num=bin.unpack('l*')[0]
1105
661
  end
1106
662
  else
1107
- puts "Warning: Oppositve endian for signed long is not working yet!"
663
+ @msg+=["Warning: Oppositve endian for signed long is not working yet!"]
1108
664
  if elements > 1
1109
665
  num=bin.unpack('l*')
1110
666
  else
@@ -1140,7 +696,12 @@ module DICOM
1140
696
 
1141
697
  # Checks the Transfer Syntax UID tag and updates class variables to prepare for correct reading of DICOM file.
1142
698
  def process_syntax(value)
1143
- case value.rstrip
699
+ ts = value.rstrip
700
+ valid = @lib.check_transfer_syntax(ts)
701
+ if not valid
702
+ @msg+=["Warning: Invalid/unknown transfer syntax! Will try reading the file, but errors may occur."]
703
+ end
704
+ case ts
1144
705
  # Some variations with uncompressed pixel data:
1145
706
  when "1.2.840.10008.1.2"
1146
707
  # Implicit VR, Little Endian
@@ -1152,39 +713,22 @@ module DICOM
1152
713
  @rest_explicit = true
1153
714
  @rest_endian = false
1154
715
  @compression = false
716
+ when "1.2.840.10008.1.2.1.99"
717
+ # Deflated Explicit VR, Little Endian
718
+ @msg+=["Warning: Transfer syntax 'Deflated Explicit VR, Little Endian' is untested. Unknown if this is handled correctly!"]
719
+ @rest_explicit = true
720
+ @rest_endian = false
721
+ @compression = false
1155
722
  when "1.2.840.10008.1.2.2"
1156
723
  # Explicit VR, Big Endian
1157
724
  @rest_explicit = true
1158
725
  @rest_endian = true
1159
726
  @compression = false
1160
- # Compressed pixel data, using various compression algorithms:
1161
- when "1.2.840.10008.1.2.4.50"
1162
- @rest_explicit = true
1163
- @rest_endian = false
1164
- @compression = "JPEG Baseline"
1165
- when "1.2.840.10008.1.2.4.51"
1166
- @rest_explicit = true
1167
- @rest_endian = false
1168
- @compression = "JPEG Extended (Process 2 & 4)"
1169
- when "1.2.840.10008.1.2.4.70"
1170
- @rest_explicit = true
1171
- @rest_endian = false
1172
- @compression = "JPEG Lossless, Non-Hierarchical"
1173
- when "1.2.840.10008.1.2.4.90"
1174
- @rest_explicit = true
1175
- @rest_endian = false
1176
- @compression = "JPEG 2000, Lossless Only"
1177
- when "1.2.840.10008.1.2.4.91"
1178
- @rest_explicit = true
1179
- @rest_endian = false
1180
- @compression = "JPEG 2000, Lossy"
1181
727
  else
1182
- # For everything else, assume unknown compression algorithm, with Explicit VR, Little Endian:
1183
- puts "Warning: Unknown Transfer Syntax UID: "+ value.to_s
1184
- puts "Handling for this data type has not been implemented, errors may occur."
728
+ # For everything else, assume compressed pixel data, with Explicit VR, Little Endian:
1185
729
  @rest_explicit = true
1186
730
  @rest_endian = false
1187
- @compression = "Unknown"
731
+ @compression = true
1188
732
  end
1189
733
  end
1190
734