find_beads 0.9.5-java → 0.9.6-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/find_beads/version.rb +1 -1
  2. data/lib/find_beads.rb +167 -153
  3. metadata +13 -20
@@ -26,7 +26,7 @@
26
26
 
27
27
  module FindBeads
28
28
 
29
- VERSION = '0.9.5'
29
+ VERSION = '0.9.6'
30
30
 
31
31
  end
32
32
 
data/lib/find_beads.rb CHANGED
@@ -29,19 +29,16 @@ require 'rimageanalysistools/get_image'
29
29
  require 'rimageanalysistools/image_shortcuts'
30
30
  require 'rimageanalysistools/create_parameters'
31
31
  require 'rimageanalysistools/graythresh'
32
-
33
32
  require 'trollop'
34
-
35
33
  require 'matrix'
36
-
37
- java_import Java::edu.stanford.cfuller.imageanalysistools.image.ImageFactory
34
+ require 'ostruct'
35
+ require 'csv'
38
36
 
39
37
  ##
40
38
  # Functions for segmenting and quantifying beads.
41
39
  #
42
40
  module FindBeads
43
-
44
-
41
+ java_import Java::edu.stanford.cfuller.imageanalysistools.image.ImageFactory
45
42
  java_import Java::edu.stanford.cfuller.imageanalysistools.image.ImageCoordinate
46
43
  java_import Java::edu.stanford.cfuller.imageanalysistools.image.ImageSet
47
44
  java_import Java::edu.stanford.cfuller.imageanalysistools.meta.parameters.ParameterDictionary
@@ -66,30 +63,22 @@ module FindBeads
66
63
  # two-element arrays containing the x,y-coordinates of the centroids of these regions.
67
64
  #
68
65
  def self.centroids(mask)
69
-
70
66
  cens = {}
71
67
 
72
68
  mask.each do |ic|
73
-
74
69
  next unless mask[ic] > 0
75
-
76
70
  cens[mask[ic]] = [0.0, 0.0] unless cens[mask[ic]]
77
-
78
71
  cens[mask[ic]][0] += ic[:x]
79
72
  cens[mask[ic]][1] += ic[:y]
80
-
81
73
  end
82
74
 
83
75
  h = Histogram.new(mask)
84
76
 
85
77
  cens.each_key do |k|
86
-
87
78
  cens[k].map! { |e| e / h.getCounts(k) }
88
-
89
79
  end
90
80
 
91
81
  cens
92
-
93
82
  end
94
83
 
95
84
 
@@ -109,15 +98,10 @@ module FindBeads
109
98
  # the other points were specified)
110
99
  #
111
100
  def self.project_point_onto_vector(origin, point_to_project, point_on_line)
112
-
113
101
  unit_vec = (Vector[*point_on_line] - Vector[*origin]).normalize
114
-
115
102
  proj_vec = Vector[*point_to_project] - Vector[*origin]
116
-
117
103
  projected = unit_vec * (proj_vec.inner_product(unit_vec)) + Vector[*origin]
118
-
119
104
  projected.to_a
120
-
121
105
  end
122
106
 
123
107
 
@@ -132,58 +116,33 @@ module FindBeads
132
116
  # @return [Boolean] whether the point is on the border between two regions.
133
117
  #
134
118
  def self.is_on_voronoi_border?(points, ic)
135
-
136
119
  x = ic[:x]
137
120
  y = ic[:y]
138
-
139
121
  closest_index = 0
140
122
  next_index = 0
141
123
  closest_dist = Float::MAX
142
124
  next_dist = Float::MAX
143
125
 
144
-
145
126
  points.each_with_index do |p, i|
146
-
147
127
  dist = Math.hypot(p[0] - x, p[1] - y)
148
128
 
149
129
  if dist < closest_dist then
150
-
151
130
  next_dist = closest_dist
152
-
153
131
  next_index = closest_index
154
-
155
132
  closest_dist = dist
156
-
157
133
  closest_index = i
158
-
159
134
  elsif dist < next_dist then
160
-
161
135
  next_dist = dist
162
-
163
136
  next_index = i
164
-
165
137
  end
166
-
167
138
  end
168
139
 
169
140
  proj_point = project_point_onto_vector(points[closest_index], [x,y], points[next_index])
170
-
171
141
  next_dist_proj = Math.hypot(points[next_index][0]-proj_point[0], points[next_index][1]-proj_point[1])
