dicoms 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.md +0 -2
- data/dicoms.gemspec +2 -1
- data/lib/dicoms.rb +4 -0
- data/lib/dicoms/cli.rb +176 -51
- data/lib/dicoms/explode.rb +421 -0
- data/lib/dicoms/histogram.rb +50 -0
- data/lib/dicoms/info.rb +43 -0
- data/lib/dicoms/progress.rb +22 -7
- data/lib/dicoms/projection.rb +40 -30
- data/lib/dicoms/sequence.rb +16 -11
- data/lib/dicoms/shared_settings.rb +7 -0
- data/lib/dicoms/sigmoid.rb +121 -0
- data/lib/dicoms/stats.rb +2 -2
- data/lib/dicoms/support.rb +48 -2
- data/lib/dicoms/transfer.rb +31 -23
- data/lib/dicoms/version.rb +1 -1
- metadata +34 -2
data/lib/dicoms/stats.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
class DicomS
|
2
2
|
def stats(dicom_directory, options = {})
|
3
|
-
# TODO: compute histogram of levels
|
4
3
|
dicom_files = find_dicom_files(dicom_directory)
|
5
4
|
if dicom_files.empty?
|
6
5
|
raise "ERROR: no se han encontrado archivos DICOM en: \n #{dicom_directory}"
|
@@ -24,7 +23,8 @@ class DicomS
|
|
24
23
|
n: n,
|
25
24
|
min: mins.min,
|
26
25
|
next_min: next_mins.min,
|
27
|
-
max: maxs.max
|
26
|
+
max: maxs.max,
|
27
|
+
histogram: compute_histogram(dicom_directory, options)
|
28
28
|
}
|
29
29
|
end
|
30
30
|
end
|
data/lib/dicoms/support.rb
CHANGED
@@ -1,6 +1,26 @@
|
|
1
1
|
require 'matrix'
|
2
2
|
|
3
3
|
class DicomS
|
4
|
+
class Error < RuntimeError
|
5
|
+
def initialize(code, *args)
|
6
|
+
@code = code
|
7
|
+
super *args
|
8
|
+
end
|
9
|
+
attr_reader :code
|
10
|
+
end
|
11
|
+
|
12
|
+
class UnsupportedDICOM < Error
|
13
|
+
def initialize(*args)
|
14
|
+
super 'unsupported_dicom', *args
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class InvaliddDICOM < Error
|
19
|
+
def initialize(*args)
|
20
|
+
super 'invalid_dicom', *args
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
4
24
|
USE_SLICE_Z = false
|
5
25
|
METADATA_TYPES = {
|
6
26
|
# Note: for axisx, axisy, axisz decode_vector should be used
|
@@ -141,7 +161,7 @@ class DicomS
|
|
141
161
|
ny = dicom.num_rows # dicom.rows.value.to_i
|
142
162
|
|
143
163
|
unless dicom.samples_per_pixel.value.to_i == 1
|
144
|
-
raise "Invalid
|
164
|
+
raise InvalidDICOM, "Invalid image format"
|
145
165
|
end
|
146
166
|
Settings[
|
147
167
|
dx: dx, dy: dy, x: x, y: y, z: z,
|
@@ -169,7 +189,7 @@ class DicomS
|
|
169
189
|
file = File.basename(name)
|
170
190
|
number_pattern = /\d+/
|
171
191
|
match = number_pattern.match(file)
|
172
|
-
raise "Invalid DICOM file name" unless match
|
192
|
+
raise UnsupportedDICOM, "Invalid DICOM file name" unless match
|
173
193
|
number = match[0]
|
174
194
|
file = file.sub(number_pattern, "%d")
|
175
195
|
if match.begin(0) == 0
|
@@ -345,5 +365,31 @@ class DicomS
|
|
345
365
|
ts = DICOM::LIBRARY.uid(dicom.transfer_syntax)
|
346
366
|
ts.name if ts.compressed_pixels?
|
347
367
|
end
|
368
|
+
|
369
|
+
def terminal_size
|
370
|
+
if $stdout.respond_to?(:tty?) && $stdout.tty? && $stdout.respond_to?(:winsize)
|
371
|
+
$stdout.winsize
|
372
|
+
else
|
373
|
+
size = [ENV['LINES'] || ENV['ROWS'], ENV['COLUMNS']]
|
374
|
+
if size[1].to_i > 0
|
375
|
+
size
|
376
|
+
else
|
377
|
+
if defined?(Readline) && Readline.respond_to?(:get_screen_size)
|
378
|
+
size = Readline.get_screen_size
|
379
|
+
if size[1].to_i > 0
|
380
|
+
size
|
381
|
+
elsif ENV['ANSICON'] =~ /\((.*)x(.*)\)/
|
382
|
+
size = [$2, $1]
|
383
|
+
if size[1].to_i > 0
|
384
|
+
size
|
385
|
+
else
|
386
|
+
[27, 80]
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
348
394
|
end
|
349
395
|
end
|
data/lib/dicoms/transfer.rb
CHANGED
@@ -17,6 +17,12 @@ class DicomS
|
|
17
17
|
# values which are mapped to the output limits.
|
18
18
|
# These values may be raw or rescaled depending on the min_max_rescaled? method
|
19
19
|
#
|
20
|
+
# Derived classes should also provide a method
|
21
|
+
#
|
22
|
+
# transfer_rescaled_pixels(dicom, data, min, max)
|
23
|
+
#
|
24
|
+
# To apply the transfer conversion to data which has been only rescaled
|
25
|
+
#
|
20
26
|
class Transfer
|
21
27
|
USE_DATA = false
|
22
28
|
|
@@ -70,8 +76,8 @@ class DicomS
|
|
70
76
|
when :unsigned
|
71
77
|
min, max = Transfer.min_max_limits(dicom)
|
72
78
|
if min < 0
|
73
|
-
min = 0
|
74
79
|
max -= min
|
80
|
+
min = 0
|
75
81
|
end
|
76
82
|
[min, max]
|
77
83
|
else
|
@@ -96,6 +102,7 @@ class DicomS
|
|
96
102
|
def initialize(options = {})
|
97
103
|
@center = options[:center]
|
98
104
|
@width = options[:width]
|
105
|
+
@float_arith = options[:float] || FLOAT_MAPPING
|
99
106
|
super options
|
100
107
|
end
|
101
108
|
|
@@ -116,6 +123,14 @@ class DicomS
|
|
116
123
|
map_to_output dicom, data, min, max
|
117
124
|
end
|
118
125
|
|
126
|
+
# Apply the transfer map to data which has been only rescaled
|
127
|
+
def transfer_rescaled_pixels(dicom, pixels, min, max)
|
128
|
+
# clip pixels to min, max # wouldn't be needed if map_to_output did output clipping...
|
129
|
+
pixels[pixels < min] = min
|
130
|
+
pixels[pixels > max] = max
|
131
|
+
map_to_output dicom, pixels, min, max
|
132
|
+
end
|
133
|
+
|
119
134
|
# def image(dicom, min, max)
|
120
135
|
# center = (min + max)/2
|
121
136
|
# width = max - min
|
@@ -128,7 +143,7 @@ class DicomS
|
|
128
143
|
output_min, output_max = min_max_limits(dicom)
|
129
144
|
output_range = output_max - output_min
|
130
145
|
input_range = max - min
|
131
|
-
float_arith =
|
146
|
+
float_arith = @float_arith || output_range < input_range
|
132
147
|
data_type = data.typecode
|
133
148
|
data = data.to_type(NArray::SFLOAT) if float_arith
|
134
149
|
data.sbt! min
|
@@ -179,6 +194,7 @@ class DicomS
|
|
179
194
|
@rescale = options[:rescale]
|
180
195
|
@ignore_min = options[:ignore_min]
|
181
196
|
@extension_factor = options[:extend] || 0.0
|
197
|
+
@float_arith = options[:float] || FLOAT_MAPPING
|
182
198
|
super options
|
183
199
|
end
|
184
200
|
|
@@ -196,16 +212,12 @@ class DicomS
|
|
196
212
|
[minimum, maximum]
|
197
213
|
end
|
198
214
|
|
199
|
-
|
200
|
-
|
201
|
-
end
|
202
|
-
|
203
|
-
def processed_data(dicom, min, max)
|
215
|
+
# Apply the transfer map to data which has been only rescaled
|
216
|
+
def transfer_rescaled_pixels(dicom, data, min, max)
|
204
217
|
output_min, output_max = min_max_limits(dicom)
|
205
218
|
output_range = output_max - output_min
|
206
219
|
input_range = max - min
|
207
|
-
float_arith =
|
208
|
-
data = dicom_narray(dicom, level: false, remap: @rescale)
|
220
|
+
float_arith = @float_arith || output_range < input_range
|
209
221
|
data_type = data.typecode
|
210
222
|
data = data.to_type(NArray::SFLOAT) if float_arith
|
211
223
|
data.sbt! min
|
@@ -217,6 +229,15 @@ class DicomS
|
|
217
229
|
data
|
218
230
|
end
|
219
231
|
|
232
|
+
def processed_data(dicom, min, max)
|
233
|
+
data = dicom_narray(dicom, level: false, remap: @rescale)
|
234
|
+
transfer_rescaled_pixels dicom, data, min, max
|
235
|
+
end
|
236
|
+
|
237
|
+
def min_max_rescaled?
|
238
|
+
@rescale
|
239
|
+
end
|
240
|
+
|
220
241
|
private
|
221
242
|
|
222
243
|
def data_range(dicom)
|
@@ -320,20 +341,7 @@ class DicomS
|
|
320
341
|
end
|
321
342
|
|
322
343
|
def min_max(sequence)
|
323
|
-
min_max_limits(sequence.first)
|
324
|
-
end
|
325
|
-
|
326
|
-
def map_to_output(dicom, data, min, max)
|
327
|
-
if @rescale
|
328
|
-
intercept = dicom_rescale_intercept(dicom)
|
329
|
-
slope = dicom_rescale_slope(dicom)
|
330
|
-
if slope != 1 || intercept != 0
|
331
|
-
return super
|
332
|
-
end
|
333
|
-
end
|
334
|
-
data = dicom_narray(dicom)
|
335
|
-
data.add! -min if min < 0
|
336
|
-
data
|
344
|
+
Transfer.min_max_limits(sequence.first)
|
337
345
|
end
|
338
346
|
end
|
339
347
|
end
|
data/lib/dicoms/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dicoms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Javier Goizueta
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dicom
|
@@ -94,6 +94,34 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.19'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: solver
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.2.0
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.2.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: histogram
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.2.4
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.2.4
|
97
125
|
- !ruby/object:Gem::Dependency
|
98
126
|
name: bundler
|
99
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,7 +187,10 @@ files:
|
|
159
187
|
- lib/dicoms.rb
|
160
188
|
- lib/dicoms/cli.rb
|
161
189
|
- lib/dicoms/command_options.rb
|
190
|
+
- lib/dicoms/explode.rb
|
162
191
|
- lib/dicoms/extract.rb
|
192
|
+
- lib/dicoms/histogram.rb
|
193
|
+
- lib/dicoms/info.rb
|
163
194
|
- lib/dicoms/meta_codec.rb
|
164
195
|
- lib/dicoms/pack.rb
|
165
196
|
- lib/dicoms/progress.rb
|
@@ -168,6 +199,7 @@ files:
|
|
168
199
|
- lib/dicoms/sequence.rb
|
169
200
|
- lib/dicoms/shared_files.rb
|
170
201
|
- lib/dicoms/shared_settings.rb
|
202
|
+
- lib/dicoms/sigmoid.rb
|
171
203
|
- lib/dicoms/stats.rb
|
172
204
|
- lib/dicoms/support.rb
|
173
205
|
- lib/dicoms/transfer.rb
|