Class: Well

Inherits:
Receptacle show all
Includes:
Api::Messages::FluidigmPlateIO::WellExtensions, Api::Messages::QcResultIO::WellExtensions, Api::WellIO::Extensions, Cherrypick::VolumeByMicroLitre, Cherrypick::VolumeByNanoGrams, Cherrypick::VolumeByNanoGramsPerMicroLitre, ModelExtensions::Well, StudyReport::WellDetails, Tag::Associations
Defined in:
app/models/well.rb

Overview

A Well is a Receptacle on a Plate, it can contain one or more aliquots. A plate may have multiple wells, with the two most common sizes being 12*8 (96) and 24*26 (384). The wells are differentiated via their Map which corresponds to a row and column. Most well locations are identified by a letter-number combination, eg. A1, H12.

Defined Under Namespace

Modules: AttributeUpdater Classes: Link

Constant Summary

Constants inherited from Receptacle

Receptacle::QC_STATE_ALIASES

Constants included from Transfer::State

Transfer::State::ALL_STATES

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Tag::Associations

#untag!

Methods included from StudyReport::WellDetails

included, #qc_report

Methods included from Cherrypick::VolumeByMicroLitre

#volume_to_cherrypick_by_micro_litre

Methods included from Cherrypick::VolumeByNanoGramsPerMicroLitre

#volume_to_cherrypick_by_nano_grams_per_micro_litre

Methods included from Cherrypick::VolumeByNanoGrams

#volume_to_cherrypick_by_nano_grams

Methods included from Api::WellIO::Extensions

included

Methods inherited from Receptacle

#any_barcode_matching?, #api_asset_type, #assign_tag2, #attach_tag, #been_through_qc?, #compatible_qc_state, #created_with_request_options, #friendly_name, #labware_comment_count, #legacy_asset_type, #library_information, #library_types, #primary_aliquot_if_unique, #related_studies, #role, #set_as_library, #set_qc_state, #tag_range, #total_comment_count, #update_aliquot_quality

Methods included from StudyReport::AssetDetails

#qc_report

Methods included from Aliquot::Remover

#on_downstream_aliquots, #process_aliquots, #remove_downstream_aliquots, #remove_matching_aliquots

Methods included from Transfer::State

#default_state, #state, #state_from, state_helper

Methods included from Commentable

#after_comment_addition

Methods included from Uuid::Uuidable

included, #unsaved_uuid!, #uuid

Methods inherited from Asset

#add_parent, #ancestor_of_purpose, #assign_relationships, #barcode_number, #compatible_purposes, #contained_samples, #generate_barcode, #get_qc_result_value_for, #has_stock_asset?, #label, #label=, #original_stock_plates, #prefix, #printable?, #printable_target, #register_stock!, #request_types, #spiked_in_buffer, #summary_hash, #type

Methods included from EventfulRecord

#has_many_events, #has_many_lab_events, #has_one_event_with_family

Methods included from Event::PlateEvents

#event_date, #fluidigm_stamp_date, #gel_qc_date, #pico_date, #qc_started_date, #sequenom_stamp_date

Methods inherited from ApplicationRecord

convert_labware_to_receptacle_for, find_by_id_or_name, find_by_id_or_name!

Methods included from Squishify

extended

Methods included from Warren::BroadcastMessages

#broadcast, included, #queue_associated_for_broadcast, #queue_for_broadcast, #warren

Class Method Details

.delegate_to_well_attribute(attribute, options = {}) ⇒ Object


164
165
166
167
168
169
170
# File 'app/models/well.rb', line 164

def delegate_to_well_attribute(attribute, options = {})
  class_eval <<-END_OF_METHOD_DEFINITION
    def get_#{attribute}
      self.well_attribute.#{attribute} || #{options[:default].inspect}
    end
  END_OF_METHOD_DEFINITION
end

.hash_stock_with_targets(wells, purpose_names) ⇒ Object


180
181
182
183
184
185
186
187
188
# File 'app/models/well.rb', line 180

def hash_stock_with_targets(wells, purpose_names)
  return {} unless purpose_names

  purposes = PlatePurpose.where(name: purpose_names)
  # We might need to be careful about this line in future.
  target_wells = Well.target_wells_for(wells).on_plate_purpose(purposes).preload(:well_attribute).with_concentration

  target_wells.group_by(&:stock_well_id)
end

.writer_for_well_attribute_as_float(attribute) ⇒ Object


172
173
174
175
176
177
178
# File 'app/models/well.rb', line 172

