sqed 0.5.8 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 189f2b34c7f74be111c238f7b8ebc5afdbe9f271defe7fe28eba2fa20fc1a11b
4
- data.tar.gz: f45e49206f74d86f6367969010056161af9d3a17e105a786c5279a3c7b3b4529
3
+ metadata.gz: 0a10699c845a53421c6ea0446eac442be0470448d0c55c876bb849c2ec4a928e
4
+ data.tar.gz: b15da56bbbd2146e8683c7c19bcf3df8712c9bdb43c4015f173992e111b52520
5
5
  SHA512:
6
- metadata.gz: 8f7bf2d0a0a89bb0f4ceaf9bb9348a3cd0e29ee146ece899dfb68f784c3b7f838d368b3f1bd25287e55a27b7e090f1ba311160e9e1cd7cc3a22ae40c713fa2af
7
- data.tar.gz: 6f1b250541ff6b4ac24a94b529e3bc73df53fd5c6ac8ebf2043d9b6e5ff9b3fa40c7b586dd9bbafb732c688d396071cfa43f77c9a4fe78362e503bdb9e21c523
6
+ metadata.gz: 1f7b7798e7e21145b3d46da2f68ff8b5bd83f341a7926d894d3f7253e5551eafa8297a26bd5fb0053707acca91c2fec2db42638bc27b54c13d58986b8ab6a051
7
+ data.tar.gz: b5ba7f2552f5db764f9436c77b874e7c094369d554a6df44ac15342a40177a7a80531fe1c3d87d2a34b725deeef21adec53fab1a311e0de7bf55e4a3ced64194
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.1
1
+ 3.0.2
data/.travis.yml CHANGED
@@ -3,7 +3,7 @@
3
3
  language: ruby
4
4
  dist: bionic
5
5
  rvm:
6
- - 2.6.3
6
+ - 2.7.1
7
7
  #before_install:
8
8
  # - sudo add-apt-repository -y ppa:moti-p/cc
9
9
  # - sudo apt-get update
@@ -12,9 +12,11 @@ rvm:
12
12
  before_install:
13
13
  - sudo apt-get update -qq
14
14
  - sudo apt-get install -qq tesseract-ocr tesseract-ocr-nld
15
+ - sudo sed -i 's/name="disk" value="1GiB"/name="disk" value="8GiB"/' /etc/ImageMagick-6/policy.xml
16
+ - identify -list resource | grep Disk | grep 8GiB # Check ImageMagick setting is actually working.
15
17
  branches:
16
18
  only:
17
- - master
19
+ - main
18
20
  notifications:
19
21
  email:
20
22
  - diapriid@gmail.com
@@ -24,7 +24,7 @@ class Sqed
24
24
  attr_accessor :complete
25
25
 
26
26
  def initialize(layout = nil)
27
- raise 'unrecognized layout' if layout && !SqedConfig::LAYOUTS.include?(layout)
27
+ raise Sqed::Error, 'unrecognized layout' if layout && !SqedConfig::LAYOUTS.include?(layout)
28
28
  @complete = false
29
29
 
30
30
  @layout = layout
@@ -15,7 +15,7 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
15
15
 
16
16
  super(image: image, layout: layout, use_thumbnail: use_thumbnail)
17
17
 
18
- raise 'No layout provided.' if @layout.nil?
18
+ raise Sqed::Error, 'No layout provided.' if @layout.nil?
19
19
 
20
20
  # !@#? why this
21
21
  @boundary_color = boundary_color
@@ -29,34 +29,39 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
29
29
 
30
30
  private
31
31
 
32
+ # boundaries.coordinates are referenced from stage image
33
+ #
34
+ # A reminder that boundaries are x1,y1, width, height
32
35
  def find_bands
33
- case layout # boundaries.coordinates are referenced from stage image
34
36
 
