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

#api_asset_type, #assign_tag2, #attach_tag, #been_through_qc?, #compatible_qc_state, #created_with_request_options, #legacy_asset_type, #library_information, #library_types, #primary_aliquot_if_unique, #related_studies, #set_as_library, #set_qc_state, #tag_range, #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

Class Method Details

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


178
179
180
181
182
183
184
# File 'app/models/well.rb', line 178

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


194
195
196
197
198
199
200
201
202
# File 'app/models/well.rb', line 194

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


186
187
188
189
190
191
192
# File 'app/models/well.rb', line 186

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

#asset_type_for_request_typesObject


359
360
361
# File 'app/models/well.rb', line 359

def asset_type_for_request_types
  self.class
end

#buffer_required?Boolean


334
335
336
# File 'app/models/well.rb', line 334

def buffer_required?
  get_buffer_volume > 0.0
end

#detailsObject


344
345
346
347
348
# File 'app/models/well.rb', line 344

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

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

#display_nameObject


338
339
340
341
342
# File 'app/models/well.rb', line 338

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

#external_identifierObject


247
248
249
# File 'app/models/well.rb', line 247

def external_identifier
  display_name
end

#generate_name(_) ⇒ Object


243
244
245
# File 'app/models/well.rb', line 243

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.


319
320
321
322
# File 'app/models/well.rb', line 319

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

#latest_stock_metrics(product) ⇒ Object


350
351
352
353
354
355
356
357
# File 'app/models/well.rb', line 350

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

#outer_request(submission_id) ⇒ Object


213
214
215
# File 'app/models/well.rb', line 213

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

#qc_dataObject


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

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

#qc_result_for(key) ⇒ Object


229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'app/models/well.rb', line 229

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


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

def qc_results_by_key
  @qc_results_by_key ||= qc_results.by_key
end

#stock_wells_for_downstream_wellsObject


205
206
207
# File 'app/models/well.rb', line 205

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

#subject_typeObject


209
210
211
# File 'app/models/well.rb', line 209

def subject_type
  'well'
end

#update_from_qc(qc_result) ⇒ Object


363
364
365
# File 'app/models/well.rb', line 363

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

#update_gender_markers!(gender_markers, resource) ⇒ Object


296
297
298
299
300
301
302
303
304
305
306
307
308
309
# File 'app/models/well.rb', line 296

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


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

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


274
275
276
277
# File 'app/models/well.rb', line 274

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


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

def well_attribute
  super || build_well_attribute
end