172
142
  closest_dist_proj = Math.hypot(points[closest_index][0]-proj_point[0], points[closest_index][1]-proj_point[1])
173
-
174
-
175
143
  cutoff = 1.01*Math.sqrt(2)
176
144
 
177
- if next_dist_proj - closest_dist_proj < cutoff then
178
-
179
- true
180
-
181
- else
182
-
183
- false
184
-
185
- end
186
-
145
+ (next_dist_proj - closest_dist_proj < cutoff)
187
146
  end
188
147
 
189
148
  ##
@@ -199,27 +158,18 @@ module FindBeads
199
158
  # @return [void]
200
159
  #
201
160
  def self.recursive_threshold(p, im, mask)
202
-
203
161
  h = Histogram.new(mask)
204
-
205
162
  changed = false
206
-
207
163
  discard_list = {}
208
164
 
209
165
  1.upto(h.getMaxValue) do |i|
210
-
211
166
  if h.getCounts(i) > p[:max_size].to_i then
212
-
213
167
  values = []
214
168
 
215
169
  im.each do |ic|
216
-
217
170
  if mask[ic] == i then
218
-
219
171
  values << im[ic]
220
-
221
172
  end
222
-
223
173
  end
224
174
 
225
175
  thresh = RImageAnalysisTools.graythresh(values)
@@ -227,46 +177,27 @@ module FindBeads
227
177
  im.each do |ic|
228
178
 
229
179
  if mask[ic] == i and im[ic] <= thresh then
230
-
231
180
  mask[ic] = 0
232
-
233
181
  changed = true
234
-
235
182
  end
236
-
237
183
  end
238
-
239
184
  elsif h.getCounts(i) > 0 and h.getCounts(i) < p[:min_size].to_i then
240
-
241
185
  discard_list[i] = true
242
-
243
186
  end
244
-
245
187
  end
246
188
 
247
189
  im.each do |ic|
248
-
249
190
  if discard_list[im[ic]] then
250
-
251
191
  mask[ic] = 0
252
-
253
192
  changed = true
254
-
255
193
  end
256
-
257
194
  end
258
195
 
259
-
260
196
  if changed then
261
-
262
197
  lf = LabelFilter.new
263
-
264
198
  lf.apply(mask)
265
-
266
199
  recursive_threshold(p, im, mask)
267
-
268
200
  end
269
-
270
201
  end
271
202
 
272
203
  ##
@@ -276,9 +207,7 @@ module FindBeads
276
207
  # @param [Fixnum] rad the radius of the bead in units of pixels.
277
208
  #
278
209
  def self.calculate_max_size_from_radius(rad)
279
-
280
210
  ((rad+1)**2 * 3.2).to_i
281
-
282
211
  end
283
212
 
284
213
  ##
@@ -291,9 +220,7 @@ module FindBeads
291
220
  # @param @see #calculate_max_size_from_radius
292
221
  #
293
222
  def self.calculate_min_size_from_radius(rad)
294
-
295
223
  (0.96* (rad+1)**2).to_i
296
-
297
224
  end
298
225
 
299
226
  ##
@@ -301,9 +228,11 @@ module FindBeads
301
228
  #
302
229
  # @param [Image] im the image to segment
303
230
  # @param [Hash] opts a hash of commandline arguments.
231
+ # @param [OpenStruct, #centroids=] centroid_storage an optional object
232
+ # to which the bead centroids will be fed using #centroids=
233
+ # default=nil, causes them not to be set
304
234
  #
305
- def self.mask_from_image(im, opts)
306
-
235
+ def self.mask_from_image(im, opts, centroid_storage = nil)
307
236
  seg_ch = nil
308
237
  seg_pl = nil
309
238
  rad = nil
@@ -320,49 +249,36 @@ module FindBeads
320
249
 
321
250
  min_size = calculate_min_size_from_radius(rad)
322
251
  max_size = calculate_max_size_from_radius(rad)
323
-
324
- sizes = ImageCoordinate.cloneCoord(im.getDimensionSizes)
325
252
 
253
+ sizes = ImageCoordinate.cloneCoord(im.getDimensionSizes)
326
254
  sizes[:c] = 1
327
255
  sizes[:z] = 1
328
256
 
329
257
  im0 = ImageCoordinate.createCoordXYZCT(0,0,0,0,0)
330
-
331
258
  im0[:c] = seg_ch
