flex-station-data 0.3.1 → 0.3.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/Gemfile.lock +1 -1
- data/lib/flex_station_data/plate.rb +12 -3
- data/lib/flex_station_data/presenters/linear_regression/sample_hash.rb +2 -2
- data/lib/flex_station_data/presenters/linear_regression/verbose_sample_csv.rb +1 -1
- data/lib/flex_station_data/presenters/plate_csv.rb +9 -4
- data/lib/flex_station_data/presenters/plates_csv.rb +9 -4
- data/lib/flex_station_data/presenters/sample_csv.rb +20 -15
- data/lib/flex_station_data/sample.rb +18 -5
- data/lib/flex_station_data/services/parse_plate.rb +4 -4
- data/lib/flex_station_data/services/parse_plate_readings.rb +15 -32
- data/lib/flex_station_data/services/parse_sample_map.rb +50 -0
- data/lib/flex_station_data/services/sample_quality.rb +1 -1
- data/lib/flex_station_data/services/value_quality.rb +2 -0
- data/lib/flex_station_data/version.rb +1 -1
- data/lib/flex_station_data/wells.rb +14 -15
- metadata +3 -4
- data/lib/flex_station_data/readings.rb +0 -16
- data/lib/flex_station_data/services/parse_plate_samples.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d58049eac2b497f587a9e2b467eb09ada8fe9582c3dced6985aa59f26cbe58b
|
4
|
+
data.tar.gz: 6154e1b4930afde05d7449df4ce0ebfce74e92d0651944d163cb4664e6c880f6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0307a6c1f8cff75dba0fb93ec17b2b49ec59db99cf1d5c18d487b40d2451695bc92fcbf911f1cba2e85fe859ccc2bd107537f6422eb1a14f0a9f5c684ac735a3
|
7
|
+
data.tar.gz: ff7e2b5c8d363aae425010d47e7e531028ae122772be9db1098f46113f28e1d04ffd6df065000ea69c21b138342071cfc4f618638754bffb7d9353bbb172252c
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,21 @@
|
|
1
|
+
require "flex_station_data/sample"
|
2
|
+
|
1
3
|
module FlexStationData
|
2
4
|
class Plate
|
3
|
-
attr_reader :label, :times, :temperatures, :
|
5
|
+
attr_reader :label, :times, :temperatures, :wells, :sample_map
|
4
6
|
|
5
|
-
def initialize(label, times, temperatures,
|
7
|
+
def initialize(label, times, temperatures, wells, sample_map)
|
6
8
|
@label = label
|
7
9
|
@times = times
|
8
10
|
@temperatures = temperatures
|
9
|
-
@
|
11
|
+
@wells = wells
|
12
|
+
@sample_map = sample_map
|
13
|
+
end
|
14
|
+
|
15
|
+
def samples
|
16
|
+
@samples ||= sample_map.map do |label, well_labels|
|
17
|
+
Sample.new(label, well_labels, self)
|
18
|
+
end
|
10
19
|
end
|
11
20
|
end
|
12
21
|
end
|
@@ -29,13 +29,13 @@ module FlexStationData
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def wells_hash
|
32
|
-
{ "wells" => sample.
|
32
|
+
{ "wells" => sample.wells.join(", ") }
|
33
33
|
end
|
34
34
|
|
35
35
|
def regression_hash
|
36
36
|
return SampleRegressionHash.headers.zip([]).to_h if errors?
|
37
37
|
|
38
|
-
SampleRegressionHash.present(times, sample.mean
|
38
|
+
SampleRegressionHash.present(times, sample.mean, **options).transform_values(&:first)
|
39
39
|
end
|
40
40
|
|
41
41
|
def present
|
@@ -15,15 +15,20 @@ module FlexStationData
|
|
15
15
|
@options = options
|
16
16
|
end
|
17
17
|
|
18
|
+
def present
|
19
|
+
[
|
20
|
+
[ "Plate #{plate.label}" ],
|
21
|
+
*samples_csv
|
22
|
+
]
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
18
27
|
def samples_csv
|
19
28
|
samples.flat_map do |sample|
|
20
29
|
sample_presenter.present(times, sample, **options)
|
21
30
|
end
|
22
31
|
end
|
23
|
-
|
24
|
-
def present
|
25
|
-
[ ["Plate #{plate.label}"], *samples_csv ]
|
26
|
-
end
|
27
32
|
end
|
28
33
|
end
|
29
34
|
end
|
@@ -14,15 +14,20 @@ module FlexStationData
|
|
14
14
|
@options = options
|
15
15
|
end
|
16
16
|
|
17
|
+
def present
|
18
|
+
[
|
19
|
+
[ "File: #{file.basename.to_path}" ],
|
20
|
+
*plates_csv
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
17
26
|
def plates_csv
|
18
27
|
plates.flat_map do |plate|
|
19
28
|
plate_presenter.present(plate, **options)
|
20
29
|
end
|
21
30
|
end
|
22
|
-
|
23
|
-
def present
|
24
|
-
[ ["File: #{file.to_path}"], *plates_csv ]
|
25
|
-
end
|
26
31
|
end
|
27
32
|
end
|
28
33
|
end
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require "flex_station_data/concerns/presenter"
|
2
|
-
require "flex_station_data/readings"
|
3
2
|
require "flex_station_data/services/sample_quality"
|
4
3
|
|
5
4
|
module FlexStationData
|
@@ -16,26 +15,24 @@ module FlexStationData
|
|
16
15
|
@options = options
|
17
16
|
end
|
18
17
|
|
19
|
-
def
|
20
|
-
@
|
18
|
+
def errors
|
19
|
+
@errors ||= quality_control.call(sample, **options).reject(&:good?)
|
21
20
|
end
|
22
21
|
|
23
|
-
def
|
24
|
-
|
22
|
+
def present
|
23
|
+
[
|
24
|
+
[ label ],
|
25
|
+
*body_csv,
|
26
|
+
[ ]
|
27
|
+
]
|
25
28
|
end
|
26
29
|
|
27
|
-
|
28
|
-
readings.map(&:values).transpose
|
29
|
-
end
|
30
|
+
private
|
30
31
|
|
31
32
|
def label
|
32
33
|
"Sample #{sample.label}"
|
33
34
|
end
|
34
35
|
|
35
|
-
def errors
|
36
|
-
@errors ||= quality_control.call(sample, **options).reject(&:good?)
|
37
|
-
end
|
38
|
-
|
39
36
|
def errors?
|
40
37
|
errors.present?
|
41
38
|
end
|
@@ -44,12 +41,20 @@ module FlexStationData
|
|
44
41
|
errors.map(&:to_s).map(&method(:Array))
|
45
42
|
end
|
46
43
|
|
44
|
+
def headers
|
45
|
+
[ "time", *sample.wells, "mean" ]
|
46
|
+
end
|
47
|
+
|
48
|
+
def values
|
49
|
+
[ times, *sample.values, sample.mean ]
|
50
|
+
end
|
51
|
+
|
47
52
|
def values_csv
|
48
|
-
[ headers, *
|
53
|
+
[ headers, *values.transpose ]
|
49
54
|
end
|
50
55
|
|
51
|
-
def
|
52
|
-
|
56
|
+
def body_csv
|
57
|
+
errors? ? errors_csv : values_csv
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
@@ -1,16 +1,29 @@
|
|
1
|
-
require "
|
1
|
+
require "matrix"
|
2
|
+
|
3
|
+
require "flex_station_data/services/compute_mean"
|
2
4
|
|
3
5
|
module FlexStationData
|
4
6
|
class Sample
|
5
|
-
attr_reader :label, :
|
7
|
+
attr_reader :label, :wells, :plate
|
8
|
+
|
9
|
+
delegate :wells, to: :plate, prefix: true
|
6
10
|
|
7
|
-
def initialize(label,
|
11
|
+
def initialize(label, wells, plate)
|
8
12
|
@label = label
|
9
|
-
@
|
13
|
+
@wells = wells
|
14
|
+
@plate = plate
|
15
|
+
end
|
16
|
+
|
17
|
+
def values
|
18
|
+
wells.map(&plate_wells.method(:values))
|
19
|
+
end
|
20
|
+
|
21
|
+
def readings
|
22
|
+
@readings ||= wells.zip(values).map { |well, v| Readings.new(well, v) }
|
10
23
|
end
|
11
24
|
|
12
25
|
def mean
|
13
|
-
@mean ||=
|
26
|
+
@mean ||= values.transpose.map(&ComputeMean)
|
14
27
|
end
|
15
28
|
end
|
16
29
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "active_support/core_ext"
|
2
2
|
|
3
3
|
require "flex_station_data/services/parse_plate_readings"
|
4
|
-
require "flex_station_data/services/
|
4
|
+
require "flex_station_data/services/parse_sample_map"
|
5
5
|
require "flex_station_data/plate"
|
6
6
|
|
7
7
|
module FlexStationData
|
@@ -16,13 +16,13 @@ module FlexStationData
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def data_blocks
|
19
|
-
plate_data.split { |row| row[0]
|
19
|
+
plate_data.split { |row| row[0] =~ /\A~End\s*\z/ }
|
20
20
|
end
|
21
21
|
|
22
22
|
def call
|
23
23
|
times, temperatures, wells = ParsePlateReadings.call(data_blocks[0])
|
24
|
-
|
25
|
-
Plate.new(label, times, temperatures,
|
24
|
+
sample_map = ParseSampleMap.call(data_blocks[1])
|
25
|
+
Plate.new(label, times, temperatures, wells, sample_map)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "active_support/core_ext"
|
2
|
+
require "matrix"
|
2
3
|
|
3
4
|
require "flex_station_data/wells"
|
4
5
|
require "flex_station_data/concerns/service"
|
@@ -13,45 +14,31 @@ module FlexStationData
|
|
13
14
|
@plate_readings_block = plate_readings_block
|
14
15
|
end
|
15
16
|
|
16
|
-
def
|
17
|
-
@
|
18
|
-
end
|
19
|
-
|
20
|
-
def parsed_rows
|
21
|
-
@parsed_rows ||= begin
|
22
|
-
rows = plate_readings_data.map { |row| parse_row(row[0...column_count]) }
|
23
|
-
rows.select { |row| row.any?(&:present?) }
|
24
|
-
end
|
17
|
+
def headers
|
18
|
+
@headers ||= plate_readings_block.first.reverse.drop_while(&:blank?).reverse
|
25
19
|
end
|
26
20
|
|
27
|
-
def
|
28
|
-
@
|
21
|
+
def matrix
|
22
|
+
@matrix ||= Matrix[
|
23
|
+
*plate_readings_block.drop(1).map { |row| parse_row(row[0...headers.size]) }.select { |row| row.any?(&:present?) }
|
24
|
+
]
|
29
25
|
end
|
30
26
|
|
31
27
|
def times
|
32
|
-
@times ||=
|
28
|
+
@times ||= matrix.column(0).to_a.compact
|
33
29
|
end
|
34
30
|
|
35
31
|
def temperatures
|
36
|
-
@temperatures ||=
|
37
|
-
end
|
38
|
-
|
39
|
-
def values
|
40
|
-
@values ||= parsed_columns.drop(2)
|
32
|
+
@temperatures ||= matrix.column(1).to_a.compact
|
41
33
|
end
|
42
34
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
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
|
35
|
+
def wells_matrix
|
36
|
+
well_row_count = matrix.row_count / times.size
|
37
|
+
Matrix[*well_values.column_vectors.map { |col| col.to_a.each_slice(well_row_count).to_a.transpose }.transpose ]
|
51
38
|
end
|
52
39
|
|
53
40
|
def wells
|
54
|
-
Wells.new(
|
41
|
+
Wells.new(wells_matrix)
|
55
42
|
end
|
56
43
|
|
57
44
|
def call
|
@@ -78,12 +65,8 @@ module FlexStationData
|
|
78
65
|
|
79
66
|
private
|
80
67
|
|
81
|
-
def
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
def plate_readings_data
|
86
|
-
@plate_readings_data ||= plate_readings_block.drop(1)
|
68
|
+
def well_values
|
69
|
+
matrix.minor(0..-1, 2..-1)
|
87
70
|
end
|
88
71
|
|
89
72
|
attr_reader :plate_readings_block
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "matrix"
|
2
|
+
require "active_support/core_ext"
|
3
|
+
|
4
|
+
require "flex_station_data/concerns/service"
|
5
|
+
|
6
|
+
module FlexStationData
|
7
|
+
class ParseSampleMap
|
8
|
+
include Concerns::Service
|
9
|
+
|
10
|
+
attr_reader :sample_map_block
|
11
|
+
|
12
|
+
def initialize(sample_map_block)
|
13
|
+
@sample_map_block = sample_map_block
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
labels.zip(matrix.column(1).to_a.each_slice(wells_per_sample).to_a).to_h
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def parse_row(row)
|
23
|
+
row.take(2).map(&:presence)
|
24
|
+
end
|
25
|
+
|
26
|
+
def empty_row?(row)
|
27
|
+
row.all?(&:blank?)
|
28
|
+
end
|
29
|
+
|
30
|
+
def sample_map_header?(row)
|
31
|
+
row[0] == "Sample"
|
32
|
+
end
|
33
|
+
|
34
|
+
def sample_map_rows
|
35
|
+
sample_map_block.map(&method(:parse_row)).split(&method(:sample_map_header?)).drop(1).first.split(&method(:empty_row?)).first
|
36
|
+
end
|
37
|
+
|
38
|
+
def matrix
|
39
|
+
@matrix ||= Matrix[*sample_map_rows]
|
40
|
+
end
|
41
|
+
|
42
|
+
def labels
|
43
|
+
@labels ||= matrix.column(0).to_a.compact
|
44
|
+
end
|
45
|
+
|
46
|
+
def wells_per_sample
|
47
|
+
matrix.row_count / labels.size
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,29 +1,28 @@
|
|
1
|
-
require "
|
1
|
+
require "matrix"
|
2
2
|
|
3
3
|
module FlexStationData
|
4
4
|
class Wells
|
5
|
-
|
6
|
-
|
5
|
+
attr_reader :matrix
|
6
|
+
|
7
|
+
def initialize(matrix)
|
8
|
+
@matrix = matrix
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
10
|
-
|
11
|
-
row, column = parse_well_label(well_label)
|
12
|
-
Readings.new(well_label, plate_readings_matrix[row][column])
|
13
|
-
end
|
11
|
+
def values(well_label)
|
12
|
+
matrix[*coordinates(well_label)]
|
14
13
|
end
|
15
14
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
15
|
+
def coordinates(well_label)
|
16
|
+
coordinates_index[well_label] ||= begin
|
17
|
+
row, column = well_label.scan(/\A([A-Z])(\d+)\z/).first
|
18
|
+
[ row.ord - "A".ord, column.to_i - 1 ]
|
19
|
+
end
|
19
20
|
end
|
20
21
|
|
21
22
|
private
|
22
23
|
|
23
|
-
def
|
24
|
-
@
|
24
|
+
def coordinates_index
|
25
|
+
@coordinates_index ||= {}
|
25
26
|
end
|
26
|
-
|
27
|
-
attr_reader :plate_readings_matrix
|
28
27
|
end
|
29
28
|
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.3.
|
4
|
+
version: 0.3.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: 2019-08-
|
11
|
+
date: 2019-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -130,13 +130,12 @@ files:
|
|
130
130
|
- lib/flex_station_data/presenters/plate_csv.rb
|
131
131
|
- lib/flex_station_data/presenters/plates_csv.rb
|
132
132
|
- lib/flex_station_data/presenters/sample_csv.rb
|
133
|
-
- lib/flex_station_data/readings.rb
|
134
133
|
- lib/flex_station_data/sample.rb
|
135
134
|
- lib/flex_station_data/services/compute_mean.rb
|
136
135
|
- lib/flex_station_data/services/load_plates.rb
|
137
136
|
- lib/flex_station_data/services/parse_plate.rb
|
138
137
|
- lib/flex_station_data/services/parse_plate_readings.rb
|
139
|
-
- lib/flex_station_data/services/
|
138
|
+
- lib/flex_station_data/services/parse_sample_map.rb
|
140
139
|
- lib/flex_station_data/services/sample_quality.rb
|
141
140
|
- lib/flex_station_data/services/value_quality.rb
|
142
141
|
- lib/flex_station_data/version.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require "flex_station_data/services/compute_mean"
|
2
|
-
|
3
|
-
module FlexStationData
|
4
|
-
class Readings
|
5
|
-
attr_reader :label, :values
|
6
|
-
|
7
|
-
def initialize(label, values)
|
8
|
-
@label = label
|
9
|
-
@values = values
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.mean(*readings, label: "mean")
|
13
|
-
new(label, readings.map(&:values).transpose.map(&ComputeMean))
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,49 +0,0 @@
|
|
1
|
-
require "flex_station_data/readings"
|
2
|
-
require "flex_station_data/concerns/service"
|
3
|
-
|
4
|
-
require "flex_station_data/sample"
|
5
|
-
|
6
|
-
module FlexStationData
|
7
|
-
class ParsePlateSamples
|
8
|
-
include Concerns::Service
|
9
|
-
|
10
|
-
def initialize(sample_map_block, wells)
|
11
|
-
@sample_map_block = sample_map_block
|
12
|
-
@wells = wells
|
13
|
-
end
|
14
|
-
|
15
|
-
def map_rows
|
16
|
-
@map_rows ||= begin
|
17
|
-
rows = sample_map_block.drop_while { |row| row[0] != "Sample" }.drop(1)
|
18
|
-
rows = rows.map { |row| row.map(&:presence) }
|
19
|
-
rows.take_while { |row| row.any?(&:present?) }.to_a
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def map_columns
|
24
|
-
@map_columns ||= map_rows.transpose
|
25
|
-
end
|
26
|
-
|
27
|
-
def labels
|
28
|
-
@labels ||= map_columns[0].compact
|
29
|
-
end
|
30
|
-
|
31
|
-
def wells_per_sample
|
32
|
-
map_rows.size / labels.size
|
33
|
-
end
|
34
|
-
|
35
|
-
def sample_map
|
36
|
-
@sample_map ||= map_columns[1].each_slice(wells_per_sample).to_a
|
37
|
-
end
|
38
|
-
|
39
|
-
def call
|
40
|
-
labels.zip(sample_map).map do |label, well_labels|
|
41
|
-
Sample.new(label, well_labels.map(&wells.method(:readings)))
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
attr_reader :sample_map_block, :wells
|
48
|
-
end
|
49
|
-
end
|