sqed 0.3.2 → 0.4.0

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.
@@ -1,71 +1,74 @@
1
- # A Sqed::Result is a container for the results of the
2
- # the data extraction for the full stage
3
- #
4
- class Sqed::Result
1
+ class Sqed
5
2
 
6
- SqedConfig::LAYOUT_SECTION_TYPES.each do |k|
7
- attr_accessor "#{k}_image".to_sym
8
- attr_accessor k
9
- end
10
-
11
- # a hash with section_type => [ ]
12
- attr_accessor :boundary_coordinates
13
-
14
- # an array of section type
15
- attr_accessor :sections
16
-
17
- def initialize
18
- @boundary_coordinates = {}
3
+ # A Sqed::Result is a container for the results of the
4
+ # the data extraction for the full stage
5
+ #
6
+ class Result
19
7
  SqedConfig::LAYOUT_SECTION_TYPES.each do |k|
20
- send("#{k}=", {})
21
- @boundary_coordinates[k] = [nil, nil, nil, nil]
8
+ attr_accessor "#{k}_image".to_sym
9
+
10
+ # @return [Hash] `barcode: '', text: ''`
11
+ attr_accessor k
22
12
  end
23
- end
24
13
 
25
- # return [String, nil]
26
- # the text derived from the OCR parsing of the section
27
- def text_for(section)
28
- send(section)[:text]
29
- end
14
+ # @return [Hash] of `section_type: [ ]`
15
+ attr_accessor :boundary_coordinates
30
16
 
31
- # return [String, nil]
32
- # the text derived from the barcode parsing of the section
33
- def barcode_text_for(section)
34
- send(section)[:barcode]
35
- end
17
+ # @return [Array]
18
+ # of section type
19
+ attr_accessor :sections
36
20
 
37
- # return [Hash]
38
- # a map of layout_section_type => value (if there is a value),
39
- # i.e. all possible parsed text values returned from the parser
40
- def text
41
- result = {}
42
- SqedConfig::LAYOUT_SECTION_TYPES.each do |k|
43
- v = self.send(k)
44
- result.merge!(k => v) if v[:barcode] || v[:text]
21
+ def initialize
22
+ @boundary_coordinates = {}
23
+ SqedConfig::LAYOUT_SECTION_TYPES.each do |k|
24
+ send("#{k}=", {})
25
+ @boundary_coordinates[k] = [nil, nil, nil, nil]
26
+ end
45
27
  end
46
- result
47
- end
48
28
 
49
- # return [Hash]
50
- # a map of layout_section_type => Rmagick::Image
51
- def images
52
- result = {}
53
- SqedConfig::LAYOUT_SECTION_TYPES.each do |k|
54
- image = self.send("#{k}_image")
55
- result.merge!(k => image) if image
29
+ # return [String, nil]
30
+ # the text derived from the OCR parsing of the section
31
+ def text_for(section)
32
+ send(section)[:text]
56
33
  end
57
- result
58
- end
59
34
 
60
- # return [True]
61
- # write the images in #images to tmp/
62
- def write_images
63
- images.each do |k, img|
64
- img.write("tmp/#{k}.jpg")
35
+ # return [String, nil]
36
+ # the text derived from the barcode parsing of the section
37
+ def barcode_text_for(section)
38
+ send(section)[:barcode]
65
39
  end
66
- true
67
- end
68
40
 
69
- end
41
+ # return [Hash]
42
+ # a map of layout_section_type => value (if there is a value),
43
+ # i.e. all possible parsed text values returned from the parser
44
+ def text
45
+ result = {}
46
+ SqedConfig::LAYOUT_SECTION_TYPES.each do |k|
47
+ v = send(k)
48
+ result[k] = v if v[:barcode] || v[:text]
49
+ end
50
+ result
51
+ end
70
52
 