332
259
  im0[:z] = seg_pl
333
260
 
334
261
  to_seg = im.subImage(sizes, im0).writableInstance
335
-
336
262
  p = RImageAnalysisTools.create_parameter_dictionary(min_size: min_size, max_size: max_size)
337
-
338
263
  im_cp = ImageFactory.create_writable(to_seg)
339
264
 
340
265
  mstf = MaximumSeparabilityThresholdingFilter.new
341
-
342
266
  lf = LabelFilter.new
343
-
344
267
  saf = SizeAbsoluteFilter.new
345
268
 
346
269
  filters = []
347
-
348
270
  filters << mstf
349
-
350
271
  filters << lf
351
272
 
352
273
  filters.each do |f|
353
-
354
274
  f.setParameters(p)
355
275
  f.setReferenceImage(im_cp)
356
276
  f.apply(to_seg)
357
-
358
277
  end
359
278
 
360
279
  recursive_threshold(p, im_cp, to_seg)
361
-
362
280
  saf.setParameters(p)
363
-
364
281
  saf.apply(to_seg)
365
-
366
282
  cens = centroids(to_seg)
367
283
 
368
284
  final_mask = ImageFactory.create_writable(to_seg)
@@ -370,51 +286,156 @@ module FindBeads
370
286
  radius = rad
371
287
 
372
288
  final_mask.each do |ic|
373
-
374
289
  final_mask[ic] = 0
375
-
376
290
  end
377
291
 
378
292
  final_mask.each do |ic|
379
-
380
293
  x = ic[:x]
381
294
  y = ic[:y]
382
295
 
383
296
  cens.each_key do |k|
384
-
385
297
  if Math.hypot(cens[k][0] - x, cens[k][1] - y) <= radius then
386
-
387
298
  final_mask[ic] = k
388
-
389
299
  end
390
-
391
300
  end
392
-
393
301
  end
394
302
 
395
-
396
303
  final_mask.each do |ic|
397
-
398
304
  next unless final_mask[ic] > 0
399
305
 
400
306
  if is_on_voronoi_border?(cens.values, ic) then
401
-
402
307
  final_mask[ic] = 0
403
-
404
308
  end
405
-
406
309
  end
407
310
 
408
311
  lf.apply(final_mask)
409
-
410
312
  saf.apply(final_mask)
411
-
412
313
  lf.apply(final_mask)
413
314
 
315
+ remapped_cens = {}
316
+ cen_coord = ImageCoordinate[0,0,0,0,0]
317
+
318
+ cens.each do |k, cen|
319
+ cen_coord[:x] = cen[0]
320
+ cen_coord[:y] = cen[1]
321
+ val = final_mask[cen_coord]
322
+
323
+ if val > 0 then
324
+ remapped_cens[val] = cen
325
+ end
326
+ end
327
+
328
+ cen_coord.recycle
329
+
330
+ if centroid_storage then
331
+ centroid_storage.centroids= remapped_cens
332
+ end
333
+
414
334
  final_mask
415
335
 
416
336
  end
417
337
 
