-
Notifications
You must be signed in to change notification settings - Fork 33
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 917 scrna faculty input submission #4067
Changes from 4 commits
70722e3
6169a70
afa18bb
e42b476
c0dd628
9c10936
4dbaedd
a61c83b
9c24c79
8ce8f7e
c0c6adb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,3 +52,4 @@ config/cucumber.yml | |
config/database.yml | ||
*.min.js | ||
public/vite-* | ||
.ruby-lsp/vendor |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,10 +22,18 @@ class UatActions::GeneratePlates < UatActions | |
form_field :well_count, | ||
:number_field, | ||
label: 'Well Count', | ||
help: 'The number of occupied wells on each plate', | ||
help: 'The number of occupied wells on each plate (locations will be randomised if less than full)', | ||
options: { | ||
minimum: 1 | ||
} | ||
form_field :number_of_samples_in_each_well, | ||
:number_field, | ||
label: 'Number of samples in each well', | ||
help: 'The number of samples to create in each well. Default is 1. Max 10.', | ||
options: { | ||
minimum: 1, | ||
maximum: 10 | ||
} | ||
form_field :study_name, | ||
:select, | ||
label: 'Study', | ||
|
@@ -38,11 +46,13 @@ class UatActions::GeneratePlates < UatActions | |
select_options: %w[Column Row Random] | ||
|
||
validate :well_count_smaller_than_plate_size | ||
validates :number_of_samples_in_each_well, numericality: { greater_than: 0, only_integer: true, allow_blank: false } | ||
|
||
def self.default | ||
new( | ||
plate_count: 1, | ||
well_count: 96, | ||
number_of_samples_in_each_well: 1, | ||
study_name: UatActions::StaticRecords.study.name, | ||
plate_purpose_name: PlatePurpose.stock_plate_purpose.name, | ||
well_layout: 'Column' | ||
|
@@ -69,21 +79,72 @@ def well_count_smaller_than_plate_size | |
false | ||
end | ||
|
||
# Ensures number of samples per occupied well is at least 1 | ||
def num_samples_per_well | ||
@num_samples_per_well ||= | ||
if number_of_samples_in_each_well.present? && number_of_samples_in_each_well.to_i.positive? | ||
number_of_samples_in_each_well.to_i | ||
else | ||
1 | ||
end | ||
end | ||
|
||
# Constructs wells for the given plate. | ||
# For each well in the plate, it creates the specified number of samples using the `create_sample` method. | ||
# @param plate [Plate] the plate for which to construct wells | ||
def construct_wells(plate) | ||
wells(plate).each do |well| | ||
sample_name = "sample_#{plate.human_barcode}_#{well.map.description}" | ||
sample = | ||
Sample.new( | ||
name: sample_name, | ||
sanger_sample_id: sample_name, | ||
studies: [study], | ||
sample_metadata_attributes: { | ||
supplier_name: sample_name, | ||
cohort: "Cohort#{plate.human_barcode}", | ||
sample_description: "Description#{plate.human_barcode}" | ||
} | ||
) | ||
sample.save!(validate: false) | ||
num_samples_per_well.times { |sample_index| create_sample(plate, well, sample_index + 1) } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UatActions::GeneratePlates#construct_wells contains iterators nested 2 deep |
||
end | ||
end | ||
|
||
# Creates a new sample with a unique name based on the plate, well, and sample index. | ||
# The sample is built using the `build_sample` method and saved using the `save_sample` method. | ||
# If the sample fails to save due to an ActiveRecord::RecordInvalid error, the error message is | ||
# added to the base errors. | ||
# @param plate [Plate] the plate associated with the sample | ||
# @param well [Well] the well associated with the sample | ||
# @param sample_index [Integer] the index of the sample | ||
# @raise [ActiveRecord::RecordInvalid] if the sample fails to save | ||
def create_sample(plate, well, sample_index) | ||
sample_name = "sample_#{sample_index}_#{plate.human_barcode}_#{well.map.description}" | ||
sample = build_sample(sample_name, plate) | ||
save_sample(sample, well, sample_index) | ||
rescue ActiveRecord::RecordInvalid => e | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UatActions::GeneratePlates#create_sample has the variable name 'e' |
||
errors.add(:base, "Failed to create sample: #{e.message}") | ||
end | ||
|
||
# Builds a new Sample object with the given name and associated plate. | ||
# The sample's metadata attributes are also set, including the supplier name, cohort, and sample description. | ||
# @param sample_name [String] the name of the sample, also used as the sanger_sample_id and supplier_name | ||
# @param plate [Plate] the plate associated with the sample, its human_barcode is used in the cohort and | ||
# sample_description | ||
# @return [Sample] the newly built Sample object | ||
def build_sample(sample_name, plate) | ||
Sample.new( | ||
name: sample_name, | ||
sanger_sample_id: sample_name, | ||
studies: [study], | ||
sample_metadata_attributes: { | ||
supplier_name: sample_name, | ||
cohort: "Cohort#{plate.human_barcode}", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UatActions::GeneratePlates#build_sample calls 'plate.human_barcode' 2 times There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UatActions::GeneratePlates#build_sample refers to 'plate' more than self (maybe move it to another class?) |
||
sample_description: "SD-#{plate.human_barcode}" | ||
} | ||
) | ||
end | ||
|
||
# Saves the given sample and creates an aliquot in the specified well. | ||
# If there are multiple samples in each well, the aliquot is created with a tag depth. | ||
# @param sample [Sample] the sample to be saved | ||
# @param well [Well] the well where the aliquot will be created | ||
# @param sample_index [Integer] the index of the sample in the well, used as tag depth | ||
# if there are multiple samples per well | ||
def save_sample(sample, well, sample_index) | ||
sample.save!(validate: false) | ||
|
||
if num_samples_per_well > 1 | ||
well.aliquots.create!(sample: sample, study: study, tag_depth: sample_index) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UatActions::GeneratePlates#save_sample calls 'well.aliquots' 2 times |
||
else | ||
well.aliquots.create!(sample: sample, study: study) | ||
end | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,6 +67,18 @@ class UatActions::TestSubmission < UatActions # rubocop:todo Metrics/ClassLength | |
options: { | ||
minimum: 1 | ||
} | ||
form_field :number_of_samples_in_each_well, | ||
:number_field, | ||
label: 'Number of samples per occupied well', | ||
help: | ||
'Use this option to create wells containing a pool of multiple samples. Enter ' \ | ||
'the number of samples per well. All occupied wells will have this number of samples.' \ | ||
'Useful for a pipeline where pools of starting samples is required.' \ | ||
'Leave blank for 1 sample per well. Max 10 samples per well.', | ||
options: { | ||
minimum: 1, | ||
maximum: 10 | ||
} | ||
form_field :number_of_wells_to_submit, | ||
:number_field, | ||
label: 'Number of wells to submit', | ||
|
@@ -80,14 +92,15 @@ class UatActions::TestSubmission < UatActions # rubocop:todo Metrics/ClassLength | |
|
||
validates :submission_template, presence: { message: 'could not be found' } | ||
validates :number_of_wells_with_samples, numericality: { greater_than: 0, only_integer: true, allow_blank: true } | ||
validates :number_of_samples_in_each_well, numericality: { greater_than: 0, only_integer: true, allow_blank: true } | ||
validates :number_of_wells_to_submit, numericality: { greater_than: 0, only_integer: true, allow_blank: true } | ||
|
||
# | ||
# Returns a default copy of the UatAction which will be used to fill in the form | ||
# | ||
# @return [UatActions::TestSubmission] A default object for rendering a form | ||
def self.default | ||
new | ||
new(number_of_samples_in_each_well: 1) | ||
end | ||
|
||
def self.compatible_submission_templates | ||
|
@@ -121,6 +134,7 @@ def perform # rubocop:todo Metrics/AbcSize | |
report['primer_panel'] = order.request_options[:primer_panel_name] if order.request_options[:primer_panel_name] | ||
.present? | ||
report['number_of_wells_with_samples'] = labware.wells.with_aliquots.size | ||
report['number_of_samples_in_each_well'] = labware.wells.with_aliquots.first.aliquots.size | ||
report['number_of_wells_to_submit'] = assets.size | ||
order.submission.built! | ||
true | ||
|
@@ -166,24 +180,48 @@ def labware | |
@labware ||= plate_barcode.blank? ? generate_plate : Plate.find_by_barcode(plate_barcode.strip) | ||
end | ||
|
||
def generate_plate # rubocop:todo Metrics/MethodLength | ||
generator = UatActions::GeneratePlates.default | ||
generator.plate_purpose_name = plate_purpose_name.presence || default_purpose_name | ||
|
||
num_sample_wells = number_of_wells_with_samples.to_i | ||
generator.well_count = | ||
if num_sample_wells.zero? | ||
# default option, create a full plate | ||
96 | ||
# Ensures number of samples per occupied well is at least 1 | ||
def num_samples_per_well | ||
@num_samples_per_well ||= | ||
if number_of_samples_in_each_well.present? && number_of_samples_in_each_well.to_i.positive? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UatActions::TestSubmission#num_samples_per_well calls 'number_of_samples_in_each_well.to_i' 2 times |
||
number_of_samples_in_each_well.to_i | ||
else | ||
# take the number entered in the form | ||
num_sample_wells | ||
1 | ||
end | ||
generator.well_layout = 'Random' | ||
end | ||
|
||
# Generates a new plate using a plate generator. | ||
# The generator is set up with the appropriate parameters, then used to perform the plate generation. | ||
# After the plate is generated, the barcode is retrieved. | ||
# @return [Plate] the newly generated Plate object | ||
def generate_plate | ||
generator = setup_generator | ||
generator.perform | ||
Plate.find_by_barcode(generator.report['plate_0']) | ||
end | ||
|
||
# Sets up a plate generator with the appropriate parameters. | ||
# The generator is created with default settings, then its attributes are set based on the current object's state. | ||
# The plate purpose name is set to the plate_purpose_name entered by the user, or to the default purpose name if | ||
# plate_purpose_name is not present. | ||
# The well count is determined by the `determine_well_count` method. | ||
# The well layout is set to 'Random'. | ||
# The number of samples in each well is set to num_samples_per_well. | ||
# @return [UatActions::GeneratePlates] the configured plate generator | ||
def setup_generator | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UatActions::TestSubmission#setup_generator has approx 6 statements |
||
generator = UatActions::GeneratePlates.default | ||
generator.plate_purpose_name = plate_purpose_name.presence || default_purpose_name | ||
generator.well_count = determine_well_count | ||
generator.well_layout = 'Random' | ||
generator.number_of_samples_in_each_well = num_samples_per_well | ||
generator | ||
end | ||
|
||
def determine_well_count | ||
num_sample_wells = number_of_wells_with_samples.to_i | ||
num_sample_wells.zero? ? 96 : num_sample_wells | ||
end | ||
|
||
def order_request_options | ||
default_request_options.merge(custom_request_options) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UatActions::GeneratePlates#num_samples_per_well calls 'number_of_samples_in_each_well.to_i' 2 times