cicada 0.9.4-java → 0.9.5-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,30 @@
1
+ #--
2
+ # Copyright (c) 2013 Colin J. Fuller
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the Software), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in
12
+ # all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ # SOFTWARE.
21
+ #++
22
+
23
+ module Cicada
24
+ ##
25
+ # An error indicating that a position cannot be corrected (possibly due to incomplete
26
+ # coverage in the correction dataset).
27
+ class UnableToCorrectError < StandardError
28
+ end
29
+ end
30
+
@@ -55,28 +55,18 @@ module Cicada
55
55
  # image objects.
56
56
  #
57
57
  def self.serialize_image_objects(image_objects)
58
-
59
58
  doc = REXML::Document.new
60
-
61
-
62
59
  doc.add_element "root"
63
60
 
64
61
  image_objects.each do |iobj|
65
-
66
62
  in_doc = REXML::Document.new iobj.writeToXMLString
67
-
68
63
  in_doc.root.elements[1, "serialized_form"].text = Base64.encode64(Marshal.dump(iobj))
69
-
70
64
  doc.root.add in_doc.elements[1,"image_object"]
71
-
72
65
  end
73
66
 
74
67
  output = ""
75
-
76
68
  doc.write(output, 2)
77
-
78
69
  output
79
-
80
70
  end
81
71
 
82
72
  ##
@@ -89,15 +79,7 @@ module Cicada
89
79
  # @return [ImageObject] the encoded ImageObject
90
80
  #
91
81
  def self.image_object_from_bytes(bin_data)
92
-
93
82
  Marshal.load(bin_data)
94
-
95
- #j_bytes = bin_data.to_java_bytes
96
-
97
- #oi = Java::java.io.ObjectInputStream.new(Java::java.io.ByteArrayInputStream.new(j_bytes))
98
-
99
- #oi.readObject
100
-
101
83
  end
102
84
 
103
85
  ##
@@ -109,23 +91,16 @@ module Cicada
109
91
  # @return [Array<ImageObject>] the image objects encoded in the string
110
92
  #
111
93
  def self.unserialize_image_objects(data)
112
-
113
94
  objs = []
114
-
115
95
  doc = REXML::Document.new data
116
96
 
117
97
  doc.elements.each("*/image_object/serialized_form") do |el|
118
-
119
98
  bin_data = Base64.decode64(el.text)
120
-
121
99
  objs << image_object_from_bytes(bin_data)
122
-
123
100
  end
124
101
 
125
102
  objs
126
-
127
103
  end
128
-
129
104
  end
130
105
 
131
106
 
@@ -133,7 +108,6 @@ module Cicada
133
108
  # A collection of methods for interacting with input and output files for cicada.
134
109
  #
135
110
  class FileInteraction
136
-
137
111
  # parameters required by the methods in this class
138
112
  REQUIRED_PARAMETERS = [:dirname_set, :basename_set, :mask_relative_dirname, :mask_extra_extension, :data_directory, :correction_date, :output_positions_to_directory]
139
113
 
@@ -155,7 +129,6 @@ module Cicada
155
129
  # separator used in the parameter file for multiple files, directories, etc.
156
130
  MULTI_NAME_SEP = ","
157
131
 
158
-
159
132
  ##
160
133
  # Loads an image from the specified file.
161
134
  #
@@ -164,12 +137,9 @@ module Cicada
164
137
  # @return [ReadOnlyImage] the image at the specified filename
165
138
  #
166
139
  def self.load_image(image_fn)
167
-
168
140
  RImageAnalysisTools.get_image(image_fn)
169
-
170
141
  end
171
142
 
172
-
173
143
  ##
174
144
  # Gets the filename to which / from which image object positions will be written /
175
145
  # read from a parameter dictionary.
@@ -182,7 +152,6 @@ module Cicada
182
152
  File.expand_path(p[:basename_set].split(MULTI_NAME_SEP)[0] + POS_XML_EXTENSION, dir)
183
153
  end
184
154
 
185
-
186
155
  ##
187
156
  # Gets the filename to which human-friendly-formatted object positions will be written.
188
157
  #
