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?, #included_for_do_task, #included_for_render_task

Methods inherited from ApplicationRecord

alias_association, 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



175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'app/models/cherrypick_task.rb', line 175

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

Returns:

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

    ] Array indicating this action can’t be linked



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

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

#do_task(workflow_controller, params, _user) ⇒ Object



166
167
168
169
170
171
# File 'app/models/cherrypick_task.rb', line 166

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(params) ⇒ 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:



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

def new_control_locator(params)
  CherrypickTask::ControlLocator.new(
    batch_id: params[:batch_id],
    total_wells: params[:total_wells],
    num_control_wells: params[:num_control_wells],
    wells_to_leave_free: params[:wells_to_leave_free] || DEFAULT_WELLS_TO_LEAVE_FREE,
    control_source_plate: params[:control_source_plate],
    template: params[:template]
  )
end

#partialObject



157
158
159
# File 'app/models/cherrypick_task.rb', line 157

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



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

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, template) 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



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

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, template) 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



161
162
163
164
# File 'app/models/cherrypick_task.rb', line 161

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