53
+ # return [Hash]
54
+ # a map of layout_section_type => Rmagick::Image
55
+ def images
56
+ result = {}
57
+ SqedConfig::LAYOUT_SECTION_TYPES.each do |k|
58
+ image = send("#{k}_image")
59
+ result[k] = image if image
60
+ end
61
+ result
62
+ end
71
63
 
64
+ # return [True]
65
+ # write the images in #images to tmp/
66
+ def write_images
67
+ images.each do |k, img|
68
+ img.write("tmp/#{k}.jpg")
69
+ end
70
+ true
71
+ end
72
+
73
+ end
74
+ end
@@ -1,3 +1,3 @@
1
1
  class Sqed
2
- VERSION = "0.3.2"
2
+ VERSION = '0.4.0'.freeze
3
3
  end
@@ -1,16 +1,14 @@
1
- # encoding: UTF-8
2
-
3
1
  # require 'zxing'
4
2
 
5
- require_relative "sqed/parser"
6
- require_relative "sqed/parser/ocr_parser"
7
- require_relative "sqed/parser/barcode_parser"
3
+ require_relative 'sqed/parser'
4
+ require_relative 'sqed/parser/ocr_parser'
5
+ require_relative 'sqed/parser/barcode_parser'
8
6
 
9
- require_relative "sqed/boundaries"
10
- require_relative "sqed/boundary_finder"
11
- require_relative "sqed/boundary_finder/cross_finder"
12
- require_relative "sqed/boundary_finder/stage_finder"
13
- require_relative "sqed/boundary_finder/color_line_finder"
7
+ require_relative 'sqed/boundaries'
8
+ require_relative 'sqed/boundary_finder'
9
+ require_relative 'sqed/boundary_finder/cross_finder'
10
+ require_relative 'sqed/boundary_finder/stage_finder'
11
+ require_relative 'sqed/boundary_finder/color_line_finder'
14
12
 
15
13
  # Sqed constants, including patterns for extraction etc.
16
14
  #
@@ -23,13 +21,13 @@ module SqedConfig
23
21
  # 0 | 1
24
22
  # ----|---- :equal_cross (always perfectly divided through the center)
25
23
  # 3 | 2
26
- #
24
+ #
27
25
  #
28
26
  # 0 | 1
29
27
  # ----|---- :cross - height of [0, 1], [2,3] same, width of [0,1], [2,3] same, otherwise variable, i.e. height(0) != height(3)
30
- # |
28
+ # |
31
29
  # 3 | 2
32
- #
30
+ #
33
31
  #
34
32
  # 0 | 1
35
33
  # |
@@ -45,7 +43,7 @@ module SqedConfig
45
43
  # | 1
46
44
  # 0 |---- :right_t
47
45
  # | 2
48
- #
46
+ #
49
47
  # 0
50
48
  # -------- :horizontal_split
51
49
  # 1
@@ -58,30 +56,28 @@ module SqedConfig
58
56
  # | 0 | :internal_box
59
57
  # -----
60
58
  #
61
- # 0 | 1 | 2
59
+ # 0 | 1 | 2
62
60
  # ------------
63
61
  # | 5 | 3 :seven_slot
64
62
  # 6 |--------
65
63
  # | 4
66
64
  #
67
65
  #
68
- #
69
-
70
66
  # Hash values are used to stub out
71
67
  # the Sqed::Boundaries instance.
72
68
  # TODO: deprecate for simpler breakdown (cross, split, t)
73
69
  LAYOUTS = {
74
- cross: [0,1,2,3],
75
- vertical_offset_cross: [0,1,2,3],
76
- horizontal_split: [0,1],
77
- vertical_split: [0,1],
78
- right_t: [0,1,2],
79
- left_t: [0,1,2],
70
+ cross: [0, 1, 2, 3],
71
+ vertical_offset_cross: [0, 1, 2, 3],
72
+ horizontal_split: [0, 1],
73
+ vertical_split: [0, 1],
74
+ right_t: [0, 1, 2],
75
+ left_t: [0, 1, 2],
80
76
  internal_box: [0],
81
- seven_slot: [0,1,2,3,4,5,6]
82
- }
77
+ seven_slot: [0, 1, 2, 3, 4, 5, 6]
78
+ }.freeze
83
79
 
