Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 4 additions & 2 deletions app/models/bulk_submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,8 @@ def process # rubocop:todo Metrics/CyclomaticComplexity
'scrna core cells per chip well',
'% phix requested',
'low diversity',
'ot recipe'
'ot recipe',
'wafer size'
].freeze

ALIAS_FIELDS = { 'plate barcode' => 'barcode', 'tube barcode' => 'barcode' }.freeze
Expand Down Expand Up @@ -360,7 +361,8 @@ def extract_request_options(details)
['scrna core cells per chip well', 'cells_per_chip_well'],
['% phix requested', 'percent_phix_requested'],
['low diversity', 'low_diversity'],
['ot recipe', 'ot_recipe']
['ot recipe', 'ot_recipe'],
['wafer size', 'wafer_size']
].each do |source_key, target_key|
assign_value_if_source_present(details, source_key, request_options, target_key)
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/ultima_sequencing_pipeline.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Specialized sequencing pipeline for Ultima
# Specialized sequencing pipeline for Ultima UG100
class UltimaSequencingPipeline < SequencingPipeline
def ot_recipe_consistent_for_batch?(batch)
ot_recipe_list = batch.requests.filter_map { |request| request.request_metadata.ot_recipe }
Expand Down
13 changes: 13 additions & 0 deletions app/models/ultima_ug200_sequencing_pipeline.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

# Specialized sequencing pipeline for Ultima UG200
class UltimaUG200SequencingPipeline < UltimaSequencingPipeline
def wafer_size_consistent_for_batch?(batch)
wafer_size_list = batch.requests.filter_map { |request| request.request_metadata.wafer_size }

# There are some requests that don't have the wafer_size attribute
return false if wafer_size_list.size != batch.requests.size

(wafer_size_list.uniq.size == 1)
end
end
45 changes: 45 additions & 0 deletions app/models/ultima_ug200_sequencing_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

# Request class specific to the Ultima UG200 sequencing platform.
# Includes wafer size and OT recipe.
class UltimaUG200SequencingRequest < SequencingRequest
include Api::Messages::UseqWaferIo::LaneExtensions

FREE = 'Free'
FLEX = 'Flex'
OT_RECIPE_OPTIONS = [FREE, FLEX].freeze

has_metadata as: Request do
# Defining the sequencing request metadata here again, as 'has_metadata'
# does not automatically append these custom attributes to the request.
#
# The has_metadata call dynamically defines an inner Metadata class and
# takes the attributes from the block and adds them to the Metadata class.
# There is an assumption that the inner Metadata class is available in a
# sequencing request class defintion. Calling has_metadata again does not
# inherit the attributes given in the block supplied in the superclass.
# They need to be supplied again for this class for a proper inner Metadata
# class definition. In a future refactoring these attributes can be moved a
# class attribute and subclasses can merge its own attibutes to that. A
# common method can set up the inner Metadata class in the subclasses.
custom_attribute(:fragment_size_required_from, integer: true, minimum: 1)
custom_attribute(:fragment_size_required_to, integer: true, minimum: 1)

# TODO: the defaults set here do NOT work on the option lists in the bulk submission screen,
# but do work on the request additional sequencing screen for some reason.
custom_attribute(:ot_recipe, default: FREE, in: OT_RECIPE_OPTIONS, required: true)
enum :ot_recipe, { Free: 0, Flex: 1 }
custom_attribute(:wafer_size, default: '10TB', validator: true, required: true, selection: true)
end

# Delegate to request_metadata so the attributes are visible to the validator in the RSpec tests.
# This delegation has no real effect outside of the tests.
delegate :wafer_size, :ot_recipe, to: :request_metadata

# Generates unique wafer ID, concatenation of batch_for_opentrons,
# id_pool_lims, and request_order.
# @return [String] unique wafer ID for LIMS
def id_wafer_lims
"#{batch.id}_#{source_labware.human_barcode}_#{position}"
end
end
31 changes: 31 additions & 0 deletions app/validators/ultima_ug200_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true
class UltimaUG200Validator < UltimaValidator
WAFER_SIZE_CONSISTENT_MSG = 'Wafer size must be the same for both requests.'
OT_RECIPE_CONSISTENT_MSG = 'OT Recipe must be the same for both requests.'

# Used in _pipeline_limit.html to display custom validation warnings
def self.validation_info
'Wafer Size and OT Recipe must be the same for both requests.'
end

