flex-station-data 0.3.0 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +33 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +106 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +23 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +51 -28
- data/README.md +16 -29
- data/Rakefile +5 -1
- data/bin/flex-station +33 -11
- data/bin/flex-station-linear-regression +19 -37
- data/flex-station-data.gemspec +7 -4
- data/lib/flex_station_data.rb +2 -0
- data/lib/flex_station_data/concerns/callable.rb +33 -0
- data/lib/flex_station_data/concerns/presenter.rb +4 -18
- data/lib/flex_station_data/concerns/service.rb +4 -18
- data/lib/flex_station_data/default_sample_map.rb +33 -0
- data/lib/flex_station_data/linear_regression.rb +2 -0
- data/lib/flex_station_data/plate.rb +14 -3
- data/lib/flex_station_data/presenters/plate_hash.rb +26 -0
- data/lib/flex_station_data/presenters/plates_hash.rb +26 -0
- data/lib/flex_station_data/presenters/sample_hash.rb +47 -0
- data/lib/flex_station_data/presenters/sample_regression_hash.rb +44 -0
- data/lib/flex_station_data/sample.rb +20 -5
- data/lib/flex_station_data/services/compute_mean.rb +2 -0
- data/lib/flex_station_data/services/load_plates.rb +12 -1
- data/lib/flex_station_data/services/parse_plate.rb +6 -4
- data/lib/flex_station_data/services/parse_plate_readings.rb +43 -36
- data/lib/flex_station_data/services/parse_sample_map.rb +47 -0
- data/lib/flex_station_data/services/sample_quality.rb +6 -5
- data/lib/flex_station_data/services/value_quality.rb +5 -1
- data/lib/flex_station_data/version.rb +3 -1
- data/lib/flex_station_data/wells.rb +16 -15
- metadata +31 -19
- data/bin/flex-station-sample-data +0 -54
- data/lib/flex_station_data/presenters/linear_regression/plate_hash.rb +0 -27
- data/lib/flex_station_data/presenters/linear_regression/plates_hash.rb +0 -28
- data/lib/flex_station_data/presenters/linear_regression/sample_hash.rb +0 -47
- data/lib/flex_station_data/presenters/linear_regression/sample_regression_hash.rb +0 -43
- data/lib/flex_station_data/presenters/linear_regression/verbose_sample_csv.rb +0 -28
- data/lib/flex_station_data/presenters/plate_csv.rb +0 -29
- data/lib/flex_station_data/presenters/plates_csv.rb +0 -28
- data/lib/flex_station_data/presenters/sample_csv.rb +0 -56
- data/lib/flex_station_data/readings.rb +0 -16
- data/lib/flex_station_data/services/parse_plate_samples.rb +0 -49
@@ -1,16 +1,31 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "matrix"
|
4
|
+
|
5
|
+
require "flex_station_data/services/compute_mean"
|
2
6
|
|
3
7
|
module FlexStationData
|
4
8
|
class Sample
|
5
|
-
attr_reader :label, :
|
9
|
+
attr_reader :label, :wells, :plate
|
6
10
|
|
7
|
-
|
11
|
+
delegate :wells, to: :plate, prefix: true
|
12
|
+
|
13
|
+
def initialize(label, wells, plate)
|
8
14
|
@label = label
|
9
|
-
@
|
15
|
+
@wells = wells
|
16
|
+
@plate = plate
|
17
|
+
end
|
18
|
+
|
19
|
+
def values
|
20
|
+
wells.map(&plate_wells.method(:values))
|
21
|
+
end
|
22
|
+
|
23
|
+
def readings
|
24
|
+
@readings ||= wells.zip(values).map { |well, v| Readings.new(well, v) }
|
10
25
|
end
|
11
26
|
|
12
27
|
def mean
|
13
|
-
@mean ||=
|
28
|
+
@mean ||= values.transpose.map(&ComputeMean)
|
14
29
|
end
|
15
30
|
end
|
16
31
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "csv"
|
2
4
|
require "active_support/core_ext"
|
3
5
|
|
@@ -18,7 +20,10 @@ module FlexStationData
|
|
18
20
|
end
|
19
21
|
|
20
22
|
def data_blocks
|
21
|
-
@data_blocks ||= data.
|
23
|
+
@data_blocks ||= data.each_with_object([]) do |row, blocks|
|
24
|
+
blocks << [] if plate_row?(row)
|
25
|
+
blocks.last&.push(row)
|
26
|
+
end
|
22
27
|
end
|
23
28
|
|
24
29
|
def call
|
@@ -26,5 +31,11 @@ module FlexStationData
|
|
26
31
|
FlexStationData::ParsePlate.call(index + 1, data_block)
|
27
32
|
end
|
28
33
|
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def plate_row?(row)
|
38
|
+
row[0].to_s =~ /\A\s*Plate:\s*/i
|
39
|
+
end
|
29
40
|
end
|
30
41
|
end
|
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext"
|
2
4
|
|
3
5
|
require "flex_station_data/services/parse_plate_readings"
|
4
|
-
require "flex_station_data/services/
|
6
|
+
require "flex_station_data/services/parse_sample_map"
|
5
7
|
require "flex_station_data/plate"
|
6
8
|
|
7
9
|
module FlexStationData
|
@@ -16,13 +18,13 @@ module FlexStationData
|
|
16
18
|
end
|
17
19
|
|
18
20
|
def data_blocks
|
19
|
-
plate_data.split { |row| row[0]
|
21
|
+
plate_data.split { |row| row[0] =~ /\A~End\s*\z/ }
|
20
22
|
end
|
21
23
|
|
22
24
|
def call
|
23
25
|
times, temperatures, wells = ParsePlateReadings.call(data_blocks[0])
|
24
|
-
|
25
|
-
Plate.new(label, times, temperatures,
|
26
|
+
sample_map = ParseSampleMap.call(data_blocks[1])
|
27
|
+
Plate.new(label, times, temperatures, wells, sample_map)
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext"
|
4
|
+
require "matrix"
|
2
5
|
|
3
6
|
require "flex_station_data/wells"
|
4
7
|
require "flex_station_data/concerns/service"
|
@@ -9,49 +12,32 @@ module FlexStationData
|
|
9
12
|
|
10
13
|
delegate :parse_time, :parse_value, :parse_row, to: :class
|
11
14
|
|
12
|
-
def initialize(
|
13
|
-
@
|
15
|
+
def initialize(plate_data)
|
16
|
+
@plate_data = plate_data
|
14
17
|
end
|
15
18
|
|
16
|
-
def
|
17
|
-
@
|
19
|
+
def readings_block
|
20
|
+
@readings_block ||= plate_data
|
21
|
+
.drop_while { |row| !header_row?(row) }
|
22
|
+
.drop_while { |row| !sample_row?(row) }
|
23
|
+
.take_while { |row| !end_row?(row) }
|
24
|
+
.select { |row| row.any?(&:present?) }
|
18
25
|
end
|
19
26
|
|
20
|
-
def
|
21
|
-
@
|
22
|
-
rows = plate_readings_data.map { |row| parse_row(row[0...column_count]) }
|
23
|
-
rows.select { |row| row.any?(&:present?) }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def parsed_columns
|
28
|
-
@parsed_columns ||= parsed_rows.transpose
|
27
|
+
def headers
|
28
|
+
@headers ||= plate_data.detect(&method(:header_row?)).reverse.drop_while(&:blank?).reverse
|
29
29
|
end
|
30
30
|
|
31
31
|
def times
|
32
|
-
@times ||=
|
32
|
+
@times ||= matrix.column(0).to_a.compact
|
33
33
|
end
|
34
34
|
|
35
35
|
def temperatures
|
36
|
-
@temperatures ||=
|
37
|
-
end
|
38
|
-
|
39
|
-
def values
|
40
|
-
@values ||= parsed_columns.drop(2)
|
41
|
-
end
|
42
|
-
|
43
|
-
def wells_row_count
|
44
|
-
parsed_rows.size / times.size
|
45
|
-
end
|
46
|
-
|
47
|
-
def plate_readings_matrix
|
48
|
-
values.map do |values_column|
|
49
|
-
values_column.each_slice(wells_row_count).to_a.transpose
|
50
|
-
end.transpose
|
36
|
+
@temperatures ||= matrix.column(1).to_a.compact
|
51
37
|
end
|
52
38
|
|
53
39
|
def wells
|
54
|
-
Wells.new(
|
40
|
+
Wells.new(wells_matrix)
|
55
41
|
end
|
56
42
|
|
57
43
|
def call
|
@@ -67,7 +53,9 @@ module FlexStationData
|
|
67
53
|
end
|
68
54
|
|
69
55
|
def parse_value(v)
|
70
|
-
|
56
|
+
Float(v)
|
57
|
+
rescue ArgumentError, TypeError
|
58
|
+
v.presence
|
71
59
|
end
|
72
60
|
|
73
61
|
def parse_row(row)
|
@@ -78,14 +66,33 @@ module FlexStationData
|
|
78
66
|
|
79
67
|
private
|
80
68
|
|
81
|
-
def
|
82
|
-
|
69
|
+
def header_row?(row)
|
70
|
+
row[1].to_s =~ /\A\s*Temperature\b/i
|
71
|
+
end
|
72
|
+
|
73
|
+
def sample_row?(row)
|
74
|
+
row[0].to_s =~ /\A\s*\d+:\d+:\d+\s*\z/
|
75
|
+
end
|
76
|
+
|
77
|
+
def end_row?(row)
|
78
|
+
row[0].to_s =~ /\A\s*~End\s*\z/i
|
79
|
+
end
|
80
|
+
|
81
|
+
def well_values
|
82
|
+
matrix.minor(0..-1, 2..-1)
|
83
|
+
end
|
84
|
+
|
85
|
+
def matrix
|
86
|
+
@matrix ||= Matrix[
|
87
|
+
*readings_block.map { |row| parse_row(row[0...headers.size]) }
|
88
|
+
]
|
83
89
|
end
|
84
90
|
|
85
|
-
def
|
86
|
-
|
91
|
+
def wells_matrix
|
92
|
+
well_row_count = matrix.row_count / times.size
|
93
|
+
Matrix[*well_values.column_vectors.map { |col| col.to_a.each_slice(well_row_count).to_a.transpose }.transpose]
|
87
94
|
end
|
88
95
|
|
89
|
-
attr_reader :
|
96
|
+
attr_reader :plate_data
|
90
97
|
end
|
91
98
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "matrix"
|
4
|
+
require "active_support/core_ext"
|
5
|
+
|
6
|
+
require "flex_station_data/concerns/service"
|
7
|
+
|
8
|
+
module FlexStationData
|
9
|
+
class ParseSampleMap
|
10
|
+
include Concerns::Service
|
11
|
+
|
12
|
+
attr_reader :plate_data
|
13
|
+
|
14
|
+
def initialize(plate_data)
|
15
|
+
@plate_data = plate_data
|
16
|
+
end
|
17
|
+
|
18
|
+
def sample_map_rows
|
19
|
+
plate_data
|
20
|
+
.drop_while { |row| !sample_map_header?(row) }
|
21
|
+
.drop(1)
|
22
|
+
.take_while { |row| !empty_row?(row) }
|
23
|
+
.map(&method(:parse_row))
|
24
|
+
end
|
25
|
+
|
26
|
+
def call
|
27
|
+
sample_map_rows.each_with_object([]) do |(label, well), memo|
|
28
|
+
memo << [ label, [] ] if label.present?
|
29
|
+
memo.last.last << well
|
30
|
+
end.to_h
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def parse_row(row)
|
36
|
+
row.take(2).map(&:presence)
|
37
|
+
end
|
38
|
+
|
39
|
+
def empty_row?(row)
|
40
|
+
row.all?(&:blank?)
|
41
|
+
end
|
42
|
+
|
43
|
+
def sample_map_header?(row)
|
44
|
+
row[0].to_s =~ /\A\s*Sample\s*\z/i && row[1].to_s =~ /\A\s*Wells\s*\z/i
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,23 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "flex_station_data/services/value_quality"
|
2
4
|
|
3
5
|
module FlexStationData
|
4
6
|
class SampleQuality
|
5
7
|
include Concerns::Service
|
6
8
|
|
7
|
-
attr_reader :sample, :
|
9
|
+
attr_reader :sample, :options
|
8
10
|
|
9
|
-
def initialize(sample,
|
11
|
+
def initialize(sample, **options)
|
10
12
|
@sample = sample
|
11
|
-
@value_quality_control = value_quality_control
|
12
13
|
@options = options
|
13
14
|
end
|
14
15
|
|
15
16
|
def value_quality(value)
|
16
|
-
|
17
|
+
ValueQuality.call(value, **options)
|
17
18
|
end
|
18
19
|
|
19
20
|
def call
|
20
|
-
sample.
|
21
|
+
sample.values.flatten.map(&method(:value_quality)).uniq(&:to_s)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
end
|
@@ -1,6 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "singleton"
|
2
4
|
require "active_support/core_ext"
|
3
5
|
|
6
|
+
require "flex_station_data/concerns/service"
|
7
|
+
|
4
8
|
module FlexStationData
|
5
9
|
class ValueQuality
|
6
10
|
include Concerns::Service
|
@@ -21,7 +25,7 @@ module FlexStationData
|
|
21
25
|
attr_reader :description
|
22
26
|
|
23
27
|
def initialize(description)
|
24
|
-
@description
|
28
|
+
@description = description
|
25
29
|
end
|
26
30
|
|
27
31
|
def good?
|
@@ -1,29 +1,30 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "matrix"
|
2
4
|
|
3
5
|
module FlexStationData
|
4
6
|
class Wells
|
5
|
-
|
6
|
-
|
7
|
+
attr_reader :matrix
|
8
|
+
|
9
|
+
def initialize(matrix)
|
10
|
+
@matrix = matrix
|
7
11
|
end
|
8
12
|
|
9
|
-
def
|
10
|
-
|
11
|
-
row, column = parse_well_label(well_label)
|
12
|
-
Readings.new(well_label, plate_readings_matrix[row][column])
|
13
|
-
end
|
13
|
+
def values(well_label)
|
14
|
+
matrix[*coordinates(well_label)]
|
14
15
|
end
|
15
16
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
17
|
+
def coordinates(well_label)
|
18
|
+
coordinates_index[well_label] ||= begin
|
19
|
+
row, column = well_label.scan(/\A([A-Z])(\d+)\z/).first
|
20
|
+
[ row.ord - "A".ord, column.to_i - 1 ]
|
21
|
+
end
|
19
22
|
end
|
20
23
|
|
21
24
|
private
|
22
25
|
|
23
|
-
def
|
24
|
-
@
|
26
|
+
def coordinates_index
|
27
|
+
@coordinates_index ||= {}
|
25
28
|
end
|
26
|
-
|
27
|
-
attr_reader :plate_readings_matrix
|
28
29
|
end
|
29
30
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flex-station-data
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Carney
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -24,20 +24,34 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rake
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
47
|
+
version: '13.0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '13.0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rspec
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,7 +67,7 @@ dependencies:
|
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '3.8'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
70
|
+
name: rubocop-rspec
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
73
|
- - ">="
|
@@ -100,12 +114,14 @@ email:
|
|
100
114
|
executables:
|
101
115
|
- flex-station
|
102
116
|
- flex-station-linear-regression
|
103
|
-
- flex-station-sample-data
|
104
117
|
extensions: []
|
105
118
|
extra_rdoc_files: []
|
106
119
|
files:
|
120
|
+
- ".github/workflows/ruby.yml"
|
107
121
|
- ".gitignore"
|
108
122
|
- ".rspec"
|
123
|
+
- ".rubocop.yml"
|
124
|
+
- ".ruby-version"
|
109
125
|
- CHANGELOG.md
|
110
126
|
- CODE_OF_CONDUCT.md
|
111
127
|
- Gemfile
|
@@ -115,28 +131,24 @@ files:
|
|
115
131
|
- Rakefile
|
116
132
|
- bin/flex-station
|
117
133
|
- bin/flex-station-linear-regression
|
118
|
-
- bin/flex-station-sample-data
|
119
134
|
- flex-station-data.gemspec
|
120
135
|
- lib/flex_station_data.rb
|
136
|
+
- lib/flex_station_data/concerns/callable.rb
|
121
137
|
- lib/flex_station_data/concerns/presenter.rb
|
122
138
|
- lib/flex_station_data/concerns/service.rb
|
139
|
+
- lib/flex_station_data/default_sample_map.rb
|
123
140
|
- lib/flex_station_data/linear_regression.rb
|
124
141
|
- lib/flex_station_data/plate.rb
|
125
|
-
- lib/flex_station_data/presenters/
|
126
|
-
- lib/flex_station_data/presenters/
|
127
|
-
- lib/flex_station_data/presenters/
|
128
|
-
- lib/flex_station_data/presenters/
|
129
|
-
- lib/flex_station_data/presenters/linear_regression/verbose_sample_csv.rb
|
130
|
-
- lib/flex_station_data/presenters/plate_csv.rb
|
131
|
-
- lib/flex_station_data/presenters/plates_csv.rb
|
132
|
-
- lib/flex_station_data/presenters/sample_csv.rb
|
133
|
-
- lib/flex_station_data/readings.rb
|
142
|
+
- lib/flex_station_data/presenters/plate_hash.rb
|
143
|
+
- lib/flex_station_data/presenters/plates_hash.rb
|
144
|
+
- lib/flex_station_data/presenters/sample_hash.rb
|
145
|
+
- lib/flex_station_data/presenters/sample_regression_hash.rb
|
134
146
|
- lib/flex_station_data/sample.rb
|
135
147
|
- lib/flex_station_data/services/compute_mean.rb
|
136
148
|
- lib/flex_station_data/services/load_plates.rb
|
137
149
|
- lib/flex_station_data/services/parse_plate.rb
|
138
150
|
- lib/flex_station_data/services/parse_plate_readings.rb
|
139
|
-
- lib/flex_station_data/services/
|
151
|
+
- lib/flex_station_data/services/parse_sample_map.rb
|
140
152
|
- lib/flex_station_data/services/sample_quality.rb
|
141
153
|
- lib/flex_station_data/services/value_quality.rb
|
142
154
|
- lib/flex_station_data/version.rb
|
@@ -155,14 +167,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
155
167
|
requirements:
|
156
168
|
- - ">="
|
157
169
|
- !ruby/object:Gem::Version
|
158
|
-
version: 2.
|
170
|
+
version: 2.7.1
|
159
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
172
|
requirements:
|
161
173
|
- - ">="
|
162
174
|
- !ruby/object:Gem::Version
|
163
175
|
version: '0'
|
164
176
|
requirements: []
|
165
|
-
rubygems_version: 3.
|
177
|
+
rubygems_version: 3.1.2
|
166
178
|
signing_key:
|
167
179
|
specification_version: 4
|
168
180
|
summary: Data analysis tool for FlexStation microplate reader
|