Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPL-812: FluidX tube rack data report #1433

Merged
merged 39 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
028620b
wip: add initial PBMC Bank Tubes Content Report
StephenHulme Oct 17, 2023
b104b1b
fix: update values
StephenHulme Oct 17, 2023
887a488
fix: remove duplicate well position
StephenHulme Oct 18, 2023
d120b61
fix: tidy up code
StephenHulme Oct 18, 2023
35e2caa
style: lint
StephenHulme Oct 18, 2023
487c631
fix: update values
StephenHulme Oct 20, 2023
5ec5451
fix: remove debug code and lint
StephenHulme Oct 20, 2023
b1eee38
fix: update report with units and additional notes
StephenHulme Oct 20, 2023
afc431c
refactor: rename destination_tube -> child_tube
StephenHulme Oct 20, 2023
2dc9a9e
tests: add test for well-aliquot-study fixture
StephenHulme Oct 19, 2023
4c54790
fix: remove existing study reference
StephenHulme Oct 20, 2023
2f32679
fix: remove existing project reference
StephenHulme Oct 23, 2023
623ee0f
fix: re-establish relationships
StephenHulme Oct 23, 2023
4107296
tests: add tests for well-aliquot relationships
StephenHulme Oct 23, 2023
66484c1
fix: restore relationships
StephenHulme Oct 23, 2023
f3047df
tests: add test for order_group
StephenHulme Oct 23, 2023
be1573b
tests: add tests to specify study and project
StephenHulme Oct 23, 2023
219daee
tests: add tests to specify study and project at well level
StephenHulme Oct 24, 2023
f438a6a
tests: add tests to specify study and project at plate level
StephenHulme Oct 24, 2023
596ae2c
tests: specify study and project at plate level for submission
StephenHulme Oct 24, 2023
93c187b
tests: add tests for same study and project
StephenHulme Oct 23, 2023
8eb2598
Merge branch 'dpl-812-tests' into dpl-812-fluidx-tube-rack-data-report
StephenHulme Oct 24, 2023
e383aa6
tests: update column headings
StephenHulme Oct 24, 2023
4e57dce
fix: remove erroneous leading line
StephenHulme Oct 24, 2023
6008819
tests: refactor and add missing values
StephenHulme Oct 24, 2023
0f7de3c
tests: add missing study
StephenHulme Oct 24, 2023
b95584b
tests: add donor and row-by-row evaluation to tests
StephenHulme Oct 24, 2023
15691a5
fix: add extraction-date and study name
StephenHulme Oct 24, 2023
59e35e6
fix: update barcodes
StephenHulme Oct 24, 2023
a742683
style: remove development comments
StephenHulme Oct 24, 2023
fbc7a10
refactor: rename child_tube -> child_tube_v1
StephenHulme Oct 24, 2023
96cc5f5
style: lint
StephenHulme Oct 24, 2023
2b6b796
style: lindt
StephenHulme Oct 24, 2023
cfc6c80
tests: specify donor_id
StephenHulme Oct 24, 2023
451eb64
Merge branch 'develop' into dpl-812-fluidx-tube-rack-data-report
StephenHulme Oct 30, 2023
f6c477b
fix: revert inadvertent debugging changes
StephenHulme Oct 30, 2023
7d3868a
fix: rename Parent barcode -> Stock barcode
StephenHulme Oct 30, 2023
3a4e64d
fix: use purpose name instead of tube name to determine destination
StephenHulme Oct 30, 2023
613c3bc
fix: update dev comment
StephenHulme Oct 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions app/sequencescape/sequencescape/api/v2/well.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ def latest_live_cell_count
latest_qc(key: 'live_cell_count', units: 'cells/ml')
end

def latest_cell_viability
latest_qc(key: 'viability', units: '%')
end

Comment on lines +38 to +41
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied across from DPL-827

def latest_qc(key:, units:)
qc_results.to_a # Convert to array to resolve any api queries. Otherwise select fails to work.
.select { |qc| qc.key.casecmp(key).zero? }
Expand Down
81 changes: 81 additions & 0 deletions app/views/exports/pbmc_bank_tubes_content_report.csv.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<%# This is a report of the contents of the tubes in the PBMC Bank plate %>
<%# Based on app/views/exports/hamilton_lrc_pbmc_bank_to_lrc_bank_seq_and_spare.csv.erb %>
<%= CSV.generate_line ['Workflow', @workflow], row_sep: '' %>

<%=
CSV.generate_line [
'Well name',
'Donor ID',
'Stock barcode',
'FluidX barcode',
'Extraction and freeze date',
'Sequencing or contingency',
'Cell count (cells/ml)',
'Viability (%)',
'Volume (µl)',
'Study name',
'Collection site'
],
row_sep: ''
%>
<%
rows_array = []
@plate.wells_in_columns.each do |source_well|
# skip if well empty (not all wells have samples in them)
next if source_well.empty?

# skip if well not in passed state
next unless source_well.passed?

