dicom 0.6.1 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,35 @@
1
+ = 0.7
2
+
3
+ === 28th February, 2010
4
+
5
+ * Added set_image() and set_image_narray() methods to write pixel data to the DICOM object, complementing set_image_magick().
6
+ * Added method get_image() which retrieves pixel data to a standard Ruby Array.
7
+ * Added a method for removing all private data elements in the DICOM object.
8
+ * Anonymizer class has gained the ability to remove all private data elements when anonymizing.
9
+ * Fixed an issue where Anonymizer failed to anonymize tags which had multiple instances in a DICOM file.
10
+ * Fixed an issue where Anonymizer failed to honor an expception folder if it ended with a file separation character.
11
+ * Private data elements can now be added to a DICOM object.
12
+ * Created a new FileHandler class where the user can customize the way incoming DICOM files are handled in DServer.
13
+ * Methods set_image_narray() and set_image_magick() takes options :min and :max to rescale pixel values.
14
+ * The magick and narray image retrieval methods now takes the option :rescale to convert pixel values to presentation values.
15
+ * Method get_pos() now takes the option :parent to narrow a search down.
16
+ * Improved the set_value() method to handle the creation of data elements inside sequences/items.
17
+ * All DObject methods who return Data Element positions now return an empty array instead of false if no matches are found.
18
+ * Improved handling of private tags in the library.
19
+ * Network transmissions with implicit encoding are now handled properly.
20
+ * Improved the handling of associations in the networking code.
21
+ * Some minor formatting improvements to the print() method.
22
+ * Improve the logic of updating group/sequence/item lengths to handle changes to Data Elements in sequence hierarchies.
23
+ * DLibrary class is permanently loaded when the gem is loaded and no longer needs to be specified by the user.
24
+ * Method get_image_magick() now handles pixel representation and window leveling.
25
+ * Program files was moved to a sub-directory and a module version string added, in accordance with gem guidelines.
26
+ * Renamed DObject attribute :types to :vr in accordance with the terminology of the official DICOM standard.
27
+ * Renamed method get_raw() to get_bin() and attribute :raw to :bin.
28
+ * Renamed get_pos() option :array to :selection.
29
+ * Updated Dictionary in accordance with the 2009 version of the official DICOM base standard.
30
+ * Various "under the hood" improvements and code cleanups.
31
+
32
+
1
33
  = 0.6.1
2
34
 
3
35
  === 23rd August, 2009
@@ -36,8 +68,8 @@
36
68
  See documentation for details.
37
69
  * Several methods have been cleaned up, making execution in some cases somewhat snappier.
38
70
  * Several methods have been made more robust.
39
- * Added new keyword :partial to the get_pos() method, which will enable search for partial string matches.
40
- * Added new keyword :array to the get_value() and get_raw() methods which enables easy extraction of
71
+ * Added new option :partial to the get_pos() method, which will enable search for partial string matches.
72
+ * Added new option :array to the get_value() and get_raw() methods which enables easy extraction of
41
73
  multiple values of a given tag to an array (relevant for tags present at multiple places in a DICOM file).
42
74
  * Fixed a bug where exception folders where ignored in the Anonymizer class.
43
75
 
@@ -46,7 +78,7 @@
46
78
 
47
79
  === 3rd February, 2009
48
80
 
49
- * Change of syntax: Keywords are now supplied as hash.
81
+ * Change of syntax: Options are now supplied as hash.
50
82
  * Method below() renamed to children().
51
83
  * Added method parents() which returns the position of all items/sequences that are the parent of
52
84
  the specified tag. This method is only relevant for DICOM tags that exist inside a hierarchy.
@@ -103,22 +135,12 @@ The library does have several known issues and lacks some features I would like
103
135
  offer basic functionality and should be usable for people interested in working with DICOM files in Ruby.
104
136
  The reading algorithm has been tested succesfully with some 40 different DICOM files, so it should be fairly robust.
105
137
 
106
- Features:
107
- * Reads DICOM files
108
- * Retrieve tags, formatted
109
- * Retrieve tags, unformatted
110
- * Retrieve image data as NArray object
111
- * Retrieve image data as RMagick object
112
- * Print file properties
113
- * Print tag information
114
-
115
138
 
