dicom 0.1 → 0.2

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.
@@ -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