# skip if no downstream tubes for this well (not set up children in Limber yet)
next if source_well.downstream_tubes.empty?

child_tube_v1 = source_well.downstream_tubes.last
child_tube_v2 =
Sequencescape::Api::V2.tube_with_custom_includes(
'custom_metadatum_collection',
nil,
barcode: child_tube_v1.labware_barcode.machine
)

next unless child_tube_v2 && child_tube_v2.custom_metadatum_collection

# get tube metadata from child_tube
metadata = child_tube_v2.custom_metadatum_collection.metadata

next unless metadata

tube_rack_barcode = metadata['tube_rack_barcode']
tube_rack_position = metadata['tube_rack_position']

next unless tube_rack_barcode && tube_rack_position

sample_uuid = source_well.aliquots.first.sample.uuid
source_well_posn = source_well.position['name']

sample_metadata = source_well.aliquots.first.sample.sample_metadata

# donor_id is sourced from the sample metadata provided by Sequencescape
donor_id = sample_metadata.respond_to?(:donor_id) ? sample_metadata.donor_id : nils
child_tube_purpose = child_tube_v2.purpose.name
destination = ((child_tube_purpose == 'LRC Blood Seq') ? 'Sequencing' : 'Contingency')
volume = 135

rows_array << [
source_well.name, # Well name
donor_id, # Donor ID
@ancestor_tubes[sample_uuid].labware_barcode.human, # LRC Blood Vac purpose barcode
child_tube_v2.barcode, # FluidX barcode
child_tube_v2.created_at, # Extraction and freeze date
destination, # Sequencing or contingency
source_well.latest_live_cell_count.value, # Cell count
source_well.latest_cell_viability.value, # Viability
volume, # Volume
source_well.aliquots.first.study.name, # Study name
source_well.aliquots.first.sample.sample_metadata&.collected_by # Collection site
]
end
%>
<% rows_array.sort_by{ |a| WellHelpers.well_coordinate(a[0]) }.each do |row| %>
<%= CSV.generate_line row, row_sep: '' %>
<% end %>
9 changes: 9 additions & 0 deletions config/exports/exports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,12 @@ hamilton_lrc_blood_bank_to_lrc_pbmc_bank:
- wells.transfer_requests_as_target.source_asset
ancestor_tube_purpose: LRC Blood Vac
ancestor_purpose: LRC Blood Bank
pbmc_bank_tubes_content_report:
csv: pbmc_bank_tubes_content_report
workflow: scRNA Core PBMC Bank
plate_includes:
- wells.downstream_tubes
- wells.aliquots
- wells.aliquots.sample
- wells.aliquots.sample.sample_metadata
ancestor_tube_purpose: LRC Blood Vac
2 changes: 2 additions & 0 deletions config/purposes/scrna_core_cell_extraction.wip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ LRC PBMC Bank:
id: hamilton_lrc_blood_bank_to_lrc_pbmc_bank
- name: 'Download Hamilton LRC PBMC Bank plate to LRC Bank Seq and Spare tubes CSV'
id: hamilton_lrc_pbmc_bank_to_lrc_bank_seq_and_spare
- name: 'Download PBMC Bank Tubes Content Report'
id: pbmc_bank_tubes_content_report
:qc_thresholds:
viability:
units: '%'
Expand Down
7 changes: 6 additions & 1 deletion spec/factories/plate_factories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@
# associated request. This allows us to over-ride that
aliquots_without_requests { 0 }

study { create :v2_study, name: 'Plate Study' }
project { create :v2_project, name: 'Plate Project' }

# Constructs the wells for the plate. Constructs
# well_count wells using the factory specified in well_factory
# Sets requests on wells by pulling them off the outer_request array
Expand All @@ -73,7 +76,9 @@
outer_request: outer_requests[i],
downstream_tubes: transfer_targets[location],
uuid: well_uuid_result % location,
aliquot_count: outer_requests[i] ? 1 : aliquots_without_requests
aliquot_count: outer_requests[i] ? 1 : aliquots_without_requests,
study: study,
project: project
end
end

Expand Down
2 changes: 2 additions & 0 deletions spec/factories/project_factories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
factory :v2_project, class: Sequencescape::Api::V2::Project do
skip_create

id

name { 'Test Project' }

uuid { SecureRandom.uuid }
Expand Down
1 change: 1 addition & 0 deletions spec/factories/sample_factories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
collected_by { 'Sanger' }
cohort { 'Cohort' }
sample_description { 'Description' }
sequence(:donor_id) { |i| "donor#{i}" }
end

factory :v2_sample_metadata_for_mbrave, class: Sequencescape::Api::V2::SampleMetadata do
Expand Down
2 changes: 2 additions & 0 deletions spec/factories/study_factories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
factory :v2_study, class: Sequencescape::Api::V2::Study do
skip_create

id

name { 'Test Study' }

uuid { SecureRandom.uuid }
Expand Down
20 changes: 13 additions & 7 deletions spec/factories/well_factories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,15 @@
# Use the stock well factory if you want the request comming out of the well
outer_request { create request_factory, state: library_state }