@@ -195,7 +164,6 @@ module Cicada
195
164
  File.expand_path(p[:basename_set].split(MULTI_NAME_SEP)[0] + POS_HUMAN_EXTENSION, dir)
196
165
  end
197
166
 
198
-
199
167
  ##
200
168
  # Gets the filename of data to use for in situ correction from a parameter dictionary.
201
169
  #
@@ -205,7 +173,7 @@ module Cicada
205
173
  # @return [String] the absolute path to the in situ correction data file
206
174
  #
207
175
  def self.in_situ_corr_data_filename(p)
208
- dir = [:data_directory]
176
+ dir = p[:data_directory]
209
177
  File.expand_path(p[:in_situ_aberr_corr_basename_set].split(MULTI_NAME_SEP)[0] + POS_XML_EXTENSION, dir)
210
178
  end
211
179
 
@@ -229,15 +197,11 @@ module Cicada
229
197
  # @return [Array<ImageObject>] the image objects contained in the file.
230
198
  #
231
199
  def self.unserialize_position_data_file(fn)
232
-
233
200
  data_str = nil
234
-
235
201
  File.open(fn) do |f|
236
202
  data_str = f.read
237
203
  end
238
-
239
204
  Serialization.unserialize_image_objects(data_str)
240
-
241
205
  end
242
206
 
243
207
  ##
@@ -248,11 +212,8 @@ module Cicada
248
212
  # @return [Array<ImageObject>] the image objects associated with the analysis
249
213
  #
250
214
  def self.read_position_data(p)
251
-
252
215
  fn = FileInteraction.position_data_filename(p)
253
-
254
216
  FileInteraction.unserialize_position_data_file(fn)
255
-
256
217
  end
257
218
 
258
219
  ##
@@ -265,11 +226,8 @@ module Cicada
265
226
  # @return [Array<ImageObject>] the image objects for in situ correction associated with the analysis
266
227
  #
267
228
  def self.read_in_situ_corr_data(p)
268
-
269
229
  fn = FileInteraction.in_situ_corr_data_filename(p)
270
-
271
230
  FileInteraction.unserialize_position_data_file(fn)
272
-
273
231
  end
274
232
 
275
233
  ##
@@ -281,35 +239,22 @@ module Cicada
281
239
  # which return each image's filename and its paired mask's filename respectively.
282
240
  #
283
241
  def self.list_files(p)
284
-
285
242
  dirnames = p[:dirname_set].split(MULTI_NAME_SEP)
286
243
  basenames = p[:basename_set].split(MULTI_NAME_SEP)
287
-
288
244
  image_sets = []
289
245
 
290
246
  dirnames.each do |d|
291
-
292
247
  mask_dirname = File.join(d, p[:mask_relative_dirname])
293
-
294
248
  Dir.foreach(d) do |f|
295
-
296
- if basenames.any? { |e| f.match(e) } then
297
-
249
+ if basenames.any? { |e| f.match(e) } then
298
250
  im = File.expand_path(f, d)
299
251
  msk = File.expand_path(f + p[:mask_extra_extension], mask_dirname)
300
-
301
- current = OpenStruct.new(image_fn: im, mask_fn: msk)
302
-
252
+ current = OpenStruct.new(image_fn: im, mask_fn: msk)
303
253
  image_sets << current
304
-
305
254
  end
306
-
307
255
  end
308
-
309
- end
310
-
256
+ end
311
257
  image_sets
312
-
313
258
  end
314
259
 
315
260
  ##
@@ -321,15 +266,10 @@ module Cicada
321
266
  # @return [void]
322
267
  #
323
268
  def self.write_position_data(image_objects, p)
324
-
325
269
  fn = position_data_filename(p)
326
-
327
270
  write_position_data_file(image_objects,fn)
328
-
329
271
  fn2 = human_friendly_position_data_filename(p)
330
-
331
- write_human_friendly_position_data_file(image_objects, fn2)
332
-
272
+ write_human_friendly_position_data_file(image_objects, fn2)
333
273
  end
334
274
 
335
275
  ##
@@ -341,13 +281,9 @@ module Cicada
341
281
  # @return [void]
