dicom 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,25 @@
1
+ = 0.9.3
2
+
3
+ === 6th May, 2012
4
+
5
+ * Deprecated all #remove* methods (replaced with #delete*) to increase consistency with Ruby.
6
+ * Changed preferred DObject variable name from obj to dcm for all examples.
7
+ * Added comparison methods (#==, #eql? and #hash) as well as dynamic #to_* methods to DObject, Element, Item & Sequence classes.
8
+ * Fixed incorrect handling of 3D pixel data with NArray (regression introduced in v0.8).
9
+ * Anonymizer can take a list of tags to be entirely deleted from the DICOM files during anonymization.
10
+ * Added Accession Number to default list of tags that are anonymized.
11
+ * Added a generate_uid method for creating custom (but valid) UIDs.
12
+ * Added an Anonymizer AuditTrail feature based on JSON, which will replace the (deprecated) identity_file feature.
13
+ * Implemented a proper UID anonymization with AuditTrail support and preservation of relations.
14
+ * Fixed and improved logging when failing to decompress pixel data.
15
+ * DServer defaults to bind to 127.0.0.1, with an option available for other bindings.
16
+ * More robust handling of invalid AT Element values when parsing DICOM files.
17
+ * Optimizations and code cleanups allowed by the introduced Ruby 1.9 requirement.
18
+
19
+
1
20
  = 0.9.2
2
21
 
3
- === (Not released yet)
22
+ === 10th Oct, 2011
4
23
 
5
24
  * Enabled the use of lower case tag letters in methods which previously required the use of upper case letters.
6
25
  * Added new DObject class methods to offload DObject#new:
@@ -13,6 +13,11 @@ communication modalities like querying, moving, sending and receiving files.
13
13
  gem install dicom
14
14
 
15
15
 
16
+ == REQUIREMENTS
17
+
18
+ * Ruby 1.9.2 (if you are still on Ruby 1.8, gems up to version 0.9.1 can be used)
19
+
20
+
16
21
  == BASIC USAGE
17
22
 
18
23
  === Load & Include
@@ -23,42 +28,42 @@ communication modalities like querying, moving, sending and receiving files.
23
28
  === Read, modify and write
24
29
 
25
30
  # Read file:
26
- obj = DObject.read("some_file.dcm")
31
+ dcm = DObject.read("some_file.dcm")
27
32
  # Extract the Patient's Name value:
28
- obj.patients_name.value
33
+ dcm.patients_name.value
29
34
  # Add or modify the Patient's Name element:
30
- obj.patients_name = "Anonymous"
35
+ dcm.patients_name = "Anonymous"
31
36
  # Remove a data element from the DICOM object:
32
- obj.pixel_data = nil
37
+ dcm.pixel_data = nil
33
38
  # Write to file:
34
- obj.write("new_file.dcm")
39
+ dcm.write("new_file.dcm")
35
40
 
36
41
  === Modify using tag strings instead of dictionary method names
37
42
 
38
43
  # Extract the Patient's Name value:
39
- obj.value("0010,0010")
44
+ dcm.value("0010,0010")
40
45
  # Modify the Patient's Name element:
41
- obj["0010,0010"].value = "Anonymous"
42
- # Remove a data element from the DICOM object:
43
- obj.remove("7FE0,0010")
46
+ dcm["0010,0010"].value = "Anonymous"
47
+ # Delete a data element from the DICOM object:
48
+ dcm.delete("7FE0,0010")
44
49
 
45
50
  === Extracting information about the DICOM object
46
51
 
47
52
  # Display a short summary of the file's properties:
48
- obj.summary
53
+ dcm.summary
49
54
  # Print all data elements to screen:
50
- obj.print
55
+ dcm.print
51
56
  # Convert the data element hierarchy to a nested hash:
52
- obj.to_hash
57
+ dcm.to_hash
53
58
 
54
59
  === Handle pixel data
55
60
 
56
61
  # Retrieve the pixel data in a Ruby Array:
57
- obj.pixels
62
+ dcm.pixels
58
63
  # Load the pixel data to an numerical array (NArray):
59
- obj.narray
64
+ dcm.narray
60
65
  # Load the pixel data to an RMagick image object and display it on the screen:
61
- obj.image.display
66
+ dcm.image.display
62
67
 
63
68
  === Transmit a DICOM file
64
69
 
@@ -91,19 +96,21 @@ that is printed to screen, regardless if you have set verbose as false. This is
91
96
  in irb every variable loaded in the program is automatically printed to the screen.
92
97
  A useful hack to avoid this effect is to append ";0" after a command.
93
98
  Example:
94
- obj = DObject.new("some_file.dcm") ;0
99
+ dcm = DObject.read("some_file.dcm") ;0
95
100
 
96
101
 
97
102
  == RESOURCES
98
103
 
99
104
  * {Official home page}[http://dicom.rubyforge.org/]
100
105
  * {Discussion forum}[http://groups.google.com/group/ruby-dicom]
106
+ * {Documentation}[http://rubydoc.info/gems/dicom/frames]
107
+ * {Tutorials}[http://dicom.rubyforge.org/tutorials.html]
101
108
  * {Source code repository}[https://github.com/dicom/ruby-dicom]
102
109
 
103
110
 
104
111
  == COPYRIGHT
105
112
 
106
- Copyright 2008-2011 Christoffer Lervåg
113
+ Copyright 2008-2012 Christoffer Lervåg
107
114
 
108
115
  This program is free software: you can redistribute it and/or modify
109
116
  it under the terms of the GNU General Public License as published by
@@ -133,7 +140,9 @@ Please don't hesitate to email me if you have any feedback related to this proje
133
140
  * {Christoffer Lervåg}[https://github.com/dicom]
134
141
  * {John Axel Eriksson}[https://github.com/johnae]
135
142
  * {Kamil Bujniewicz}[https://github.com/icdark]
143
+ * {Jeff Miller}[https://github.com/jeffmax]
136
144
  * {Donnie Millar}[https://github.com/dmillar]
137
145
  * {Björn Albers}[https://github.com/bjoernalbers]
138
146
  * {Lars Benner}[https://github.com/Maturin]
147
+ * {Felix Petriconi}[https://github.com/FelixPetriconi]
139
148
  * {Steven Bedrick}[https://github.com/stevenbedrick]
@@ -2,46 +2,50 @@
2
2
  #
3
3
  # The following classes are meant to be used by users of Ruby DICOM:
4
4
  # * DObject - for reading, manipulating and writing DICOM files.
5
- # * Element, Sequence, Item, Parent, Elemental - users who wish to interact with their DICOM objects will use these classes/modules.
5
+ # * Element, Sequence, Item, Parent, Elemental - users who wish to interact with
6
+ # their DICOM objects will use these classes/modules.
6
7
  # * ImageItem - Image related methods are found in this class.
7
8
  # * DClient - for client side network communication, like querying, moving & sending DICOM files.
8
9
  # * DServer - for server side network communication: Setting up your own DICOM storage node (SCP).
9
10
  # * Anonymizer - a convenience class for anonymizing your DICOM files.
10
11
  #
11
- # The rest of the classes visible in the documentation generated by RDoc is in principle
12
- # 'private' classes, which are mainly of interest to developers.
12
+ # The rest of the classes visible in the documentation generated by RDoc are
13
+ # in principle 'private' classes, which are mainly of interest to developers.
13
14
 
14
15
  # Logging:
15
- require 'dicom/logging'
16
+ require_relative 'dicom/logging'
16
17
  # Core library:
17
18
  # Super classes/modules:
18
- require 'dicom/image_processor'
19
- require 'dicom/parent'
20
- require 'dicom/image_item'
21
- require 'dicom/elemental'
19
+ require_relative 'dicom/image_processor'
20
+ require_relative 'dicom/parent'
21
+ require_relative 'dicom/image_item'
22
+ require_relative 'dicom/elemental'
22
23
  # Subclasses and independent classes:
23
- require 'dicom/d_client'
24
- require 'dicom/dictionary'
25
- require 'dicom/d_library'
26
- require 'dicom/d_object'
27
- require 'dicom/d_read'
28
- require 'dicom/d_server'
29
- require 'dicom/d_write'
30
- require 'dicom/element'
31
- require 'dicom/file_handler'
32
- require 'dicom/item'
33
- require 'dicom/link'
34
- require 'dicom/sequence'
35
- require 'dicom/stream'
24
+ require_relative 'dicom/d_client'
25
+ require_relative 'dicom/dictionary'
26
+ require_relative 'dicom/d_library'
27
+ require_relative 'dicom/d_object'
28
+ require_relative 'dicom/d_read'
29
+ require_relative 'dicom/d_server'
30
+ require_relative 'dicom/d_write'
31
+ require_relative 'dicom/element'
32
+ require_relative 'dicom/file_handler'
33
+ require_relative 'dicom/item'
34
+ require_relative 'dicom/link'
35
+ require_relative 'dicom/sequence'
36
+ require_relative 'dicom/stream'
36
37
  # Extensions to the Ruby library:
37
- require 'dicom/ruby_extensions'
38
+ require_relative 'dicom/ruby_extensions'
38
39
  # Module settings:
39
- require 'dicom/version'
40
- require 'dicom/constants'
41
- require 'dicom/variables'
40
+ require_relative 'dicom/version'
41
+ require_relative 'dicom/constants'
42
+ require_relative 'dicom/variables'
42
43
  # Image processors:
43
- require 'dicom/image_processor_mini_magick'
44
- require 'dicom/image_processor_r_magick'
44
+ require_relative 'dicom/image_processor_mini_magick'
45
+ require_relative 'dicom/image_processor_r_magick'
46
+ # Deprecated methods:
47
+ require_relative 'dicom/deprecated'
45
48
 
46
49
  # Extensions (non-core functionality):
47
- require 'dicom/anonymizer'
50
+ require_relative 'dicom/anonymizer'
51
+ require_relative 'dicom/audit_trail'
@@ -11,18 +11,26 @@ module DICOM
11
11
  class Anonymizer
12
12
  include Logging
13
13
 
14
+ # An AuditTrail instance used for this anonymization (if specified).
15
+ attr_reader :audit_trail
16
+ # The file name used for the AuditTrail serialization (if specified).
17
+ attr_reader :audit_trail_file
14
18
  # A boolean that if set as true will cause all anonymized tags to be blank instead of get some generic value.
15
19
  attr_accessor :blank
16
20
  # A boolean that if set as true will cause all anonymized tags to be get enumerated values, to enable post-anonymization identification by the user.
17
21
  attr_accessor :enumeration
18
- # A string, which if set (and enumeration has been set as well), will make the Anonymizer produce an identity file that provides a relationship between the original and enumerated, anonymized values.
19
- attr_accessor :identity_file
20
- # An array containing status messages accumulated for the Anonymization instance.
21
- attr_accessor :log
22
- # A boolean that if set as true, will make the anonymization remove all private tags.
23
- attr_accessor :remove_private
22
+ # The identity file attribute.
23
+ attr_reader :identity_file
24
+ # A boolean that if set as true, will make the anonymization delete all private tags.
25
+ attr_accessor :delete_private
24
26
  # The path where the anonymized files will be saved. If this value is not set, the original DICOM files will be overwritten.
25
27
  attr_accessor :write_path
28
+ # A boolean indicating whether or not UIDs shall be replaced when executing the anonymization.
29
+ attr_accessor :uid
30
+ # The DICOM UID root to use when generating new UIDs.
31
+ attr_accessor :uid_root
32
+ # An array of UID tags that will be anonymized if the uid option is used.
33
+ attr_accessor :uids
26
34
 
27
35
  # Creates an Anonymizer instance.
28
36
  #
@@ -30,19 +38,33 @@ module DICOM
30
38
  #
31
39
  # * To customize logging behaviour, refer to the Logging module documentation.
32
40
  #
41
+ # === Parameters
42
+ #
43
+ # * <tt>options</tt> -- A hash of parameters.
44
+ #
45
+ # === Options
46
+ #
47
+ # * <tt>:audit_trail</tt> -- String. A file name path. If the file contains old audit data, these are loaded and used in the current anonymization.
48
+ # * <tt>:uid</tt> -- Boolean. If true, all (top level) UIDs will be replaced with custom generated UIDs. To preserve UID relations in studies/series, the AuditTrail feature must be used.
49
+ # * <tt>:uid_root</tt> -- String. An organization (or custom) UID root to use when replacing UIDs.
50
+ #
33
51
  # === Examples
34
52
  #
35
53
  # # Create an Anonymizer instance and restrict the log output:
36
54
  # a = Anonymizer.new
37
55
  # a.logger.level = Logger::ERROR
38
- #
39
- def initialize
56
+ # # Carry out anonymization using the audit trail feature:
57
+ # a = Anonymizer.new(:audit_trail => "trail.json")
58
+ # a.enumeration = true
59
+ # a.folder = "//dicom/today/"
60
+ # a.write_path = "//anonymized/"
61
+ # a.execute
62
+ #
63
+ def initialize(options={})
40
64
  # Default value of accessors:
41
65
  @blank = false
42
66
  @enumeration = false
43
- @identity_file = nil
44
- @remove_private = false
45
- @write_path = nil
67
+ @delete_private = false
46
68
  # Array of folders to be processed for anonymization:
47
69
  @folders = Array.new
48
70
  # Folders that will be skipped:
@@ -60,8 +82,21 @@ module DICOM
60
82
  @files = Array.new
61
83
  # Write paths will be determined later and put in this array:
62
84
  @write_paths = Array.new
63
- # Keep track of status messages:
64
- @log = Array.new
85
+ # Register the uid anonymization option:
86
+ @uid = options[:uid]
87
+ # Set the uid_root to be used when anonymizing study_uid series_uid and sop_instance_uid
88
+ @uid_root = options[:uid_root] ? options[:uid_root] : UID
89
+ # Setup audit trail if requested:
90
+ if options[:audit_trail]
91
+ @audit_trail_file = options[:audit_trail]
92
+ if File.exists?(@audit_trail_file) && File.size(@audit_trail_file) > 2
93
+ # Load the pre-existing audit trail from file:
94
+ @audit_trail = AuditTrail.read(@audit_trail_file)
95
+ else
96
+ # Start from scratch with an empty audit trail:
97
+ @audit_trail = AuditTrail.new
98
+ end
99
+ end
65
100
  # Set the default data elements to be anonymized:
66
101
  set_defaults
67
102
  end
@@ -160,17 +195,24 @@ module DICOM
160
195
  all_write = true
161
196
  files_written = 0
162
197
  files_failed_read = 0
198
+ begin
199
+ require 'progressbar'
200
+ pbar = ProgressBar.new("Anonymizing", @files.length)
201
+ rescue LoadError
202
+ pbar = nil
203
+ end
163
204
  # Temporarily increase the log threshold to suppress messages from the DObject class:
164
205
  anonymizer_level = logger.level
165
206
  logger.level = Logger::FATAL
166
207
  @files.each_index do |i|
208
+ pbar.inc if pbar
167
209
  # Read existing file to DICOM object:
168
- obj = DICOM::DObject.read(@files[i])
169
- if obj.read_success
210
+ dcm = DObject.read(@files[i])
211
+ if dcm.read?
170
212
  # Anonymize the desired tags:
171
213
  @tags.each_index do |j|
172
- if obj.exists?(@tags[j])
173
- element = obj[@tags[j]]
214
+ if dcm.exists?(@tags[j])
215
+ element = dcm[@tags[j]]
174
216
  if element.is_a?(Element)
175
217
  if @blank
176
218
  value = ""
@@ -178,7 +220,7 @@ module DICOM
178
220
  old_value = element.value
179
221
  # Only launch enumeration logic if there is an actual value to the data element:
180
222
  if old_value
181
- value = get_enumeration_value(old_value, j)
223
+ value = enumerated_value(old_value, j)
182
224
  else
183
225
  value = ""
184
226
  end
@@ -190,11 +232,17 @@ module DICOM
190
232
  end
191
233
  end
192
234
  end
193
- # Remove private tags?
194
- obj.remove_private if @remove_private
235
+ # Handle UIDs if requested:
236
+ replace_uids(dcm) if @uid
237
+ # Delete private tags?
238
+ dcm.delete_private if @delete_private
239
+ # Delete Tags marked for removal:
240
+ @delete_tags.each_index do |j|
241
+ dcm.delete(@delete_tags[j]) if dcm.exists?(@delete_tags[j])
242
+ end
195
243
  # Write DICOM file:
196
- obj.write(@write_paths[i])
197
- if obj.write_success
244
+ dcm.write(@write_paths[i])
245
+ if dcm.written?
198
246
  files_written += 1
199
247
  else
200
248
  all_write = false
@@ -204,7 +252,8 @@ module DICOM
204
252
  files_failed_read += 1
205
253
  end
206
254
  end
207
- # Finished anonymizing files. Reset the logg threshold:
255
+ pbar.finish if pbar
256
+ # Finished anonymizing files. Reset the log threshold:
208
257
  logger.level = anonymizer_level
209
258
  # Print elapsed time and status of anonymization:
210
259
  end_time = Time.now.to_f
@@ -219,8 +268,9 @@ module DICOM
219
268
  else
220
269
  logger.warn("Some DICOM objects were NOT succesfully written to file. You are advised to investigate the result (#{files_written} files succesfully written).")
221
270
  end
271
+ @audit_trail.write(@audit_trail_file) if @audit_trail
222
272
  # Has user requested enumeration and specified an identity file in which to store the anonymized values?
223
- if @enumeration and @identity_file
273
+ if @enumeration and @identity_file and !@audit_trail
224
274
  logger.info("Writing identity file.")
225
275
  write_identity_file
226
276
  logger.info("Done")
@@ -235,6 +285,16 @@ module DICOM
235
285
  end
236
286
  end
237
287
 
288
+ # Setter method for the identity file.
289
+ # NB! The identity file feature is deprecated!
290
+ # Please use the AuditTrail feature instead.
291
+ #
292
+ def identity_file=(file_name)
293
+ # Deprecation warning:
294
+ logger.warn("The identity_file feature of the Anonymization class has been deprecated! Please use the AuditTrail feature instead.")
295
+ @identity_file = file_name
296
+ end
297
+
238
298
  # Prints to screen a list of which tags are currently selected for anonymization along with
239
299
  # the replacement values that will be used and enumeration status.
240
300
  #
@@ -310,6 +370,22 @@ module DICOM
310
370
  @enumerations.delete_at(pos)
311
371
  end
312
372
  end
373
+
374
+ # Compeletely deletes a tag from the file
375
+ #
376
+ # === Parameters
377
+ #
378
+ # * <tt>tag</tt> -- String. A data element tag.
379
+ #
380
+ # === Examples
381
+ #
382
+ # a.delete_tag("0010,0010")
383
+ #
384
+ def delete_tag(tag)
385
+ raise ArgumentError, "Expected String, got #{tag.class}." unless tag.is_a?(String)
386
+ raise ArgumentError, "Expected a valid tag of format 'GGGG,EEEE', got #{tag}." unless tag.tag?
387
+ @delete_tags.push(tag) if not @delete_tags.include?(tag)
388
+ end
313
389
 
314
390
  # Sets the anonymization settings for the specified tag. If the tag is already present in the list
315
391
  # of tags to be anonymized, its settings are updated, and if not, a new tag entry is created.
@@ -406,39 +482,53 @@ module DICOM
406
482
  end
407
483
  end
408
484
 
409
- # Handles the enumeration for the current data element tag.
410
- # If its value has been encountered before, its corresponding enumerated value is retrieved,
411
- # and if a new value is encountered, a new enumerated value is found by increasing an index by 1.
412
- # Returns the value which will be used for the anonymization of this tag.
485
+ # Handles the enumeration for the given data element tag.
486
+ # If its value has been encountered before, its corresponding enumerated
487
+ # replacement value is retrieved, and if a new original value is encountered,
488
+ # a new enumerated replacement value is found by increasing an index by 1.
489
+ # Returns the replacement value which is used for the anonymization of the tag.
413
490
  #
414
491
  # === Parameters
415
492
  #
416
- # * <tt>current</tt> -- The original value of the tag that are about to be anonymized.
493
+ # * <tt>original</tt> -- The original value of the tag that to be anonymized.
417
494
  # * <tt>j</tt> -- Fixnum. The index of this tag in the tag-related instance arrays.
418
495
  #
419
- def get_enumeration_value(current, j)
496
+ def enumerated_value(original, j)
420
497
  # Is enumeration requested for this tag?
421
498
  if @enumerations[j]
422
- # Retrieve earlier used anonymization values:
423
- previous_old = @enum_old_hash[@tags[j]]
424
- previous_new = @enum_new_hash[@tags[j]]
425
- p_index = previous_old.length
426
- if previous_old.index(current) == nil
427
- # Current value has not been encountered before:
428
- value = @values[j]+(p_index + 1).to_s
429
- # Store value in array (and hash):
430
- previous_old << current
431
- previous_new << value
432
- @enum_old_hash[@tags[j]] = previous_old
433
- @enum_new_hash[@tags[j]] = previous_new
499
+ if @audit_trail
500
+ # Check if the UID has been encountered already:
501
+ replacement = @audit_trail.replacement(@tags[j], original)
502
+ unless replacement
503
+ # This original value has not been encountered yet. Determine the index to use.
504
+ index = @audit_trail.records(@tags[j]).length + 1
505
+ # Create the replacement value:
506
+ replacement = @values[j] + index.to_s
507
+ # Add this tag record to the audit trail:
508
+ @audit_trail.add_record(@tags[j], original, replacement)
509
+ end
434
510
  else
435
- # Current value has been observed before:
436
- value = previous_new[previous_old.index(current)]
511
+ # Retrieve earlier used anonymization values:
512
+ previous_old = @enum_old_hash[@tags[j]]
513
+ previous_new = @enum_new_hash[@tags[j]]
514
+ p_index = previous_old.length
515
+ if previous_old.index(original) == nil
516
+ # Current value has not been encountered before:
517
+ replacement = @values[j]+(p_index + 1).to_s
518
+ # Store value in array (and hash):
519
+ previous_old << original
520
+ previous_new << replacement
521
+ @enum_old_hash[@tags[j]] = previous_old
522
+ @enum_new_hash[@tags[j]] = previous_new
523
+ else
524
+ # Current value has been observed before:
525
+ replacement = previous_new[previous_old.index(original)]
526
+ end
437
527
  end
438
528
  else
439
- value = @values[j]
529
+ replacement = @values[j]
440
530
  end
441
- return value
531
+ return replacement
442
532
  end
443
533
 
444
534
  # Discovers all the files contained in the specified directory (all its sub-directories),
@@ -502,10 +592,54 @@ module DICOM
502
592
  end
503
593
  end
504
594
 
505
- # Sets up the default tags that will be anonymized, along with default replacement values and enumeration settings.
506
- # The data is stored in 3 separate instance arrays for tags, values and enumeration.
595
+ # Replaces the UIDs of the given DICOM object.
596
+ #
597
+ # === Notes
598
+ #
599
+ # Empty UIDs are ignored (we don't generate new UIDs for these).
600
+ # If AuditTrail is set, the relationship between old and new UIDs
601
+ # are preserved, and the relations between files in a study/series
602
+ # should remain valid.
603
+ #
604
+ #
605
+ def replace_uids(dcm)
606
+ @uids.each_pair do |tag, prefix|
607
+ original = dcm.value(tag)
608
+ if original && original.length > 0
609
+ # We have a UID value, go ahead and replace it:
610
+ if @audit_trail
611
+ # Check if the UID has been encountered already:
612
+ replacement = @audit_trail.replacement(tag, original)
613
+ unless replacement
614
+ # The UID has not been stored previously. Generate a new one:
615
+ replacement = DICOM.generate_uid(@uid_root, prefix)
616
+ # Add this tag record to the audit trail:
617
+ @audit_trail.add_record(tag, original, replacement)
618
+ end
619
+ # Replace the UID in the DICOM object:
620
+ dcm[tag].value = replacement
621
+ # NB! The SOP Instance UID must also be written to the Media Storage SOP Instance UID tag:
622
+ dcm["0002,0003"].value = replacement if tag == "0008,0018" && dcm.exists?("0002,0003")
623
+ else
624
+ # We don't care about preserving UID relations. Just insert a custom UID:
625
+ dcm[tag].value = DICOM.generate_uid(@uid_root, prefix)
626
+ end
627
+ end
628
+ end
629
+ end
630
+
631
+ # Sets up some default information variables that are used by the Anonymizer.
507
632
  #
508
633
  def set_defaults
634
+ # A hash of UID tags to be replaced (if requested) and prefixes to use for each tag:
635
+ @uids = {
636
+ "0008,0018" => 3, # SOP Instance UID
637
+ "0020,000D" => 1, # Study Instance UID
638
+ "0020,000E" => 2, # Series Instance UID
639
+ "0020,0052" => 9 # Frame of Reference UID
640
+ }
641
+ # Sets up default tags that will be anonymized, along with default replacement values and enumeration settings.
642
+ # This data is stored in 3 separate instance arrays for tags, values and enumeration.
509
643
  data = [
510
644
  ["0008,0012", "20000101", false], # Instance Creation Date
511
645
  ["0008,0013", "000000.00", false], # Instance Creation Time
@@ -513,6 +647,7 @@ module DICOM
513
647
  ["0008,0023", "20000101", false], # Image Date
514
648
  ["0008,0030", "000000.00", false], # Study Time
515
649
  ["0008,0033", "000000.00", false], # Image Time
650
+ ["0008,0050", "", true], # Accession Number
516
651
  ["0008,0080", "Institution", true], # Institution name
517
652
  ["0008,0090", "Physician", true], # Referring Physician's name
518
653
  ["0008,1010", "Station", true], # Station name
@@ -526,6 +661,10 @@ module DICOM
526
661
  @tags = data[0]
527
662
  @values = data[1]
528
663
  @enumerations = data[2]
664
+
665
+ # Tags to be deleted completely during anonymization
666
+ @delete_tags = [
667
+ ]
529
668
  end
530
669
 
531
670
  # Writes an identity file, which allows reidentification of DICOM files that have been anonymized
@@ -552,6 +691,5 @@ module DICOM
552
691
  end
553
692
  end
554
693
  end
555
-
556
694
  end
557
695
  end