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


151
152
153
154
155
# File 'app/models/sample_manifest.rb', line 151

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


147
148
149
# File 'app/models/sample_manifest.rb', line 147

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

#created_broadcast_eventObject


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

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

#default_asset_typeObject


113
114
115
# File 'app/models/sample_manifest.rb', line 113

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

#default_filenameObject


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

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

#generateObject


138
139
140
141
142
143
144
145
# File 'app/models/sample_manifest.rb', line 138

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

#indexed_manifest_assetsObject


169
170
171
# File 'app/models/sample_manifest.rb', line 169

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

#nameObject


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

def name
  "Manifest_#{id}"
end

#purposeObject

Fall back to stock plate by default


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

def purpose
  super || default_purpose
end

#purpose_idObject


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

def purpose_id
  super || purpose.id
end

#templateObject


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

def template; end

#truncate_errorsObject


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

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

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

    self.last_errors = full_last_errors

  end
end

#update_barcodesObject

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


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

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

#updated_broadcast_event(user_updating_manifest, updated_samples_ids) ⇒ Object


161
162
163
164
165
166
167
# File 'app/models/sample_manifest.rb', line 161

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