dicom 0.9.3 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +312 -290
- data/COPYING +674 -674
- data/Gemfile +3 -0
- data/dicom.gemspec +31 -0
- data/lib/dicom.rb +53 -51
- data/lib/dicom/anonymizer.rb +98 -123
- data/lib/dicom/audit_trail.rb +104 -116
- data/lib/dicom/constants.rb +219 -170
- data/lib/dicom/d_client.rb +122 -150
- data/lib/dicom/d_library.rb +219 -287
- data/lib/dicom/d_object.rb +451 -539
- data/lib/dicom/d_read.rb +151 -245
- data/lib/dicom/d_server.rb +329 -359
- data/lib/dicom/d_write.rb +327 -395
- data/lib/dicom/deprecated.rb +1 -72
- data/lib/dicom/dictionary/elements.txt +3646 -0
- data/lib/dicom/dictionary/uids.txt +334 -0
- data/lib/dicom/dictionary_element.rb +61 -0
- data/lib/dicom/element.rb +278 -218
- data/lib/dicom/elemental.rb +21 -27
- data/lib/dicom/file_handler.rb +121 -121
- data/lib/dicom/image_item.rb +819 -861
- data/lib/dicom/image_processor.rb +24 -15
- data/lib/dicom/image_processor_mini_magick.rb +21 -23
- data/lib/dicom/image_processor_r_magick.rb +39 -34
- data/lib/dicom/item.rb +133 -120
- data/lib/dicom/link.rb +1531 -1532
- data/lib/dicom/logging.rb +155 -158
- data/lib/dicom/parent.rb +782 -847
- data/lib/dicom/ruby_extensions.rb +248 -229
- data/lib/dicom/sequence.rb +109 -92
- data/lib/dicom/stream.rb +480 -511
- data/lib/dicom/uid.rb +82 -0
- data/lib/dicom/variables.rb +9 -9
- data/lib/dicom/version.rb +5 -5
- data/rakefile.rb +29 -0
- metadata +130 -76
- data/lib/dicom/dictionary.rb +0 -3280
data/Gemfile
ADDED
data/dicom.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path('../lib/dicom/version', __FILE__)
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.platform = Gem::Platform::RUBY
|
7
|
+
s.name = 'dicom'
|
8
|
+
s.version = DICOM::VERSION
|
9
|
+
s.date = Time.now
|
10
|
+
s.summary = "Library for handling DICOM files and DICOM network communication."
|
11
|
+
s.require_paths = ['lib']
|
12
|
+
s.author = "Christoffer Lervag"
|
13
|
+
s.email = "chris.lervag@gmail.com"
|
14
|
+
s.homepage = "http://dicom.rubyforge.org/"
|
15
|
+
s.license = "GPLv3"
|
16
|
+
s.description = "DICOM is a standard widely used throughout the world to store and transfer medical image data. This library enables efficient and powerful handling of DICOM in Ruby, to the benefit of any student or professional who would like to use their favorite language to process DICOM files and communicate across the network."
|
17
|
+
s.files = Dir["{lib}/**/*", "[A-Z]*"]
|
18
|
+
s.rubyforge_project = 'dicom'
|
19
|
+
|
20
|
+
s.required_ruby_version = '>= 1.9.2'
|
21
|
+
s.required_rubygems_version = '>= 1.8.6'
|
22
|
+
|
23
|
+
s.add_development_dependency('bundler', '>= 1.0.0')
|
24
|
+
s.add_development_dependency('rake', '>= 0.9.2.2')
|
25
|
+
s.add_development_dependency('rspec', '>= 2.9.0')
|
26
|
+
s.add_development_dependency('mocha', '>= 0.10.5')
|
27
|
+
s.add_development_dependency('narray', '>= 0.6.0.0')
|
28
|
+
s.add_development_dependency('rmagick', '>= 2.12.0')
|
29
|
+
s.add_development_dependency('mini_magick', '>= 3.2.1')
|
30
|
+
s.add_development_dependency('yard', '>= 0.8.2')
|
31
|
+
end
|
data/lib/dicom.rb
CHANGED
@@ -1,51 +1,53 @@
|
|
1
|
-
# Loads the files that are used by
|
2
|
-
#
|
3
|
-
# The following classes are meant to be used by users of
|
4
|
-
# * DObject - for reading, manipulating and writing DICOM files.
|
5
|
-
# * Element, Sequence, Item, Parent, Elemental - users who wish to interact with
|
6
|
-
# their DICOM objects will use these classes/modules.
|
7
|
-
# * ImageItem - Image related methods are found in this class.
|
8
|
-
# * DClient - for client side network communication, like querying, moving & sending DICOM files.
|
9
|
-
# * DServer - for server side network communication: Setting up your own DICOM storage node (SCP).
|
10
|
-
# * Anonymizer - a convenience class for anonymizing your DICOM files.
|
11
|
-
#
|
12
|
-
# The rest of the classes visible in the documentation generated by
|
13
|
-
# in principle 'private' classes, which are mainly of interest to developers.
|
14
|
-
|
15
|
-
# Logging:
|
16
|
-
require_relative 'dicom/logging'
|
17
|
-
# Core library:
|
18
|
-
# Super classes/modules:
|
19
|
-
require_relative 'dicom/image_processor'
|
20
|
-
require_relative 'dicom/parent'
|
21
|
-
require_relative 'dicom/image_item'
|
22
|
-
require_relative 'dicom/elemental'
|
23
|
-
# Subclasses and independent classes:
|
24
|
-
require_relative 'dicom/d_client'
|
25
|
-
require_relative 'dicom/
|
26
|
-
require_relative 'dicom/
|
27
|
-
require_relative 'dicom/
|
28
|
-
require_relative 'dicom/
|
29
|
-
require_relative 'dicom/
|
30
|
-
require_relative 'dicom/
|
31
|
-
require_relative 'dicom/
|
32
|
-
require_relative 'dicom/
|
33
|
-
require_relative 'dicom/
|
34
|
-
require_relative 'dicom/
|
35
|
-
|
36
|
-
require_relative 'dicom/
|
37
|
-
|
38
|
-
require_relative 'dicom/
|
39
|
-
#
|
40
|
-
require_relative 'dicom/
|
41
|
-
|
42
|
-
require_relative 'dicom/
|
43
|
-
|
44
|
-
require_relative 'dicom/
|
45
|
-
|
46
|
-
|
47
|
-
require_relative 'dicom/
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
1
|
+
# Loads the files that are used by ruby-dicom.
|
2
|
+
#
|
3
|
+
# The following classes are meant to be used by users of ruby-dicom:
|
4
|
+
# * DObject - for reading, manipulating and writing DICOM files.
|
5
|
+
# * Element, Sequence, Item, Parent, Elemental - users who wish to interact with
|
6
|
+
# their DICOM objects will use these classes/modules.
|
7
|
+
# * ImageItem - Image related methods are found in this class.
|
8
|
+
# * DClient - for client side network communication, like querying, moving & sending DICOM files.
|
9
|
+
# * DServer - for server side network communication: Setting up your own DICOM storage node (SCP).
|
10
|
+
# * Anonymizer - a convenience class for anonymizing your DICOM files.
|
11
|
+
#
|
12
|
+
# The rest of the classes visible in the documentation generated by YARD are
|
13
|
+
# in principle 'private' classes, which are mainly of interest to developers.
|
14
|
+
|
15
|
+
# Logging:
|
16
|
+
require_relative 'dicom/logging'
|
17
|
+
# Core library:
|
18
|
+
# Super classes/modules:
|
19
|
+
require_relative 'dicom/image_processor'
|
20
|
+
require_relative 'dicom/parent'
|
21
|
+
require_relative 'dicom/image_item'
|
22
|
+
require_relative 'dicom/elemental'
|
23
|
+
# Subclasses and independent classes:
|
24
|
+
require_relative 'dicom/d_client'
|
25
|
+
require_relative 'dicom/d_object'
|
26
|
+
require_relative 'dicom/d_read'
|
27
|
+
require_relative 'dicom/d_server'
|
28
|
+
require_relative 'dicom/d_write'
|
29
|
+
require_relative 'dicom/element'
|
30
|
+
require_relative 'dicom/file_handler'
|
31
|
+
require_relative 'dicom/item'
|
32
|
+
require_relative 'dicom/link'
|
33
|
+
require_relative 'dicom/sequence'
|
34
|
+
require_relative 'dicom/stream'
|
35
|
+
# Dictionary:
|
36
|
+
require_relative 'dicom/d_library'
|
37
|
+
require_relative 'dicom/dictionary_element'
|
38
|
+
require_relative 'dicom/uid'
|
39
|
+
# Extensions to the Ruby library:
|
40
|
+
require_relative 'dicom/ruby_extensions'
|
41
|
+
# Module settings:
|
42
|
+
require_relative 'dicom/version'
|
43
|
+
require_relative 'dicom/constants'
|
44
|
+
require_relative 'dicom/variables'
|
45
|
+
# Image processors:
|
46
|
+
require_relative 'dicom/image_processor_mini_magick'
|
47
|
+
require_relative 'dicom/image_processor_r_magick'
|
48
|
+
# Deprecated methods:
|
49
|
+
require_relative 'dicom/deprecated'
|
50
|
+
|
51
|
+
# Extensions (non-core functionality):
|
52
|
+
require_relative 'dicom/anonymizer'
|
53
|
+
require_relative 'dicom/audit_trail'
|
data/lib/dicom/anonymizer.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
module DICOM
|
2
2
|
|
3
|
-
# This is a convenience class for handling anonymization of DICOM files.
|
3
|
+
# This is a convenience class for handling the anonymization (de-identification) of DICOM files.
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# (Clinical Trials De-identification Profiles, DICOM Standards Committee, Working Group 18)
|
5
|
+
# @note
|
6
|
+
# For 'advanced' anonymization, a good resource might be the work on "Clinical Trials
|
7
|
+
# De-identification Profiles" by the DICOM Standards Committee, Working Group 18:
|
8
|
+
# ftp://medical.nema.org/medical/dicom/supps/sup142_pc.pdf
|
10
9
|
#
|
11
10
|
class Anonymizer
|
12
11
|
include Logging
|
@@ -34,26 +33,15 @@ module DICOM
|
|
34
33
|
|
35
34
|
# Creates an Anonymizer instance.
|
36
35
|
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
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
|
-
#
|
51
|
-
# === Examples
|
52
|
-
#
|
53
|
-
# # Create an Anonymizer instance and restrict the log output:
|
36
|
+
# @note To customize logging behaviour, refer to the Logging module documentation.
|
37
|
+
# @param [Hash] options the options to create an anonymizer instance with
|
38
|
+
# @option options [String] :audit_trail a file name path. If the file contains old audit data, these are loaded and used in the current anonymization.
|
39
|
+
# @option options [Boolean] :uid 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.
|
40
|
+
# @option options [String] :uid_root an organization (or custom) UID root to use when replacing UIDs.
|
41
|
+
# @example Create an Anonymizer instance and restrict the log output
|
54
42
|
# a = Anonymizer.new
|
55
43
|
# a.logger.level = Logger::ERROR
|
56
|
-
#
|
44
|
+
# @example Perform anonymization using the audit trail feature
|
57
45
|
# a = Anonymizer.new(:audit_trail => "trail.json")
|
58
46
|
# a.enumeration = true
|
59
47
|
# a.folder = "//dicom/today/"
|
@@ -85,7 +73,7 @@ module DICOM
|
|
85
73
|
# Register the uid anonymization option:
|
86
74
|
@uid = options[:uid]
|
87
75
|
# 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] :
|
76
|
+
@uid_root = options[:uid_root] ? options[:uid_root] : UID_ROOT
|
89
77
|
# Setup audit trail if requested:
|
90
78
|
if options[:audit_trail]
|
91
79
|
@audit_trail_file = options[:audit_trail]
|
@@ -103,12 +91,8 @@ module DICOM
|
|
103
91
|
|
104
92
|
# Adds an exception folder which will be avoided when anonymizing.
|
105
93
|
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
# * <tt>path</tt> -- String. A path that will be avoided.
|
109
|
-
#
|
110
|
-
# === Examples
|
111
|
-
#
|
94
|
+
# @param [String] path a path that will be avoided
|
95
|
+
# @example Adding a folder
|
112
96
|
# a.add_exception("/home/dicom/tutorials/")
|
113
97
|
#
|
114
98
|
def add_exception(path)
|
@@ -122,12 +106,8 @@ module DICOM
|
|
122
106
|
|
123
107
|
# Adds a folder who's files will be anonymized.
|
124
108
|
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
# * <tt>path</tt> -- String. A path that will be included in the anonymization.
|
128
|
-
#
|
129
|
-
# === Examples
|
130
|
-
#
|
109
|
+
# @param [String] path a path that will be included in the anonymization
|
110
|
+
# @example Adding a folder
|
131
111
|
# a.add_folder("/home/dicom")
|
132
112
|
#
|
133
113
|
def add_folder(path)
|
@@ -135,12 +115,10 @@ module DICOM
|
|
135
115
|
@folders << path
|
136
116
|
end
|
137
117
|
|
138
|
-
#
|
139
|
-
# Returns nil if no match is found for the provided tag.
|
118
|
+
# Checks the enumeration status of this tag.
|
140
119
|
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
# * <tt>tag</tt> -- String. A data element tag.
|
120
|
+
# @param [String] tag a data element tag
|
121
|
+
# @return [Boolean, NilClass] the enumeration status of the tag, or nil if the tag has no match
|
144
122
|
#
|
145
123
|
def enum(tag)
|
146
124
|
raise ArgumentError, "Expected String, got #{tag.class}." unless tag.is_a?(String)
|
@@ -158,14 +136,10 @@ module DICOM
|
|
158
136
|
#
|
159
137
|
# This method is run when all settings have been finalized for the Anonymization instance.
|
160
138
|
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
# * Only top level data elements are anonymized!
|
164
|
-
#
|
165
|
-
#--
|
166
|
-
# FIXME: This method has grown a bit lengthy. Perhaps it should be looked at one day.
|
139
|
+
# @note Only top level data elements are anonymized!
|
167
140
|
#
|
168
141
|
def execute
|
142
|
+
# FIXME: This method has grown a bit lengthy. Perhaps it should be looked at one day.
|
169
143
|
# Search through the folders to gather all the files to be anonymized:
|
170
144
|
logger.info("Initiating anonymization process.")
|
171
145
|
start_time = Time.now.to_f
|
@@ -286,8 +260,10 @@ module DICOM
|
|
286
260
|
end
|
287
261
|
|
288
262
|
# Setter method for the identity file.
|
289
|
-
#
|
290
|
-
#
|
263
|
+
#
|
264
|
+
# @deprecated The identity file feature is deprecated!
|
265
|
+
# Please use the AuditTrail feature instead.
|
266
|
+
# @param [String] file_name the path of the identity file
|
291
267
|
#
|
292
268
|
def identity_file=(file_name)
|
293
269
|
# Deprecation warning:
|
@@ -307,7 +283,7 @@ module DICOM
|
|
307
283
|
type_lengths = Array.new
|
308
284
|
value_lengths = Array.new
|
309
285
|
@tags.each_index do |i|
|
310
|
-
name, vr = LIBRARY.
|
286
|
+
name, vr = LIBRARY.name_and_vr(@tags[i])
|
311
287
|
names << name
|
312
288
|
types << vr
|
313
289
|
tag_lengths[i] = @tags[i].length
|
@@ -352,12 +328,8 @@ module DICOM
|
|
352
328
|
|
353
329
|
# Removes a tag from the list of tags that will be anonymized.
|
354
330
|
#
|
355
|
-
#
|
356
|
-
#
|
357
|
-
# * <tt>tag</tt> -- String. A data element tag.
|
358
|
-
#
|
359
|
-
# === Examples
|
360
|
-
#
|
331
|
+
# @param [String] tag a data element tag
|
332
|
+
# @example Do not anonymize the Patient's Name tag
|
361
333
|
# a.remove_tag("0010,0010")
|
362
334
|
#
|
363
335
|
def remove_tag(tag)
|
@@ -370,15 +342,11 @@ module DICOM
|
|
370
342
|
@enumerations.delete_at(pos)
|
371
343
|
end
|
372
344
|
end
|
373
|
-
|
345
|
+
|
374
346
|
# Compeletely deletes a tag from the file
|
375
347
|
#
|
376
|
-
#
|
377
|
-
#
|
378
|
-
# * <tt>tag</tt> -- String. A data element tag.
|
379
|
-
#
|
380
|
-
# === Examples
|
381
|
-
#
|
348
|
+
# @param [String] tag a data element tag
|
349
|
+
# @example Completely delete the Patient's Name tag from the DICOM files
|
382
350
|
# a.delete_tag("0010,0010")
|
383
351
|
#
|
384
352
|
def delete_tag(tag)
|
@@ -390,19 +358,12 @@ module DICOM
|
|
390
358
|
# Sets the anonymization settings for the specified tag. If the tag is already present in the list
|
391
359
|
# of tags to be anonymized, its settings are updated, and if not, a new tag entry is created.
|
392
360
|
#
|
393
|
-
#
|
394
|
-
#
|
395
|
-
#
|
396
|
-
#
|
397
|
-
#
|
398
|
-
#
|
399
|
-
#
|
400
|
-
# * <tt>:value</tt> -- The replacement value to be used when anonymizing this data element. Defaults to the pre-existing value and "" for new tags.
|
401
|
-
# * <tt>:enum</tt> -- Boolean. Specifies if enumeration is to be used for this tag. Defaults to the pre-existing value and false for new tags.
|
402
|
-
#
|
403
|
-
# === Examples
|
404
|
-
#
|
405
|
-
# a.set_tag("0010,0010, :value => "MrAnonymous", :enum => true)
|
361
|
+
# @param [String] tag a data element tag
|
362
|
+
# @param [Hash] options the anonymization settings for the specified tag
|
363
|
+
# @option options [String, Integer, Float] :value the replacement value to be used when anonymizing this data element. Defaults to the pre-existing value and "" for new tags.
|
364
|
+
# @option options [String, Integer, Float] :enum specifies if enumeration is to be used for this tag. Defaults to the pre-existing value and false for new tags.
|
365
|
+
# @example Set the anonymization settings of the Patient's Name tag
|
366
|
+
# a.set_tag("0010,0010", :value => "MrAnonymous", :enum => true)
|
406
367
|
#
|
407
368
|
def set_tag(tag, options={})
|
408
369
|
raise ArgumentError, "Expected String, got #{tag.class}." unless tag.is_a?(String)
|
@@ -415,19 +376,18 @@ module DICOM
|
|
415
376
|
else
|
416
377
|
# Add new elements:
|
417
378
|
@tags << tag
|
418
|
-
@values << (options[:value] ? options[:value] :
|
379
|
+
@values << (options[:value] ? options[:value] : default_value(tag))
|
419
380
|
@enumerations << (options[:enum] ? options[:enum] : false)
|
420
381
|
end
|
421
382
|
end
|
422
383
|
|
423
|
-
#
|
424
|
-
# If enumeration is selected for the particular tag, a number will be
|
425
|
-
# appended in addition to the string that is returned here.
|
426
|
-
# Returns nil if no match is found for the provided tag.
|
384
|
+
# Gives the value which will be used when anonymizing this tag.
|
427
385
|
#
|
428
|
-
#
|
386
|
+
# @note If enumeration is selected for a string type tag, a number will be
|
387
|
+
# appended in addition to the string that is returned here.
|
429
388
|
#
|
430
|
-
#
|
389
|
+
# @param [String] tag a data element tag
|
390
|
+
# @return [String, Integer, Float, NilClass] the replacement value for the specified tag, or nil if the tag is not matched
|
431
391
|
#
|
432
392
|
def value(tag)
|
433
393
|
raise ArgumentError, "Expected String, got #{tag.class}." unless tag.is_a?(String)
|
@@ -442,18 +402,15 @@ module DICOM
|
|
442
402
|
end
|
443
403
|
|
444
404
|
|
445
|
-
# The following methods are private:
|
446
405
|
private
|
447
406
|
|
448
407
|
|
449
408
|
# Finds the common path (if any) in the instance file path array, by performing a recursive search
|
450
409
|
# on the folders that make up the path of one such file.
|
451
|
-
# Returns the index of the last folder in the path of the selected file that is common for all file paths.
|
452
|
-
#
|
453
|
-
# === Parameters
|
454
410
|
#
|
455
|
-
#
|
456
|
-
#
|
411
|
+
# @param [Array<String>] str_arr an array of folder strings from the path of a select file
|
412
|
+
# @param [Fixnum] index the index of the folder in str_arr to check against all file paths
|
413
|
+
# @return [Fixnum] the index of the last folder in the path of the selected file that is common for all file paths
|
457
414
|
#
|
458
415
|
def common_path(str_arr, index=0)
|
459
416
|
common_folders = Array.new
|
@@ -482,16 +439,31 @@ module DICOM
|
|
482
439
|
end
|
483
440
|
end
|
484
441
|
|
442
|
+
# Determines a default value to use for anonymizing the given tag.
|
443
|
+
#
|
444
|
+
# @param [String] tag a data element tag
|
445
|
+
# @return [String, Integer, Float] the default replacement value for a given tag
|
446
|
+
#
|
447
|
+
def default_value(tag)
|
448
|
+
name, vr = LIBRARY.name_and_vr(tag)
|
449
|
+
conversion = VALUE_CONVERSION[vr] || :to_s
|
450
|
+
case conversion
|
451
|
+
when :to_i then return 0
|
452
|
+
when :to_f then return 0.0
|
453
|
+
else
|
454
|
+
# Assume type is string and return an empty string:
|
455
|
+
return ""
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
485
459
|
# Handles the enumeration for the given data element tag.
|
486
460
|
# If its value has been encountered before, its corresponding enumerated
|
487
461
|
# replacement value is retrieved, and if a new original value is encountered,
|
488
462
|
# 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.
|
490
|
-
#
|
491
|
-
# === Parameters
|
492
463
|
#
|
493
|
-
#
|
494
|
-
#
|
464
|
+
# @param [String, Integer, Float] original the original value of the tag to be anonymized
|
465
|
+
# @param [Fixnum] j the index of this tag in the tag-related instance arrays
|
466
|
+
# @return [String, Integer, Float] the replacement value which is used for the anonymization of the tag
|
495
467
|
#
|
496
468
|
def enumerated_value(original, j)
|
497
469
|
# Is enumeration requested for this tag?
|
@@ -503,7 +475,11 @@ module DICOM
|
|
503
475
|
# This original value has not been encountered yet. Determine the index to use.
|
504
476
|
index = @audit_trail.records(@tags[j]).length + 1
|
505
477
|
# Create the replacement value:
|
506
|
-
|
478
|
+
if @values[j].is_a?(String)
|
479
|
+
replacement = @values[j] + index.to_s
|
480
|
+
else
|
481
|
+
replacement = @values[j] + index
|
482
|
+
end
|
507
483
|
# Add this tag record to the audit trail:
|
508
484
|
@audit_trail.add_record(@tags[j], original, replacement)
|
509
485
|
end
|
@@ -558,8 +534,8 @@ module DICOM
|
|
558
534
|
end
|
559
535
|
|
560
536
|
# Analyzes the write_path and the 'read' file path to determine if they have some common root.
|
561
|
-
# If there are parts of the file path that exists also in the write path, the common parts will
|
562
|
-
# The processed paths are put in a write_path instance array.
|
537
|
+
# If there are parts of the file path that exists also in the write path, the common parts will
|
538
|
+
# not be added to the write_path. The processed paths are put in a write_path instance array.
|
563
539
|
#
|
564
540
|
def process_write_paths
|
565
541
|
# First make sure @write_path ends with a file separator character:
|
@@ -594,13 +570,10 @@ module DICOM
|
|
594
570
|
|
595
571
|
# Replaces the UIDs of the given DICOM object.
|
596
572
|
#
|
597
|
-
#
|
598
|
-
#
|
599
|
-
#
|
600
|
-
#
|
601
|
-
# are preserved, and the relations between files in a study/series
|
602
|
-
# should remain valid.
|
603
|
-
#
|
573
|
+
# @note Empty UIDs are ignored (we don't generate new UIDs for these).
|
574
|
+
# @note If AuditTrail is set, the relationship between old and new UIDs are preserved,
|
575
|
+
# and the relations between files in a study/series should remain valid.
|
576
|
+
# @param [DObject] dcm the dicom object to be processed
|
604
577
|
#
|
605
578
|
def replace_uids(dcm)
|
606
579
|
@uids.each_pair do |tag, prefix|
|
@@ -641,28 +614,27 @@ module DICOM
|
|
641
614
|
# Sets up default tags that will be anonymized, along with default replacement values and enumeration settings.
|
642
615
|
# This data is stored in 3 separate instance arrays for tags, values and enumeration.
|
643
616
|
data = [
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
617
|
+
["0008,0012", "20000101", false], # Instance Creation Date
|
618
|
+
["0008,0013", "000000.00", false], # Instance Creation Time
|
619
|
+
["0008,0020", "20000101", false], # Study Date
|
620
|
+
["0008,0023", "20000101", false], # Image Date
|
621
|
+
["0008,0030", "000000.00", false], # Study Time
|
622
|
+
["0008,0033", "000000.00", false], # Image Time
|
623
|
+
["0008,0050", "", true], # Accession Number
|
624
|
+
["0008,0080", "Institution", true], # Institution name
|
625
|
+
["0008,0090", "Physician", true], # Referring Physician's name
|
626
|
+
["0008,1010", "Station", true], # Station name
|
627
|
+
["0008,1070", "Operator", true], # Operator's Name
|
628
|
+
["0010,0010", "Patient", true], # Patient's name
|
629
|
+
["0010,0020", "ID", true], # Patient's ID
|
630
|
+
["0010,0030", "20000101", false], # Patient's Birth Date
|
631
|
+
["0010,0040", "N", false], # Patient's Sex
|
632
|
+
["0020,4000", "", false], # Image Comments
|
660
633
|
].transpose
|
661
634
|
@tags = data[0]
|
662
635
|
@values = data[1]
|
663
636
|
@enumerations = data[2]
|
664
|
-
|
665
|
-
# Tags to be deleted completely during anonymization
|
637
|
+
# Tags to be deleted completely during anonymization:
|
666
638
|
@delete_tags = [
|
667
639
|
]
|
668
640
|
end
|
@@ -670,6 +642,9 @@ module DICOM
|
|
670
642
|
# Writes an identity file, which allows reidentification of DICOM files that have been anonymized
|
671
643
|
# using the enumeration feature. Values are saved in a text file, using semi colon delineation.
|
672
644
|
#
|
645
|
+
# @deprecated The identity file feature is deprecated!
|
646
|
+
# Please use the AuditTrail feature instead.
|
647
|
+
#
|
673
648
|
def write_identity_file
|
674
649
|
raise ArgumentError, "Expected String, got #{@identity_file.class}. Unable to write identity file." unless @identity_file.is_a?(String)
|
675
650
|
# Open file and prepare to write text:
|