84
- # Each element of the layout is a "section".
80
+ # Each element of the layout is a "section".
85
81
  LAYOUT_SECTION_TYPES = [
86
82
  :annotated_specimen, # a specimen is present, and metadata is too
87
83
  :collecting_event_labels, # the section that contains collecting event labels (only)
@@ -91,67 +87,67 @@ module SqedConfig
91
87
  :image_registration, # the section contains only image registration information,
92
88
  :labels, # the section contains collecting event and other non-determination labels
93
89
  :nothing, # section is empty
94
- :other_labels, # the section that contains text that misc.
90
+ :other_labels, # the section that contains text that misc.
95
91
  :specimen, # the specimen only, no metadata should be present
96
- :stage, # the image contains the full stage
97
- ]
92
+ :stage, # the image contains the full stage
93
+ ].freeze
98
94
 
99
95
  # Links section types to data parsers
100
96
  SECTION_PARSERS = {
101
- annotated_specimen: [ Sqed::Parser::OcrParser],
102
- collecting_event_labels: [ Sqed::Parser::OcrParser],
103
- curator_metadata: [ Sqed::Parser::OcrParser ],
104
- deterimination_labels: [ Sqed::Parser::OcrParser ],
105
- identifier: [ Sqed::Parser::BarcodeParser, Sqed::Parser::OcrParser ],
97
+ annotated_specimen: [Sqed::Parser::OcrParser],
98
+ collecting_event_labels: [Sqed::Parser::OcrParser],
99
+ curator_metadata: [Sqed::Parser::OcrParser],
100
+ determination_labels: [Sqed::Parser::OcrParser],
101
+ identifier: [Sqed::Parser::BarcodeParser, Sqed::Parser::OcrParser],
106
102
  image_registration: [],
107
- labels: [ Sqed::Parser::OcrParser ],
103
+ labels: [Sqed::Parser::OcrParser],
108
104
  nothing: [],
109
- other_labels: [ Sqed::Parser::OcrParser ],
105
+ other_labels: [Sqed::Parser::OcrParser],
110
106
  specimen: [],
111
107
  stage: []
112
- }
108
+ }.freeze
113
109
 
114
110
  EXTRACTION_PATTERNS = {
115
111
  right_t: {
116
112
  boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
117
113
  layout: :right_t,
118
- target_metadata_map: {0 => :annotated_specimen, 1 => :identifier, 2 =>:image_registration }
114
+ metadata_map: { 0 => :annotated_specimen, 1 => :identifier, 2 => :image_registration }
119
115
  },
120
116
 
121
117
  vertical_offset_cross: {
122
- boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
123
- layout: :vertical_offset_cross,
124
- target_metadata_map: {0 => :curator_metadata, 1 => :identifier, 2 => :image_registration, 3 => :annotated_specimen }
118
+ boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
119
+ layout: :vertical_offset_cross,
120
+ metadata_map: { 0 => :curator_metadata, 1 => :identifier, 2 => :image_registration, 3 => :annotated_specimen }
121
+ },
122
+
123
+ equal_cross: {
124
+ boundary_finder: Sqed::BoundaryFinder::CrossFinder,
125
+ layout: :equal_cross,
126
+ metadata_map: { 0 => :curator_metadata, 1 => :identifier, 2 => :image_registration, 3 => :annotated_specimen }
125
127
  },
126
-
127
- equal_cross: {
128
- boundary_finder: Sqed::BoundaryFinder::CrossFinder,
129
- layout: :equal_cross,
130
- target_metadata_map: {0 => :curator_metadata, 1 => :identifier, 2 => :image_registration, 3 => :annotated_specimen }
131
- },
132
128
 
133
129
  cross: {
134
130
  boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
135
- layout: :cross,
136
- target_metadata_map: {0 => :curator_metadata, 1 => :identifier, 2 => :image_registration, 3 => :annotated_specimen }
131
+ layout: :cross,
132
+ metadata_map: { 0 => :curator_metadata, 1 => :identifier, 2 => :image_registration, 3 => :annotated_specimen }
137
133
  },
138
134
 
139
135
  stage: {
140
136
  boundary_finder: Sqed::BoundaryFinder::StageFinder,
141
- layout: :internal_box,
142
- target_metadata_map: {0 => :stage}
137
+ layout: :internal_box,
138
+ metadata_map: { 0 => :stage}
143
139
  },
144
-
140
+
145
141
  seven_slot: {
146
142
  boundary_finder: Sqed::BoundaryFinder::ColorLineFinder,
147
143
  layout: :seven_slot,
148
- target_metadata_map: {0 => :collecting_event_labels, 1 => :determination_labels, 2 => :other_labels, 3 => :image_registration, 4 => :curator_metadata, 5 => :identifier, 6 => :specimen }
144
+ metadata_map: { 0 => :collecting_event_labels, 1 => :determination_labels, 2 => :other_labels, 3 => :image_registration, 4 => :curator_metadata, 5 => :identifier, 6 => :specimen }
149
145
  }
150
- }
146
+ }.freeze
151
147
 