# Validates that a batch contains the two requests.
def validate(record)
validate_exactly_two_requests(record)
requests_have_same_ot_recipe(record)
requests_have_same_wafer_size(record)
end

private

def requests_have_same_wafer_size(record)
return if record.pipeline.wafer_size_consistent_for_batch?(record)

record.errors.add(:base, WAFER_SIZE_CONSISTENT_MSG)
end

def requests_have_same_ot_recipe(record)
return if record.pipeline.ot_recipe_consistent_for_batch?(record)

record.errors.add(:base, OT_RECIPE_CONSISTENT_MSG)
end
end
1 change: 1 addition & 0 deletions app/views/bulk_submissions/_guidance.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ used to split a submission up into orders, and as a result must have the same re
<dt>% PhiX requested</dt><dd>Required percentage of PhiX needed.</dd>
<dt>Low Diversity</dt><dd>Low Diversity value being "Yes" or "No"</dd>
<dt>OT Recipe</dt><dd>OT (OpenTron liquid handler) Recipe value being "Free" or "Flex"</dd>
<dt>Wafer Size</dt><dd>Wafer size value being "5TB", "10TB" or "20TB"</dd>
</dl>
19 changes: 19 additions & 0 deletions config/bulk_submission_excel/columns.yml
Original file line number Diff line number Diff line change
Expand Up @@ -367,3 +367,22 @@ ot_recipe:
range_name: :ot_recipe
conditional_formattings:
empty_cell:
wafer_size:
heading: "Wafer Size"
unlocked: true
attribute: :wafer_size
validation:
options:
type: :list
formula1: "$A$1:$A$2"
allowBlank: false
showInputMessage: true
showErrorMessage: true
errorStyle: :stop
errorTitle: "Wafer Size"
error: "You must enter a value from the list provided."
promptTitle: "Wafer Size"
prompt: "Select a value type from the approved list"
range_name: :wafer_size
conditional_formattings:
empty_cell:
5 changes: 5 additions & 0 deletions config/bulk_submission_excel/ranges.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ ot_recipe:
options:
- "Free"
- "Flex"
wafer_size:
options:
- "5TB"
- "10TB"
- "20TB"
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
"OTR carrier Lot #":
name: "OTR carrier Lot #"
task: Opentrons
workflow: Ultima UG200
kind: Text
required: false
sorter: 0
OTR carrier expiry:
name: OTR carrier expiry
task: Opentrons
workflow: Ultima UG200
kind: Date
required: false
sorter: 1
"Reaction Mix 7 Lot #":
name: "Reaction Mix 7 Lot #"
task: Opentrons
workflow: Ultima UG200
kind: Text
required: false
sorter: 2
Reaction Mix 7 expiry:
name: Reaction Mix 7 expiry
task: Opentrons
workflow: Ultima UG200
kind: Date
required: false
sorter: 3
"NFW Lot #":
name: "NFW Lot #"
task: Opentrons
workflow: Ultima UG200
kind: Text
required: false
sorter: 4
NFW expiry:
name: NFW expiry
task: Opentrons
workflow: Ultima UG200
kind: Date
required: false
sorter: 5
"Oil Lot #":
name: "Oil Lot #"
task: Opentrons
workflow: Ultima UG200
kind: Text
required: false
sorter: 6
Oil expiry:
name: Oil expiry
task: Opentrons
workflow: Ultima UG200
kind: Date
required: false
sorter: 7
Pipette carousel:
name: Pipette carousel
task: Opentrons
workflow: Ultima UG200
kind: Text
required: false
sorter: 8
Opentrons Inst. Name:
name: Opentrons Inst. Name
task: Opentrons
workflow: Ultima UG200
kind: Text
required: true
sorter: 9
Assign Control Bead Tube:
name: Assign Control Bead Tube
task: Amp
workflow: Ultima UG200
kind: Text
required: false
sorter: 0
UG AMP Inst. Name:
name: UG AMP Inst. Name
task: Amp
workflow: Ultima UG200
kind: Text
required: true
sorter: 1
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
FragmentSizeRequiredFromInformationTypeForUltimaUG200:
pipeline_name: Ultima UG200
request_information_type_key: fragment_size_required_from

FragmentSizeRequiredToInformationTypeForUltimaUG200:
pipeline_name: Ultima UG200
request_information_type_key: fragment_size_required_to

WaferSizeInformationTypeForUltimaUG200:
pipeline_name: Ultima UG200
request_information_type_key: wafer_size

