Class: SampleManifest
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- SampleManifest
- 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 generated 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
50_000
- 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
Constants included from BarcodePrinterBehaviour
BarcodePrinterBehaviour::ASSET_TYPE_TO_PRINTER_TYPE
Instance Attribute Summary collapse
- #invalid_wells ⇒ Object
-
#only_first_label ⇒ Object
Returns the value of attribute only_first_label.
-
#override ⇒ Object
Returns the value of attribute override.
-
#rows_per_well ⇒ Object
Number of rows per well in the manifest file, specified in manifest_types.yml.
Instance Method Summary collapse
-
#barcode_printer ⇒ Object
Needed for the UI to work!.
- #create_sample(sanger_sample_id) ⇒ Object
- #create_sample_and_aliquot(sanger_sample_id, asset) ⇒ Object
- #created_broadcast_event ⇒ Object
- #default_asset_type ⇒ Object
- #default_filename ⇒ Object
-
#find_or_create_qc_assay! ⇒ Object
rubocop:disable Naming/MemoizedInstanceVariableName.
- #generate ⇒ Object
- #indexed_manifest_assets ⇒ Object
- #name ⇒ Object
-
#pools ⇒ Object
Used in manifest upload code to determine if pools are present, so that tag_depth can be set on the aliquots if needed.
-
#purpose ⇒ Object
Fall back to stock plate by default.
- #purpose_id ⇒ Object
-
#qc_assay ⇒ Object
Upon upload, sample manifests might generate qc_results for certain specialised fields.
- #template ⇒ Object
-
#truncate_errors ⇒ Object
rubocop:todo Metrics/MethodLength.
- #tube_rack_purpose ⇒ Object
- #tube_rack_purpose_id ⇒ Object
-
#update_barcodes ⇒ Object
updates the manifest barcode list e.g.
- #updated_broadcast_event(user_updating_manifest, updated_samples_ids) ⇒ Object
Methods included from StateMachine
Methods included from Document::Associations
Methods included from CoreBehaviour
Methods included from BarcodePrinterBehaviour
Methods included from Uuid::Uuidable
included, #unsaved_uuid!, #uuid
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
Instance Attribute Details
#invalid_wells ⇒ Object
145 146 147 |
# File 'app/models/sample_manifest.rb', line 145 def invalid_wells @invalid_wells || [] end |
#only_first_label ⇒ Object
Returns the value of attribute only_first_label.
51 52 53 |
# File 'app/models/sample_manifest.rb', line 51 def only_first_label @only_first_label end |
#override ⇒ Object
Returns the value of attribute override.
51 52 53 |
# File 'app/models/sample_manifest.rb', line 51 def override @override end |
#rows_per_well ⇒ Object
Number of rows per well in the manifest file, specified in manifest_types.yml. Used to pre-populate the spreadsheet with a sufficient number of rows, in the case where we are importing a plate containing pools, and want to provide sample-level information for each pool. Developed initially for the scRNA Core pipeline.
Uses a default value of 1 if not set.
141 142 143 |
# File 'app/models/sample_manifest.rb', line 141 def rows_per_well @rows_per_well || 1 end |
Instance Method Details
#barcode_printer ⇒ Object
Needed for the UI to work!
60 61 |
# File 'app/models/sample_manifest.rb', line 60 def end |
#create_sample(sanger_sample_id) ⇒ Object
192 193 194 195 196 |
# File 'app/models/sample_manifest.rb', line 192 def create_sample(sanger_sample_id) Sample .create!(name: sanger_sample_id, sanger_sample_id: sanger_sample_id, sample_manifest: self) .tap { |sample| sample.events.created_using_sample_manifest!(user) } end |
#create_sample_and_aliquot(sanger_sample_id, asset) ⇒ Object
188 189 190 |
# File 'app/models/sample_manifest.rb', line 188 def create_sample_and_aliquot(sanger_sample_id, asset) core_behaviour.generate_sample_and_aliquot(sanger_sample_id, asset) end |
#created_broadcast_event ⇒ Object
198 199 200 |
# File 'app/models/sample_manifest.rb', line 198 def created_broadcast_event BroadcastEvent::SampleManifestCreated.create!(seed: self, user: user) end |
#default_asset_type ⇒ Object
122 123 124 |
# File 'app/models/sample_manifest.rb', line 122 def default_asset_type self.asset_type = 'plate' if asset_type.blank? end |
#default_filename ⇒ Object
130 131 132 |
# File 'app/models/sample_manifest.rb', line 130 def default_filename "#{study_id}stdy_manifest_#{id}_#{created_at.to_fs(:dmy)}" end |
#find_or_create_qc_assay! ⇒ Object
rubocop:disable Naming/MemoizedInstanceVariableName
250 251 252 |
# File 'app/models/sample_manifest.rb', line 250 def find_or_create_qc_assay! @qc_assay ||= QcAssay.find_or_create_by!(lot_number: "sample_manifest_id:#{id}") end |
#generate ⇒ Object
179 180 181 182 183 184 185 186 |
# File 'app/models/sample_manifest.rb', line 179 def generate ActiveRecord::Base.transaction do self. = [] core_behaviour.generate end created_broadcast_event nil end |
#indexed_manifest_assets ⇒ Object
216 217 218 |
# File 'app/models/sample_manifest.rb', line 216 def indexed_manifest_assets sample_manifest_assets.includes(*core_behaviour.included_resources).index_by(&:sanger_sample_id) end |
#name ⇒ Object
126 127 128 |
# File 'app/models/sample_manifest.rb', line 126 def name "Manifest_#{id}" end |
#pools ⇒ Object
Used in manifest upload code to determine if pools are present, so that tag_depth can be set on the aliquots if needed.
Returns a hash of receptacle to array of sample manifest assets. Returns nil if all receptacles only contain 0 or 1 sample.
154 155 156 157 158 159 160 161 162 163 164 |
# File 'app/models/sample_manifest.rb', line 154 def pools @pools ||= begin # Sample manifest assets are a join table between sample manifests and samples, # created upfront when the manifest is generated. # Here we use them to see how many samples are in each receptacle. receptacle_to_smas = sample_manifest_assets.group_by(&:asset) receptacle_to_smas.values.all? { |smas| smas.size <= 1 } ? nil : receptacle_to_smas end end |
#purpose ⇒ Object
Fall back to stock plate by default
227 228 229 |
# File 'app/models/sample_manifest.rb', line 227 def purpose super || default_purpose end |
#purpose_id ⇒ Object
231 232 233 |
# File 'app/models/sample_manifest.rb', line 231 def purpose_id super || purpose.id end |
#qc_assay ⇒ Object
Upon upload, sample manifests might generate qc_results for certain specialised fields. We want to keep one qc_assay per sample manifest.
245 246 247 |
# File 'app/models/sample_manifest.rb', line 245 def qc_assay @qc_assay ||= QcAssay.find_by(lot_number: "sample_manifest_id:#{id}") end |
#template ⇒ Object
63 64 |
# File 'app/models/sample_manifest.rb', line 63 def template end |
#truncate_errors ⇒ Object
rubocop:todo Metrics/MethodLength
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'app/models/sample_manifest.rb', line 101 def truncate_errors # rubocop:todo Metrics/MethodLength 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_purpose ⇒ Object
235 236 237 |
# File 'app/models/sample_manifest.rb', line 235 def tube_rack_purpose super || default_tube_rack_purpose end |
#tube_rack_purpose_id ⇒ Object
239 240 241 |
# File 'app/models/sample_manifest.rb', line 239 def tube_rack_purpose_id super || tube_rack_purpose.id end |
#update_barcodes ⇒ Object
updates the manifest barcode list e.g. after applying a foreign barcode
221 222 223 224 |
# File 'app/models/sample_manifest.rb', line 221 def self. = labware.map(&:human_barcode) save! end |
#updated_broadcast_event(user_updating_manifest, updated_samples_ids) ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'app/models/sample_manifest.rb', line 202 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 |