35
- when :cross # 4 zones, with perfectly intersected horizontal and vertical division
37
+ # see config/sqed_config.rb
38
+ case layout
39
+
40
+ when :cross # 4 windows, with perfectly intersected horizontal and vertical division
36
41
  v = self.class.new(image: @image, layout: :vertical_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
37
- h = self.class.new(image: @image, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false).boundaries
42
+ h = self.class.new(image: @image, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false).boundaries
38
43
 
39
44
  return if v.nil? || h.nil?
40
45
 
41
- boundaries.set(0, [0,0, v.width_for(0), h.height_for(0) ])
42
- boundaries.set(1, [ v.x_for(1), 0, v.width_for(1), h.height_for(0) ])
43
- boundaries.set(2, [ v.x_for(1), h.y_for(1), v.width_for(1), h.height_for(1) ])
44
- boundaries.set(3, [0, h.y_for(1), v.width_for(0), h.height_for(1) ])
46
+ boundaries.set(0, [0,0, v.width_for(0), h.height_for(0) ])
47
+ boundaries.set(1, [ v.x_for(1), 0, v.width_for(1), h.height_for(0) ])
48
+ boundaries.set(2, [ v.x_for(1), h.y_for(1), v.width_for(1), h.height_for(1) ])
49
+ boundaries.set(3, [0, h.y_for(1), v.width_for(0), h.height_for(1) ])
45
50
 
46
51
  # No specs for this yet
47
52
  when :horizontal_offset_cross
48
53
  horizontal = self.class.new(image: @image, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
49
54
 
50
- itop = image.crop(*horizontal.for(0), true)
55
+ itop = image.crop(*horizontal.for(0), true)
51
56
  ibottom = image.crop(*horizontal.for(1), true)
52
57
 
53
58
  top = self.class.new(image: itop, layout: :vertical_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
54
59
  bottom = self.class.new(image: ibottom, layout: :vertical_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
55
60
 
56
- boundaries.set(0, [0, 0, top.width_for(0), top.height_for(0) ])
57
- boundaries.set(1, [top.x_for(1), 0, top.width_for(1), top.height_for(1) ])
58
- boundaries.set(2, [bottom.x_for(1), horizontal.y_for(1), bottom.width_for(1), bottom.height_for(1) ])
59
- boundaries.set(3, [0, horizontal.y_for(1), bottom.width_for(0), bottom.height_for(0) ])
61
+ boundaries.set(0, [0, 0, top.width_for(0), top.height_for(0) ])
62
+ boundaries.set(1, [top.x_for(1), 0, top.width_for(1), top.height_for(1) ])
63
+ boundaries.set(2, [bottom.x_for(1), horizontal.y_for(1), bottom.width_for(1), bottom.height_for(1) ])
64
+ boundaries.set(3, [0, horizontal.y_for(1), bottom.width_for(0), bottom.height_for(0) ])
60
65
 
61
66
  when :lep_stage
62
67
  top_bottom_split = Sqed::BoundaryFinder.color_boundary_finder(image: image, scan: :columns, boundary_color: boundary_color) # detect vertical division [array]
@@ -64,9 +69,9 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
64
69
 
65
70
  boundaries.set(6, [0, top_bottom_split[2], left_right_split[0], image.rows - top_bottom_split[2]] )
66
71
 
67
- left_top_image = image.crop( 0, 0, left_right_split[0], top_bottom_split[0], true)
72
+ left_top_image = image.crop( 0, 0, left_right_split[0], top_bottom_split[0], true)
68
73
 
69
- left_top_split =
74
+ left_top_split =
70
75
  SqedUtils.corrected_frequency(
71
76
  Sqed::BoundaryFinder.color_boundary_finder(image: left_top_image, boundary_color: boundary_color),
72
77
  max_width: left_top_image.columns,
@@ -74,8 +79,8 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
74
79
  )
75
80
 
76
81
  boundaries.set(0, [0, 0, left_top_split[1], top_bottom_split[0]] ) # keep as 1 for safety
77
-
78
- boundaries.set(1, [left_top_split[2], 0, left_top_image.columns - left_top_split[2], top_bottom_split[0]] )
82
+
83
+ boundaries.set(1, [left_top_split[2], 0, left_top_image.columns - left_top_split[2], top_bottom_split[0]] )
79
84
  boundaries.set(2, [left_right_split[2], 0, image.columns - left_right_split[0], top_bottom_split[0]] )
80
85
 
81
86
  bottom_right_image = image.crop(left_right_split[2], top_bottom_split[2], image.columns - left_right_split[2], image.rows - top_bottom_split[2], true)
@@ -89,7 +94,7 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
89
94
 
90
95
  boundaries.set(3, [left_right_split[2] + bottom_right_split[2], top_bottom_split[2], image.columns - bottom_right_split[2], image.rows - top_bottom_split[2] ] )
91
96
 
92
- bottom_right_left_image = image.crop(left_right_split[2], top_bottom_split[2], bottom_right_split[0], image.rows - top_bottom_split[2], true)
97
+ bottom_right_left_image = image.crop(left_right_split[2], top_bottom_split[2], bottom_right_split[0], image.rows - top_bottom_split[2], true)
93
98
 
94
99
  bottom_right_left_split =
95
100
  SqedUtils.corrected_frequency(
@@ -101,25 +106,104 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
101
106
  boundaries.set(4, [left_right_split[2], top_bottom_split[2], bottom_right_image.columns - bottom_right_left_image.columns, bottom_right_left_split[0] ] )
102
107
 
103
108
  boundaries.set(5, [
104
- left_right_split[2],
109
+ left_right_split[2],
105
110
  top_bottom_split[2] + bottom_right_left_split[2],
106
111
  bottom_right_image.columns - bottom_right_left_image.columns,
107
- bottom_right_left_image.rows - bottom_right_left_split[2]
112
+ bottom_right_left_image.rows - bottom_right_left_split[2]
108
113
  ])
109
114
 
115
+ when :lep_stage2
116
+ top_bottom_split = Sqed::BoundaryFinder.color_boundary_finder(image: image, scan: :columns, boundary_color: boundary_color) # detect vertical division [array]
117
+ left_right_split = Sqed::BoundaryFinder.color_boundary_finder(image: image, sample_subdivision_size: 2, boundary_color: boundary_color) # detect horizontal division [array]
118
+
119
+ boundaries.set(6, [0, top_bottom_split[2], left_right_split[0], image.rows - top_bottom_split[2]] ) # OK
120
+
121
+ left_top_image = image.crop( 0, 0, left_right_split[0], top_bottom_split[0], true)
122
+
123
+ left_top_split =
124
+ SqedUtils.corrected_frequency(
125
+ Sqed::BoundaryFinder.color_boundary_finder(image: left_top_image, boundary_color: boundary_color),
126
+ max_width: left_top_image.columns,
127
+ width_factor: 1.8
128
+ )
129
+
130
+ boundaries.set(0, [0, 0, left_top_split[1], top_bottom_split[0]] ) # OK
131
+
132
+ boundaries.set(1, [left_top_split[2], 0, left_top_image.columns - left_top_split[2], top_bottom_split[0]] )
133
+ boundaries.set(2, [left_right_split[2], 0, image.columns - left_right_split[0], top_bottom_split[0]] )
134
+
135
+ bottom_right_image = image.crop(left_right_split[2], top_bottom_split[2], image.columns - left_right_split[2], image.rows - top_bottom_split[2], true)
136
+
137
+ bottom_right_split =
138
+ SqedUtils.corrected_frequency(
139
+ Sqed::BoundaryFinder.color_boundary_finder(image: bottom_right_image, boundary_color: boundary_color, scan: :rows),
140
+ max_width: bottom_right_image.columns,
141
+ width_factor: 1.8
142
+ )
143
+
144
+ boundaries.set(3, [
145
+ left_right_split[2] + bottom_right_split[2],
146
+ top_bottom_split[2],
147
+ image.columns - bottom_right_split[2],
148
+ top_bottom_split[0] ])
149
+
150
+ bottom_right_left_image = image.crop(left_right_split[2], top_bottom_split[2], bottom_right_split[0], image.rows - top_bottom_split[2], true)
151
+
152
+ bottom_right_left_top_bottom_split =
153
+ SqedUtils.corrected_frequency(
154
+ Sqed::BoundaryFinder.color_boundary_finder(image: bottom_right_left_image, scan: :columns, boundary_color: boundary_color),
155
+ max_width: bottom_right_left_image.columns,
156
+ width_factor: 1.8
157
+ )
158
+
159
+ boundaries.set(4, [
160
+ left_right_split[2],
161
+ top_bottom_split[2] + bottom_right_left_top_bottom_split[2],
162
+ bottom_right_left_image.columns,
163
+ bottom_right_left_top_bottom_split[2]
164
+ ])
165
+
166
+
167
+ boundaries.set(5, [
168
+ left_right_split[2],
169
+ top_bottom_split[2],
170
+ bottom_right_left_image.columns,
171
+ bottom_right_left_top_bottom_split[0],
172
+ ])
173
+
174
+ when :t
175
+ horizontal = self.class.new(image: @image, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
176
+
177
+ bottom = image.crop(*horizontal.for(1), true)
178
+ btm_split = self.class.new(image: bottom, layout: :vertical_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
179
+
180
+ boundaries.set(0, horizontal.for(0))
181
+ boundaries.set(1, [ btm_split.x_for(1), horizontal.height_for(0), btm_split.width_for(1), btm_split.height_for(1) ] )
182
+ boundaries.set(2, [ 0, horizontal.height_for(0), btm_split.width_for(0), btm_split.height_for(0) ] )
183
+
184
+ when :inverted_t
185
+ horizontal = self.class.new(image: @image, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
186
+
187
+ top = image.crop(*horizontal.for(0), true)
188
+ top_split = self.class.new(image: top, layout: :vertical_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
189
+
190
+ boundaries.set(0, [ 0,0, top_split.width_for(0), top_split.height_for(0)] )
191
+ boundaries.set(1, [ top_split.width_for(0), 0, top_split.width_for(1), top_split.height_for(1)] )
192
+ boundaries.set(2, horizontal.for(1))
193
+
110
194
  when :right_t
111
195
  vertical = self.class.new(image: @image, layout: :vertical_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
112
196
 
113
197
  irt = image.crop(*vertical.for(1), true)
114
198
  right = self.class.new(image: irt, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries
115
199
 
116
- boundaries.set(0, vertical.for(0))
117
- boundaries.set(1, [ vertical.x_for(1), 0, right.width_for(0), right.height_for(0) ] )
118
- boundaries.set(2, [ vertical.x_for(1), right.y_for(1), right.width_for(1), right.height_for(1)] )
200
+ boundaries.set(0, vertical.for(0))
201
+ boundaries.set(1, [ vertical.x_for(1), 0, right.width_for(0), right.height_for(0) ] )
202
+ boundaries.set(2, [ vertical.x_for(1), right.y_for(1), right.width_for(1), right.height_for(1)] )
119
203
 
120
204
  when :seven_slot
121
205
  top_bottom_split = Sqed::BoundaryFinder.color_boundary_finder(image: image, scan: :columns, boundary_color: boundary_color) # detect vertical division [array]
122
- left_right_split = Sqed::BoundaryFinder.color_boundary_finder(image: image, sample_subdivision_size: 2, boundary_color: boundary_color) # detect horizontal division [array]
206
+ left_right_split = Sqed::BoundaryFinder.color_boundary_finder(image: image, sample_subdivision_size: 1, boundary_color: boundary_color) # detect horizontal division [array]
123
207
 
124
208
  boundaries.set(0, [0, 0, left_right_split[0], top_bottom_split[0]])
125
209
  boundaries.set(6, [0, top_bottom_split[2], left_right_split[0], image.rows - top_bottom_split[2]] )
@@ -128,18 +212,22 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
128
212
  right_bottom_image = image.crop(left_right_split[2], top_bottom_split[2], image.columns - left_right_split[2], image.rows - top_bottom_split[2], true) # sections 3,4,5
129
213
 
130
214
  right_top_split = ::SqedUtils.corrected_frequency(
131
- Sqed::BoundaryFinder.color_boundary_finder(image: right_top_image, boundary_color: boundary_color, scan: :rows),
132
- width_factor: 1.8,
133
- max_width: right_top_image.columns
215
+ Sqed::BoundaryFinder.color_boundary_finder(
216
+ image: right_top_image, boundary_color: boundary_color, scan: :rows),
217
+ width_factor: 1.8,
218
+ max_width: right_top_image.columns
134
219
  ) # vertical line b/w 1 & 2, use "corrected_frequency" to account for color bleed from previous crop
135
220
 
136
221
  boundaries.set(1, [left_right_split[2], 0, right_top_split[0], top_bottom_split[0]] )
137
222
  boundaries.set(2, [left_right_split[2] + right_top_split[2], 0, right_top_image.columns - right_top_split[2], top_bottom_split[0]])
138
223
 
139
224
  right_bottom_split = SqedUtils.corrected_frequency(
140
- Sqed::BoundaryFinder.color_boundary_finder(image: right_bottom_image, scan: :columns, sample_subdivision_size: 2, boundary_color: boundary_color),
141
- width_factor: 1.8,
142
- max_width: right_bottom_image.rows) # horizontal line b/w (5,3) & 4, use "corrected_frequency" to account for color bleed from previous crop
225
+ Sqed::BoundaryFinder.color_boundary_finder(
226
+ image: right_bottom_image,
227
+ scan: :columns,
228
+ sample_subdivision_size: 2, boundary_color: boundary_color),
229
+ width_factor: 1.8,
230
+ max_width: right_bottom_image.rows) # horizontal line b/w (5,3) & 4, use "corrected_frequency" to account for color bleed from previous crop
143
231
 
144
232
  bottom_right_top_image = right_bottom_image.crop(0,0, image.columns - left_right_split[2], right_bottom_split[0], true) # 3,5
145
233
 
@@ -151,18 +239,18 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
151
239
  when :vertical_offset_cross # 4 zones expected, with (varying) horizontal division in left- and right- sides of vertical division
152
240
  vertical = self.class.new(image: @image, layout: :vertical_split, boundary_color: boundary_color, use_thumbnail: false).boundaries
153
241
 
154
- ilt = image.crop(*vertical.for(0), true)
242
+ ilt = image.crop(*vertical.for(0), true)
155
243
  irt = image.crop(*vertical.for(1), true)
156
244
 
157
245
  left = self.class.new(image: ilt, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false).boundaries # fails
158
246
  right = self.class.new(image: irt, layout: :horizontal_split, boundary_color: boundary_color, use_thumbnail: false ).boundaries # OK
159
247
 
160
- boundaries.set(0, [0, 0, left.width_for(0), left.height_for(0) ])
161
- boundaries.set(1, [vertical.x_for(1), 0, right.width_for(0), right.height_for(0) ])
162
- boundaries.set(2, [vertical.x_for(1), right.y_for(1), right.width_for(1), right.height_for(1) ])
163
- boundaries.set(3, [0, left.y_for(1), left.width_for(1), left.height_for(1) ])
248
+ boundaries.set(0, [0, 0, left.width_for(0), left.height_for(0) ])
249
+ boundaries.set(1, [vertical.x_for(1), 0, right.width_for(0), right.height_for(0) ])
250
+ boundaries.set(2, [vertical.x_for(1), right.y_for(1), right.width_for(1), right.height_for(1) ])
251
+ boundaries.set(3, [0, left.y_for(1), left.width_for(1), left.height_for(1) ])
164
252
 
165
- when :vertical_split
253
+ when :vertical_split
166
254
  t = Sqed::BoundaryFinder.color_boundary_finder(image: image, boundary_color: boundary_color) #detect vertical division
167
255
  return if t.nil?
168
256
  boundaries.set(0, [0, 0, t[0], image.rows]) # left section of image
@@ -175,10 +263,7 @@ class Sqed::BoundaryFinder::ColorLineFinder < Sqed::BoundaryFinder
175
263
  boundaries.set(0, [0, 0, image.columns, t[0]]) # upper section of image
176
264
  boundaries.set(1, [0, t[2], image.columns, image.rows - t[2]]) # lower section of image
177
265
 
178
-
179
-
180
266
  else # no @layout provided !?
181
-
182
267
  boundaries.set(0, [0, 0, image.columns, image.rows]) # totality of image as default
183
268
  end
184
269
 
@@ -6,6 +6,7 @@ class Sqed
6
6
  #
7
7
  class BoundaryFinder
8
8
 
9
+ # Problemantic (e.g. seven slot) seem to resolve at ~360
9
10
  THUMB_SIZE = 100
10
11
  COLOR_DELTA = 1.3 # color (e.g. red) must be this much be *COLOR_DELTA > than other values (e.g. blue/green)
11
12
 
@@ -18,7 +19,8 @@ class Sqed
18
19
  # A Sqed::Boundaries instance, stores the coordinates of all of the layout sections
19
20
  attr_reader :boundaries
20
21
 
21
- # Whether to compress the original image to a thumbnail when finding boundaries
22
+ # @return Boolean
23
+ # Whether to compress the original image to a thumbnail when finding boundaries at certain steps of the processing
22
24
  attr_reader :use_thumbnail
23
25
 
24
26
  # when we compute using a derived thumbnail we temporarily store the full size image here
@@ -31,8 +33,8 @@ class Sqed
31
33
  @layout = opts[:layout]
32
34
  @image = opts[:image]
33
35
 
34
- raise 'No layout provided.' if layout.nil?
35
- raise 'No image provided.' if image.nil? || image.class.name != 'Magick::Image'
36
+ raise Sqed::Error, 'No layout provided.' if layout.nil?
37
+ raise Sqed::Error, 'No image provided.' if image.nil? || image.class.name != 'Magick::Image'
36
38
 
37
39
  true
38
40
  end
@@ -135,7 +137,7 @@ class Sqed
135
137
  while attempts < 5 do
136
138
  samples_to_take = (image_width / sample_subdivision_size).to_i - 1
137
139
  border_hits = sample_border(image, boundary_color, samples_to_take, sample_subdivision_size, scan)
138
-
140
+
139
141
  break if border_hits.select{|k,v| v > 1}.size > 2 || sample_subdivision_size == 1
140
142
 
141
143
  sample_subdivision_size = (sample_subdivision_size.to_f / 2.0).to_i
@@ -164,7 +166,7 @@ class Sqed
164
166
  elsif scan == :columns
165
167
  j = image.crop(s * sample_subdivision_size, 0, 1, image.rows, true)
166
168
  else
167
- raise
169
+ raise Sqed::Error
168
170
  end
169
171
 
170
172
  j.each_pixel do |pixel, c, r|
@@ -207,7 +209,7 @@ class Sqed
207
209
  # the start, mid, endpoint position of all (pixel) positions that have a count greater than the cutoff
208
210
  def self.frequency_stats(frequency_hash, sample_cutoff = 0)
209
211
 
210
- return nil if sample_cutoff.nil? || sample_cutoff < 1
212
+ return nil if sample_cutoff.nil? || sample_cutoff < 1
211
213
  hit_ranges = []
212
214
 
213
215
  frequency_hash.each do |position, count|
@@ -236,6 +238,11 @@ class Sqed
236
238
  [hit_ranges.first, hit_ranges[(hit_ranges.length / 2).to_i], hit_ranges.last]
237
239
  end
238
240
 
241
+ def self.max_difference(array)
242
+ array.max - array.min
243
+ end
244
+
245
+ # Usused
239
246
 
240
247
  # Returns an Integer, the maximum of the pairwise differences of the values in the array
241
248
  # For example, given
@@ -248,10 +255,6 @@ class Sqed
248
255
  (0..array.length - 2).map{|i| (array[i] - array[i + 1]).abs }.max
249
256
  end
250
257
 
251
- def self.max_difference(array)
252
- array.max - array.min
253
- end
254
-
255
258
  def self.derivative_signs(array)
256
259
  (0..array.length - 2).map { |i| (array[i + 1] - array[i]) <=> 0 }
257
260
  end
data/lib/sqed/error.rb ADDED
@@ -0,0 +1,2 @@
1
+ class Sqed::Error < StandardError
2
+ end
@@ -23,9 +23,9 @@ class Sqed
23
23
  @boundaries = opts[:boundaries]
24
24
  @image = opts[:image]
25
25
 
26
- raise Error, 'boundaries not provided or provided boundary is not a Sqed::Boundaries' if boundaries.nil? || !boundaries.class == Sqed::Boundaries
27
- raise Error, 'metadata_map not provided or metadata_map not a Hash' if metadata_map.nil? || !metadata_map.class == Hash
28
- raise Error, 'image not provided' if image.nil? || !image.class.name == 'Magick::Image'
26
+ raise Sqed::Error, 'boundaries not provided or provided boundary is not a Sqed::Boundaries' if boundaries.nil? || !boundaries.class.name == 'Sqed::Boundaries'
27
+ raise Sqed::Error, 'metadata_map not provided or metadata_map not a Hash' if metadata_map.nil? || !metadata_map.class.name == 'Hash'
28
+ raise Sqed::Error, 'image not provided' if image.nil? || !image.class.name == 'Magick::Image'
29
29
  end
30
30
 
31
31
  def result
data/lib/sqed/parser.rb CHANGED
@@ -9,8 +9,9 @@ class Sqed::Parser
9
9
  attr_accessor :extracted_text
10
10
 
11
11
  def initialize(image)
12
+ raise Sqed::Error, 'no image passed to parser' if image.nil?
13
+ raise Sqed::Error, 'image is not a Magick::Image' if !(image.class.name == 'Magick::Image')
12
14
  @image = image
13
- raise 'no image provided to parser' if @image && !(@image.class.name == 'Magick::Image')
14
15
  end
15
16
 
16
17
  end
data/lib/sqed/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Sqed
2
- VERSION = '0.5.8'.freeze
2
+ VERSION = '0.7.1'.freeze
3
3
  end
data/lib/sqed.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  recent_ruby = RUBY_VERSION >= '2.4.1'
4
- raise 'IMPORTANT: sqed gem requires ruby >= 2.4.1' unless recent_ruby
4
+ raise Sqed::Error, 'IMPORTANT: sqed gem requires ruby >= 2.4.1' unless recent_ruby
5
5
 
6
6
  require 'rmagick'
7
7
  require 'sqed_utils'
@@ -17,10 +17,12 @@ require 'sqed_utils'
17
17
  #
18
18
  class Sqed
19
19
 
20
+ require_relative 'sqed/error'
20
21
  require_relative 'sqed_config'
21
22
  require_relative 'sqed/extractor'
22
23
  require_relative 'sqed/result'
23
24
 
25
+
24
26
  # initial image which is an instance of ImageMagick::Image, containing background and stage, or just stage
25
27
  attr_accessor :image
26
28
 
@@ -68,6 +70,7 @@ class Sqed
68
70
  # Provide a metadata map, overrides metadata taken from pattern
69
71
  attr_accessor :metadata_map
70
72
 
73
+ # @return [Sqed::BoundaryFinder::<Klass>]
71
74
  # Provide a boundary_finder, overrides metadata taken from pattern
72
75
  attr_accessor :boundary_finder
73
76
 
@@ -165,6 +168,8 @@ class Sqed
165
168
  configure_layout(opts)
166
169
  configure_metadata_map(opts)
167
170
 
171
+ raise Sqed::Error, 'boundary_finder not provided' if @boundary_finder.nil?
172
+
168
173
  @has_border = opts[:has_border]
169
174
  @has_border = true if @has_border.nil?
170
175
 
@@ -178,18 +183,18 @@ class Sqed
178
183
  def configure_from_pattern(value)
179
184
  return if value.nil?
180
185
  value = value.to_sym
181
- raise "provided extraction pattern '#{value}' not defined" if !SqedConfig::EXTRACTION_PATTERNS.keys.include?(value)
186
+ raise Sqed::Error, "provided extraction pattern '#{value}' not defined" if !SqedConfig::EXTRACTION_PATTERNS.keys.include?(value)
182
187
  @pattern = value
183
188
  a = SqedConfig::EXTRACTION_PATTERNS[pattern]
184
189
  @boundary_finder = a[:boundary_finder]
185
190
  @layout = a[:layout]
186
191
  @metadata_map = a[:metadata_map]
192
+
187
193
  true
188
194
  end
189
195
 
190
196
  def configure_boundary_finder(opts)
191
- @boundary_finder = opts[:boundary_finder].constantize if !opts[:boundary_finder].nil?
192
- @boundary_finder ||= Sqed::BoundaryFinder::CrossFinder
197
+ @boundary_finder = opts[:boundary_finder] if !opts[:boundary_finder].nil?
193
198
  end
194
199
 
195
200
  def configure_layout(opts)
@@ -212,7 +217,7 @@ class Sqed
212
217
  end
213
218
 
214
219
  def get_section_boundaries
215
- boundary_finder.new(section_params).boundaries
220
+ boundary_finder.new(**section_params).boundaries
216
221
  end
217
222
 
218
223
  # @return [Hash]
@@ -232,7 +237,7 @@ class Sqed
232
237
  if boundary.populated?
233
238
  @stage_boundary.set(0, boundary.for(0))
234
239
  else
235
- raise 'error detecting stage'
240
+ raise Sqed::Error, 'error detecting stage'
236
241
  end
237
242
  else
238
243
  @stage_boundary.set(0, [0, 0, image.columns, image.rows])
data/lib/sqed_config.rb CHANGED
@@ -17,33 +17,40 @@ require_relative 'sqed/boundary_finder/color_line_finder'
17
17
  module SqedConfig
18
18
 
19
19
  # Layouts refer to the arrangement of the divided stage.
20
- # Windows are enumerated from the top left, moving around the border
20
+ # Windows are enumerated from the top left, moving around the border
21
21
  # in a clockwise position. For example:
22
22
  #
23
23
  # 0 | 1
24
24
  # ----|---- :cross (any cross pattern)
25
25
  # |
26
26
  # 3 | 2
27
- #
27
+ #
28
28
  #
29
29
  # 0 | 1
30
30
  # |
31
- # --------- :horizontal_offset_cross
31
+ # --------- :horizontal_offset_cross
32
32
  # 3 | 2
33
- #
33
+ #
34
34
  #
35
35
  # 0
36
36
  # -------- :horizontal_split
37
37
  # 1
38
- #
38
+ #
39
39
  #
40
40
  # 0 | 1 | 2
41
41
  # ------------
42
42
  # | 5 | :lep_stage
43
- # 6 |---- 3
43
+ # 6 |---- 3
44
44
  # | 4 |
45
45
  #
46
46
  #
47
+ # 0 | 1 | 2
48
+ # --------------
49
+ # | 5 | :lep_stage2
50
+ # 6 |---- 3
51
+ # | 4 |
52
+ #
53
+ #
47
54
  # | 1
48
55
  # 0 |---- :right_t
49
56
  # | 2
@@ -55,28 +62,41 @@ module SqedConfig
55
62
  # 6 |--------
56
63
  # | 4
57
64
  #
58
- #
65
+ #
59
66
  # 0 | 1
60
67
  # |____
61
- # ----| :vertical_offset_cross
68
+ # ----| :vertical_offset_cross
62
69
  # 3 | 2
63
- #
64
70
  #
65
- # |
66
- # 0 | 1 :vertical_split
67
- # |
71
+ #
72
+ # |
73
+ # 0 | 1 :vertical_split
74
+ # |
68
75
  #
69
76
  # -----
70
- # | 0 | :internal_box
77
+ # | 0 | :internal_box
71
78
  # -----
72
- #
79
+ #
80
+ # 0 | 1 :inverted_t
81
+ # -----
82
+ # 2
83
+ #
84
+ # 0 :t
85
+ # -----
86
+ # 2 | 1
87
+ #
88
+ #
89
+ #
73
90
  # Hash values are used to stub out
74
91
  # the Sqed::Boundaries instance.
75
92
  LAYOUTS = {
93
+ t: [0,1,2],
94
+ inverted_t: [0, 1, 2],
76
95
  cross: [0, 1, 2, 3],
77
96
  horizontal_offset_cross: [0, 1, 2, 3],
78
97
  horizontal_split: [0, 1],
79
98
  lep_stage: [0, 1, 2, 3, 4, 5, 6],
99
+ lep_stage2: [0, 1, 2, 3, 4, 5, 6],
80
100
  right_t: [0, 1, 2],
81
101
  seven_slot: [0, 1, 2, 3, 4, 5, 6],
82
102
  vertical_offset_cross: [0, 1, 2, 3],
@@ -93,7 +113,7 @@ module SqedConfig
93
113
  :identifier, # the section contains an identifier (e.g. barcode or unique number)
94
114
  :image_registration, # the section contains only image registration information,
95
115
  :labels, # the section contains collecting event and other non-determination labels
96
- :nothing, # section is empty
116
+ :nothing, # section is empty
97
117
  :other_labels, # the section that contains text that misc.
98
118
  :specimen, # the specimen only, no metadata should be present
99
119
  :stage, # the image contains the full stage
@@ -115,6 +135,18 @@ module SqedConfig
115
135
  }.freeze
116
136
 
117
137
  EXTRACTION_PATTERNS = {
138
+ t: {
139
+ boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
140
+ layout: :t,
141
+ metadata_map: { 0 => :annotated_specimen, 1 => :identifier, 2 => :image_registration }
142
+ },
143
+
144
+ inverted_t: {
145
+ boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
146
+ layout: :inverted_t,
147
+ metadata_map: { 0 => :identifier, 1 => :image_registration, 2 => :annotated_specimen }
148
+ },
149
+
118
150
  cross: {
119
151
  boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
120
152
  layout: :cross,
@@ -139,6 +171,12 @@ module SqedConfig
139
171
  metadata_map: { 0 => :curator_metadata, 1 => :collecting_event_labels, 2 => :image_registration, 3 => :identifier, 4 => :other_labels, 5 => :determination_labels, 6 => :specimen }
140
172
  },
141
173
 
174
+ lep_stage2: {
175
+ boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
176
+ layout: :lep_stage2,
177
+ metadata_map: { 0 => :curator_metadata, 1 => :collecting_event_labels, 2 => :image_registration, 3 => :identifier, 4 => :other_labels, 5 => :determination_labels, 6 => :specimen }
178
+ },
179
+
142
180
  right_t: {
143
181
  boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
144
182
  layout: :right_t,
@@ -7,13 +7,11 @@ describe SqedConfig do
7
7
  end
8
8
 
9
9
  specify 'layouts' do
10
- expect(SqedConfig.metadata[:layouts].keys).to contain_exactly(:cross, :horizontal_offset_cross, :horizontal_split, :lep_stage, :right_t, :seven_slot, :vertical_offset_cross, :vertical_split)
10
+ expect(SqedConfig.metadata[:layouts].keys).to contain_exactly(:t, :inverted_t, :cross, :horizontal_offset_cross, :horizontal_split, :lep_stage, :lep_stage2, :right_t, :seven_slot, :vertical_offset_cross, :vertical_split)
11
11
  end
12
12
 
13
13
  specify 'layouts are in patterns' do
14
- expect(SqedConfig.metadata[:layouts].keys + [:stage]).to contain_exactly(*SqedConfig::EXTRACTION_PATTERNS.keys)
14
+ expect(SqedConfig.metadata[:layouts].keys + [:stage]).to contain_exactly(*SqedConfig::EXTRACTION_PATTERNS.keys)
15
15
  end
16
16
 
17
-
18
-
19
17
  end