116
139
  Known issues:
117
- * Network communication is highly experimental.
118
- * 12 bit image data not supported.
119
- * Color images not supported in NArray and RMagick retrieve methods.
120
- * Unpacking compressed image data has basic support but is not properly tested yet.
121
- * Reading Big Endian files has fairly good, but possibly not full, support.
122
- * Reading on a Big Endian system is not tested.
123
- * Reading of multiple frame image data to RMagick does not work in all cases.
124
- * Retrieving images when file contains two or more unrelated images may not be handled correctly.
140
+ * The retrieve file network functionality (get_image() in DClient class) has not been tested.
141
+ * Compressed pixel data is poorly handled.
142
+ * Read/Write 12 bit image data not available.
143
+ * Color image data is poorly handled.
144
+ * Incomplete support for Big endian (Everything but signed short and signed long has been implemented).
145
+ * Incomplete support for multiple frame image data to NArray and RMagick objects (partial support already featured).
146
+ * Image handling does not take into consideration DICOM tags which specify orientation, samples per pixel and photometric interpretation.
@@ -1,8 +1,8 @@
1
- DICOM is a small and simple library for handling DICOM files (reading, editing
1
+ Ruby DICOM is a small and simple library for handling DICOM files (reading, editing
2
2
  and writing) and DICOM network communication (both client and server side).
3
3
  It is written completely in Ruby and has no external dependencies.
4
4
 
5
- Copyright 2008-2009 Christoffer Lerv�g (chris.lervag [@nospam] @gmail.com)
5
+ Copyright 2008-2010 Christoffer Lervåg (chris.lervag [@nospam] @gmail.com)
6
6
 
7
7
  INSTALLATION
8
8
 
@@ -12,20 +12,6 @@ gem install dicom
12
12
 
13
13
  DOCUMENTATION
14
14
 
15
- CLASS DLibrary
16
-
17
- PUBLIC CLASS METHODS
18
-
19
- new()
20
-
21
- Initialize a new Library (dictionary) object.
22
- Useful if you want to make a script that reads hundreds or thousands of DICOM files,
23
- because you can save time by loading the library one time at startup instead of
24
- having the library being loaded for each DICOM file being read.
25
- Example:
26
- myLib = DICOM::DLibrary.new
27
-
28
-
29
15
  CLASS DObject
30
16
 
31
17
  PUBLIC CLASS METHODS
@@ -36,10 +22,10 @@ PUBLIC CLASS METHODS
36
22
  Example 1: (The simplest way)
37
23
  require 'dicom'
38
24
  obj = DICOM::DObject.new("myFile.dcm")
39
- Example 2: (Using a pre-loaded library to speed up reading when reading multiple files)
40
- obj = DICOM::DObject.new("myFile.dcm", :verbose => false, :lib => myLib)
41
- Example 3: (Open an empty DICOM object)
42
- obj = DICOM::DObject.new(nil)
25
+ Example 2: (Reading a DICOM file that has already been loaded into memory in a binary string)
26
+ obj = DICOM::DObject.new(bin_data, :bin => true, :syntax => syntax_string)
27
+ Example 3: (Open an empty DICOM object & choose non-verbose behaviour)
28
+ obj = DICOM::DObject.new(nil, :verbose => false)
43
29
 
44
30
  ACCESSORS (read only)
45
31
  :read_success
@@ -60,10 +46,10 @@ ACCESSORS (read only)
60
46
  As such, their length is equal to the number of tags in a DICOM object.
61
47
  :names
62
48
  :tags
63
- :types
49
+ :vr
64
50
  :lengths
65
51
  :values
66
- :raw
52
+ :bin
67
53
  :levels
68
54
 
69
55
  PUBLIC INSTANCE METHODS
@@ -78,26 +64,50 @@ PUBLIC INSTANCE METHODS
78
64
  Example 2: (Return all element positions that is contained only directly beneath the following sequence)
79
65
  pos = obj.children("3006,0082", :next_only => true)
80
66
 
67
+ get_bin(element, options={})
68
+ Returns the unprocessed, binary string of the requested DICOM data element.
69
+ Element may be an array index, element name or element tag.
70
+ If you wish to return multiple data values of a tag that occurs several times in the file,
71
+ use the keyword :array => true .
72
+ Example: (Returns all data values in a array)
73
+ contour_data = obj.get_bin("3006,0050", :array => true)
74
+
81
75
  get_frames
82
76
  Returns the number of frames present in the image data in the DICOM file.
83
77
 
84
- get_image_magick
78
+ get_image(options={})
79
+ Returns a standard Ruby array with the pixel data, where the length of the array corresponds
80
+ with the number of pixels in the image.
81
+ Example 1: (Retrieve the pixel data)
82
+ pixels = obj.get_image
83
+ Example 2: (Retrieve the pixel data rescaled to presentation values according to window center/width settings)
84
+ pixels = obj.get_image(:rescale => true)
85
+ Example 3: (Retrieve the rescaled pixel data and using a numerical array in the rescaling process (~2 times faster))
86
+ pixels = obj.get_image(:rescale => true, :narray => true)
87
+
88
+ get_image_magick(options={})
85
89
  Returns an array of RMagick image objects, where the size of the array corresponds
86
90
  with the number of frames in the image data.
87
91
  To call this method the user needs to have loaded the RMagick bindings in advance (require 'RMagick').
88
- Example (retrieve object and display first frame):
89
- require 'RMagick'
90
- data = dicom.get_image_magick()
91
- data[0].display
92
-
93
- get_image_narray
92
+ Example 1: (Retrieve object and display first frame)
93
+ require 'RMagick'
94
+ images = obj.get_image_magick
95
+ images[0].display
96
+ Example 2: (Retrieve image object rescaled to presentation values according to window center/width settings)
97
+ images = obj.get_image_magick(:rescale => true)
98
+ Example 3: (Retrieve rescaled image object and using a numerical array in the rescaling process (~2 times faster))
99
+ images = obj.get_image_magick(:rescale => true, :narray => true)
100
+
101
+ get_image_narray(options={})
94
102
  Returns a 3d NArray object where the array dimensions are related to [frames, columns, rows].
95
103
  To call this method the user needs to have loaded the NArray library in advance (require 'narray').
96
- Example (retrieve object and display first frame):
104
+ Example 1: (Retrieve object and display first frame):
97
105
  require 'narray'
98
106
  require 'nimage'
99
- data = obj.get_image_narray()
107
+ data = obj.get_image_narray
100
108
  NImage.show data[0,true,true]
109
+ Example 2: (Retrieve numerical array rescaled from the original pixel values to presentation values)
110
+ data = obj.get_image_narray(:rescale => true)
101
111
 
102
112
  get_image_pos
103
113
  Returns the index(es) of the data element(s) that contain image data.
@@ -108,22 +118,16 @@ PUBLIC INSTANCE METHODS
108
118
  Example 1: (Find all occurences of the specified tag in the object)
109
119
  pos = obj.get_pos("3006,0080")
110
120
  Example 2: (Find all occurences of the specified tag inside the specified sequence)
111
- selection = obj.children("3006,0082")
112
- pos = obj.get_pos("3006,0080", :array => selection)
113
- Example 3: (Using the :partial argument to find position of all elements containing a specific string)
121
+ mySelection = obj.children("3006,0082")
122
+ pos = obj.get_pos("3006,0080", :selection => mySelection)
123
+ Example 3: (Same as above, but slightly more concise using the :parent option)
124
+ pos = obj.get_pos("3006,0080", :parent => "3006,0082")
125
+ Example 4: (Using the :partial argument to find position of all elements containing a specific string)
114
126
  pos = obj.get_pos("0010", :partial => true)
115
127
  pos = obj.get_pos("Name", :partial => true)
116
128
 
117
- get_raw(element, options={})
118
- Returns the raw data of the requested DICOM data element.
119
- Element may be an array index, element name or element tag.
120
- If you wish to return multiple data values of a tag that occurs several times in the file,
121
- use the keyword :array => true .
122
- Example: (Returns all data values in a array)
123
- contour_data = obj.get_raw("3006,0050", :array => true)
124
-
125
129
  get_value(element)
126
- Returns the value (processed raw data) of the requested DICOM data element.
130
+ Returns the value (processed binary data) of the requested DICOM data element.
127
131
  Element may be an array index, element name or element tag.
128
132
  If you wish to return multiple values of a tag that occurs several times in the file,
129
133
  use the keyword :array => true .
@@ -143,7 +147,7 @@ PUBLIC INSTANCE METHODS
143
147
 
144
148
  print(pos, options={})
145
149
  Prints the information gathered on one or several/all tag(s) in the DICOM object:
146
- (index, [hierarchy level,] label, name, type, length, value)
150
+ (index, [hierarchy level,] label, name, vr, length, value)
147
151
  The method can print to both screen or to a text file. If print to file is chosen,
148
152
  the text file will be put in the folder of the original DICOM file with a '.txt' extension.
149
153
  The argument pos may be a number (array position), an array of numbers, or true.
@@ -153,15 +157,51 @@ PUBLIC INSTANCE METHODS
153
157
  obj.print([4,5,6])
154
158
 
155
159
  print_all
156
- Prints information of all tags stored in the DICOM object to the screen.
160
+ Prints information of all tags stored in the DICOM object to the screen (This is equal to using print(true)).
157
161
 
158
162
  print_properties
159
163
  Prints the key structural properties of the DICOM file to the screen.
160
164
 
161
- remove(element)
165
+ remove(element, options={})
162
166
  Removes the specified data element from the DICOM object. You can use this method
163
167
  if you are editing a DICOM object and wants to get rid of one or more elements.
164
168
  Element may be an array index, element name or element tag.
169
+ The default behaviour of this method is to remove any encapsulated elements if a sequence
170
+ or item is selected for removal. If for some reason you want to avoid this, user the :ignore_children option.
171
+ Example 1: (Remove a sequence tag along with all its 'children' tags)
172
+ obj.remove("Request Attributes Sequence")
173
+ Example 2: (Remove a specific sequence tag only (not recommended unless you really know what you are doing))
174
+ obj.remove("0040,0275", :ignore_children => true)
175
+
176
+ remove_private
177
+ Removes all private data elements from the DICOM object.
178
+
179
+ set_image(array)
180
+ Encodes and inserts the content of your array to the pixel data element of your DICOM object.
181
+ Note that this method does not create or update tags related to image information in the DICOM object.
182
+
183
+ set_image_file(file)
184
+ Inserts the binary content of a file to the Pixel Data tag in your DICOM object.
185
+ This can be useful if you have processed some image data using a custom program
186
+ and just wants to put that data back into a DICOM object.
187
+
188
+ set_image_magick(object, options={})
189
+ Encodes and inserts a RMagick image object to the pixel data element of your DICOM object.
190
+ Note that this method does not create or update tags related to image information in the DICOM object.
191
+ If pixel value rescaling is desired, this can be specified by using both the :min and :max options.
192
+ NB! Because of rescaling when importing pixel values to a RMagick object, and the possible
193
+ difference between presentation values and original pixel values, the use of set_image_magick() may
194
+ result in pixel data that is completely different from what is expected.
195
+ This method should be used only with great care: Do not be suprised if your resulting DICOM image looks strange!
196
+ Example: (Encode an image object and requesting a specific pixel value range to be encoded)
197
+ obj.set_image_magick(myImage, :min => -2000, :max => 3000)
198
+
199
+ set_image_narray(object, options={})
200
+ Encodes and inserts a NArray object to the pixel data element of your DICOM object.
201
+ Note that this method does not create or update tags related to image information in the DICOM object.
202
+ If pixel value rescaling is desired, this can be specified by using both the :min and :max options.
203
+ Example: (Encode a numerical pixel data array and requesting a specific pixel value range to be encoded)
204
+ obj.set_image_narray(myArray, :min => -2000, :max => 3000)
165
205
 
166
206
  set_value(value, element, options={})
167
207
  This method can be used both to edit an existing data element, or to create
@@ -171,14 +211,11 @@ PUBLIC INSTANCE METHODS
171
211
  obj.set_value("Anonymous", "0010,0010", :create => false)
172
212
  Example 2: (Insert binary data for a specific tag)
173
213
  obj.set_value(data, 52, :bin => true, :create => false)
174
-
175
- set_image_magick(object)
176
- Inserts a RMagick image object to the pixel data tag of your DICOM object.
177
-
178
- set_image_file(file)
179
- Inserts the binary content of a file to the Pixel Data tag in your DICOM object.
180
- This can be useful if you have processed some image data using a custom program
181
- and just wants to put that data back into a DICOM object.
214
+ Example 3: (Create a private data element)
215
+ obj.set_value("Test", "0011,0010", :vr => "LO")
216
+ Example 4: (Create/edit a data element in a specific item in a given sequence)
217
+ items = obj.get_pos("FFFE,E000", :parent => "0040,0275")
218
+ obj.set_value("CT1", "0040,0007", :parent => items.first)
182
219
 
183
220
  write(file)
184
221
  Writes the DICOM object to the specified file.
@@ -197,10 +234,10 @@ PUBLIC CLASS METHODS
197
234
 
198
235
  ACCESSORS (Read & write)
199
236
  :blank
200
- A boolean that you can set if you want to all anonymization tags to be blank
237
+ A boolean that you can set as true if you want all anonymization tags to be blank
201
238
  instead of having some generic value.
202
239
  :enumeration
203
- A boolean that if set will make the script set enumerated values on anonymized tags,
240
+ A boolean that if set as true will make the script set enumerated values on anonymized tags,
204
241
  such that you are able to separate the DICOM files of unique individuals after anonymization.
205
242
  Example of fictious result:
206
243
  "Joe Sixpack" => "Person1" and "Joe Schmoe" => "Person2"
@@ -209,7 +246,9 @@ ACCESSORS (Read & write)
209
246
  the anonymized DICOM files at a later stage. The relationship between original names and
210
247
  enumerated values is stored in a text file which you can keep for yourself, while handing out
211
248
  the anonymized DICOM files to a third party.
212
-
249
+ :remove_private
250
+ If this accessor is set as true, all private tags in the selected DICOM files will be removed.
251
+ This can be useful if you are unsure whether the private tags contain sensitive data or not.
213
252
  :write_path
214
253
  You may set a different path for where the anonymized DICOM files will be stored. If this
215
254
  value is not set, the Anonymizer script will overwrite the old DICOM files.
@@ -218,14 +257,14 @@ ACCESSORS (Read & write)
218
257
 
219
258
  PUBLIC INSTANCE METHODS
220
259
 
260
+ add_exception(path)
261
+ Adds a folder who's files (including all files in its subfolders) will be excluded from anonymization.
262
+
221
263
  add_folder(path)
222
264
  Adds a folder who's files (including all files in subfolders) will be anonymized.
223
265
  Example:
224
266
  a.add_folder("/home/dicom")
225
267
 
226
- add_exception(path)
227
- Adds a folder who's files (including all files in its subfolders) will be excluded from anonymization.
228
-
229
268
  add_tag(tag, options={})
230
269
  Adds a tag to the list of tags that will be anonymized. As options you can specify value to be used
231
270
  and whether the tag should be included for enumeration if this feature has been activated.
@@ -288,16 +327,6 @@ ACCESSORS (Read only)
288
327
 
289
328
  PUBLIC INSTANCE METHODS
290
329
 
291
- get_image(path, options={})
292
- Retrieve a DICOM image file from a server (C-GET-RQ) (this method is untested (might not work)).
293
- Accepted options:
294
- "0008,0018" (SOP Instance UID)
295
- "0008,0052" (Query/Retrieve Level)
296
- "0020,000D" (Study Instance UID)
297
- "0020,000E" (Series Instance UID)
298
- Example:
299
- node.get_image("/home/dicom/", "0008,0018" => sop_uid, "0020,000D" => study_uid, "0020,000E" => series_uid)
300
-
301
330
  find_images(options={})
302
331
  Query a server for DICOM images that matches your specified criteria.
303
332
  Accepted options:
@@ -351,6 +380,16 @@ PUBLIC INSTANCE METHODS
351
380
  Example:
352
381
  result = node.find_studies("0008,0020" => study_date, "0010,000D" => patient_id)
353
382
 
383
+ get_image(path, options={})
384
+ Retrieve a DICOM image file from a server (C-GET-RQ) (this method is untested (might not work)).
385
+ Accepted options:
386
+ "0008,0018" (SOP Instance UID)
387
+ "0008,0052" (Query/Retrieve Level)
388
+ "0020,000D" (Study Instance UID)
389
+ "0020,000E" (Series Instance UID)
390
+ Example:
391
+ node.get_image("/home/dicom/", "0008,0018" => sop_uid, "0020,000D" => study_uid, "0020,000E" => series_uid)
392
+
354
393
  move_image(destination, options={})
355
394
  Move an image to a dicom node other than yourself.
356
395
  Accepted options:
@@ -385,10 +424,17 @@ PUBLIC CLASS METHODS
385
424
 
386
425
  new(port, options={})
387
426
  Initialize a new DServer instance.
388
- Example:
427
+ Example 1:
389
428
  server = DICOM::DServer.new(104)
429
+ Example 2: (Initialize a DServer using a customized FileHandler placed in your local folder)
430
+ require 'MyFileHandler'
431
+ server = DICOM::DServer.new(104, :host_ae => "RUBY_SERVER", :file_handler => DICOM::MyFileHandler)
390
432
 
391
433
  ACCESSORS (Read & write)
434
+ :file_handler
435
+ You may write your own, customized FileHandler (the file that determines how incoming DICOM files are handled),
436
+ put it in your local execution environment, and hook it to your DServer instance by using this accessor.
437
+ This is quite a powerful option, as it will enable you to do practically whatever you want with incoming DICOM files.
392
438
  :host_ae
393
439
  Called application entity (name of the service class provider - server).
394
440
  :max_package_size
data/README CHANGED
@@ -9,7 +9,7 @@ and Communications in Medicine) is a standard for handling, storing, printing,
9
9
  and transmitting information in medical imaging. It includes a file format definition