338
+ ##
339
+ # Swaps the x and y coordinates of an ImageCoordinate in place relative to a supplied origin.
340
+ #
341
+ # @param [ImageCoordinate] coord the coordinate whose components will be swapped.
342
+ # @param [Numeric] cen_x the x-coordinate of the origin relative to which the swap will be calculated
343
+ # @param [Numeric] cen_y the y-coordinate of the origin relative to which the swap will be calculated
344
+ #
345
+ # @return [ImageCoordinate] coord
346
+ #
347
+ def self.mirror_coord!(coord, cen_x, cen_y)
348
+ rel_x = coord[:x] - cen_x
349
+ rel_y = coord[:y] - cen_y
350
+ coord[:x] = (rel_y + cen_x).round.to_i
351
+ coord[:y] = (rel_x + cen_y).round.to_i
352
+ coord
353
+ end
354
+
355
+ ##
356
+ # Computes the two-channel correlation for a single bead.
357
+ #
358
+ # @param [Image] mask the mask of labeled, segmented beads
359
+ # @param [Image] im the image of the beads (single z-section, multiple channels)
360
+ # @param [Integer] ch0 the (0-based) index of the first channel of the correlation
361
+ # @param [Integer] ch1 the (0-based) index of the second channel of the correlation
362
+ # @param [Array] cen an array containing the x,y coordinates of the centroid of the current bead
363
+ # @param [Integer] id the label of the current bead in the mask
364
+ # @param [Numeric] bead_radius the radius of a bead
365
+ # @param [Boolean] do_normalization whether to normalize to the geometric mean of the autocorrelations of the two channels
366
+ #
367
+ # @return [Hash] a hash containing components :norm_corr (the background-subtracted, normalized correlation), :corr (the
368
+ # non-normalized, non-subtracted two-channel correlation), and :bg_corr (the non-normalized background
369
+ # two-channel correlation, calculated by rotating one channel of the bead 90 degrees around the bead centroid)
370
+ #
371
+ def self.compute_single_bead_correlation(mask, im, ch0, ch1, cen, id, bead_radius, do_normalization)
372
+ normalization = if do_normalization then
373
+ auto_00 = compute_single_bead_correlation(mask, im, ch0, ch0, cen, id, bead_radius, false)[:norm_corr]
374
+ auto_11 = compute_single_bead_correlation(mask, im, ch1, ch1, cen, id, bead_radius, false)[:norm_corr]
375
+ Math.sqrt(auto_00 * auto_11)*(auto_00.abs/auto_00)
376
+ else
377
+ 1
378
+ end
379
+
380
+ box_lower = ImageCoordinate[cen[0] - bead_radius - 1, cen[1] - bead_radius - 1,0,0,0]
381
+ box_upper = ImageCoordinate[cen[0] + bead_radius + 2, cen[1] + bead_radius + 2,1,1,1]
382
+ mask.setBoxOfInterest(box_lower, box_upper)
383
+
384
+ ch_coord = ImageCoordinate[0,0,0,0,0]
385
+ corr_sum = 0
386
+ bg_sum = 0
387
+ count = 0
388
+ bg_count = 0
389
+
390
+ mask.each do |ic|
391
+ next unless mask[ic] == id
392
+ ch_coord.setCoord(ic)
393
+ ch_coord[:c] = ch0
394
+ val = im[ch_coord]
395
+ ch_coord[:c] = ch1
396
+ corr_sum += val * im[ch_coord]
397
+ count += 1
398
+ mirror_coord!(ch_coord, cen[0], cen[1])
399
+ if im.inBounds(ch_coord) then
400
+ bg_sum += val * im[ch_coord]
401
+ bg_count += 1
402
+ end
403
+ end
404
+
405
+ mask.clearBoxOfInterest
406
+ box_lower.recycle
407
+ box_upper.recycle
408
+ ch_coord.recycle
409
+
410
+ {norm_corr: (corr_sum/count - bg_sum/bg_count)/normalization , corr: corr_sum/count, bg_corr: bg_sum/bg_count}
411
+
412
+ end
413
+
414
+ ##
415
+ # Runs a correlation analysis between two channels of the image. This is done by directly
416
+ # computing the correlation for each bead and then computing an effective background by
417
+ # swapping the x- and y- axes of one channel within each bead.
418
+ #
419
+ # @param [Image] mask the mask of the beads
420
+ # @param [Integer] ch0 the first channel for the correlation
421
+ # @param [Integer] ch1 the second channel for the correlation
422
+ # @param [Hash] cens a hash mapping bead labels in the mask to the centroids of the beads
423
+ # @param [Hash] opts the options hash
424
+ #
425
+ # @return [Hash] a hash mapping :norm_corr, :corr, and :bg_corr to a hash mapping bead labels to their measurements
426
+ #
427
+ def self.compute_correlation(mask, im, ch0, ch1, cens, opts)
428
+ result = {norm_corr: {}, corr: {}, bg_corr: {}}
429
+ cens.each do |id, cen|
430
+ corr_for_bead = compute_single_bead_correlation(mask, im, ch0, ch1, cen, id, opts[:beadradius], true)
431
+ result[:norm_corr][id] = corr_for_bead[:norm_corr]
432
+ result[:corr][id] = corr_for_bead[:corr]
433
+ result[:bg_corr][id] = corr_for_bead[:bg_corr]
434
+ end
435
+ result
436
+ end
437
+
438
+
418
439
  ##
419
440
  # Writes the output data and mask to files.
420
441
  #
@@ -423,36 +444,44 @@ module FindBeads
423
444
  # @param [Image] mask the mask to write
424
445
  #
425
446
  def self.write_output(fn_orig, quant_str, mask)
