Module: Submission::ScrnaCoreCdnaPrepPoolingPlanGenerator

Defined in:
app/models/submission/scrna_core_cdna_prep_pooling_plan_generator.rb

Overview

This module provides a basic pooling plan generator for scRNA core cDNA prep submissions. It generates a CSV string which outlines the pooling strategy for the submitted samples based on the number of pools and cells per chip well specified in the submission and grouped by study and project. The logic for determining the pool layout is aimed to be a mirror of the pooling logic used in Limber, specifically in the DonorPoolingCalculator's allocate_wells_to_pools method.

This module also assumes the submission has already been validated with the scrna_core_cdna_prep validators to ensure donor clashes and pooling parameters are already checked.

Class Method Summary collapse

Class Method Details

.calculate_pools_layout(number_of_samples, number_of_pools) ⇒ Object

This method calculates the layout of pools based on the total number of samples and the number of pools requested. It divides the samples as evenly as possible across the pools, and evenly distributes any remainder samples



35
36
37
38
39
40
41
42
# File 'app/models/submission/scrna_core_cdna_prep_pooling_plan_generator.rb', line 35

def self.calculate_pools_layout(number_of_samples, number_of_pools)
  # Ideal pool size is just the number of samples divided by the number of pools, but we need to account for
  # any remainder if the division isn't exact
  ideal_pool_size, remainder = number_of_samples.divmod(number_of_pools)
  pools_layout = Array.new(number_of_pools, ideal_pool_size)
  remainder.times { |i| pools_layout[i] += 1 }
  pools_layout
end

.generate_pooling_plan(submission) ⇒ Object

This logic attemps to mirror Limber's pooling logic See Limber LabwareCreators::DonorPoolingCalculator (allocate_wells_to_pools)



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'app/models/submission/scrna_core_cdna_prep_pooling_plan_generator.rb', line 14

def self.generate_pooling_plan(submission)
  CSV.generate(row_sep: "\r\n") do |csv|
    csv << ['Study / Project', 'Pools (num samples)', 'Cells per chip well']
    # It would be nice to refactor the scRNA Validator logic here to pull out the pooling plan logic
    grouped_requests(submission).each do |study_project, subgroup|
      # Get number_of_pools and cells_per_chip_well requested from the submission
      number_of_pools = subgroup.first..number_of_pools
      cells_per_chip_well = subgroup.first..cells_per_chip_well
      # Build the pools
      pools_layout = calculate_pools_layout(subgroup.size, number_of_pools)

      # Join the pool sizes into a string for the CSV output
      number_of_samples_in_pool = pools_layout.join(', ')

      csv << [study_project, number_of_samples_in_pool, cells_per_chip_well]
    end
  end
end

.grouped_requests(submission) ⇒ Object

Groups the requests associated with a submission by study and project.



45
46
47
48
49
50
51
52
53
# File 'app/models/submission/scrna_core_cdna_prep_pooling_plan_generator.rb', line 45

def self.grouped_requests(submission)
  # Unique by asset to avoid counting the same sample tube multiple times if it appears in multiple requests
  # e.g. if a sample tube is requested in two different lanes, we only want to count it once for pooling plan purposes
  submission.requests.uniq(&:asset).group_by do |request|
    study = request.initial_study.name
    project = request.initial_project.name
    "#{study} / #{project}"
  end
end