From 714739f9c0d0c4f2a5172cf8e49599d4b7bca382 Mon Sep 17 00:00:00 2001 From: Leandro Radusky Date: Tue, 8 Aug 2023 17:49:27 +0200 Subject: [PATCH 1/3] Correction to unintentionally modified upload_box.csv file --- public/templates/upload_box.csv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/templates/upload_box.csv b/public/templates/upload_box.csv index de884b586..86a3f3998 100644 --- a/public/templates/upload_box.csv +++ b/public/templates/upload_box.csv @@ -1,5 +1,5 @@ Batch,Concentration,Distractor,Instructions,Replicates -borrar,100,no,Add 175 ml of media,2 -borrar,1000,no,Add 175 ml of media,2 -Blank,2,yes,Add 250 ml of media,4 -Blank,200,yes,Add 100 ml of media,4 +batch1,100,no,Add 175 ml of media,2 +batch1,1000,no,Add 175 ml of media,2 +batch2,2,yes,Add 250 ml of media,4 +batch2,200,yes,Add 100 ml of media,4 From 5c2188a18412541cdf5bb32cdfc2cbbd953f923a Mon Sep 17 00:00:00 2001 From: Leandro Radusky Date: Mon, 28 Aug 2023 09:00:34 +0200 Subject: [PATCH 2/3] Instructions file for NIH tables and fixes after iteration with the client --- .../components/box_batches_form.js.jsx | 2 +- .../samples_reports_bar_chart.js.jsx | 2 +- .../samples_reports_line_chart.js.jsx | 2 +- .../components/samples_selector.js.jsx | 2 +- .../nih_tables/nih_challenge.csv.csvbuilder | 14 +++++----- .../nih_tables/nih_results.csv.csvbuilder | 2 +- .../nih_tables/nih_samples.csv.csvbuilder | 2 +- app/views/samples/_form.haml | 2 +- app/views/samples_reports/show.haml | 11 ++++---- public/templates/Instructions.txt | 27 ++++++++++++++++++- 10 files changed, 46 insertions(+), 20 deletions(-) diff --git a/app/assets/javascripts/components/box_batches_form.js.jsx b/app/assets/javascripts/components/box_batches_form.js.jsx index 5f94cc5fc..69e7a6fa1 100644 --- a/app/assets/javascripts/components/box_batches_form.js.jsx +++ b/app/assets/javascripts/components/box_batches_form.js.jsx @@ -273,7 +273,7 @@ var BoxBatchForm = React.createClass({
- copies/ml + copies/mL
); diff --git a/app/assets/javascripts/components/samples_reports_bar_chart.js.jsx b/app/assets/javascripts/components/samples_reports_bar_chart.js.jsx index deb3925d7..222dd9c3a 100644 --- a/app/assets/javascripts/components/samples_reports_bar_chart.js.jsx +++ b/app/assets/javascripts/components/samples_reports_bar_chart.js.jsx @@ -85,7 +85,7 @@ var SamplesReportsBarChart = React.createClass({ ref={function(ref) { if (ref) { d3.select(ref.getDOMNode()).call(xAxis); rotateLabels(ref); }}}> CONCENTRATION (copies/ml) + y="6" dy=".1em" style={{textAnchor: 'end'}}>CONCENTRATION (copies/mL) {/* Y Axis */} diff --git a/app/assets/javascripts/components/samples_reports_line_chart.js.jsx b/app/assets/javascripts/components/samples_reports_line_chart.js.jsx index 9501f442c..e538b041c 100644 --- a/app/assets/javascripts/components/samples_reports_line_chart.js.jsx +++ b/app/assets/javascripts/components/samples_reports_line_chart.js.jsx @@ -119,7 +119,7 @@ var SamplesReportsLineChart = React.createClass({ ref={function(ref) { if (ref) { d3.select(ref.getDOMNode()).call(xAxis); rotateLabels(ref); }}}> CONCENTRATION (copies/ml) + y="6" dy=".1em" style={{textAnchor: 'end'}}>CONCENTRATION (copies/mL) {/* Y Axis */}
{sample.uuid} {sample.batch_number}
-
{sample.concentration} copies/ml
+
{sample.concentration} copies/mL
); } else { diff --git a/app/views/nih_tables/nih_challenge.csv.csvbuilder b/app/views/nih_tables/nih_challenge.csv.csvbuilder index ccc7cda87..799ac0f17 100644 --- a/app/views/nih_tables/nih_challenge.csv.csvbuilder +++ b/app/views/nih_tables/nih_challenge.csv.csvbuilder @@ -9,7 +9,7 @@ csv << [ 'pango_lineage', 'who_label', 'non_clinical_cutoff_min', - 'non_clinical_cutoff_unit', + 'non_clinical_cutoff_min_unit', 'true_positives', 'false_positives', 'true_negatives', @@ -35,19 +35,19 @@ csv << [ @target_sample.target_organism_taxonomy_id, @target_sample.pango_lineage, @target_sample.who_label, - @samples_report.threshold, - 'copies/ml', + params[:threshold], + 'copies/mL', params[:true_positives], params[:false_positives], params[:true_negatives], params[:false_negatives], - params[:tpr], + params[:sensitivity], nil, nil, - params[:fpr], + params[:specificity], nil, nil, params[:auc], - params[:roc_x_values], - params[:roc_y_values] + params[:roc_x_values].gsub(",","|"), + params[:roc_y_values].gsub(",","|") ] diff --git a/app/views/nih_tables/nih_results.csv.csvbuilder b/app/views/nih_tables/nih_results.csv.csvbuilder index 756aaa93c..8dae7710c 100644 --- a/app/views/nih_tables/nih_results.csv.csvbuilder +++ b/app/views/nih_tables/nih_results.csv.csvbuilder @@ -11,7 +11,7 @@ csv << [ @samples_report.samples.each do |sample| csv << [ - sample.id, + sample.uuid, sample.box.uuid, "#{sample.box.purpose}-panel", nil, diff --git a/app/views/nih_tables/nih_samples.csv.csvbuilder b/app/views/nih_tables/nih_samples.csv.csvbuilder index 78486991f..7a3344edd 100644 --- a/app/views/nih_tables/nih_samples.csv.csvbuilder +++ b/app/views/nih_tables/nih_samples.csv.csvbuilder @@ -29,7 +29,7 @@ csv << [ nil, nil, sample.concentration, - 'copies/ml', + 'copies/mL', sample.reference_gene, sample.uuid, sample.batch_number, diff --git a/app/views/samples/_form.haml b/app/views/samples/_form.haml index 52e6f9344..d02d182c2 100644 --- a/app/views/samples/_form.haml +++ b/app/views/samples/_form.haml @@ -85,7 +85,7 @@ - @sample_form.blinded_attribute(:concentration) do .row.input-unit = f.text_field :concentration, min:0, readonly: !@can_update, :class=> "input-medium", :value => humanize_concentration(@sample_form.concentration), :pattern => "[\\d.]+(?:[eE]\\+?\\d+)?", :title => "(examples: 120, 12e1, 1.2e2, 1.2e+2, 1.2E2, 1.2E+2, 1.2E+02)" - .span.unit (copies/ml) + .span.unit (copies/mL) = f.form_field :replicate do - @sample_form.blinded_attribute(:replicate) do diff --git a/app/views/samples_reports/show.haml b/app/views/samples_reports/show.haml index c164e3b4c..efe0b5e83 100644 --- a/app/views/samples_reports/show.haml +++ b/app/views/samples_reports/show.haml @@ -316,11 +316,12 @@ true_negatives: ret.confusion_matrix.true_negative || 0, false_positives: ret.confusion_matrix.false_positive || 0, false_negatives: ret.confusion_matrix.false_negative || 0, - tpr: (ret.confusion_matrix.true_positive || 0) / ((ret.confusion_matrix.true_positive || 0) + (ret.confusion_matrix.false_negative || 0)), - fpr: (ret.confusion_matrix.false_positive || 0) / ((ret.confusion_matrix.false_positive || 0) + (ret.confusion_matrix.true_negative || 0)), - auc: #{auc(roc_curve(@samples_report))}, - roc_x_values: #{roc_curve(@samples_report).map{|x| x[0]}}, - roc_y_values: #{roc_curve(@samples_report).map{|x| x[1]}}, + sensitivity: ((ret.confusion_matrix.true_positive || 0) / ((ret.confusion_matrix.true_positive || 0) + (ret.confusion_matrix.false_negative || 0))).toFixed(3), + specificity: 1-((ret.confusion_matrix.false_positive || 0) / ((ret.confusion_matrix.false_positive || 0) + (ret.confusion_matrix.true_negative || 0))).toFixed(3), + auc: #{auc(roc_curve(@samples_report)).round(3)}, + roc_x_values: #{roc_curve(@samples_report).map{|x| x[0].round(3)}}, + roc_y_values: #{roc_curve(@samples_report).map{|x| x[1].round(3)}}, + threshold: parseFloat(threshold).toFixed(3), }; // create url params with the params dictionary diff --git a/public/templates/Instructions.txt b/public/templates/Instructions.txt index 3c3d62191..a95ff8cfb 100644 --- a/public/templates/Instructions.txt +++ b/public/templates/Instructions.txt @@ -1,2 +1,27 @@ -Instructions for the use of NIH tables. +This compressed file contains three tables containing data elements for the RADx-rad Data Hub. The tables +contain pre-filled data based on the information available to the CDx LIMS system. The tables are provided +to the user to fill in the missing information. Please note that you need to maintain the same format as +the one provided in the tables (CSV file format, with identical columns and rows). +The three provided tables are as follows: + +1. _samples.csv +2. _samples_results.csv +3. _.csv + +The first table contains one row per sample with general information about each sample. + +The second table contains one row per sample result, providing information about the results obtained for +each sample by the user, including the readout, measurement units, used technology, etc. + +The third table contains one row per panel and provides information about the aggregated results obtained +after the tests were performed. The can be either "LOD" or "Challenge" depending on the type of +test performed. + +Once the developer completes the missing data, these files are ready to be submitted to the RADx-rad +Data Core (https://www.radxrad.org/) for quality assurance. For more information, please contact +Dr. Peter Rose (pwrose.ucsd@gmail.com). The Data Core administrator will review the data for completeness +and consistency and will reach out to the developer if any issues arise. + +After the data passes the quality check, the Data Core administrator uploads the data files, common data +element dictionaries, and metadata files to the NIH COVID RADx-rad Data Hub (https://radx-hub.nih.gov/). From 59fc7986a338d9acd5688fdf61e6318b1b1b7959 Mon Sep 17 00:00:00 2001 From: Leandro Radusky Date: Mon, 28 Aug 2023 09:34:24 +0200 Subject: [PATCH 3/3] Spec fixes --- app/views/nih_tables/nih_challenge.csv.csvbuilder | 4 ++-- spec/controllers/nih_tables_controller_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/nih_tables/nih_challenge.csv.csvbuilder b/app/views/nih_tables/nih_challenge.csv.csvbuilder index 799ac0f17..a75381692 100644 --- a/app/views/nih_tables/nih_challenge.csv.csvbuilder +++ b/app/views/nih_tables/nih_challenge.csv.csvbuilder @@ -48,6 +48,6 @@ csv << [ nil, nil, params[:auc], - params[:roc_x_values].gsub(",","|"), - params[:roc_y_values].gsub(",","|") + params[:roc_x_values].to_s.gsub(",","|"), + params[:roc_y_values].to_s.gsub(",","|") ] diff --git a/spec/controllers/nih_tables_controller_spec.rb b/spec/controllers/nih_tables_controller_spec.rb index b14b655f6..8fb730872 100644 --- a/spec/controllers/nih_tables_controller_spec.rb +++ b/spec/controllers/nih_tables_controller_spec.rb @@ -61,7 +61,7 @@ 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}) + expect(samples_table["sample_id"]).to eq(@samples_report.samples_report_samples.map{|srs| srs.sample.uuid.to_s}) end it "should contain the LOD table for if the box purpose is LOD" do