426
-
427
447
  mask_dir = "output_mask"
428
-
429
448
  quant_dir = "quantification"
430
-
431
449
  mask_ext = "_mask.ome.tif"
432
-
433
450
  quant_ext = "_quant.txt"
434
451
 
435
452
  dir = File.dirname(fn_orig)
436
-
437
453
  base = File.basename(fn_orig)
438
-
439
454
  base = base.gsub(".ome.tif", "")
440
-
441
455
  mask_dir = File.expand_path(mask_dir, dir)
442
-
443
456
  quant_dir = File.expand_path(quant_dir, dir)
444
-
445
457
  Dir.mkdir(mask_dir) unless Dir.exist?(mask_dir)
446
458
  Dir.mkdir(quant_dir) unless Dir.exist?(quant_dir)
447
459
 
448
460
  mask.writeToFile(File.expand_path(base + mask_ext, mask_dir))
449
461
 
450
462
  File.open(File.expand_path(base + quant_ext, quant_dir), 'w') do |f|
451
-
452
463
  f.puts(quant_str)
453
-
454
464
  end
465
+ end
455
466
 
467
+ ##
468
+ # Organizes the correlation data into a csv string where each row is a bead and each column is a measurement.
469
+ # Also creates a header row.
470
+ #
471
+ # @param [Hash] corr_output a hash formatted like the output of FindBeads.compute_correlation
472
+ #
473
+ # @return [String] a string containing the same data in csv format.
474
+ #
475
+ def self.format_correlation_output(corr_output)
476
+ header_row = ["bead index", "normalized, corrected correlation", "correlation", "background correlation"]
477
+
478
+ CSV.generate do |csv|
479
+ csv << header_row
480
+
481
+ corr_output[:corr].each_key do |id|
482
+ csv << [id, corr_output[:norm_corr][id], corr_output[:corr][id], corr_output[:bg_corr][id]]
483
+ end
484
+ end
456
485
  end
457
486
 
458
487
  ##
@@ -462,60 +491,60 @@ module FindBeads
462
491
  # @param [Hash] opts a hash of command line options.
463
492
  #
464
493
  def self.process_file(fn, opts=nil)
465
-
466
494
  puts "processing #{fn}"
467
495
 
468
- im = RImageAnalysisTools.get_image(fn)
469
-
470
- mask = mask_from_image(im, opts)
496
+ cens = if opts and opts[:correlation_channels] then
497
+ OpenStruct.new
498
+ else
499
+ nil
500
+ end
471
501
 
502
+ im = RImageAnalysisTools.get_image(fn)
503
+ mask = mask_from_image(im, opts, cens)
472
504
  proj = Java::edu.stanford.cfuller.imageanalysistools.frontend.MaximumIntensityProjection.projectImage(im)
473
-
474
505
  ims = proj.splitChannels
475
-
476
506
  is = ImageSet.new(ParameterDictionary.emptyDictionary)
477
507
 
478
508
  ims.each do |imc|
479
-
480
509
  is.addImageWithImage(imc)
481
-
482
510
  end
483
511
 
484
- met = IntensityPerPixelMetric.new
485
-
486
- q = met.quantify(mask, is)
487
-
488
- outdat = Java::edu.stanford.cfuller.imageanalysistools.frontend.LocalAnalysis.generateDataOutputString(q, nil)
512
+ outdat = if opts and opts[:correlation_channels] then
513
+ q = compute_correlation(mask, proj, opts[:correlation_channels][0], opts[:correlation_channels][1], cens.centroids, opts)
514
+ format_correlation_output(q)
515
+ else
516
+ met = IntensityPerPixelMetric.new
517
+ q = met.quantify(mask, is)
518
+ Java::edu.stanford.cfuller.imageanalysistools.frontend.LocalAnalysis.generateDataOutputString(q, nil)
519
+ end
489
520
 
490
521
  write_output(fn, outdat, mask)
491
-
492
522
  end
493
523
 
494
524
  ##
495
525
  # Runs the bead finding on a file or directory, and grabs options from the command line.
496
526
  #
497
527
  def self.run_find_beads
498
-
499
528
  opts = Trollop::options do
500
-
501
529
  opt :dir, "Directory to process", :type => :string
502
530
  opt :file, "File to process", :type => :string
503
531
  opt :segchannel, "Channel on which to segment (0-indexed)", :type => :integer, :default => DEFAULT_SEG_CH
