flex-station-data 0.3.0 → 1.0.2
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 +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
|