sqed 0.5.8 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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