Class: SampleManifest

Inherits:
ApplicationRecord show all
Extended by:
Document::Associations, StateMachine
Includes:
ModelExtensions::SampleManifest, BarcodePrinterBehaviour, CoreBehaviour, Uuid::Uuidable
Defined in:
app/models/sample_manifest.rb

Overview

A SampleManifest is the primary way in which new samples enter Sequencescape. When the manifest is generated Sequencescape registers the labware, and reserves a series of Sanger sample ids for the potential samples. It also generates a SampleManifestExcel spreadsheet which gets sent to the customer.

The labware that gets generate is determined by the #asset_type which switches out the CoreBehaviour#core_behaviour module CoreBehaviour. This is concerned with generating Labware and receptacles, generating any event specific to the asset type, and setting manifest specific properties on Aliquot

All samples in a given manifest will initially belong to a single Study, although it is possible for them to become associated with additional studies over time.

Defined Under Namespace

Modules: Associations, BarcodePrinterBehaviour, CoreBehaviour, LibraryPlateBehaviour, LibraryTubeBehaviour, MultiplexedLibraryBehaviour, PlateBehaviour, SampleTubeBehaviour, SharedTubeBehaviour, StateMachine, TubeRackBehaviour, UnspecifiedBehaviour Classes: Generator, Uploader

Constant Summary collapse

LIMIT_ERROR_LENGTH =

While the maximum length of the column is 65536 we place a shorter restriction to allow for: 1) Subsequent serialization by the delayed job 2) The addition of a 'too many errors' message

50000
INDIVIDUAL_ERROR_LIMIT =

In addition we truncate individual messages, this ensures that we don't inadvertently filter out ALL our errors if the first message is especially long. We don't re-use the figure above as that would prevent any display of subsequent messages, which probably indicate a different issue.

LIMIT_ERROR_LENGTH / 10
SAMPLES_PER_EVENT =

Samples have a similar issue when generating update events This limit sets a very comfortable safety margin.

3000

Constants included from CoreBehaviour

CoreBehaviour::BEHAVIOURS

Constants included from BarcodePrinterBehaviour

BarcodePrinterBehaviour::ASSET_TYPE_TO_PRINTER_TYPE

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Document::Associations

has_uploaded_document

Methods included from StateMachine

extended

Methods included from CoreBehaviour

#core_behaviour, included

Methods included from BarcodePrinterBehaviour

#applicable_barcode_printers

Methods included from Uuid::Uuidable

included, #unsaved_uuid!, #uuid

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

Instance Attribute Details

#only_first_labelObject

Returns the value of attribute only_first_label


50
51
52
# File 'app/models/sample_manifest.rb', line 50

def only_first_label
  @only_first_label
end

#overrideObject

Returns the value of attribute override


50
51
52
# File 'app/models/sample_manifest.rb', line 50

def override
  @override
end

Instance Method Details

#barcode_printerObject

Needed for the UI to work!


58
# File 'app/models/sample_manifest.rb', line 58

def barcode_printer; end

#create_sample(sanger_sample_id) ⇒ Object


154
155
156
157
158
# File 'app/models/sample_manifest.rb', line 154

def create_sample(sanger_sample_id)
  Sample.create!(name: sanger_sample_id, sanger_sample_id: sanger_sample_id, sample_manifest: self).tap do |sample|
    sample.events.created_using_sample_manifest!(user)
  end
end

#create_sample_and_aliquot(sanger_sample_id, asset) ⇒ Object


150
151
152
# File 'app/models/sample_manifest.rb', line 150

def create_sample_and_aliquot(sanger_sample_id, asset)
  core_behaviour.generate_sample_and_aliquot(sanger_sample_id, asset)
end

#created_broadcast_eventObject


160
161
162
# File 'app/models/sample_manifest.rb', line 160

def created_broadcast_event
  BroadcastEvent::SampleManifestCreated.create!(seed: self, user: user)
end

#default_asset_typeObject


116
117
118
# File 'app/models/sample_manifest.rb', line 116