study { create :v2_study, name: 'Well Study' }
project { create :v2_project, name: 'Well Project' }

# The factory to use for aliquots
aliquot_factory { :v2_aliquot }
aliquots do
# Conditional to avoid generating requests when not required
if aliquot_count > 0
create_list aliquot_factory, aliquot_count, outer_request: outer_request
create_list aliquot_factory, aliquot_count, outer_request: outer_request, study: study, project: project
else
[]
end
Expand Down Expand Up @@ -256,8 +259,8 @@
# Alias for request: The request set on the aliquot itself
outer_request { create :library_request, state: library_state }
well_location { 'A1' }
study_id { 1 }
project_id { 1 }
study { create :v2_study, name: 'Test Aliquot Study' }
project { create :v2_project, name: 'Test Aliquot Project' }
sample_attributes { {} }
end

Expand All @@ -271,16 +274,19 @@
request { outer_request }

after(:build) do |aliquot, evaluator|
aliquot._cached_relationship(:request) { evaluator.request }
aliquot._cached_relationship(:sample) { evaluator.sample }
# Set up relationships downstream
Sequencescape::Api::V2::Aliquot.associations.each do |association|
aliquot._cached_relationship(association.attr_name) { evaluator.send(association.attr_name) }
end

aliquot.relationships.study = {
'links' => {
'self' => "http://localhost:3000/api/v2/aliquots/#{aliquot.id}/relationships/study",
'related' => "http://localhost:3000/api/v2/aliquots/#{aliquot.id}/study"
},
'data' => {
'type' => 'studies',
'id' => evaluator.study_id.to_s
'id' => evaluator.study.id.to_s
}
}
aliquot.relationships.project = {
Expand All @@ -290,7 +296,7 @@
},
'data' => {
'type' => 'projects',
'id' => evaluator.project_id.to_s
'id' => evaluator.project.id.to_s
}
}
end
Expand Down
84 changes: 84 additions & 0 deletions spec/factory_outputs/plate_factory_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,87 @@
expect(JSON.parse(subject)).to include_json(JSON.parse(json_content))
end
end

RSpec.describe 'v2_plate' do
context 'with specified study and project at plate level' do
subject { create(:v2_plate, aliquots_without_requests: 1, study: study, project: project) }

# study
let(:study_uuid) { SecureRandom.uuid }
let(:study) { create(:v2_study, name: 'Provided Study', uuid: study_uuid) }

# project
let(:project_uuid) { SecureRandom.uuid }
let(:project) { create(:v2_project, name: 'Provided Project', uuid: project_uuid) }

describe 'first aliquot' do
let(:first_aliquot) { subject.wells.first.aliquots.first }

it 'should be a version 2 aliquot' do
expect(first_aliquot.class).to eq(Sequencescape::Api::V2::Aliquot)
end

it 'should have a valid study' do
expect(first_aliquot.study).to be_kind_of(Sequencescape::Api::V2::Study)
end
it 'should have a valid study uuid' do
expect(first_aliquot.study.uuid).to eq(study_uuid)
end
it 'should have a valid study name' do
expect(first_aliquot.study.name).to eq('Provided Study')
end

it 'should have a valid project' do
expect(first_aliquot.project).to be_kind_of(Sequencescape::Api::V2::Project)
end
it 'should have a valid project uuid' do
expect(first_aliquot.project.uuid).to eq(project_uuid)
end
it 'should have a valid project name' do
expect(first_aliquot.project.name).to eq('Provided Project')
end
end
end
end

RSpec.describe 'v2_plate_for_submission' do
context 'with specified study and project at plate level' do
subject { create(:v2_plate_for_submission, aliquots_without_requests: 1, study: study, project: project) }

# study
let(:study_uuid) { SecureRandom.uuid }
let(:study) { create(:v2_study, name: 'Provided Study', uuid: study_uuid) }

# project
let(:project_uuid) { SecureRandom.uuid }
let(:project) { create(:v2_project, name: 'Provided Project', uuid: project_uuid) }

describe 'first aliquot' do
let(:first_aliquot) { subject.wells.first.aliquots.first }

it 'should be a version 2 aliquot' do
expect(first_aliquot.class).to eq(Sequencescape::Api::V2::Aliquot)
end

it 'should have a valid study' do
expect(first_aliquot.study).to be_kind_of(Sequencescape::Api::V2::Study)
end
it 'should have a valid study uuid' do
expect(first_aliquot.study.uuid).to eq(study_uuid)
end
it 'should have a valid study name' do
expect(first_aliquot.study.name).to eq('Provided Study')
end

it 'should have a valid project' do
expect(first_aliquot.project).to be_kind_of(Sequencescape::Api::V2::Project)
end
it 'should have a valid project uuid' do
expect(first_aliquot.project.uuid).to eq(project_uuid)
end
it 'should have a valid project name' do
expect(first_aliquot.project.name).to eq('Provided Project')
end
end
end
end
Loading
Loading