504
532
  opt :segplane, "Plane on which to segment (0-indexed)", :type => :integer, :default => DEFAULT_SEG_PL
505
533
  opt :max_threads, "Maximum number of paralell execution threads", :type => :integer, :default => DEFAULT_THREADS
506
534
  opt :beadradius, "Radius of the bead in pixels", :type => :float, :default => DEFAULT_BEAD_RADIUS
535
+ opt :correlation_channels, "Runs correlation between the specified two comma separated channels", :type => :string, :default => nil
536
+ end
507
537
 
538
+ if opts[:correlation_channels] then
539
+ opts[:correlation_channels] = opts[:correlation_channels].gsub("\s+", "").split(",").map(&:to_i)
508
540
  end
509
541
 
510
542
  if opts[:dir] then
511
-
512
543
  fod = opts[:dir]
513
-
514
544
  sleep_time_s = 0.5
515
545
  threads = []
516
546
 
517
547
  Dir.foreach(fod) do |f|
518
-
519
548
  until threads.count { |t| t.alive? } < opts[:max_threads] do
520
549
  sleep sleep_time_s
521
550
  end
@@ -523,39 +552,24 @@ module FindBeads
523
552
  fn = File.expand_path(f, fod)
524
553
 
525
554
  if File.file?(fn) then
526
-
527
555
  begin
528
-
529
556
  threads << Thread.new do
530
-
531
557
  process_file(fn, opts)
532
-
533
558
  end
534
559
 
535
560
  rescue Exception => e
536
-
537
561
  puts "Unable to process #{fn}:"
538
562
  puts e.message
539
-
540
563
  end
541
-
542
564
  end
543
-
544
565
  end
545
566
 
546
567
  threads.each { |t| t.join }
547
-
548
568
  end
549
569
 
550
-
551
-
552
570
  if opts[:file] then
553
-
554
571
  process_file(opts[:file], opts)
555
-
556
572
  end
557
-
558
573
  end
559
-
560
574
  end
561
575
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: find_beads
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.5
4
+ version: 0.9.6
5
5
  prerelease:
6
6
  platform: java
7
7
  authors:
@@ -15,17 +15,15 @@ dependencies:
15
15
  name: rimageanalysistools
16
16
  version_requirements: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - '>='
19
19
  - !ruby/object:Gem::Version
20
- version: !binary |-
21
- MA==
20
+ version: '0'
22
21
  none: false
23
22
  requirement: !ruby/object:Gem::Requirement
24
23
  requirements:
25
- - - ">="
24
+ - - '>='
26
25
  - !ruby/object:Gem::Version
27
- version: !binary |-
28
- MA==
26
+ version: '0'
29
27
  none: false
30
28
  prerelease: false
31
29
  type: :runtime
@@ -33,17 +31,15 @@ dependencies:
33
31
  name: trollop
34
32
  version_requirements: !ruby/object:Gem::Requirement
35
33
  requirements:
36
- - - ">="
34
+ - - '>='
37
35
  - !ruby/object:Gem::Version
38
- version: !binary |-
39
- MA==
36
+ version: '0'
40
37
  none: false
41
38
  requirement: !ruby/object:Gem::Requirement
42
39
  requirements:
43
- - - ">="
40
+ - - '>='
44
41
  - !ruby/object:Gem::Version
45
- version: !binary |-
46
- MA==
42
+ version: '0'
47
43
  none: false
48
44
  prerelease: false
49
45
  type: :runtime
@@ -67,17 +63,15 @@ require_paths:
67
63
  - lib
68
64
  required_ruby_version: !ruby/object:Gem::Requirement
69
65
  requirements:
70
- - - ">="
66
+ - - '>='
71
67
  - !ruby/object:Gem::Version
72
- version: !binary |-
73
- MA==
68
+ version: '0'
74
69
  none: false
75
70
  required_rubygems_version: !ruby/object:Gem::Requirement
76
71
  requirements:
77
- - - ">="
72
+ - - '>='
78
73
  - !ruby/object:Gem::Version
79
- version: !binary |-
80
- MA==
74
+ version: '0'
81
75
  none: false
82
76
  requirements:
83
77
  - jruby
@@ -87,4 +81,3 @@ signing_key:
87
81
  specification_version: 3
88
82
  summary: Segments and quantifies beads in microscopy images
89
83
  test_files: []
90
- has_rdoc: