sqed 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)