def default_asset_type
  self.asset_type = 'plate' if asset_type.blank?
end

#default_filenameObject


124
125
126
# File 'app/models/sample_manifest.rb', line 124

def default_filename
  "#{study_id}stdy_manifest_#{id}_#{created_at.to_formatted_s(:dmy)}"
end

#find_or_create_qc_assay!Object

rubocop:disable Naming/MemoizedInstanceVariableName


207
208
209
# File 'app/models/sample_manifest.rb', line 207

def find_or_create_qc_assay!
  @qc_assay ||= QcAssay.find_or_create_by!(lot_number: "sample_manifest_id:#{id}")
end

#generateObject


141
142
143
144
145
146
147
148
# File 'app/models/sample_manifest.rb', line 141

def generate
  ActiveRecord::Base.transaction do
    self.barcodes = []
    core_behaviour.generate
  end
  created_broadcast_event
  nil
end

#indexed_manifest_assetsObject


173
174
175
# File 'app/models/sample_manifest.rb', line 173

def indexed_manifest_assets
  sample_manifest_assets.includes(*core_behaviour.included_resources).index_by(&:sanger_sample_id)
end

#nameObject


120
121
122
# File 'app/models/sample_manifest.rb', line 120

def name
  "Manifest_#{id}"
end

#purposeObject

Fall back to stock plate by default


184
185
186
# File 'app/models/sample_manifest.rb', line 184

def purpose
  super || default_purpose
end

#purpose_idObject


188
189
190
# File 'app/models/sample_manifest.rb', line 188

def purpose_id
  super || purpose.id
end

#qc_assayObject

Upon upload, sample manifests might generate qc_results for certain specialised fields. We want to keep one qc_assay per sample manifest.


202
203
204
# File 'app/models/sample_manifest.rb', line 202

def qc_assay
  @qc_assay ||= QcAssay.find_by(lot_number: "sample_manifest_id:#{id}")
end

#templateObject


60
# File 'app/models/sample_manifest.rb', line 60

def template; end

#truncate_errorsObject


93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'app/models/sample_manifest.rb', line 93

def truncate_errors
  if last_errors && last_errors.join.length > LIMIT_ERROR_LENGTH

    # First we truncate individual error messages. This ensures that it the first message is already
    # longer than out max limit, we still show something.
    full_last_errors = last_errors.map { |error| error.truncate(INDIVIDUAL_ERROR_LIMIT) }

    removed_errors = 0

    while full_last_errors.join.length > LIMIT_ERROR_LENGTH
      full_last_errors.pop
      removed_errors += 1
    end

    if removed_errors.positive?
      full_last_errors << "There were too many errors to record. #{removed_errors} additional errors are not shown."
    end

    self.last_errors = full_last_errors

  end
end

#tube_rack_purposeObject


192
193
194
# File 'app/models/sample_manifest.rb', line 192

def tube_rack_purpose
  super || default_tube_rack_purpose
end

#tube_rack_purpose_idObject


196
197
198
# File 'app/models/sample_manifest.rb', line 196

def tube_rack_purpose_id
  super || tube_rack_purpose.id
end

#update_barcodesObject

updates the manifest barcode list e.g. after applying a foreign barcode


178
179
180
181
# File 'app/models/sample_manifest.rb', line 178

def update_barcodes
  self.barcodes = labware.map(&:human_barcode)
  save!
end

#updated_broadcast_event(user_updating_manifest, updated_samples_ids) ⇒ Object


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

def updated_broadcast_event(user_updating_manifest, updated_samples_ids)
  # We chunk samples into groups of 3000 to avoid issues with the column size in broadcast_events.properties
  # In practice we have 11 characters per sample with current id lengths. This allows for up to 21 characters
  updated_samples_ids.each_slice(SAMPLES_PER_EVENT) do |chunked_sample_ids|
    BroadcastEvent::SampleManifestUpdated.create!(seed: self, user: user_updating_manifest,
                                                  properties: { updated_samples_ids: chunked_sample_ids })
  end
end