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-829 pbmc plate to tube rack bed verification #1415

Merged
merged 56 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
7f5b6b7
Added bed numbers to config
yoldas Oct 12, 2023
6fb48d9
Fixed syntax in config
yoldas Oct 12, 2023
c739e89
Fixed syntax in config 2
yoldas Oct 12, 2023
220fcf2
Removed the relationships section from plate to tube racks robot config
yoldas Oct 16, 2023
5ec11f9
Added relationships back as it allows specifying multiple children fr…
yoldas Oct 18, 2023
6c56bb3
Fixed typo in robot config
yoldas Oct 20, 2023
79faa29
Adding tube rack wrapper to reuse existing validations
yoldas Oct 20, 2023
e10f3ba
Fixed error message for created_with_robot metadata
yoldas Oct 22, 2023
5e0561b
Changes for bed verification with tube racks so far
yoldas Oct 23, 2023
918d0f2
robot controller start action created_with_robot metadata
yoldas Oct 26, 2023
775799d
Robot finds labware for beds
yoldas Oct 26, 2023
cdf9d09
Initialise labware store in robot and find labware for beds
yoldas Oct 26, 2023
d96124d
Added parent field to tube rack wrapper
yoldas Oct 26, 2023
b9e55a1
Added code comments to plate to tube racks robot
yoldas Oct 26, 2023
83b0ca2
Removed parents attr_accessor from bed
yoldas Oct 26, 2023
ddd94e4
Updated bed code comments
yoldas Oct 26, 2023
3d7b172
Comment about using machine barcode for setting robot_barcode in meta…
yoldas Oct 27, 2023
1c5bdc6
Switched to human barcode for indexing
yoldas Oct 27, 2023
fa6e2cb
Delegate tube-rack wrapper attributes to the last tube
yoldas Oct 27, 2023
d985cdb
Added test for a valid scanned layout
yoldas Oct 27, 2023
6a994a7
Reduced method sizes for updating labware metadata
yoldas Oct 28, 2023
0930176
Disabled valid_relationships rubocop metrics for now
yoldas Oct 28, 2023
2581134
Updated tube rack wrapper to handle duplicate tubes
yoldas Oct 28, 2023
ffdcdd5
Renamed wrapper methods
yoldas Oct 29, 2023
ad67012
Added initial test for contingency-only bed verification
yoldas Oct 29, 2023
5fef285
Merge branch 'develop' into dpl-829-pbmc-plate-tube-rack-bed-verifica…
yoldas Oct 29, 2023
c68f0bb
Prepare robot for contingency-only verification
yoldas Oct 29, 2023
0ae1fbe
Added test for a contingency-only valid scanned layout
yoldas Oct 29, 2023
4b7bd86
Added test for a plate on an unknown bed
yoldas Oct 29, 2023
53f8f8f
Added test for a child tube-rack missing
yoldas Oct 29, 2023
1022ba7
Fixed incorrect tube-rack barcode in error message
yoldas Oct 29, 2023
d3527e9
Added test for all child tube-racks missing
yoldas Oct 29, 2023
07d948c
Added test for a tube-rack on an unknown bed
yoldas Oct 29, 2023
ac3cfa4
Added state transition for all tubes of the tube-rack on the bed
yoldas Oct 29, 2023
8e41684
Subclass SplittingRobot for validating relationships
yoldas Oct 29, 2023
140ebe6
Added test for state changing for all tubes of tube-racks
yoldas Oct 29, 2023
da6942e
Added well_order to get wells by coordinate
yoldas Oct 30, 2023
9a8f1ce
Updated param description in code comments
yoldas Oct 30, 2023
879e774
Fixed pushing the tubes supplied as an argument
yoldas Oct 30, 2023
6e6c8ac
Updated code comments of robots controller
yoldas Oct 30, 2023
ae2a08a
Updated more code comments of robots controller
yoldas Oct 30, 2023
7b80d7c
Removed type from robot config relationships
yoldas Oct 30, 2023
be3e7bc
Update app/models/robots/tube_rack_wrapper.rb
yoldas Oct 30, 2023
e836394
Update app/models/robots/plate_to_tube_racks_robot.rb
yoldas Oct 30, 2023
cc5deb6
Update app/models/robots/tube_rack_wrapper.rb
yoldas Oct 30, 2023
1a6ba66
Update app/models/robots/tube_rack_wrapper.rb
yoldas Oct 30, 2023
28f7c67
Update app/models/robots/tube_rack_wrapper.rb
yoldas Oct 30, 2023
5e83c03
Removed typo from code comment
yoldas Oct 30, 2023
f7a67f2
Prettier
yoldas Oct 30, 2023
ba21795
Renamed find_or_create_tube_rack to find_or_create_tube_rack_wrapper
yoldas Oct 30, 2023
bc03b3b
Updated comments about @tube_positions
yoldas Oct 31, 2023
62636bb
Updated transfer test to check the state change on all tubes
yoldas Nov 2, 2023
aa5787c
Fixed the order of tag data for Yard @param tags
yoldas Nov 3, 2023
b6f2e12
Merge branch 'develop' into dpl-829-pbmc-plate-tube-rack-bed-verifica…
yoldas Nov 6, 2023
4b27f3a
Merge branch 'develop' into dpl-829-pbmc-plate-tube-rack-bed-verifica…
yoldas Nov 6, 2023
1e5941a
Merge branch 'develop' into dpl-829-pbmc-plate-tube-rack-bed-verifica…
yoldas Nov 9, 2023
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
39 changes: 23 additions & 16 deletions app/controllers/robots_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,7 @@ def show

