Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPL-916 PBMC Donor Pooling create plate #1582

Merged
merged 95 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
aceec0e
Added creator class to LRC PBMC Pools purpose
yoldas Feb 13, 2024
9f2313f
Added automatic state changer class to LRC PBMC Pools purpose
yoldas Feb 13, 2024
e5c7d03
Added work completion request type to LRC PBMC Pools purpose
yoldas Feb 13, 2024
bac22b6
Added pooling lookup table, same as Cardinal
yoldas Feb 14, 2024
a23b111
Add creator_class configuration for LRC PBMC Pools purpose
yoldas Feb 23, 2024
e1a4003
Added pooling algorithm for donor pooling labware creator
yoldas Feb 23, 2024
d92ae65
Fixed split_single_group_by_donor_ids call
yoldas Feb 23, 2024
a6726d2
Added transfer requests and tag_depth info
yoldas Feb 23, 2024
fa56710
Formatted labware creator code comments
yoldas Feb 23, 2024
dcccca8
Add donor pooling template for receving source plate barcodes
yoldas Feb 23, 2024
dd1033b
Add donor pooling plate purpose config factory
yoldas Feb 23, 2024
f8483ac
Prettier
yoldas Feb 23, 2024
cb5599e
Merge branch 'develop' into 1390-dpl-916-pbmc-donor-pooling-create-plate
yoldas Feb 23, 2024
529cace
Merged transfer_hash methods
yoldas Feb 24, 2024
2e0a199
Added initializer to load the lookup table
yoldas Feb 24, 2024
3d96ccf
Add attribute readers for barcodes and minimal barcodes
yoldas Feb 25, 2024
05de79a
Rubocop
yoldas Feb 25, 2024
acc4d5c
Add test for source_plates method
yoldas Feb 25, 2024
8279d4d
Add test for source_wells_for_pooling method
yoldas Feb 25, 2024
c4287ba
Fix config name in number_of_pools method
yoldas Feb 25, 2024
1ebd41b
Add test for number_of_pools method
yoldas Feb 25, 2024
9afc083
Add tests for barcodes= and group_by_study_and_project methods
yoldas Feb 25, 2024
9988999
Add test for unique_donor_ids method
yoldas Feb 25, 2024
60fbf63
Fix unique_donor_ids method
yoldas Feb 25, 2024
7421274
Add test for split_single_group_by_donor_ids method
yoldas Feb 25, 2024
0aebf5c
Fix split_single_group_by_donor_ids method
yoldas Feb 25, 2024
71b9c70
Rename donor_id split methods
yoldas Feb 25, 2024
c1fd115
Move helper methods to a separate module
yoldas Feb 26, 2024
de63cdb
Fix distribute_groups_across_pools method
yoldas Feb 26, 2024
7e957e1
Check nil in split_single_group_by_unique_donor_ids
yoldas Feb 26, 2024
81e71a9
Fix distribute_groups_across_pools call in build_pools
yoldas Feb 26, 2024
6b791e3
Add test for build_pools method
yoldas Feb 26, 2024
f84278c
Add tests for tag depth and transfer request attributes
yoldas Feb 27, 2024
37b5db7
Add test for transfer_material_from_parent! method
yoldas Feb 27, 2024
580e4b7
Add test for pools method
yoldas Feb 27, 2024
52dd3c5
Prettier
yoldas Feb 27, 2024
b3bbe22
Change module name from helper to calculator
yoldas Feb 28, 2024
96a79e3
Rename file for donor pooling calculator
yoldas Feb 28, 2024
4c97d08
Update the include with the pooling calculator module name
yoldas Feb 28, 2024
c2fbbaa
Add donor pooling validations
yoldas Feb 28, 2024
d35641d
Include validator in labware creator
yoldas Feb 28, 2024
2d9f022
Prettier
yoldas Feb 28, 2024
616f4c4
Updated message for number_of_pools_must_not_exceed_configured validator
yoldas Feb 28, 2024
d5cdca5
Remove redundant include from validator
yoldas Feb 28, 2024
c8ffdb9
Add comments to validation methods
yoldas Feb 28, 2024
05bd224
Prettier
yoldas Feb 28, 2024
c74e242
Add tests for validations
yoldas Feb 28, 2024
bd90134
Add test for wells_with_aliquots_must_have_donor_id
yoldas Mar 1, 2024
d484671
Add validation wells_with_aliquots_must_have_donor_id
yoldas Mar 1, 2024
61ec788
Rename labware creator argument to max_number_of_source_plates
yoldas Mar 7, 2024
7acfec8
Fix typo in labware_wells method doc
yoldas Mar 7, 2024
a3fda01
Use number_of_pools and default_number_of_pools from purpose_config
yoldas Mar 10, 2024
407f630
Add pooling and default_number_pools to labware creator arguments
yoldas Mar 10, 2024
698d887
Updated docs with config:generate
yoldas Mar 10, 2024
127c487
Load pooling configurations with config task
yoldas Mar 10, 2024
89045f9
Add labware creator arguments to donor_pooling_plate_purpose_config f…
yoldas Mar 10, 2024
649eb89
Update test with default_number_of_pools from purpose config
yoldas Mar 10, 2024
595b8cb
Reset Settings.poolings in spec_config to allow testing with custom s…
yoldas Mar 10, 2024
542c209
Add config loader for poolings
yoldas Mar 10, 2024
75f0db3
Add donor_pooling_config factory for testing pooling configurations f…
yoldas Mar 10, 2024
2ca3b52
Add interim scrna donor pooling config YAML file (lookup table; copy …
yoldas Mar 10, 2024
58f224d
Add fixtures for testing with pooling configurations
yoldas Mar 10, 2024
08bd157
Add test for poolings config loader
yoldas Mar 10, 2024
c312ead
Add well_at_location method to Plate
yoldas Mar 10, 2024
b491741
Use plate.well_at_location method instead of get_well_for_plate_location
yoldas Mar 10, 2024
37e3b6a
Remove get_well_for_plate_location method from labware creator
yoldas Mar 10, 2024
f209901
Remove test for get_well_for_plate_location method
yoldas Mar 10, 2024
2a89e43
Update config rake task stdout progress with pooling config
yoldas Mar 10, 2024
7bc4277
Add method to compute all tag depths at once into a hash
yoldas Mar 10, 2024
254c788
Use pre-computed tag depths (as strings) in request_hash
yoldas Mar 10, 2024
918f710
Remove per well tag_depth method because they are pre-computed now
yoldas Mar 10, 2024
4440b33
Replace tag_depth test with tag_depth_hash test
yoldas Mar 10, 2024
a4c43cf
Fix caching the result of tag_depth_hash computation
yoldas Mar 10, 2024
7ed1788
Use less strong wording in the view as suggested in code-review
yoldas Mar 10, 2024
3bb5088
Update instructions with the conditions of pooling
yoldas Mar 10, 2024
a815052
Apply doc suggestion for DonorPoolingCalculator
yoldas Mar 10, 2024
67693fe
Add to doc: only one aliquot is expected per well
yoldas Mar 10, 2024
e8dbe18
Remove redundant nil-check
yoldas Mar 10, 2024
ec22680
Use counter instead of empty check for the while loop condition
yoldas Mar 10, 2024
68b1e83
Prettier
yoldas Mar 10, 2024
80b1bea
Add examples in the comments for methods
yoldas Mar 10, 2024
7224c0d
Add missing source plate barcodes to the error message
yoldas Mar 10, 2024
d02883c
Update test with missing source plate barcodes
yoldas Mar 10, 2024
711ac1c
Rubocop
yoldas Mar 10, 2024
9d08807
Separate assigment statement from the chain
yoldas Mar 10, 2024
4ce1bcc
Update error message strings
yoldas Mar 10, 2024
4386930
Remove redundant source_plate param from locations_with_missing_donor_id
yoldas Mar 10, 2024
efc8360
Add a method to map source wells to their plates
yoldas Mar 10, 2024
f458b48
Ensure validator uses the same filtered wells as the labware creator
yoldas Mar 10, 2024
8590d76
Add test for source_wells_to_plates method
yoldas Mar 10, 2024
651445c
Update code documentation of locations_with_missing_donor_id method
yoldas Mar 10, 2024
fe38028
Remove pooling config CSV file
yoldas Mar 10, 2024
e3960c4
Remove CSV config file loader
yoldas Mar 10, 2024
169891b
Prettier
yoldas Mar 11, 2024
d4b8573
Merge branch 'develop' into 1390-dpl-916-pbmc-donor-pooling-create-plate
yoldas Mar 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
280 changes: 280 additions & 0 deletions app/models/labware_creators/donor_pooling_plate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
# frozen_string_literal: true

module LabwareCreators
# This labware creator receives barcodes for a configured number of source
# plates from the user. It pools samples from the passed wells into a
# destination plate. It's used for scRNA Donor Pooling to create 'LRC PBMC
# Pools' plates from 'LRC PBMC Defrost PBS' plates.
#
# The creator imposes restrictions:
# - It doesn't allow combining samples from different studies or projects.
# - It doesn't allow samples with the same donor_id in the same pool.
#
# The number of pools is determined by a lookup table based on sample count.
# Tag depth index is added to aliquot attributes to avoid tag clashes.
class DonorPoolingPlate < Base
yoldas marked this conversation as resolved.
Show resolved Hide resolved
include LabwareCreators::CustomPage
include SupportParent::PlateOnly

# The name of the template that will be used for rendering the barcode
# input page.
self.page = 'donor_pooling_plate'

# Add the :barcodes attribute to the list of attributes for this class.
# The :barcodes attribute is initialized as an empty array.
self.attributes += [{ barcodes: [] }]
yoldas marked this conversation as resolved.
Show resolved Hide resolved

# Define related objects to be included when retrieving source plates using
# the Sequencescape::API::V2.Plate.find_all method. The 'includes' argument
# of the method is expected to be an array of strings.
SOURCE_PLATE_INCLUDES = %w[
purpose
wells.aliquots.study
yoldas marked this conversation as resolved.
Show resolved Hide resolved
wells.aliquots.project
wells.aliquots.request
wells.aliquots.sample.sample_metadata
wells.requests_as_source
].freeze

# The default number of pools to be created if the count is not found in
# the lookup table. For scRNA Donor Pooling, until a new CSV file is
# provided, a copy of Cardinal pooling config is used, which goes up to 96
# samples. From 97 to 160 samples, the number of pools to create is 16.
DEFAULT_NUMBER_OF_POOLS = 16
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this number be coming from the purpose config?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I have removed the constant and added it as argument to the labware creator in the purpose config.


# Returns the number of source plates from the purpose configuration.
#
# @return [Integer] The number of source plates.
def number_of_source_plates
@number_of_source_plates ||= purpose_config.dig(:creator_class, :args, :number_of_source_plates)

Check warning on line 49 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L49

Added line #L49 was not covered by tests
end
yoldas marked this conversation as resolved.
Show resolved Hide resolved

# Returns the WellFilter instance associated with this creator. The filter
# uses the callback method 'labware_wells' to get the list of wells to
# filter, which specifies wells in 'passed' state from the source plates.
# The 'source_wells_for_pooling' method is used to get the filtered wells.
#
# @return [WellFilter] The WellFilter instance.
def well_filter
@well_filter ||= WellFilter.new(creator: self)

Check warning on line 59 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L59

Added line #L59 was not covered by tests
end

# Reurns all passed wells from the source plates in column order.
yoldas marked this conversation as resolved.
Show resolved Hide resolved
#
# @return [Array<Well>] An array of passed wells.
def labware_wells
source_plates.flat_map { |plate| plate.wells_in_columns.select(&:passed?) }

Check warning on line 66 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L66

Added line #L66 was not covered by tests
end

# Returns all source plates associated with the minimal barcodes.
#
# @return [Array<Plate>] An array of source plates.
def source_plates
@source_plates ||=

Check warning on line 73 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L73

Added line #L73 was not covered by tests
Sequencescape::Api::V2::Plate.find_all({ barcode: minimal_barcodes }, includes: SOURCE_PLATE_INCLUDES)
end

# Returns the source wells for pooling. The wells are filtered using the
# well_filter.
#
# @return [Array<Well>] An array of source wells for pooling.
def source_wells_for_pooling
well_filter.filtered.map(&:first) # The first element is the well.

Check warning on line 82 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L82

Added line #L82 was not covered by tests
end
yoldas marked this conversation as resolved.
Show resolved Hide resolved

# Returns the pools for the destination plate.
#
# @return [Array<Pool>] An array of pools.
def pools
@pools ||= build_pools

Check warning on line 89 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L89

Added line #L89 was not covered by tests
end

# Sets the barcodes and minimal_barcodes instance variables. The
# minimal_barcodes are derived from the barcodes by removing any blank
# values and stripping whitespace from the remaining values.
#
# @param barcodes [Array<String>] An array of barcodes.
def barcodes=(barcodes)
@barcodes = barcodes
@minimal_barcodes = barcodes.compact_blank.map(&:strip)

Check warning on line 99 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L98-L99

Added lines #L98 - L99 were not covered by tests
end

# Returns the number of pools based on the sample count from the lookup
# table. If the count is not found in the table, the default number of
# pools is returned.
#
# @return [Integer] The number of pools.
def number_of_pools
Rails.application.config.scrna_core_donor_pooling.fetch(source_wells_for_pooling.count, DEFAULT_NUMBER_OF_POOLS)

Check warning on line 108 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L108

Added line #L108 was not covered by tests
end

# Creates transfer requests from source wells to the destination plate in
# Sequencescape.
#
# @param dest_uuid [String] The UUID of the destination plate.
# @return [Boolean] Returns true if no exception is raised.
def transfer_material_from_parent!(dest_uuid)
dest_plate = Sequencescape::Api::V2::Plate.find_by(uuid: dest_uuid)
api.transfer_request_collection.create!(

Check warning on line 118 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L117-L118

Added lines #L117 - L118 were not covered by tests
user: user_uuid,
transfer_requests: transfer_request_attributes(dest_plate)
)
true

Check warning on line 122 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L122

Added line #L122 was not covered by tests
end

# Generates the attributes for transfer requests from the source wells to the
# destination plate.
#
# @param dest_plate [Sequencescape::Api::V2::Plate] The destination plate.
# @return [Array<Hash>] An array of hashes, each representing the attributes
# for a transfer request.
def transfer_request_attributes(dest_plate)
well_filter.filtered.filter_map do |source_well, additional_parameters|
request_hash(source_well, dest_plate, additional_parameters)

Check warning on line 133 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L132-L133

Added lines #L132 - L133 were not covered by tests
end
end

# Returns the well from a plate that matches the specified location. If no
# well is found at the specified location, nil is returned. Used by the
# 'request_hash' method to find the destination well.
#
# @param plate [Sequencescape::Api::V2::Plate] The destination plate.
# @param well_location [String] The location to match.
# @return [Sequencescape::Api::V2::Well, nil] The well at the specified location,
# or nil if no well is found.
def get_well_for_plate_location(plate, well_location)
plate.wells.detect { |well| well.location == well_location }

Check warning on line 146 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L146

Added line #L146 was not covered by tests
end
KatyTaylor marked this conversation as resolved.
Show resolved Hide resolved

# Generates a hash representing a transfer request from a source well to a
# destination well. Additional parameters generated by the well filter are
# merged into the request hash, i.e.'outer_request' and 'submission_id'.
# tag_depth is added to the aliquot attributes.
#
# @param source_well [Sequencescape::Api::V2::Well] The source well.
# @param dest_plate [Sequencescape::Api::V2::Plate] The destination plate.
# @param additional_parameters [Hash] Additional parameters to include.
# @return [Hash] A hash representing a transfer request.
def request_hash(source_well, dest_plate, additional_parameters)
dest_location = transfer_hash[source_well][:dest_locn]

Check warning on line 159 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L159

Added line #L159 was not covered by tests
{
'source_asset' => source_well.uuid,

Check warning on line 161 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L161

Added line #L161 was not covered by tests
'target_asset' => get_well_for_plate_location(dest_plate, dest_location)&.uuid,
:aliquot_attributes => {
'tag_depth' => tag_depth(source_well)
}
}.merge(additional_parameters)
end

# Returns a hash representing the transfer from source wells to destination
# locations. The hash is build using the 'build_transfer_hash' method.
#
# @return [Hash] A hash where each key is a source well and each value is a
# hash with a single key-value pair: { dest_locn: destination_location }.
def transfer_hash
@transfer_hash ||= build_transfer_hash

Check warning on line 175 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L175

Added line #L175 was not covered by tests
end

# Builds a mapping between each source well to a destination location.
#
# @return [Hash] A hash where each key is a source well and each value is a
# hash with a single key-value pair: { dest_locn: destination_location }.
def build_transfer_hash
pools

Check warning on line 183 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L183

Added line #L183 was not covered by tests
.each_with_index
.with_object({}) do |(pool, index), result|
dest_location = WellHelpers.well_at_column_index(index) # column order, 96 wells
pool.each { |source_well| result[source_well] = { dest_locn: dest_location } }

Check warning on line 187 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L186-L187

Added lines #L186 - L187 were not covered by tests
end
end

# Returns the tag depth for the given source well. The tag depth is the
# position of the well in its pool. It is used used as an aliquot attribute
# in the transfer request. It is recorded in Sequencescape to avoid tag
# clashes.
#
# @param source_well [Well] The source well for which to retrieve the tag depth.
# @return [String] The tag depth as a string, or nil if the well is not in a pool.
def tag_depth(source_well)
pools.each do |pool|
return (pool.index(source_well) + 1).to_s if pool.index(source_well)

Check warning on line 200 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L199-L200

Added lines #L199 - L200 were not covered by tests
# index + 1 incase of 0th index
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats this comment referring to? is it needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was referring to 1-based index but not obvious. I have already removed this method to address another comment.

end
end
KatyTaylor marked this conversation as resolved.
Show resolved Hide resolved

# Builds the pools for the destination plate. The wells are first grouped
# by study and project, then split by donor_ids, and finally distributed
# across pools.
#
# @return [Array<Array<Well>>] An array of well groups distributed across pools.
def build_pools
groups = group_by_study_and_project
groups = split_groups_by_donor_ids(groups)
distribute_samples_across_pools(groups)

Check warning on line 213 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L211-L213

Added lines #L211 - L213 were not covered by tests
end

# Groups source wells for pooling by study and project. Wells are grouped
# based on the study and project of the first aliquot in each well. Returns
# an array of groups, where each group is an array of wells with the same
# study and project.
#
# @return [Array<Array<Well>>] An array of well groups.
def group_by_study_and_project
source_wells_for_pooling.group_by { |well| [well.aliquots.first.study.id, well.aliquots.first.project.id] }.values

Check warning on line 223 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L223

Added line #L223 was not covered by tests
end

# Splits groups ensuring unique donor_ids within each group. Iterates over
# each group, creating subgroups with wells from a unique donor. The first
# occurrences of unique donor_ids are grouped, then the second occurrences,
# and so on. This prevents combining samples with the same donor_id.
#
# @param groups [Array<Array<Well>>] Array of well groups to be split.
# @return [Array<Array<Well>>] Array of subgroups split by donor ID.
def split_groups_by_donor_ids(groups)
groups.flat_map { |group| split_single_group_by_donor_ids(group) }

Check warning on line 234 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L234

Added line #L234 was not covered by tests
end

# Splits a single group of wells by donor_ids. Used by the
# 'split_groups_by_donor_ids' method.
#
# @param group [Array<Well>] The group of wells to split.
# @return [Array<Array<Well>>] An array of subgroups, each containing wells
# from a unique donor.
def split_single_group_by_donor_ids(group)
output = []
while group.any?
subgroup = []
unique_donor_ids(group).each do |donor_id|
index = group.index { |well| well.aliquots.sample.sample_metadata.donor_id == donor_id }
subgroup << group.delete_at(index)

Check warning on line 249 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L244-L249

Added lines #L244 - L249 were not covered by tests
end
output << subgroup

Check warning on line 251 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L251

Added line #L251 was not covered by tests
end
output

Check warning on line 253 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L253

Added line #L253 was not covered by tests
end

# Returns the unique donor_ids from a group of wells. Used by the
# 'split_single_group_by_donor_ids' method.
#
# @param group [Array<Well>] The group of wells from which to retrieve donor_ids.
# @return [Array<String>] An array of unique donor_ids.
def unique_donor_ids(group)
group.map { |well| well.aliquots.sample.sample_metadata.donor_id }.uniq

Check warning on line 262 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L262

Added line #L262 was not covered by tests
end

# Distributes samples across pools based on group sizes. It sorts the groups
# by size and splits the largest group into two until the number of groups
# equals the number of pools or until all groups have a size of 1.
#
# @param groups [Array<Array<Well>>] Array of well groups to be distributed.
# @return [Array<Array<Well>>] Array of distributed groups.
def distribute_samples_across_pools(groups)
groups.sort_by!(&:size)
while groups.any? && groups.last.size > 1 && groups.size < number_of_pools
splits = (largest = groups.pop).each_slice(largest.size / 2).to_a
groups.concat(splits).sort_by!(&:size)

Check warning on line 275 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L272-L275

Added lines #L272 - L275 were not covered by tests
end
groups

Check warning on line 277 in app/models/labware_creators/donor_pooling_plate.rb

View check run for this annotation

Codecov / codecov/patch

app/models/labware_creators/donor_pooling_plate.rb#L277

Added line #L277 was not covered by tests
end
end
end
44 changes: 44 additions & 0 deletions app/views/plate_creation/donor_pooling_plate.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<%= page('donor-pooling-page') do %>
<%= content do %>
<%= card id: 'main-content' do %>
<div>
<h3>Instructions</h3>
<p>This step uses multiple source plates for pooling together into a destination plate.</p>
KatyTaylor marked this conversation as resolved.
Show resolved Hide resolved
<p>This process checks that the source plates are compatible and can be used together.</p>
KatyTaylor marked this conversation as resolved.
Show resolved Hide resolved
<p>Scan the source plate barcodes into the panel on the right of the screen (the order doesn't matter) and click <i>Create Plate</i>.</p>
</div>
<% end %>
<% end %>
<%= sidebar do %>
<%= card title: 'Add plates to pool', without_block: true do %>
<div id="validation_report"></div>
<div id="add-plates-instructions-block" class="card-body" >
<div class="instructions">
<p>Scan in up to <% @labware_creator.number_of_source_plates %> plates.</p>
</div>
</div>
<% end %>
<div class="card-body">
<%= form_for(
@labware_creator,
url: limber_plate_children_path(@labware_creator.parent_uuid),
as: :plate,
html: { method: :post }) do |form| %>

<%= form.hidden_field :parent_uuid %>
<%= form.hidden_field :purpose_uuid %>
<% @labware_creator.number_of_source_plates.times do |index| %>
<div class="labware-container scan-labware form-group row">
<label for="plate[barcodes][<%= index %>]"
class="plate-label col-md-2" >Source Plate <%= index + 1 %></label>
<input type="text"
id="plate[barcodes][<%= index %>]"
name="plate[barcodes][]"
class="form-control col-md-8"
required="required"/>
</div>
<% end %>
<%= form.submit 'Create Plate', class: 'btn btn-success btn-lg', id: 'create-labware' %>
</div>
<% end %>
<% end %>
KatyTaylor marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 6 additions & 0 deletions config/purposes/scrna_core_cdna_prep.wip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ LRC PBMC Defrost PBS:
# This plate has come from the LRC PBMC Defrost PBS plate, in SeqOps.
LRC PBMC Pools:
:asset_type: plate
:creator_class:
name: LabwareCreators::DonorPoolingPlate
args:
number_of_source_plates: 2
:state_changer_class: StateChangers::AutomaticPlateStateChanger
:work_completion_request_type: 'limber_scrna_core_donor_pooling'
:stock_plate: false
:input_plate: false
# Plate containing pooled PBMCs from different donors.
Expand Down
Loading
Loading