Skip to content

Commit

Permalink
General nih tables exporting (#1956)
Browse files Browse the repository at this point in the history
* General nih tables exporting

* Lint fixes and tests added

* Fixes PR review

* Fix: CI can't run the analysis step (docker error) (#1957)

This is a bug introduced in docker compose v2.19.0:
docker/compose#10751

* General nih tables exporting

* Lint fixes and tests added

* Fixes PR review

* Revert "Merge branch '1905-general-nih-tables' of https://github.com/instedd/cdx into 1905-general-nih-tables"

This reverts commit 32366c1.

* Revert "Revert "Merge branch '1905-general-nih-tables' of https://github.com/instedd/cdx into 1905-general-nih-tables""

This reverts commit 8994214.

* Fixes PR review

* Zip as buffer

---------

Co-authored-by: Julien Portalier <[email protected]>
  • Loading branch information
leandroradusky and ysbaddaden authored Jul 7, 2023
1 parent cbe2039 commit d70369d
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 32 deletions.
56 changes: 26 additions & 30 deletions app/controllers/nih_tables_controller.rb
Original file line number Diff line number Diff line change
@@ -1,41 +1,37 @@
class NihTablesController < ApplicationController
def show
samples_report = SamplesReport.find(params[:id])
return unless authorize_resource(samples_report, READ_SAMPLES_REPORT)
@samples_report = SamplesReport.find(params[:id])
return unless authorize_resource(@samples_report, READ_SAMPLES_REPORT)

purpose = samples_report.samples[0].box.purpose
zip_file = create_zip_file(samples_report.name)

if purpose == "LOD"
add_lod_table(zip_file)
elsif purpose == "Challenge"
add_challenge_table(zip_file)
end

zip_file.close

send_zip_file(zip_file, samples_report.name)
zip_data = create_zip_file
send_data zip_data.read, type: 'application/zip', filename: "#{@samples_report.name}_nih_tables.zip"
end

private

def create_zip_file(filename)
zip_file = Tempfile.new("#{filename}_nih_tables.zip")
Zip::File.open(zip_file.path, Zip::File::CREATE) do |zip|
zip.add("Instructions.txt", Rails.root.join('public/templates/Instructions.txt'))
def create_zip_file
purpose = @samples_report.samples[0].box.purpose

zip_stream = Zip::OutputStream.write_buffer do |stream|
# Read public/templates/Instructions.txt contents and write to zip
stream.put_next_entry('Instructions.txt')
stream.write(File.read(Rails.root.join('public/templates/Instructions.txt')))

add_nih_table('samples', stream)
add_nih_table('results', stream)

if purpose == "LOD"
#add_nih_table('lod', stream)
elsif purpose == "Challenge"
#add_nih_table('challenge', stream)
end
end
zip_file
zip_stream.rewind
zip_stream
end

def add_lod_table(zip_file)
# TODO: Add the LOD table to the zip file
end

def add_challenge_table(zip_file)
# TODO: Add the Challenge table to the zip file
end

def send_zip_file(zip_file, filename)
send_file zip_file.path, type: 'application/zip', filename: "#{filename}_nih_tables.zip"

def add_nih_table(table_name, stream)
stream.put_next_entry("#{@samples_report.name}_#{table_name}.csv")
stream.write(render_to_string('samples_reports/nih_'+table_name, formats: :csv))
end
end
23 changes: 23 additions & 0 deletions app/views/samples_reports/nih_results.csv.csvbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
csv << [
'sample_id',
'vqa_box_id',
'sample_group',
'protocol_id',
'technology_platform',
'assay_readout',
'assay_readout_unit',
'assay_readout_description'
]

@samples_report.samples.each do |sample|
csv << [
sample.id,
sample.box.uuid,
"#{sample.box.purpose}-panel",
nil,
nil,
sample.measured_signal,
nil,
nil
]
end
44 changes: 44 additions & 0 deletions app/views/samples_reports/nih_samples.csv.csvbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
csv << [
'sample_id',
'vqa_box_id',
'sample_group',
'sample_media',
'sample_media_id',
'sample_media_source',
'sample_media_source_url',
'sample_concentration',
'sample_concentration_unit',
'sample_concentration_reference_gene',
'virus_sample_id',
'virus_batch_number',
'target_analyte_type',
'target_organism_name',
'target_organism_taxonomy_id',
'pango_lineage',
'who_label',
'virus_sample_inactivation_method'
]

@samples_report.samples.each do |sample|
batch = Batch.find_by(batch_number: sample.batch_number)
csv << [
sample.id,
sample.box.uuid,
"#{sample.box.purpose}-panel",
nil,
nil,
nil,
nil,
sample.concentration,
'copies/ml',
batch.reference_gene,
sample.id,
sample.batch_number,
'inactivated virus',
'SARS-CoV-2',
batch.target_organism_taxonomy_id,
batch.pango_lineage,
batch.who_label,
sample.inactivation_method
]
end
29 changes: 27 additions & 2 deletions spec/controllers/nih_tables_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,43 @@
it "should download a zip file on show" do
get :show, params: { id: @samples_report.id }

#expect sent file to be a zip file
expect(response.headers["Content-Type"]).to eq("application/zip")
expect(response.headers["Content-Disposition"]).to eq("attachment; filename=\"Test_nih_tables.zip\"")
end

it "should contain the Instructions.txt file" do
get :show, params: { id: @samples_report.id }

#expect the zip file to contain the Instructions.txt file
expect(Zip::File.open_buffer(response.body).entries.map(&:name)).to include("Instructions.txt")
end

it "should contain the samples & results table" do
get :show, params: { id: @samples_report.id }

expect(Zip::File.open_buffer(response.body).entries.map(&:name)).to include("#{@samples_report.name}_samples.csv")
expect(Zip::File.open_buffer(response.body).entries.map(&:name)).to include("#{@samples_report.name}_results.csv")
end

it "should contain the samples table with the correct data" do
get :show, params: { id: @samples_report.id }

samples_table = CSV.parse(Zip::File.open_buffer(response.body).entries.find{|e| e.name == "Test_samples.csv"}.get_input_stream.read, headers: true)

expect(samples_table.count).to eq(@samples_report.samples_report_samples.count)

expect(samples_table["sample_id"]).to eq(@samples_report.samples_report_samples.map{|srs| srs.sample.id.to_s})
end

it "should contain the results table with the correct data" do
get :show, params: { id: @samples_report.id }

samples_table = CSV.parse(Zip::File.open_buffer(response.body).entries.find{|e| e.name == "Test_results.csv"}.get_input_stream.read, headers: true)

expect(samples_table.count).to eq(@samples_report.samples_report_samples.count)

expect(samples_table["sample_id"]).to eq(@samples_report.samples_report_samples.map{|srs| srs.sample.id.to_s})
end

it "should not allow access to user without read access" do
sign_in @other_user
get :show, params: { id: @samples_report.id, context: @other_institution.uuid }
Expand Down

0 comments on commit d70369d

Please sign in to comment.