def start # rubocop:todo Metrics/AbcSize
@robot.perform_transfer(stripped_beds)
if params[:robot_barcode].present?
@robot.beds.each_value do |bed|
next unless bed.transitions? && bed.labware

labware_barcode = bed.labware.barcode.machine
begin
LabwareMetadata
.new(api: api, user: current_user_uuid, barcode: labware_barcode)
.update!(created_with_robot: params[:robot_barcode])
rescue Sequencescape::Api::ResourceNotFound
respond_to do |format|
format.html { redirect_to robot_path(id: @robot.id), notice: "Plate #{plate_barcode} not found." }
end
end
end
end
update_labware_metadata(params[:robot_barcode]) if params[:robot_barcode].present?
respond_to { |format| format.html { redirect_to search_path, notice: "Robot #{@robot.name} has been started." } }
rescue Robots::Bed::BedError => e
# Our beds complained, nothing has happened.
Expand All @@ -47,6 +32,28 @@ def start # rubocop:todo Metrics/AbcSize
end
end

def update_labware_metadata(robot_barcode)
yoldas marked this conversation as resolved.
Show resolved Hide resolved
@robot.beds.each_value do |bed|
next unless bed.transitions? && bed.labware
labware_barcode = bed.labware.barcode.machine
if bed.respond_to?(:labware_created_with_robot)
bed.labware_created_with_robot(robot_barcode)
else
labware_created_with_robot(labware_barcode, robot_barcode)
end
rescue Sequencescape::Api::ResourceNotFound
respond_to do |format|
format.html { redirect_to robot_path(id: @robot.id), notice: "Labware #{labware_barcode} not found." }
end
end
end

def labware_created_with_robot(labware_barcode, robot_barcode)
LabwareMetadata
.new(api: api, user: current_user_uuid, barcode: labware_barcode)
.update!(created_with_robot: robot_barcode)
end

def verify
render(json: @robot.verify(robot_params))
end
Expand Down
28 changes: 28 additions & 0 deletions app/models/robots/bed/plate_to_tube_racks_bed.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# frozen_string_literal: true

module Robots::Bed
# Plate to tube racks robot beds
class PlateToTubeRacksBed < Robots::Bed::Base
# TODO: Do I need this accessor?
attr_accessor :parents

def labware_created_with_robot(robot_barcode)
labware.tubes.each do |tube|
LabwareMetadata
.new(api: api, user: user_uuid, barcode: tube.barcode.machine)
.update!(created_with_robot: robot_barcode)
end
end

def child_labware
return [] if labware.blank?

@child_labware ||= robot.child_labware(labware)
end

def load(barcodes)
@barcodes = Array(barcodes).filter_map(&:strip).uniq
@labware = @barcodes.present? ? robot.find_bed_labware(@barcodes) : []
end
end
end
98 changes: 98 additions & 0 deletions app/models/robots/plate_to_tube_racks_robot.rb
yoldas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# frozen_string_literal: true

module Robots
class PlateToTubeRacksRobot < Robots::Robot
attr_writer :relationships

PLATE_INCLUDES = 'purpose,wells,wells.downstream_tubes,wells.downstream_tubes.custom_metadatum_collection'

def bed_class
Robots::Bed::PlateToTubeRacksBed
end

def perform_transfer(bed_settings)
init_labware_store(bed_settings)
super
end