342
282
  #
343
283
  def self.write_position_data_file(image_objects, fn)
344
-
345
284
  File.open(fn, 'w') do |f|
346
-
347
285
  f.write(Serialization.serialize_image_objects(image_objects))
348
-
349
286
  end
350
-
351
287
  end
352
288
 
353
289
  ##
@@ -357,39 +293,25 @@ module Cicada
357
293
  # @see write_position_data_file
358
294
  #
359
295
  def self.write_human_friendly_position_data_file(image_objects, fn)
360
-
361
296
  CSV.open(fn, 'wb') do |csv|
362
-
363
297
  obj = image_objects[0]
364
-
365
298
  n_channels = obj.getFitParametersByChannel.size
366
-
367
299
  headers = ["object_id"]
368
300
  n_channels.times do |i|
369
301
  headers.concat(["pos#{i}_x", "pos#{i}_y", "pos#{i}_z"])
370
302
  end
371
-
372
303
  csv << headers
373
304
 
374
305
  image_objects.each do |im_obj|
375
-
376
306
  row = [im_obj.getLabel]
377
-
378
307
  n_channels.times do |i|
379
-
380
308
  row.concat(im_obj.getPositionForChannel(i).toArray)
381
-
382
309
  end
383
-
384
310
  csv << row
385
-
386
311
  end
387
-
388
312
  end
389
-
390
313
  end
391
314
 
392
-
393
315
  ##
394
316
  # Gets the filename for storing/reading the correction based upon the supplied parameter dictionary.
395
317
  #
@@ -398,12 +320,9 @@ module Cicada
398
320
  # @return [String] the filename for the correction file.
399
321
  #
400
322
  def self.correction_filename(p)
401
-
402
323
  dir = p[:data_directory]
403
324
  fn = p[:correction_date]
404
-
405
325
  File.expand_path(fn + CORR_XML_EXTENSION, dir)
406
-
407
326
  end
408
327
 
409
328
  ##
@@ -415,25 +334,13 @@ module Cicada
415
334
  # @return [void]
416
335
  #
417
336
  def self.write_differences(diffs, p)
418
-
419
337
  dirname = p[:output_positions_to_directory]
420
-
421
338
  fn = File.expand_path(p[:basename_set] + DIFFS_TXT_EXTENSION, dirname)
422
-
423
339
  File.open(fn, 'w') do |f|
424
-
425
340
  diffs.each do |d|
426
-
427
341
  f.puts(d.to_s)
428
-
429
342
  end
430
-
431
343
  end
432
-
433
344
  end
434
-
435
345
  end
436
-
437
346
  end
438
-
439
-
@@ -23,7 +23,6 @@
23
23
  # * ***** END LICENSE BLOCK ***** */
24
24
 
25
25
  require 'rimageanalysistools'
26
-
27
26
  require 'facets/math/mean'
28
27
  require 'facets/math/std'
29
28
 
@@ -34,7 +33,6 @@ module Cicada
34
33
  # to some distribution.
35
34
  #
36
35
  class DistributionFitter
37
-
38
36
  attr_accessor :parameters
39
37
 
40
38
  ##
@@ -44,9 +42,7 @@ module Cicada
44
42
  # @param [ParameterDictionary, Hash] params a hash-like object containing the parameters
45
43
  #
46
44
  def initialize(params)
47
-
48
45
  @parameters = params
49
-
50
46
  end
51
47
 
52
48
  ##
@@ -63,7 +59,6 @@ module Cicada
63
59
  def fit(objects, diffs)
64
60
  nil
65
61
  end
66
-
67
62
  end
68
63
 
69
64
  ##
@@ -74,24 +69,20 @@ module Cicada
74
69
  #
75
70
  #
76
71
  class P3DObjectiveFunction
77
-
78
72
  include Java::edu.stanford.cfuller.imageanalysistools.fitting.ObjectiveFunction
79
73
 
80
74
  ##
81
75
  # Constructs an empty P3DObjectiveFunction.
82
76
  #
83
77
  def initialize
84
-
85
78
  @r = nil
86
79
  @s = nil