10
10
  and a network communications protocol. Ruby DICOM supports reading from, editing and
11
11
  writing to this file format. It also features experimental support for network
12
- communication modalities like query, move and send.
12
+ communication modalities like query, move, sending and receiving files.
13
13
 
14
14
  BASIC USAGE
15
15
  -----------
@@ -47,7 +47,7 @@ dcm = DICOM::DObject.new("myFile.dcm") ;0
47
47
  COPYRIGHT
48
48
  ---------
49
49
 
50
- Copyright 2008-2009 Christoffer Lerv�g
50
+ Copyright 2008-2010 Christoffer Lervåg
51
51
 
52
52
  This program is free software: you can redistribute it and/or modify
53
53
  it under the terms of the GNU General Public License as published by
@@ -67,7 +67,7 @@ ABOUT ME
67
67
  --------
68
68
 
69
69
  Name:
70
- Christoffer Lerv�g
70
+ Christoffer Lervåg
71
71
 
72
72
  Location:
73
73
  Oslo, Norway
@@ -1,14 +1,25 @@
1
1
  # Core library:
2
- require 'DClient'
3
- require 'Dictionary'
4
- require 'DLibrary'
5
- require 'DObject'
6
- require 'DRead'
7
- require 'DServer'
8
- require 'DWrite'
9
- require 'Link'
10
- require 'Stream'
2
+ require 'dicom/DClient'
3
+ require 'dicom/Dictionary'
4
+ require 'dicom/DLibrary'
5
+ require 'dicom/DObject'
6
+ require 'dicom/DRead'
7
+ require 'dicom/DServer'
8
+ require 'dicom/DWrite'
9
+ require 'dicom/FileHandler'
10
+ require 'dicom/Link'
11
+ require 'dicom/Stream'
11
12
  # Extended library:
12
- require 'Anonymizer'
13
- # Ruby library extensions:
14
- require 'ruby_extensions'
13
+ require 'dicom/Anonymizer'
14
+ # Extensions to the Ruby library:
15
+ require 'dicom/ruby_extensions'
16
+
17
+ # Ruby DICOM version string:
18
+ DICOM::VERSION = "0.7"
19
+
20
+ # Load the DICOM Library class (dictionary):
21
+ DICOM::LIBRARY = DICOM::DLibrary.new
22
+
23
+ # Ruby DICOM implementation name and uid:
24
+ DICOM::NAME = "RUBY_DICOM_" + DICOM::VERSION
25
+ DICOM::UID = "1.2.826.0.1.3680043.8.641"