dicom 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +47 -25
- data/DOCUMENTATION +72 -43
- data/README +20 -20
- data/lib/Anonymizer.rb +61 -56
- data/lib/DLibrary.rb +47 -24
- data/lib/DObject.rb +457 -461
- data/lib/DRead.rb +131 -130
- data/lib/DWrite.rb +87 -89
- data/lib/Dictionary.rb +14 -12
- data/lib/dicom.rb +1 -0
- data/lib/ruby_extensions.rb +25 -0
- metadata +12 -9
data/CHANGELOG
CHANGED
@@ -1,4 +1,24 @@
|
|
1
|
-
=0.
|
1
|
+
= 0.5
|
2
|
+
|
3
|
+
=== 4th May, 2009
|
4
|
+
|
5
|
+
* Several small changes have been made to achieve compatibility with both Ruby versions 1.8 and 1.9.
|
6
|
+
* Implemented a change in syntax for several methods with a goal of simplification.
|
7
|
+
* Implemented a change in syntax for some methods, variables and messages in order
|
8
|
+
to better match the terminology used in the official DICOM documents.
|
9
|
+
* Added a new attr_reader :errors, an array that holds any warnings issued during your
|
10
|
+
interaction with DObject.
|
11
|
+
* DObject has received new attr_readers for the arrays holding information on the DICOM object.
|
12
|
+
See documentation for details.
|
13
|
+
* Several methods have been cleaned up, making execution in some cases somewhat snappier.
|
14
|
+
* Several methods have been made more robust.
|
15
|
+
* Added new keyword :partial to the get_pos() method, which will enable search for partial string matches.
|
16
|
+
* Added new keyword :array to the get_value() and get_raw() methods which enables easy extraction of
|
17
|
+
multiple values of a given tag to an array (relevant for tags present at multiple places in a DICOM file)
|
18
|
+
* Fixed a bug where exception folders where ignored in the Anonymizer class.
|
19
|
+
|
20
|
+
|
21
|
+
= 0.4
|
2
22
|
|
3
23
|
=== 3rd February, 2009
|
4
24
|
|
@@ -22,6 +42,7 @@
|
|
22
42
|
* Introducing the Anonymizer class, which takes advantage of the new write capability in Ruby DICOM
|
23
43
|
to offer a fairly powerful and customizable tool for anonymizing your DICOM files.
|
24
44
|
|
45
|
+
|
25
46
|
= 0.3
|
26
47
|
|
27
48
|
=== 12th October, 2008
|
@@ -48,28 +69,29 @@
|
|
48
69
|
* DRead class is more resistant to breaking if it is handed a faulty file to read, and will return an error message instead of halting execution.
|
49
70
|
* Added option to load DICOM object in verbose or silent mode.
|
50
71
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
*
|
61
|
-
* Retrieve tags,
|
62
|
-
* Retrieve
|
63
|
-
* Retrieve image data as
|
64
|
-
*
|
65
|
-
* Print
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
*
|
71
|
-
*
|
72
|
-
*
|
73
|
-
* Reading
|
74
|
-
* Reading
|
72
|
+
|
73
|
+
= 0.1
|
74
|
+
|
75
|
+
=== 20th July, 2008
|
76
|
+
|
77
|
+
First public release.
|
78
|
+
The library does have several known issues and lacks some features I would like it to have, but it does offer basic functionality and should be usable for people interested in working with DICOM files in Ruby. The reading algorithm has been tested succesfully with some 40 different DICOM files, so it should be fairly robust.
|
79
|
+
|
80
|
+
Features:
|
81
|
+
* Reads DICOM files
|
82
|
+
* Retrieve tags, formatted
|
83
|
+
* Retrieve tags, unformatted
|
84
|
+
* Retrieve image data as NArray object
|
85
|
+
* Retrieve image data as RMagick object
|
86
|
+
* Print file properties
|
87
|
+
* Print tag information
|
88
|
+
|
89
|
+
|
90
|
+
Known issues:
|
91
|
+
* 12 bit image data not supported
|
92
|
+
* Color images not supported in NArray and RMagick retrieve methods
|
93
|
+
* Unpacking compressed image data has basic support but is not properly tested yet.
|
94
|
+
* Reading Big Endian files has fairly good, but possibly not full, support.
|
95
|
+
* Reading on a Big Endian system is not tested.
|
96
|
+
* Reading of multiple frame image data to RMagick does not work in all cases.
|
75
97
|
* Retrieving images when file contains two or more unrelated images may not be handled correctly.
|
data/DOCUMENTATION
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
DICOM is a small library for reading, editing and writing DICOM files.
|
2
2
|
It is written completely in Ruby and has no external dependencies.
|
3
3
|
|
4
|
-
Copyright 2008-2009 Christoffer
|
4
|
+
Copyright 2008-2009 Christoffer Lerv�g (chris.lervag [@nospam] @gmail.com)
|
5
5
|
|
6
6
|
INSTALLATION
|
7
7
|
|
@@ -40,11 +40,14 @@ PUBLIC CLASS METHODS
|
|
40
40
|
Example 3: (Open an empty DICOM object)
|
41
41
|
obj = DICOM::DObject.new(nil)
|
42
42
|
|
43
|
-
ACCESSORS
|
43
|
+
ACCESSORS (read only)
|
44
44
|
:read_success
|
45
45
|
A boolean that is true if DICOM object was read successfully, and false if not.
|
46
46
|
:write_success
|
47
47
|
A boolean that is true if DICOM object was written successfully, and false if not.
|
48
|
+
:errors
|
49
|
+
An array holding any error messages, warnings or notices that have been logged
|
50
|
+
during your interaction with DObject.
|
48
51
|
:modality
|
49
52
|
A string which holds the description of the modality of the DICOM object that has been read.
|
50
53
|
Example of use:
|
@@ -52,95 +55,121 @@ ACCESSORS
|
|
52
55
|
if obj.read_success
|
53
56
|
puts obj.modality
|
54
57
|
end
|
58
|
+
The following accessors are the arrays that hold all the information gathered on the DICOM object.
|
59
|
+
As such, their length is equal to the number of tags in a DICOM object.
|
60
|
+
:names
|
61
|
+
:tags
|
62
|
+
:types
|
63
|
+
:lengths
|
64
|
+
:values
|
65
|
+
:raw
|
66
|
+
:levels
|
55
67
|
|
56
68
|
PUBLIC INSTANCE METHODS
|
57
69
|
|
58
|
-
children(
|
59
|
-
Returns the positions of all
|
60
|
-
This is useful if you later want to get the position(s) of a certain
|
70
|
+
children(element, options={})
|
71
|
+
Returns the positions of all data elements inside the hierarchy of a sequence or an item.
|
72
|
+
This is useful if you later want to get the position(s) of a certain element,
|
61
73
|
restricted to the positions inside the given sequence or item.
|
62
|
-
|
74
|
+
Element may be an array index, element name or element tag.
|
75
|
+
Example 1: (Return all element positions that is contained in the following sequence)
|
63
76
|
pos = obj.children("3006,0082")
|
64
|
-
Example 2: (Return all
|
77
|
+
Example 2: (Return all element positions that is contained only directly beneath the following sequence)
|
65
78
|
pos = obj.children("3006,0082", :next_only => true)
|
66
79
|
|
67
|
-
get_frames
|
80
|
+
get_frames
|
68
81
|
Returns the number of frames present in the image data in the DICOM file.
|
69
82
|
|
70
|
-
get_image_magick
|
83
|
+
get_image_magick
|
71
84
|
Returns an array of RMagick image objects, where the size of the array corresponds
|
72
85
|
with the number of frames in the image data.
|
73
|
-
To call this method the user needs to have
|
86
|
+
To call this method the user needs to have loaded the RMagick bindings in advance (require 'RMagick').
|
74
87
|
Example (retrieve object and display first frame):
|
75
88
|
require 'RMagick'
|
76
|
-
data = dicom.get_image_magick()
|
89
|
+
data = dicom.get_image_magick()
|
77
90
|
data[0].display
|
78
91
|
|
79
|
-
get_image_narray
|
92
|
+
get_image_narray
|
80
93
|
Returns a 3d NArray object where the array dimensions are related to [frames, columns, rows].
|
81
|
-
To call this method the user needs to have
|
94
|
+
To call this method the user needs to have loaded the NArray library in advance (require 'narray').
|
82
95
|
Example (retrieve object and display first frame):
|
83
96
|
require 'narray'
|
84
97
|
require 'nimage'
|
85
|
-
data = obj.get_image_narray()
|
98
|
+
data = obj.get_image_narray()
|
86
99
|
NImage.show data[0,true,true]
|
87
100
|
|
88
|
-
get_image_pos
|
89
|
-
Returns the index(es) of the
|
101
|
+
get_image_pos
|
102
|
+
Returns the index(es) of the data element(s) that contain image data.
|
90
103
|
|
91
|
-
get_pos(
|
92
|
-
Returns the index(es) of the
|
104
|
+
get_pos(string, options={})
|
105
|
+
Returns the index(es) of the data element(s) in the DICOM file that match
|
106
|
+
the supplied element tag or name.
|
93
107
|
Example 1: (Find all occurences of the specified tag in the object)
|
94
108
|
pos = obj.get_pos("3006,0080")
|
95
109
|
Example 2: (Find all occurences of the specified tag inside the specified sequence)
|
96
110
|
selection = obj.children("3006,0082")
|
97
111
|
pos = obj.get_pos("3006,0080", :array => selection)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
112
|
+
Example 3: (Using the :partial argument to find position of all elements containing a specific string)
|
113
|
+
pos = obj.get_pos("0010", :partial => true)
|
114
|
+
pos = obj.get_pos("Name", :partial => true)
|
115
|
+
|
116
|
+
get_raw(element, options={})
|
117
|
+
Returns the raw data of the requested DICOM data element.
|
118
|
+
Element may be an array index, element name or element tag.
|
119
|
+
If you wish to return multiple data values of a tag that occurs several times in the file,
|
120
|
+
use the keyword :array => true .
|
121
|
+
Example: (Returns all data values in a array)
|
122
|
+
contour_data = obj.get_raw("3006,0050", :array => true)
|
123
|
+
|
124
|
+
get_value(element)
|
125
|
+
Returns the value (processed raw data) of the requested DICOM data element.
|
126
|
+
Element may be an array index, element name or element tag.
|
127
|
+
If you wish to return multiple values of a tag that occurs several times in the file,
|
128
|
+
use the keyword :array => true .
|
129
|
+
Example: (Returns all data values in a array)
|
130
|
+
contour_data = obj.get_value("3006,0050", :array => true)
|
106
131
|
|
107
132
|
image_to_file(file)
|
108
133
|
Dumps the pixel data of the DICOM object directly to the specified file.
|
109
134
|
This is useful if you wish to extract this data to process it with another program.
|
110
135
|
|
111
|
-
parents(
|
136
|
+
parents(element)
|
112
137
|
Returns the positions of all parents of this tag in the hierarchy.
|
113
138
|
This is useful if you want to know the position of the items or sequence tags that 'hold' your tag.
|
139
|
+
Element may be an array index, element name or element tag.
|
114
140
|
Example:
|
115
141
|
pos = obj.parents("300C,0006")
|
116
142
|
|
117
|
-
print(
|
118
|
-
Prints the information
|
143
|
+
print(pos, options={})
|
144
|
+
Prints the information gathered on one or several/all tag(s) in the DICOM object:
|
119
145
|
(index, [hierarchy level,] label, name, type, length, value)
|
120
146
|
The method can print to both screen or to a text file. If print to file is chosen,
|
121
147
|
the text file will be put in the folder of the original DICOM file with a '.txt' extension.
|
122
|
-
The
|
148
|
+
The argument pos may be a number (array position), an array of numbers, or true.
|
123
149
|
Example 1: (Print all tags to file, with both tree visualization and level numbers)
|
124
150
|
obj.print(true, :levels => true, :tree => true, :file => true)
|
125
151
|
Example 2: (Print an array of tags to screen, no level or tree visualization)
|
126
152
|
obj.print([4,5,6])
|
127
153
|
|
128
|
-
print_all
|
154
|
+
print_all
|
129
155
|
Prints information of all tags stored in the DICOM object to the screen.
|
130
156
|
|
131
|
-
print_properties
|
157
|
+
print_properties
|
132
158
|
Prints the key structural properties of the DICOM file to the screen.
|
133
159
|
|
134
|
-
|
135
|
-
Removes the specified
|
136
|
-
if you are editing a DICOM object and wants to get rid of
|
160
|
+
remove(element)
|
161
|
+
Removes the specified data element from the DICOM object. You can use this method
|
162
|
+
if you are editing a DICOM object and wants to get rid of one or more elements.
|
163
|
+
Element may be an array index, element name or element tag.
|
137
164
|
|
138
|
-
set_value(value, options={})
|
139
|
-
This method can be used both to edit an existing
|
165
|
+
set_value(value, element, options={})
|
166
|
+
This method can be used both to edit an existing data element, or to create
|
167
|
+
new data elements in your DICOM object.
|
168
|
+
Element may be an array index, element name or element tag.
|
140
169
|
Example 1: (Edit patient name)
|
141
|
-
obj.set_value("Anonymous",
|
170
|
+
obj.set_value("Anonymous", "0010,0010", :create => false)
|
142
171
|
Example 2: (Insert binary data for a specific tag)
|
143
|
-
obj.set_value(data,
|
172
|
+
obj.set_value(data, 52, :bin => true, :create => false)
|
144
173
|
|
145
174
|
set_image_magick(object)
|
146
175
|
Inserts a RMagick image object to the pixel data tag of your DICOM object.
|
@@ -150,10 +179,10 @@ PUBLIC INSTANCE METHODS
|
|
150
179
|
This can be useful if you have processed some image data using a custom program
|
151
180
|
and just wants to put that data back into a DICOM object.
|
152
181
|
|
153
|
-
|
182
|
+
write(file)
|
154
183
|
Writes the DICOM object to the specified file.
|
155
184
|
Example:
|
156
|
-
obj.
|
185
|
+
obj.write(myPath + "test_file.dcm")
|
157
186
|
|
158
187
|
|
159
188
|
CLASS Anonymizer
|
@@ -165,7 +194,7 @@ PUBLIC CLASS METHODS
|
|
165
194
|
Example:
|
166
195
|
a = DICOM::Anonymizer.new
|
167
196
|
|
168
|
-
ACCESSORS
|
197
|
+
ACCESSORS (Read & write)
|
169
198
|
:blank
|
170
199
|
A boolean that you can set if you want to all anonymization tags to be blank
|
171
200
|
instead of having some generic value.
|
@@ -211,7 +240,7 @@ PUBLIC INSTANCE METHODS
|
|
211
240
|
Verbose (=true/false) will apply to the read/update/write process that takes place in DObject, and not
|
212
241
|
the messages of the Anonymization script itself.
|
213
242
|
|
214
|
-
print
|
243
|
+
print
|
215
244
|
Prints the list of tags that have been selected for anonymization, along with the values
|
216
245
|
that the original tags will be replaced with. If enumeration is selected, this method will also
|
217
246
|
print which tags have been selected for enumeration.
|
data/README
CHANGED
@@ -4,42 +4,42 @@ RUBY DICOM
|
|
4
4
|
SUMMARY
|
5
5
|
--------
|
6
6
|
|
7
|
-
This is a fairly basic library for
|
7
|
+
This is a fairly basic library for handling DICOM files in Ruby. Digital Imaging and Communications in Medicine (DICOM) is a standard for handling, storing, printing, and transmitting information in medical imaging. It includes a file format definition and a network communications protocol. Ruby DICOM supports reading from, editing and writing to this file format.
|
8
8
|
|
9
9
|
BASIC USAGE
|
10
10
|
-----------
|
11
11
|
|
12
12
|
require 'dicom'
|
13
13
|
# Read file:
|
14
|
-
dcm = DICOM::DObject.new("myFile.dcm")
|
15
|
-
# Display some key information about the file:
|
14
|
+
dcm = DICOM::DObject.new("myFile.dcm")
|
15
|
+
# Display some key information about the file:
|
16
16
|
dcm.print_properties()
|
17
17
|
# Print all tags to screen:
|
18
18
|
dcm.print(true)
|
19
|
-
# Retrieve a
|
19
|
+
# Retrieve a data element value:
|
20
20
|
name = dcm.get_value("0010.0010")
|
21
21
|
# Retrieve pixel data:
|
22
22
|
pixels = dcm.get_value("7FE0.0010")
|
23
|
-
# Load pixel data
|
23
|
+
# Load pixel data to a RMagick object and display it on screen:
|
24
24
|
image = dcm.get_image_magick()
|
25
25
|
image[0].display
|
26
|
-
# Load pixel data
|
26
|
+
# Load pixel data to a NArray object and display it on screen:
|
27
27
|
image = dcm.get_image_narray()
|
28
|
-
NImage.show image[0,true,true]
|
29
|
-
|
30
|
-
Tip:
|
31
|
-
When playing around with Ruby DICOM in irb, you may be annoyed
|
32
|
-
with all the information that is printed to screen, regardless
|
33
|
-
if you have specified verbose as false. This is because in irb
|
34
|
-
every variable loaded in the program is automatically printed.
|
35
|
-
A hack to avoid this effect is to append ";0" after a command.
|
36
|
-
Example:
|
28
|
+
NImage.show image[0,true,true]
|
29
|
+
|
30
|
+
Tip:
|
31
|
+
When playing around with Ruby DICOM in irb, you may be annoyed
|
32
|
+
with all the information that is printed to screen, regardless
|
33
|
+
if you have specified verbose as false. This is because in irb
|
34
|
+
every variable loaded in the program is automatically printed.
|
35
|
+
A hack to avoid this effect is to append ";0" after a command.
|
36
|
+
Example:
|
37
37
|
dcm = DICOM::DObject.new("myFile.dcm") ;0
|
38
|
-
|
38
|
+
|
39
39
|
COPYRIGHT
|
40
40
|
---------
|
41
41
|
|
42
|
-
Copyright 2008-2009 Christoffer
|
42
|
+
Copyright 2008-2009 Christoffer Lerv�g
|
43
43
|
|
44
44
|
This program is free software: you can redistribute it and/or modify
|
45
45
|
it under the terms of the GNU General Public License as published by
|
@@ -59,12 +59,12 @@ ABOUT ME
|
|
59
59
|
--------
|
60
60
|
|
61
61
|
Name:
|
62
|
-
Christoffer
|
62
|
+
Christoffer Lerv�g
|
63
63
|
|
64
64
|
Location:
|
65
65
|
Oslo, Norway
|
66
66
|
|
67
67
|
Email:
|
68
68
|
chris.lervag [@nospam] @gmail.com
|
69
|
-
Please don't hesitate to email me if have any thoughts on this project!
|
70
|
-
|
69
|
+
Please don't hesitate to email me if have any thoughts on this project!
|
70
|
+
|
data/lib/Anonymizer.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
-
# Copyright 2008-2009 Christoffer
|
1
|
+
# Copyright 2008-2009 Christoffer Lervag
|
2
2
|
module DICOM
|
3
3
|
|
4
4
|
# Class for anonymizing DICOM files:
|
5
5
|
# A good resource on this topic (report from the DICOM standards committee, work group 18):
|
6
6
|
# ftp://medical.nema.org/medical/dicom/Supps/sup142_03.pdf
|
7
7
|
class Anonymizer
|
8
|
-
|
8
|
+
|
9
9
|
attr_accessor :blank, :enumeration, :identity_file, :verbose, :write_path
|
10
|
-
|
10
|
+
|
11
11
|
# Initialize the Anonymizer instance:
|
12
12
|
def initialize(opts={})
|
13
13
|
# Default verbosity is true: # NB: verbosity is not used currently
|
@@ -22,11 +22,11 @@ module DICOM
|
|
22
22
|
# Array of folders to be processed for anonymization:
|
23
23
|
@folders = Array.new
|
24
24
|
@exceptions = Array.new
|
25
|
-
#
|
25
|
+
# Data elements which will be anonymized (the array will hold a list of tag strings):
|
26
26
|
@tags = Array.new
|
27
|
-
# Default values to use on anonymized
|
27
|
+
# Default values to use on anonymized data elements:
|
28
28
|
@values = Array.new
|
29
|
-
# Which
|
29
|
+
# Which data elements will have enumeration applied, if requested by the user:
|
30
30
|
@enum = Array.new
|
31
31
|
# We use a hash to store information from DICOM files if enumeration is desired:
|
32
32
|
@enum_old_hash = {}
|
@@ -35,23 +35,23 @@ module DICOM
|
|
35
35
|
@files = Array.new
|
36
36
|
# Write paths will be determined later and put in this array:
|
37
37
|
@write_paths = Array.new
|
38
|
-
# Set the default
|
38
|
+
# Set the default data elements to be anonymized:
|
39
39
|
set_defaults()
|
40
40
|
end # of method initialize
|
41
|
-
|
42
|
-
|
41
|
+
|
42
|
+
|
43
43
|
# Adds a folder who's files will be anonymized:
|
44
44
|
def add_folder(path)
|
45
45
|
@folders += [path] if path
|
46
46
|
end
|
47
|
-
|
48
|
-
|
47
|
+
|
48
|
+
|
49
49
|
# Adds an exception folder that is to be avoided when anonymizing:
|
50
50
|
def add_exception(path)
|
51
51
|
@exceptions += [path] if path
|
52
52
|
end
|
53
|
-
|
54
|
-
|
53
|
+
|
54
|
+
|
55
55
|
# Adds a tag to the list of tags that will be anonymized:
|
56
56
|
def add_tag(tag, opts={})
|
57
57
|
# Options and defaults:
|
@@ -60,7 +60,7 @@ module DICOM
|
|
60
60
|
if tag
|
61
61
|
if tag.is_a?(String)
|
62
62
|
if tag.length == 9
|
63
|
-
# Add
|
63
|
+
# Add anonymization information for this tag:
|
64
64
|
@tags += [tag]
|
65
65
|
@values += [value]
|
66
66
|
@enum += [enum]
|
@@ -74,8 +74,8 @@ module DICOM
|
|
74
74
|
puts "Warning: No tag supplied. Nothing to add."
|
75
75
|
end
|
76
76
|
end # of method add_tag
|
77
|
-
|
78
|
-
|
77
|
+
|
78
|
+
|
79
79
|
# Set enumeration status for a specific tag (toggle true/false)
|
80
80
|
def change_enum(tag, enum)
|
81
81
|
pos = @tags.index(tag)
|
@@ -89,8 +89,8 @@ module DICOM
|
|
89
89
|
puts "Specified tag not found in anonymization array. No changes made."
|
90
90
|
end
|
91
91
|
end # of method change_enum
|
92
|
-
|
93
|
-
|
92
|
+
|
93
|
+
|
94
94
|
# Changes the value used in anonymization for a specific tag:
|
95
95
|
def change_value(tag, value)
|
96
96
|
pos = @tags.index(tag)
|
@@ -104,8 +104,8 @@ module DICOM
|
|
104
104
|
puts "Specified tag not found in anonymization array. No changes made."
|
105
105
|
end
|
106
106
|
end # of method change_value
|
107
|
-
|
108
|
-
|
107
|
+
|
108
|
+
|
109
109
|
# Executes the anonymization process:
|
110
110
|
def execute(verbose=false)
|
111
111
|
# Search through the folders to gather all the files to be anonymized:
|
@@ -132,7 +132,7 @@ module DICOM
|
|
132
132
|
# existing information associated with each tag:
|
133
133
|
create_enum_hash() if @enumeration
|
134
134
|
# Start the read/update/write process:
|
135
|
-
puts "Initiating read/update/write process..."
|
135
|
+
puts "Initiating read/update/write process (This may take some time)..."
|
136
136
|
# Monitor whether every file read/write was successful:
|
137
137
|
all_read = true
|
138
138
|
all_write = true
|
@@ -158,10 +158,10 @@ module DICOM
|
|
158
158
|
value = @values[j]
|
159
159
|
end # of if @blank..else..
|
160
160
|
# Update DICOM object with new value:
|
161
|
-
obj.set_value(value, :create => false
|
161
|
+
obj.set_value(value, @tags[j], :create => false)
|
162
162
|
end
|
163
163
|
# Write DICOM file:
|
164
|
-
obj.
|
164
|
+
obj.write(@write_paths[i])
|
165
165
|
all_write = false unless obj.write_success
|
166
166
|
else
|
167
167
|
all_read = false
|
@@ -195,15 +195,15 @@ module DICOM
|
|
195
195
|
end
|
196
196
|
puts "*******************************************************"
|
197
197
|
end # of method execute
|
198
|
-
|
199
|
-
|
198
|
+
|
199
|
+
|
200
200
|
# Prints a list of which tags are currently selected for anonymization along with
|
201
201
|
# replacement values that will be used and enumeration status.
|
202
202
|
def print()
|
203
203
|
# Extract the string lengths which are needed to make the formatting nice:
|
204
204
|
names = Array.new
|
205
205
|
types = Array.new
|
206
|
-
|
206
|
+
tag_lengths = Array.new
|
207
207
|
name_lengths = Array.new
|
208
208
|
type_lengths = Array.new
|
209
209
|
value_lengths = Array.new
|
@@ -211,14 +211,14 @@ module DICOM
|
|
211
211
|
arr = @lib.get_name_vr(@tags[i])
|
212
212
|
names += [arr[0]]
|
213
213
|
types += [arr[1]]
|
214
|
-
|
214
|
+
tag_lengths[i] = @tags[i].length
|
215
215
|
name_lengths[i] = names[i].length
|
216
216
|
type_lengths[i] = types[i].length
|
217
217
|
value_lengths[i] = @values[i].to_s.length unless @blank
|
218
218
|
value_lengths[i] = "" if @blank
|
219
219
|
end
|
220
220
|
# To give the printed output a nice format we need to check the string lengths of some of these arrays:
|
221
|
-
|
221
|
+
tag_maxL = tag_lengths.max
|
222
222
|
name_maxL = name_lengths.max
|
223
223
|
type_maxL = type_lengths.max
|
224
224
|
value_maxL = value_lengths.max
|
@@ -227,7 +227,7 @@ module DICOM
|
|
227
227
|
@tags.each_index do |i|
|
228
228
|
# Configure empty spaces:
|
229
229
|
s = " "
|
230
|
-
f1 = " "*(
|
230
|
+
f1 = " "*(tag_maxL-@tags[i].length+1)
|
231
231
|
f2 = " "*(name_maxL-names[i].length+1)
|
232
232
|
f3 = " "*(type_maxL-types[i].length+1)
|
233
233
|
f4 = " " if @blank
|
@@ -240,7 +240,7 @@ module DICOM
|
|
240
240
|
if @blank
|
241
241
|
value = ""
|
242
242
|
else
|
243
|
-
value = @values
|
243
|
+
value = @values[i]
|
244
244
|
end
|
245
245
|
tag = @tags[i]
|
246
246
|
lines += [tag + f1 + names[i] + f2 + types[i] + f3 + value.to_s + f4 + enum.to_s ]
|
@@ -250,8 +250,8 @@ module DICOM
|
|
250
250
|
puts line
|
251
251
|
end
|
252
252
|
end # of method print_tags
|
253
|
-
|
254
|
-
|
253
|
+
|
254
|
+
|
255
255
|
# Removes a tag from the list of tags that will be anonymized:
|
256
256
|
def remove_tag(tag)
|
257
257
|
pos = @tags.index(tag)
|
@@ -263,12 +263,12 @@ module DICOM
|
|
263
263
|
puts "Specified tag not found in anonymization array. No changes made."
|
264
264
|
end
|
265
265
|
end # of method remove_tag
|
266
|
-
|
267
|
-
|
266
|
+
|
267
|
+
|
268
268
|
# The following methods are private:
|
269
269
|
private
|
270
|
-
|
271
|
-
|
270
|
+
|
271
|
+
|
272
272
|
# Finds the common path in an array of files, by performing a recursive search.
|
273
273
|
# Returns the index of the last folder in str_arr that is common in all file paths.
|
274
274
|
def common_path(str_arr, index)
|
@@ -288,8 +288,8 @@ module DICOM
|
|
288
288
|
end
|
289
289
|
return result
|
290
290
|
end # of method common_path
|
291
|
-
|
292
|
-
|
291
|
+
|
292
|
+
|
293
293
|
# Creates a hash that is used for storing information used when enumeration is desired.
|
294
294
|
def create_enum_hash()
|
295
295
|
@enum.each_index do |i|
|
@@ -297,8 +297,8 @@ module DICOM
|
|
297
297
|
@enum_new_hash[@tags[i]] = Array.new
|
298
298
|
end
|
299
299
|
end
|
300
|
-
|
301
|
-
|
300
|
+
|
301
|
+
|
302
302
|
# Handles enumeration for current DICOM tag:
|
303
303
|
def get_enumeration_value(current, j)
|
304
304
|
# Is enumeration requested for this tag?
|
@@ -324,8 +324,8 @@ module DICOM
|
|
324
324
|
end # of if @enum[j]..else..
|
325
325
|
return value
|
326
326
|
end # of method handle_enumeration
|
327
|
-
|
328
|
-
|
327
|
+
|
328
|
+
|
329
329
|
# Discover all the files contained in the specified directory and all its sub-directories:
|
330
330
|
def load_files()
|
331
331
|
# Load find library:
|
@@ -334,10 +334,14 @@ module DICOM
|
|
334
334
|
for dir in @folders
|
335
335
|
Find.find(dir) do |path|
|
336
336
|
if FileTest.directory?(path)
|
337
|
-
|
338
|
-
|
339
|
-
|
337
|
+
proceed = true
|
338
|
+
@exceptions.each do |e|
|
339
|
+
proceed = false if e == path
|
340
|
+
end
|
341
|
+
if proceed
|
340
342
|
next
|
343
|
+
else
|
344
|
+
Find.prune # Don't look any further into this directory.
|
341
345
|
end
|
342
346
|
else
|
343
347
|
@files += [path] # Store the file in our array
|
@@ -345,13 +349,14 @@ module DICOM
|
|
345
349
|
end
|
346
350
|
end # of for dir...
|
347
351
|
end # of method load_files
|
348
|
-
|
349
|
-
|
352
|
+
|
353
|
+
|
350
354
|
# Analyses the write_path and the 'read' file path to determine if the have some common root.
|
351
355
|
# If there are parts of file that exist also in write path, it will not add those parts to write_path.
|
352
356
|
def process_write_paths()
|
353
|
-
# First make sure @write_path ends with a "/"
|
354
|
-
|
357
|
+
# First make sure @write_path ends with a "/":
|
358
|
+
last_character = @write_path[(@write_path.length-1)..(@write_path.length-1)]
|
359
|
+
@write_path = @write_path + "/" unless last_character == "/"
|
355
360
|
# Separate behaviour if we have one, or several files in our array:
|
356
361
|
if @files.length == 1
|
357
362
|
# One file.
|
@@ -379,8 +384,8 @@ module DICOM
|
|
379
384
|
end
|
380
385
|
end # of if @files.length..
|
381
386
|
end # of method process_write_paths
|
382
|
-
|
383
|
-
|
387
|
+
|
388
|
+
|
384
389
|
# Default tags that will be anonymized, along with some settings for each:
|
385
390
|
def set_defaults()
|
386
391
|
data = [
|
@@ -403,14 +408,14 @@ module DICOM
|
|
403
408
|
@values = data[1]
|
404
409
|
@enum = data[2]
|
405
410
|
end # of method set_defaults
|
406
|
-
|
407
|
-
|
411
|
+
|
412
|
+
|
408
413
|
# Writes an identity file, which allows reidentification of DICOM files that have been anonymized
|
409
414
|
# using the enumeration feature. Values will be saved in a text file, using semi colon delineation.
|
410
415
|
def write_identity_file()
|
411
416
|
# Open file and prepare to write text:
|
412
417
|
File.open( @identity_file, 'w' ) do |output|
|
413
|
-
# Cycle through each
|
418
|
+
# Cycle through each
|
414
419
|
@tags.each_index do |i|
|
415
420
|
if @enum[i]
|
416
421
|
# This tag has had enumeration. Gather original and anonymized values:
|
@@ -427,7 +432,7 @@ module DICOM
|
|
427
432
|
end # of @tags.each...
|
428
433
|
end # of File.open...
|
429
434
|
end # of method write...
|
430
|
-
|
431
|
-
|
435
|
+
|
436
|
+
|
432
437
|
end # of class
|
433
438
|
end # of module
|