def verify(params)
init_labware_store(params[:bed_labwares])
super
end

def valid_relationships # rubocop:todo Metrics/AbcSize
yoldas marked this conversation as resolved.
Show resolved Hide resolved
raise StandardError, "Relationships for #{name} are empty" if @relationships.empty?

@relationships.each_with_object({}) do |relationship, validations|
parent_bed = relationship.dig('options', 'parent')
child_beds = relationship.dig('options', 'children')

validations[parent_bed] = beds[parent_bed].child_labware.present?
error(beds[parent_bed], 'should not be empty.') if beds[parent_bed].empty?
error(beds[parent_bed], 'should have children.') if beds[parent_bed].child_labware.empty?

expected_children = beds[parent_bed].child_labware
expected_children.each_with_index do |expected_child, index|
child_bed = child_beds[index]
validations[child_bed] = check_labware_identity([expected_child], child_bed)
end
end
end

def find_bed_labware(barcodes)
barcodes.filter_map { |barcode| labware_store[barcode] }
end

def child_labware(plate)
labware_store.values.select { |labware| labware.respond_to?(:parent) && labware.parent.uuid == plate.uuid }
end

def init_labware_store(bed_labwares)
return if labware_store.present?
stripped_barcodes(bed_labwares).each do |barcode|
plate = find_plate(barcode)
next if plate.blank?
add_plate_to_labware_store(plate)
add_tube_racks_to_labware_store(plate)
end
end

def stripped_barcodes(bed_labwares)
bed_labwares.values.flatten.filter_map(&:strip).uniq
end

def add_plate_to_labware_store(plate)
labware_store[plate.barcode.machine] = plate
end

def add_tube_racks_to_labware_store(plate)
find_tube_racks(plate).each { |rack| labware_store[rack.barcode.machine] = rack }
end

def labware_store
@labware_store ||= {}
end

def find_plate(barcode)
Sequencescape::Api::V2::Plate.find_all({ barcode: barcode }, includes: PLATE_INCLUDES).first
end

def find_tube_racks(plate)
yoldas marked this conversation as resolved.
Show resolved Hide resolved
plate
.wells
.sort_by(&well_order)
.each_with_object([]) do |well, racks|
next if well.downstream_tubes.empty?
well.downstream_tubes.each do |tube|
barcode = tube.custom_metadatum_collection.metadata[:tube_rack_barcode]
rack = racks.detect { |tube_rack| tube_rack.barcode.machine == barcode }
if rack.nil?
labware_barcode = LabwareBarcode.new(human: barcode, machine: barcode)
rack = racks.push(TubeRackWrapper.new(labware_barcode, plate)).last
end
rack.tubes << tube
end
end
end
end
end
18 changes: 18 additions & 0 deletions app/models/robots/tube_rack_wrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true
module Robots
# Tube rack info from tube metadata
class TubeRackWrapper
attr_accessor :barcode, :parent, :tubes
delegate :purpose_name, :purpose, :human_barcode, :state, :uuid, to: :first_tube, allow_nil: true

def initialize(barcode, parent, tubes: [])
@barcode = barcode
@parent = parent
@tubes = tubes
end

def first_tube
@tubes.first
end
end
end
36 changes: 36 additions & 0 deletions config/robots.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3061,4 +3061,40 @@
}
}
)

# LRC Hamilton Star bed verification
# LRC PBMC Bank to LRC Bank Seq and LRC Bank Spare
custom_robot(
'hamilton-lrc-pbmc-bank-to-lrc-bank-seq-and-lrc-bank-spare',
name: 'Hamilton LRC PBMC Bank => LRC Bank Seq and LRC Bank Spare',
beds: {
bed(12).barcode => {
purpose: 'LRC PBMC Bank',
states: ['passed'],
label: 'Bed 12'
},
bed(15).barcode => {
purpose: 'LRC Bank Seq',
states: ['pending'],
label: 'Bed 15',
target_state: 'passed'
},
bed(14).barcode => {
purpose: 'LRC Bank Spare',
states: ['pending'],
label: 'Bed 14',
target_state: 'passed'
}
},
class: 'Robots::PlateToTubeRacksRobot',
relationships: [
{
'type' => 'LRC PBMC Bank to LRC Bank Seq/Spare',
yoldas marked this conversation as resolved.
Show resolved Hide resolved
'options' => {
'parent' => bed(12).barcode,
'children' => [bed(15).barcode, bed(14).barcode]
}
}
]
)
end
Loading