Class: CherrypickTask

Inherits:
Task show all
Defined in:
app/models/cherrypick_task.rb

Overview

A Task used in cherrypick pipelines Performs the main bulk of cherrypick action. Although a lot of the options on this page are presented as part of the previous step, and get persisted on this page as hidden fields. This page shows a drag-drop plate layout which lets users set-up the way the plate will be picked. The target asset of each request will have its plate and map set accordingly. Well attributes are set to track picking volumes

Defined Under Namespace

Classes: ControlLocator, PickTarget

Constant Summary collapse

EMPTY_WELL =

rubocop:todo Metrics/ClassLength

[0, 'Empty', ''].freeze
TEMPLATE_EMPTY_WELL =
[0, '---', ''].freeze
DEFAULT_WELLS_TO_LEAVE_FREE =
Rails.application.config.plate_default_control_wells_to_leave_free

Instance Method Summary collapse

Methods inherited from Task

#can_process?, #find_batch, #find_batch_requests, #included_for_do_task, #included_for_render_task

Methods inherited from ApplicationRecord

convert_labware_to_receptacle_for, find_by_id_or_name, find_by_id_or_name!

Methods included from Squishify

extended

Instance Method Details

#build_plate_wells_from_requests(requests, workflow_controller = nil) ⇒ Object

returns array [ [ request id, source plate barcode, source coordinate ] ] rubocop:todo Metrics/MethodLength


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'app/models/cherrypick_task.rb', line 159

def build_plate_wells_from_requests(requests, workflow_controller = nil) # rubocop:todo Metrics/AbcSize
  loaded_requests = Request.where(requests: { id: requests }).includes(asset: [{ plate: :barcodes }, :map])

  source_plate_barcodes = loaded_requests.map { |request| request.asset.plate.human_barcode }.uniq

  begin
    # retrieve Labwhere locations for all source_plate_barcodes, in form { 'DN1234' => 'Sanger / Room 1 - Shelf 2' }
    labwhere_response = Labware.labwhere_locations(source_plate_barcodes)
    barcodes_sorted_by_location = labwhere_response.sort_by { |_k, v| v }.to_h.keys
  rescue LabWhereClient::LabwhereException => e
    message = "Labware locations are unavailable (#{e.message}). Wells are sorted by plate creation order."
    workflow_controller.send(:flash)[:error] = message unless workflow_controller.nil?

    barcodes_sorted_by_location = source_plate_barcodes
  end

  # sort by location in lab, followed by plate id, followed by well coordinate on plate
  sorted_requests =
    loaded_requests.sort_by do |request|
      [
        barcodes_sorted_by_location.index(request.asset.plate.human_barcode),
        request.asset.plate.id,
        request.asset.map.column_order
      ]
    end

  sorted_requests.map { |request| [request.id, request.asset.plate.human_barcode, request.asset.map_description] }
end

Cherrypick tasks are directly coupled to the previous task, due to the awkward way in which the WorkflowsController operates. See issues#2831 for aims to help improve some of this

Parameters:

  • batch (Batch)

    The batch on which the action will be performed

Returns:

  • (false, 'Can only be accessed via the previous step')

    ] Array indicating this action can't be linked


41
42
43
# File 'app/models/cherrypick_task.rb', line 41

def can_link_directly?(_batch)
  [false, 'Can only be accessed via the previous step']
end

#do_task(workflow_controller, params, _user) ⇒ Object


150
151
152
153
154
155
# File 'app/models/cherrypick_task.rb', line 150

def do_task(workflow_controller, params, _user)
  workflow_controller.do_cherrypick_task(self, params)
rescue Cherrypick::Error => e
  workflow_controller.send(:flash)[:error] = e.message
  [false, e.message]
end

#new_control_locator(batch_id, total_wells, num_control_wells, wells_to_leave_free: DEFAULT_WELLS_TO_LEAVE_FREE) ⇒ CherrypickTask::ControlLocator

Returns a ControlLocator which can generate control locations for plates in a batch. It responds to #control_positions which takes a plate number as an argument

Returns:


24
25
26
27
28
29
30
31
# File 'app/models/cherrypick_task.rb', line 24

def new_control_locator(batch_id, total_wells, num_control_wells, wells_to_leave_free: DEFAULT_WELLS_TO_LEAVE_FREE)
  CherrypickTask::ControlLocator.new(
    batch_id: batch_id,
    total_wells: total_wells,
    num_control_wells: num_control_wells,
    wells_to_leave_free: wells_to_leave_free
  )
end

#partialObject


141
142
143
# File 'app/models/cherrypick_task.rb', line 141

def partial
  'cherrypick_batches'
end

#pick_new_plate(requests, template, robot, plate_purpose, control_source_plate = nil, workflow_controller = nil) ⇒ Object

rubocop:todo Metrics/ParameterLists


46
47
48
49
50
51
# File 'app/models/cherrypick_task.rb', line 46

def pick_new_plate(requests, template, robot, plate_purpose, control_source_plate = nil, workflow_controller = nil)
  target_type = PickTarget.for(plate_purpose)
  perform_pick(requests, robot, control_source_plate, workflow_controller) do
    target_type.new(template, plate_purpose.try(:asset_shape))
  end
end

#pick_onto_partial_plate(requests, template, robot, partial_plate, control_source_plate = nil, workflow_controller = nil) ⇒ Object


53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'app/models/cherrypick_task.rb', line 53

def pick_onto_partial_plate(
  requests,
  template,
  robot,
  partial_plate,
  control_source_plate = nil,
  workflow_controller = nil
)
  purpose = partial_plate.plate_purpose
  target_type = PickTarget.for(purpose)

  perform_pick(requests, robot, control_source_plate, workflow_controller) do
    target_type
      .new(template, purpose.try(:asset_shape), partial_plate)
      .tap do
        partial_plate = nil # Ensure that subsequent calls have no partial plate
      end
  end
end

#render_task(workflow_controller, params, _user) ⇒ Object


145
146
147
148
# File 'app/models/cherrypick_task.rb', line 145

def render_task(workflow_controller, params, _user)
  super
  workflow_controller.render_cherrypick_task(self, params)
end