87
80
  @min_prob = nil
88
81
  @use_min_prob = false
89
82
  @should_fit_s = true
90
-
91
83
  end
92
84
 
93
85
  attr_accessor :r, :use_min_prob, :should_fit_s
94
-
95
86
  attr_reader :s, :min_prob
96
87
 
97
88
  ##
@@ -117,10 +108,8 @@ module Cicada
117
108
  # @return [void]
118
109
  #
119
110
  def min_prob=(min_prob)
120
-
121
111
  @min_prob = min_prob
122
112
  @use_min_prob = true
123
-
124
113
  end
125
114
 
126
115
  ##
@@ -133,9 +122,7 @@ module Cicada
133
122
  # @return [Float] the probability density at the given point
134
123
  #
135
124
  def p3d(r, m, s)
136
-
137
125
  (Math.sqrt(2.0/Math::PI)*r/(2*m*s))*(Math.exp(-1 * (m-r)**2/(2*s**2)) - Math.exp( -1 * (m+r)**2/(2*s**2)))
138
-
139
126
  end
140
127
 
141
128
  ##
@@ -148,47 +135,32 @@ module Cicada
148
135
  # @return [Float] the negative log-likelihood of the data.
149
136
  #
150
137
  def evaluate(point)
151
-
152
138
  point = point.toArray unless point.is_a? Array
153
-
154
139
  m = point[0]
155
140
  s = point[1]
156
141
  s = @s unless @should_fit_s
157
-
158
142
  return Float::MAX if (m < 0 or s < 0)
159
143
 
160
144
  r.reduce(0.0) do |sum, ri|
161
-
162
145
  temp_neg_log_p = -1.0*Math.log( p3d(ri, m, s))
163
-
164
- if (@use_min_prob and temp_neg_log_p > @min_prob) then
165
-
146
+ if (@use_min_prob and temp_neg_log_p > @min_prob) then
166
147
  sum + @min_prob
167
-
168
148
  else
169
-
170
149
  sum + temp_neg_log_p
171
-
172
150
  end
173
-
174
- end
175
-
151
+ end
176
152
  end
177
-
178
153
  end
179
-
180
154
 
181
155
  ##
182
156
  # A distribution fitter that fits data to a P3D distribution.
183
157
  #
184
158
  class P3DFitter < DistributionFitter
185
-
186
159
  # parameters required by the methods in this class
187
160
  REQUIRED_PARAMETERS = []
188
161
 
189
162
  # parmeters used but not required in this class or only required for optional functionality
190
163
  OPTIONAL_PARAMETERS = [:robust_p3d_fit_cutoff]
191
-
192
164
 
193
165
  ##
194
166
  # Fits the P3D mean- and standard-deviation-like parameters to the data.
@@ -199,36 +171,22 @@ module Cicada
199
171
  # @return [Array] a two-element array containing the mean- and standard-deviation-like parameters.
200
172
  #
201
173
  def fit(objects, diffs)
202
-
203
174
  of = P3DObjectiveFunction.new
204
-
205
175
  of.r = diffs
206
-
207
176
  tol = 1e-12
208
-
209
177
  nmm = Java::edu.stanford.cfuller.imageanalysistools.fitting.NelderMeadMinimizer.new(tol)
210
-
211
178
  initial_mean = Math.mean(diffs)
212
-
213
179
  initial_width = Math.std(diffs)
214
-
215
180
  starting_point = Java::org.apache.commons.math3.linear.ArrayRealVector.new(2, 0.0)
216
-
217
181
  starting_point.setEntry(0, initial_mean)
218
182
  starting_point.setEntry(1, initial_width)
219
-
220
- if @parameters[:robust_p3d_fit_cutoff] then
221
-
183
+ if @parameters[:robust_p3d_fit_cutoff] then
222
184
  of.min_prob= @parmaeters[:robust_p3d_fit_cutoff].to_f
223
-
224
185
  end
225
186
 
226
187
  nmm.optimize(of, starting_point).toArray.to_a
227
-
228
188
  end
229
-
230
189
  end
231
-
232
190
  end
233
191
 
234
192