152
- DEFAULT_TMP_DIR = "/tmp"
148
+ DEFAULT_TMP_DIR = '/tmp'.freeze
153
149
 
154
150
  def self.index_for_section_type(pattern, section_type)
155
- EXTRACTION_PATTERNS[pattern][:target_metadata_map].invert[section_type]
151
+ EXTRACTION_PATTERNS[pattern][:metadata_map].invert[section_type]
156
152
  end
157
153
  end
@@ -33,7 +33,7 @@ describe Sqed::Boundaries do
33
33
  end
34
34
 
35
35
  context '#offset' do
36
- let(:s) { Sqed.new(target_image: ImageHelpers.crossy_green_line_specimen, target_pattern: :vertical_offset_cross) }
36
+ let(:s) { Sqed.new(image: ImageHelpers.crossy_green_line_specimen, pattern: :vertical_offset_cross) }
37
37
  let(:offset_boundaries) {
38
38
  s.crop_image
39
39
  s.boundaries.offset(s.stage_boundary)
@@ -1,32 +1,32 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Sqed::BoundaryFinder::ColorLineFinder do
3
+ describe Sqed::BoundaryFinder::ColorLineFinder do
4
4
 
5
5
  let(:image) { ImageHelpers.crossy_green_line_specimen }
6
6
 
7
- let(:b) { Sqed::BoundaryFinder::StageFinder.new(target_image: image) }
8
- let(:c) {b.boundaries}
7
+ let(:b) { Sqed::BoundaryFinder::StageFinder.new(image: image) }
8
+ let(:c) { b.boundaries }
9
9
  let(:d) { image.crop(*c.for(0), true) }
10
-
11
- let(:e) { Sqed::BoundaryFinder::ColorLineFinder.new(target_image: d, target_layout: :right_t, use_thumbnail: false) }
10
+
11
+ let(:e) { Sqed::BoundaryFinder::ColorLineFinder.new(image: d, layout: :right_t, use_thumbnail: false) }
12
12
  let(:f) { e.boundaries }
13
- let(:g) { Sqed::BoundaryFinder::ColorLineFinder.new(target_image: d, target_layout: :vertical_offset_cross, use_thumbnail: false)}
13
+ let(:g) { Sqed::BoundaryFinder::ColorLineFinder.new(image: d, layout: :vertical_offset_cross, use_thumbnail: false)}
14
14
  let(:h) { g.boundaries }
15
- let(:gv) { Sqed::BoundaryFinder::ColorLineFinder.new(target_image: d, target_layout: :vertical_split, use_thumbnail: false) }
15
+ let(:gv) { Sqed::BoundaryFinder::ColorLineFinder.new(image: d, layout: :vertical_split, use_thumbnail: false) }
16
16
  let(:hv) { gv.boundaries }
17
-
17
+
18
18
  let(:ah) { ImageHelpers.vertical_offset_cross_red }
19
- let(:bh) { Sqed::BoundaryFinder::StageFinder.new(target_image: ah) }
19
+ let(:bh) { Sqed::BoundaryFinder::StageFinder.new(image: ah) }
20
20
  let(:ch) { bh.boundaries }
21
21
  let(:dh) { ah.crop(*ch.for(0), true) }
22
- let(:gh) { Sqed::BoundaryFinder::ColorLineFinder.new(target_image: dh, target_layout: :horizontal_split, boundary_color: :red, use_thumbnail: false) } # was :horizontal_split
22
+ let(:gh) { Sqed::BoundaryFinder::ColorLineFinder.new(image: dh, layout: :horizontal_split, boundary_color: :red, use_thumbnail: false) } # was :horizontal_split
23
23
  let(:hh) { gh.boundaries }
24
24
 
25
- let(:ibs) { ImageHelpers.black_stage_green_line_specimen }
26
- let(:bbs) { Sqed::BoundaryFinder::StageFinder.new(target_image: ibs) }
25
+ let(:ibs) { ImageHelpers.black_stage_green_line_specimen }
26
+ let(:bbs) { Sqed::BoundaryFinder::StageFinder.new(image: ibs) }
27
27
  let(:cbs) { bbs.boundaries }
28
28
  let(:dbs) { ibs.crop(*cbs.for(0), true) }
29
- let(:gbs) { Sqed::BoundaryFinder::ColorLineFinder.new(target_image: dbs, target_layout: :vertical_offset_cross, use_thumbnail: false) }
29
+ let(:gbs) { Sqed::BoundaryFinder::ColorLineFinder.new(image: dbs, layout: :vertical_offset_cross, use_thumbnail: false) }
30
30
  let(:hbs) { gbs.boundaries }
31
31
 
32
32
  specify 'initial image columns are as expected for :image above' do
@@ -49,7 +49,7 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
49
49
  end
50
50
  end
51
51
 
52
- specify "CrossGreenLinesSpecimen using right_t layout should yield 3 rectangular boundaries" do
52
+ specify 'CrossGreenLinesSpecimen using right_t layout should yield 3 rectangular boundaries' do
53
53
  # use the f object for right_t
54
54
  f.each do |i, coord|
55
55
  q = d.crop(*coord, true)
@@ -58,7 +58,7 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
58
58
 
59
59
  expect(f.count).to eq(3)
60
60
  pct = 0.02
61
-
61
+
62
62
  expect(f.x_for(0)).to be_within(1).of(1)
63
63
  expect(f.y_for(0)).to be_within(1).of(1)
64
64
  expect(f.width_for(0)).to be_within(pct*2051).of(2051)
@@ -75,7 +75,7 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
75
75
  expect(f.height_for(2)).to be_within(pct*964).of(964)
76
76
  end
77
77
 
78
- specify "CrossGreenLinesSpecimen using vertical_offset_cross layout should yield 4 rectangular boundaries" do
78
+ specify 'CrossGreenLinesSpecimen using vertical_offset_cross layout should yield 4 rectangular boundaries' do
79
79
  h.each do |i, coord|
80
80
  q = d.crop(*coord, true)
81
81
  q.write("tmp/q1#{i}.jpg")
@@ -106,7 +106,7 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
106
106
  expect(h.height_for(3)).to be_within(pct*897).of(897)
107
107
  end
108
108
 
109
- specify "CrossGreenLinesSpecimen using vertical_split layout should yield 2 rectangular boundaries" do
109
+ specify 'CrossGreenLinesSpecimen using vertical_split layout should yield 2 rectangular boundaries' do
110
110
  hv.each do |k, v|
111
111
  q = d.crop(*v, true)
112
112
  q.write("tmp/q2#{k}.jpg")
@@ -124,7 +124,7 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
124
124
  expect(hv.height_for(1)).to be_within(0.02*1990).of(1990)
125
125
  end
126
126
 
127
- specify "boundary_vertical_offset_cross_red using horizontal_split layout should yield 2 rectangular boundaries" do
127
+ specify 'boundary_vertical_offset_cross_red using horizontal_split layout should yield 2 rectangular boundaries' do
128
128
  hh.each do |k, v|
129
129
  q = dh.crop(*v, true)
130
130
  q.write("tmp/q3#{k}.jpg")
@@ -136,7 +136,7 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
136
136
  expect(hh.coordinates[1]).to eq([0, 154, 799, 445]) # for quadrant 1
137
137
  end
138
138
 
139
- specify "offset cross method on black stage specimen should yield 4 rectangular boundaries for 0" do
139
+ specify 'offset cross method on black stage specimen should yield 4 rectangular boundaries for 0' do
140
140
  (hbs.first[0]..hbs.count - 1).each do |j|
141
141
  q = dbs.crop(*hbs.for(j), true)
142
142
  q.write("tmp/qb#{j}.jpg")
@@ -149,17 +149,17 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
149
149
  expect(hbs.height_for(0)).to be_within(pct*506).of(506)
150
150
  end
151
151
 
152
- specify "offset cross method on black stage specimen should yield 4 rectangular boundaries for 1" do
152
+ specify 'offset cross method on black stage specimen should yield 4 rectangular boundaries for 1' do
153
153
  expect(hbs.width_for(1)).to be_within(0.02*447).of(447)
154
154
  expect(hbs.height_for(1)).to be_within(0.02*487).of(487)
155
155
  end
156
156
 
157
- specify "offset cross method on black stage specimen should yield 4 rectangular boundaries for 2" do
157
+ specify 'offset cross method on black stage specimen should yield 4 rectangular boundaries for 2' do
158
158
  expect(hbs.width_for(2)).to be_within(0.02*447).of(447)
159
159
  expect(hbs.height_for(2)).to be_within(0.02*1680).of(1680)
160
160
  end
161
161
 
162
- specify "offset cross method on black stage specimen should yield 4 rectangular boundaries for 3" do
162
+ specify 'offset cross method on black stage specimen should yield 4 rectangular boundaries for 3' do
163
163
  expect(hbs.width_for(3)).to be_within(0.02*2999).of(2999)
164
164
  expect(hbs.height_for(3)).to be_within(0.02*1677).of(1677)
165
165
  end
@@ -167,7 +167,7 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
167
167
  context 'thumbnail processing finds reasonable boundaries' do
168
168
 
169
169
  let(:thumb) { ImageHelpers.frost_stage_thumb }
170
- let(:finder) { Sqed::BoundaryFinder::ColorLineFinder.new(target_image: thumb, target_layout: :cross, use_thumbnail: false)}
170
+ let(:finder) { Sqed::BoundaryFinder::ColorLineFinder.new(image: thumb, layout: :cross, use_thumbnail: false)}
171
171
  let(:finder_boundaries) { finder.boundaries }
172
172
 
173
173
  let(:pct) { 0.08 }
@@ -179,7 +179,7 @@ describe Sqed::BoundaryFinder::ColorLineFinder do
179
179
  # end
180
180
  # }
181
181
 
182
- specify "for section 0" do
182
+ specify 'for section 0' do
183
183
  expect(finder_boundaries.x_for(0)).to be_within(pct*thumb.columns).of(0)
184
184
  expect(finder_boundaries.y_for(0)).to be_within(pct*0).of(0)
185
185
  expect(finder_boundaries.width_for(0)).to be_within(pct*66).of(66)