def writer_for_well_attribute_as_float(attribute)
  class_eval <<-END_OF_METHOD_DEFINITION
    def set_#{attribute}(value)
      self.well_attribute.update!(:#{attribute} => value.to_f)
    end
  END_OF_METHOD_DEFINITION
end

Instance Method Details

#absolute_position_nameObject

Returns the name of the position (eg. A1) of the well


306
307
308
# File 'app/models/well.rb', line 306

def absolute_position_name
  map_description
end

#asset_type_for_request_typesObject


343
344
345
# File 'app/models/well.rb', line 343

def asset_type_for_request_types
  self.class
end

#buffer_required?Boolean

Returns:

  • (Boolean)

317
318
319
# File 'app/models/well.rb', line 317

def buffer_required?
  get_buffer_volume > 0.0
end

#detailsObject


328
329
330
331
332
# File 'app/models/well.rb', line 328

def details
  return 'Not yet picked' if plate.nil?

  plate.purpose.try(:name) || 'Unknown plate purpose'
end

#display_nameObject


321
322
323
324
325
326
# File 'app/models/well.rb', line 321

def display_name
  source = association_cached?(:plate) ? plate : labware
  plate_name = source.present? ? source.human_barcode : '(not on a plate)'
  plate_name ||= source.display_name # In the even the plate is barcodeless (ie strip tubes) use its name
  "#{plate_name}:#{map_description}"
end

#external_identifierObject


225
226
227
# File 'app/models/well.rb', line 225

def external_identifier
  display_name
end

#generate_name(_) ⇒ Object


221
222
223
# File 'app/models/well.rb', line 221

def generate_name(_)
  # Do nothing
end

#get_sequenom_passObject

The sequenom pass value is either the string 'Unknown' or it is the combination of gender marker values.


297
298
299
300
# File 'app/models/well.rb', line 297

def get_sequenom_pass
  markers = well_attribute.gender_markers
  markers.is_a?(Array) ? markers.join : markers
end

#latest_stock_metrics(product) ⇒ Object


334
335
336
337
338
339
340
341
# File 'app/models/well.rb', line 334

def latest_stock_metrics(product)
  # If we don't have any stock wells, use ourself. If it is a stock well, we'll find our
  # qc metric. If its not a stock well, then a metric won't be present anyway
  metric_wells = stock_wells.empty? ? [self] : stock_wells
  metric_wells.map do |stock_well|
    stock_well.qc_metrics.for_product(product).most_recent_first.first
  end.compact.uniq
end

#library_nameObject


355
356
357
# File 'app/models/well.rb', line 355

def library_name
  nil
end

#nameObject


351
352
353
# File 'app/models/well.rb', line 351

def name
  nil
end

#outer_request(submission_id) ⇒ Object


199
200
201
# File 'app/models/well.rb', line 199

def outer_request(submission_id)
  outer_requests.order(id: :desc).find_by(submission_id: submission_id)
end

#qc_dataObject


310
311
312
313
314
315
# File 'app/models/well.rb', line 310

def qc_data
  { pico: get_pico_pass,
    gel: get_gel_pass,
    sequenom: get_sequenom_pass,
    concentration: get_concentration }
end

#qc_result_for(key) ⇒ Object


207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'app/models/well.rb', line 207

def qc_result_for(key)
  result =  if key == 'quantity_in_nano_grams'
              well_attribute.quantity_in_nano_grams
            else
              results = qc_results_by_key[key]
              results.first.value if results.present?
            end

  return if result.nil?
  return result.to_f.round(3) if result.to_s.include?('.')

  result.to_i
end

#qc_results_by_keyObject


203
204
205
# File 'app/models/well.rb', line 203

def qc_results_by_key
  @qc_results_by_key ||= qc_results.by_key
end

#stock_wells_for_downstream_wellsObject


191
192
193
# File 'app/models/well.rb', line 191

def stock_wells_for_downstream_wells
  labware&.stock_plate? ? [self] : stock_wells
end

#subject_typeObject


195
196
197
# File 'app/models/well.rb', line 195

def subject_type
  'well'
end

#update_from_qc(qc_result) ⇒ Object


347
348
349
# File 'app/models/well.rb', line 347

def update_from_qc(qc_result)
  Well::AttributeUpdater.update(self, qc_result)
end

#update_gender_markers!(gender_markers, resource) ⇒ Object


274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'app/models/well.rb', line 274

def update_gender_markers!(gender_markers, resource)
  if well_attribute.gender_markers == gender_markers
    gender_marker_event = events.where(family: 'update_gender_markers').order('id desc').first
    if gender_marker_event.blank?
      events.update_gender_markers!(resource)
    elsif resource == 'SNP' && gender_marker_event.content != resource
      events.update_gender_markers!(resource)
    end
  else
    events.update_gender_markers!(resource)
  end

  well_attribute.update!(gender_markers: gender_markers)
end

#update_sequenom_count!(sequenom_count, resource) ⇒ Object


289
290
291
292
293
294
# File 'app/models/well.rb', line 289

def update_sequenom_count!(sequenom_count, resource)
  unless well_attribute.sequenom_count == sequenom_count
    events.update_sequenom_count!(resource)
  end
  well_attribute.update!(sequenom_count: sequenom_count)
end

#update_volume(volume_change) ⇒ Object


252
253
254
255
# File 'app/models/well.rb', line 252

def update_volume(volume_change)
  value_current_volume = get_current_volume.nil? ? 0 : get_current_volume
  set_current_volume([0, value_current_volume + volume_change].max)
end

#well_attributeObject


229
230
231
# File 'app/models/well.rb', line 229

def well_attribute
  super || build_well_attribute
end