Class: Sample
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- Sample
- Extended by:
- EventfulRecord, Metadata, ValidationStateGuard
- Includes:
- ActiveRecord::AttributeMethods::Dirty, Aliquot::Aliquotable, Api::SampleIo::Extensions, Commentable, ModelExtensions::Sample, Role::Authorized, SampleAccessioning, SharedBehaviour::Named, StandardNamedScopes, Uuid::Uuidable
- Defined in:
- app/models/sample.rb
Overview
A Sample is an abstract concept, with represents the life of a sample of DNA/RNA as it moves through our processes. As a result, a sample may exist in multiple receptacles at the same time, in the form of an Aliquot. As a result Sample is mainly concerned with dealing with aspects which are always true, such as tracking where it originally came from.
An individual sample may be subject to library creation and sequencing multiple different times. These processes may be different each time.
Sample Creation
Samples can enter Sequencescape via a number of different routes. Such as: - SampleManifest: Large spreadsheets of sample information are generated. When uploaded samples are created in the corresponding Receptacle. - Heron: Heron samples get registered via the Api::V2::Heron::PlatesController - Special samples: Samples such as PhiX are generated internally
Defined Under Namespace
Constant Summary collapse
- GC_CONTENTS =
['Neutral', 'High AT', 'High GC'].freeze
- GENDERS =
['Male', 'Female', 'Mixed', 'Hermaphrodite', 'Unknown', 'Not Applicable'].freeze
- DNA_SOURCES =
[ 'Genomic', 'Whole Genome Amplified', 'Blood', 'Cell Line', 'Saliva', 'Brain', 'FFPE', 'Amniocentesis Uncultured', 'Amniocentesis Cultured', 'CVS Uncultured', 'CVS Cultured', 'Fetal Blood', 'Tissue' ].freeze
- SRA_HOLD_VALUES =
%w[Hold Public Protect].freeze
- AGE_REGEXP =
'\d+(?:\.\d+|\-\d+|\.\d+\-\d+\.\d+|\.\d+\-\d+\.\d+)?\s+(?:second|minute|day|week|month|year)s?|Not Applicable|N/A|To be provided'- DOSE_REGEXP =
rubocop:enable Layout/LineLength
'\d+(?:\.\d+)?\s+\w+(?:\/\w+)?|Not Applicable|N/A|To be provided'- REMAPPED_ATTRIBUTES =
The spreadsheets that people upload contain various fields that could be mistyped. Here we ensure that the capitalisation of these is correct.
{ gc_content: GC_CONTENTS, gender: GENDERS, dna_source: DNA_SOURCES, sample_sra_hold: SRA_HOLD_VALUES }.transform_values { |v| v.index_by { |b| b.downcase } }
Constants included from Metadata
Constants included from SampleAccessioning
Constants included from StandardNamedScopes
StandardNamedScopes::SORT_FIELDS, StandardNamedScopes::SORT_ORDERS
Instance Attribute Summary collapse
-
#empty_supplier_sample_name ⇒ Boolean
deprecated
Deprecated.
Only set on older samples where samples were created at manifest generation, rather than upload
Attributes included from SampleAccessioning
Instance Method Summary collapse
-
#can_be_included_in_submission? ⇒ Boolean
if sample is registered through sample manifest it should have supplier sample name (without it the row is considered empty) if sample was registered directly, only sample name is a required field, so supplier sample name can be empty but it is reasonably safe to assume that required metadata was provided.
- #control_formatted ⇒ Object
- #error ⇒ Object
- #friendly_name ⇒ Object
- #handle_update_event(user) ⇒ Object
- #name_unchanged ⇒ Object
-
#registered_through_manifest? ⇒ Boolean
sample can either be registered through sample manifest, historically through studies/:id/sample_registration or via external services like Heron.
-
#rename_to!(new_name) ⇒ Object
this method has to be before validation_guarded_by.
- #sample_empty?(supplier_sample_name = name) ⇒ Boolean
- #sample_reference_genome ⇒ Object
- #sample_supplier_name_empty?(supplier_sample_name) ⇒ Boolean
-
#shorten_sanger_sample_id ⇒ Object
Truncates the sanger_sample_id for display on labels - Returns the sanger_sample_id AS IS if it is nil or less than 10 characters - Tries to truncate it to the last 7 digits, and returns that - If it cannot extract 7 digits, the full sanger_sample_id is returned Earlier implementations were supposed to fall back to the name in the absence of a sanger_sample_id, but the feature was incorrectly implemented, and would have thrown an exception.
- #subject_type ⇒ Object
Methods included from EventfulRecord
has_many_events, has_many_lab_events, has_one_event_with_family
Methods included from ValidationStateGuard
validation_guard, validation_guarded_by
Methods included from Metadata
Methods included from SampleAccessioning
#accession_and_handle_validation_errors, #accession_number?, #all_accessionable_studies_open?, #current_accession_status, #ebi_accession_number, #ena_study, #should_be_accessioned?, #studies_for_accessioning, #study_for_accessioning, tags, #validate_sample_for_accessioning!
Methods included from IncludeTag
Methods included from Commentable
Methods included from Aliquot::Aliquotable
Methods included from SharedBehaviour::Named
Methods included from StandardNamedScopes
Methods included from Uuid::Uuidable
included, #unsaved_uuid!, #uuid
Methods included from Api::SampleIo::Extensions
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
#empty_supplier_sample_name ⇒ Boolean
Only set on older samples where samples were created at manifest generation, rather than upload
Returns true if the customer didn't fill in the supplier_sample_name. Indicating that there is actually no sample in the well.
|
|
# File 'app/models/sample.rb', line 77
|
Instance Method Details
#can_be_included_in_submission? ⇒ Boolean
if sample is registered through sample manifest it should have supplier sample name (without it the row is considered empty) if sample was registered directly, only sample name is a required field, so supplier sample name can be empty but it is reasonably safe to assume that required metadata was provided
511 512 513 |
# File 'app/models/sample.rb', line 511 def can_be_included_in_submission? registered_through_manifest? ? .supplier_name.present? : true end |
#control_formatted ⇒ Object
515 516 517 518 519 520 521 522 |
# File 'app/models/sample.rb', line 515 def control_formatted return nil if control.nil? return 'No' if control == false type_text = control_type || 'type unspecified' "Yes (#{type_text})" end |
#error ⇒ Object
455 456 457 |
# File 'app/models/sample.rb', line 455 def error 'Default error message' end |
#friendly_name ⇒ Object
491 492 493 |
# File 'app/models/sample.rb', line 491 def friendly_name sanger_sample_id || name end |
#handle_update_event(user) ⇒ Object
470 471 472 |
# File 'app/models/sample.rb', line 470 def handle_update_event(user) events.updated_using_sample_manifest!(user) end |
#name_unchanged ⇒ Object
495 496 497 498 |
# File 'app/models/sample.rb', line 495 def name_unchanged errors.add(:name, 'cannot be changed') unless can_rename_sample can_rename_sample end |
#registered_through_manifest? ⇒ Boolean
sample can either be registered through sample manifest, historically through studies/:id/sample_registration or via external services like Heron
503 504 505 |
# File 'app/models/sample.rb', line 503 def registered_through_manifest? sample_manifest.present? end |
#rename_to!(new_name) ⇒ Object
this method has to be before validation_guarded_by
364 365 366 |
# File 'app/models/sample.rb', line 364 def rename_to!(new_name) update!(name: new_name) end |
#sample_empty?(supplier_sample_name = name) ⇒ Boolean
459 460 461 462 463 |
# File 'app/models/sample.rb', line 459 def sample_empty?(supplier_sample_name = name) return true if empty_supplier_sample_name sample_supplier_name_empty?(supplier_sample_name) end |
#sample_reference_genome ⇒ Object
474 475 476 477 478 479 |
# File 'app/models/sample.rb', line 474 def sample_reference_genome return .reference_genome if .reference_genome.try(:name).present? return study_reference_genome if study_reference_genome.try(:name).present? nil end |
#sample_supplier_name_empty?(supplier_sample_name) ⇒ Boolean
465 466 467 468 |
# File 'app/models/sample.rb', line 465 def sample_supplier_name_empty?(supplier_sample_name) supplier_sample_name.blank? || ['empty', 'blank', 'water', 'no supplier name available', 'none'].include?(supplier_sample_name.downcase) end |
#shorten_sanger_sample_id ⇒ Object
This appears to be set up to handle legacy data. All currently generated Sanger sample ids will be meet criteria 1 or 2.
Truncates the sanger_sample_id for display on labels - Returns the sanger_sample_id AS IS if it is nil or less than 10 characters - Tries to truncate it to the last 7 digits, and returns that - If it cannot extract 7 digits, the full sanger_sample_id is returned Earlier implementations were supposed to fall back to the name in the absence of a sanger_sample_id, but the feature was incorrectly implemented, and would have thrown an exception.
442 443 444 445 446 447 448 449 450 451 452 453 |
# File 'app/models/sample.rb', line 442 def shorten_sanger_sample_id case sanger_sample_id when nil sanger_sample_id when sanger_sample_id.size < 10 sanger_sample_id when /(\d{7})$/ Regexp.last_match(1) else sanger_sample_id end end |
#subject_type ⇒ Object
481 482 483 |
# File 'app/models/sample.rb', line 481 def subject_type 'sample' end |