OTRecipeInformationTypeForUltima:
pipeline_name: Ultima
request_information_type_key: ot_recipe
17 changes: 17 additions & 0 deletions config/default_records/pipelines/004_ultima_ug200_pipelines.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
Ultima UG200:
name: Ultima UG200 Sequencing
sti_type: UltimaUG200SequencingPipeline
validator_class_name: UltimaUG200Validator
sorter: 10
max_size: 2
summary: 1
externally_managed: 0
group_name: Sequencing
control_request_type_id: 0
min_size: 1
request_type_keys:
- ultima_ug200_sequencing
workflow:
name: Ultima UG200
item_limit: 2
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
wafer_size:
name: Wafer size
key: wafer_size
label: Wafer size
width: 5
hide_in_inbox: 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
WaferSizeRequestedUltimaUG200Sequencing:
request_type_key: ultima_ug200_sequencing
request_option: wafer_size
valid_options:
- 5TB
- 10TB
- 20TB
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Request types for Ultima UG200 sequencing platform.
---
ultima_ug200_sequencing:
name: Ultima UG200 sequencing
asset_type: LibraryTube
order: 2
initial_state: pending
billable: true
# Using same product line name as Ultima UG100
product_line_name: Ultima
request_class_name: UltimaUG200SequencingRequest
request_purpose: standard
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This submission template is associated with the Ultima PCR Free Library preparation pipeline
# and the Ultima UG200 sequencing platform.
---
Limber-Htp - Ultima PCR Free - Ultima UG200 sequencing:
submission_class_name: "LinearSubmission"
related_records:
request_type_keys: ["limber_ultima_htp_pcr_free", "limber_multiplexing_ultima", "ultima_ug200_sequencing"]
order_role: PCR Free
product_line_name: Ultima
product_catalogue_name: GenericNoPCR
Limber-Htp - Ultima PCR Free - Ultima UG200 sequencing Automated:
submission_class_name: "LinearSubmission"
related_records:
request_type_keys: ["ultima_ug200_sequencing"]
order_role: PCR Free
product_line_name: Ultima
product_catalogue_name: GenericNoPCR
13 changes: 13 additions & 0 deletions config/default_records/tasks/005_ultima_ug200_tasks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
Opentrons:
name: Opentrons
workflow: Ultima UG200
sorted: 0
lab_activity: true
sti_type: SetDescriptorsTask
Amp:
name: Amp
workflow: Ultima UG200
sorted: 1
lab_activity: true
sti_type: SetDescriptorsTask
1 change: 1 addition & 0 deletions config/initializers/inflections.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
inflect.acronym 'ENA' # European Nucleotide Archive
inflect.acronym 'HTTP' # HyperText Transfer Protocol
inflect.acronym 'EBI' # European Bioinformatics Institute
inflect.acronym 'UG200' # Ultima UG200
end

# These inflection rules are supported but not enabled by default:
Expand Down
6 changes: 6 additions & 0 deletions config/locales/metadata/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ en:
ot_recipe:
label: OT Recipe

wafer_size:
label: Wafer Size

library_creation_request:
<<: *REQUEST
sequencing_request:
Expand Down Expand Up @@ -107,6 +110,9 @@ en:
ultima_sequencing_request:
<<: *REQUEST

ultima_ug200_sequencing_request:
<<: *REQUEST

pulldown:
requests:
wgs_library_request:
Expand Down
10 changes: 10 additions & 0 deletions db/migrate/20260324112536_add_wafer_size_to_request_metadata.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

# This migration adds a wafer_size column to the request_metadata table, which is used to store
# the wafer size for Ultima sequencing requests. This is stored as a string, with possible
# values of 5TB, 10TB, and 20TB at time of writing.
class AddWaferSizeToRequestMetadata < ActiveRecord::Migration[7.1]
def change
add_column :request_metadata, :wafer_size, :string
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.2].define(version: 2026_03_17_142326) do
ActiveRecord::Schema[7.2].define(version: 2026_03_24_112536) do
create_table "accession_sample_statuses", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
t.integer "sample_id", null: false
t.string "status", null: false
Expand Down Expand Up @@ -1191,6 +1191,7 @@
t.boolean "low_diversity"
t.integer "percent_phix_requested"
t.integer "ot_recipe"
t.string "wafer_size"
t.index ["request_id"], name: "index_request_metadata_on_request_id"
end

Expand Down
Loading
Loading