From aac20ef8e1e96a907cb80b5c83eac8b78cba74ff Mon Sep 17 00:00:00 2001 From: davids60 Date: Fri, 6 Dec 2024 07:54:07 -0500 Subject: [PATCH] Pushed code, in-progress documentation, and added license info to documents. --- DigitalAssays/DigitalAnalysis.ipynb | 1326 +++++++++++++++++++++++++ DigitalAssays/DigitalAssayAnalysis.py | 218 ++++ DigitalAssays/README.md | 7 + PrimerAnalysis/PrimerAnalysis.ipynb | 518 ++++++++++ PrimerAnalysis/PrimerAnalysis.py | 511 ++++++++++ PrimerAnalysis/README.md | 146 +++ README.md | 2 + 7 files changed, 2728 insertions(+) create mode 100644 DigitalAssays/DigitalAnalysis.ipynb create mode 100644 DigitalAssays/DigitalAssayAnalysis.py create mode 100644 DigitalAssays/README.md create mode 100644 PrimerAnalysis/PrimerAnalysis.ipynb create mode 100644 PrimerAnalysis/PrimerAnalysis.py create mode 100644 PrimerAnalysis/README.md diff --git a/DigitalAssays/DigitalAnalysis.ipynb b/DigitalAssays/DigitalAnalysis.ipynb new file mode 100644 index 0000000..beda1f0 --- /dev/null +++ b/DigitalAssays/DigitalAnalysis.ipynb @@ -0,0 +1,1326 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Digital Assay Analysis\n", + "\n", + "## License\n", + "Copyright (C) 2024 Purdue Research Foundation. This work is protected under GNU Affero General Public License Version 3 with Commons Clause. Please see the `LICENSE` file for more information." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import DigitalAssayAnalysis\n", + "from os import walk\n", + "from os.path import join" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculation of concentration for fine LODs using dPCR" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SampleAvgConc(rxn)AvgConc(rxn) LowAvgConc(rxn) High
A12x_LOD811732892
B11x_LOD393370417
C19%Field_NTC000
\n", + "
" + ], + "text/plain": [ + " Sample AvgConc(rxn) AvgConc(rxn) Low AvgConc(rxn) High\n", + "A1 2x_LOD 811 732 892\n", + "B1 1x_LOD 393 370 417\n", + "C1 9%Field_NTC 0 0 0" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SampleConc(cps/rxn)LowConcHighConcAvgConc(rxn)AvgConc(rxn) LowAvgConc(rxn) HighTotalPositiveNegativeConc(cps/uL)lambda_perclambda_centerlambda_lowlambda_highAvgConc(uL)AvgConc(uL) LowAvgConc(uL) HighVolume
A12x_LOD764.314957708.735036820.011980811.800693731.080398892.520988254407252471538.2157487.2795220.0289120.0268100.03101940.59003536.55402044.62604919.961
A22x_LOD850.882651791.982111909.913629811.800693731.080398892.520988254648002466442.5441336.9299520.0319210.0297110.03413640.59003536.55402044.62604919.796
A32x_LOD820.619420762.679124878.685657811.800693731.080398892.520988254207692465141.0309717.0682300.0307190.0285500.03289240.59003536.55402044.62604919.753
B11x_LOD406.819557366.212498447.488448393.260788369.114740417.406836254693852508420.3409789.9891890.0152320.0137110.01675519.66303918.45573720.87034219.757
B21x_LOD380.613504340.823378420.461404393.260788369.114740417.406836254843512513319.03067510.4617970.0138690.0124190.01532119.66303918.45573720.87034219.228
B31x_LOD391.993868351.863179432.184143393.260788369.114740417.406836254563662509019.59969310.2451810.0144820.0129990.01596719.66303918.45573720.87034219.495
C19%Field_NTC0.0000000.0000000.0000000.0000000.0000000.000000254400254400.0000000.0000000.0000000.0000000.0000000.0000000.0000000.00000019.519
C29%Field_NTC0.0000000.0000000.0000000.0000000.0000000.000000255070255070.0000000.0000000.0000000.0000000.0000000.0000000.0000000.00000018.829
C39%Field_NTC0.0000000.0000000.0000000.0000000.0000000.000000254540254540.0000000.0000000.0000000.0000000.0000000.0000000.0000000.00000019.324
\n", + "
" + ], + "text/plain": [ + " Sample Conc(cps/rxn) LowConc HighConc AvgConc(rxn) \\\n", + "A1 2x_LOD 764.314957 708.735036 820.011980 811.800693 \n", + "A2 2x_LOD 850.882651 791.982111 909.913629 811.800693 \n", + "A3 2x_LOD 820.619420 762.679124 878.685657 811.800693 \n", + "B1 1x_LOD 406.819557 366.212498 447.488448 393.260788 \n", + "B2 1x_LOD 380.613504 340.823378 420.461404 393.260788 \n", + "B3 1x_LOD 391.993868 351.863179 432.184143 393.260788 \n", + "C1 9%Field_NTC 0.000000 0.000000 0.000000 0.000000 \n", + "C2 9%Field_NTC 0.000000 0.000000 0.000000 0.000000 \n", + "C3 9%Field_NTC 0.000000 0.000000 0.000000 0.000000 \n", + "\n", + " AvgConc(rxn) Low AvgConc(rxn) High Total Positive Negative \\\n", + "A1 731.080398 892.520988 25440 725 24715 \n", + "A2 731.080398 892.520988 25464 800 24664 \n", + "A3 731.080398 892.520988 25420 769 24651 \n", + "B1 369.114740 417.406836 25469 385 25084 \n", + "B2 369.114740 417.406836 25484 351 25133 \n", + "B3 369.114740 417.406836 25456 366 25090 \n", + "C1 0.000000 0.000000 25440 0 25440 \n", + "C2 0.000000 0.000000 25507 0 25507 \n", + "C3 0.000000 0.000000 25454 0 25454 \n", + "\n", + " Conc(cps/uL) lambda_perc lambda_center lambda_low lambda_high \\\n", + "A1 38.215748 7.279522 0.028912 0.026810 0.031019 \n", + "A2 42.544133 6.929952 0.031921 0.029711 0.034136 \n", + "A3 41.030971 7.068230 0.030719 0.028550 0.032892 \n", + "B1 20.340978 9.989189 0.015232 0.013711 0.016755 \n", + "B2 19.030675 10.461797 0.013869 0.012419 0.015321 \n", + "B3 19.599693 10.245181 0.014482 0.012999 0.015967 \n", + "C1 0.000000 0.000000 0.000000 0.000000 0.000000 \n", + "C2 0.000000 0.000000 0.000000 0.000000 0.000000 \n", + "C3 0.000000 0.000000 0.000000 0.000000 0.000000 \n", + "\n", + " AvgConc(uL) AvgConc(uL) Low AvgConc(uL) High Volume \n", + "A1 40.590035 36.554020 44.626049 19.961 \n", + "A2 40.590035 36.554020 44.626049 19.796 \n", + "A3 40.590035 36.554020 44.626049 19.753 \n", + "B1 19.663039 18.455737 20.870342 19.757 \n", + "B2 19.663039 18.455737 20.870342 19.228 \n", + "B3 19.663039 18.455737 20.870342 19.495 \n", + "C1 0.000000 0.000000 0.000000 19.519 \n", + "C2 0.000000 0.000000 0.000000 18.829 \n", + "C3 0.000000 0.000000 0.000000 19.324 " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "inputFilePath = \"/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/data/BRD/SensSpec/input/20240109_BRSV.M2.1_SensSpec-dPCRData.csv\"\n", + "outputFilePath = \"/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/data/BRD/SensSpec/output/20240109_BRSV.M2.1_SensSpec-dPCRData.xlsx\"\n", + "summary_df, results_df = DigitalAssayAnalysis.calc_dPCRStats(inputFilePath, outputFilePath, plate_type='26k')\n", + "display(summary_df, results_df)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Calculation of background sample concentration using dPCR" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:23: RuntimeWarning: divide by zero encountered in scalar divide\n", + " partitionVol = row['Volume']/(numHyperwells * partition_count[plate_type])\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:23: RuntimeWarning: divide by zero encountered in scalar divide\n", + " partitionVol = row['Volume']/(numHyperwells * partition_count[plate_type])\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: divide by zero encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:78: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5\n", + "/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/DigitalAssayAnalysis.py:85: RuntimeWarning: invalid value encountered in scalar divide\n", + " std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5\n" + ] + } + ], + "source": [ + "# For background data, we will simply loop through each file, one per virus and run the analysis\n", + "fileNames = [(dirpath,f) for (dirpath, dirnames, filenames) in walk('/home/davids60/working/src/AnalysisScripts/DigitalAssayAnalysis/data/BRD/Background') for f in filenames]\n", + "\n", + "# For each file we found in our directory for the input background data files, see if it is in the input folder, and run the analysis\n", + "for file in fileNames:\n", + " # Split directory and file name to get directory path and file name\n", + " dir = file[0]\n", + " fn = file[1]\n", + "\n", + " # Check if the file is in the input folder\n", + " if(dir.split(\"/\")[-1] == 'input'):\n", + " # Join the directory and file name to get the full file path\n", + " fInPath = join(dir, fn)\n", + "\n", + " # Determine the output directory and file name\n", + " outputDirIdx = dir.rfind(\"/\")\n", + " fileNameIdx = fn.rfind(\".\")\n", + " fOutPath = f\"{dir[:outputDirIdx]}/output/{fn[:fileNameIdx]}.xlsx\"\n", + "\n", + " # Run analysis. For this specific setup, the background analysis was conducted on a 96-well, 8.5k plate with hyperwelling every E3 - H3 and E6 - H6.\n", + " # Additionally, since we are interested in the copies per microliter as opposed to copies per reaction, we will set the template_rxn_vol to 1\n", + " # and interpret the concentration as copies per microliter in the output file where it indicates copies per reaction.\n", + " DigitalAssayAnalysis.calc_dPCRStats(fInPath, fOutPath, plate_type='8.5k', makeSummary = False, rxn_dilution_factor = 4 , template_rxn_vol = 1, hyperwellGroups=[['E3','F3','G3','H3'], ['E6', 'F6', 'G6', 'H6']])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "homepy39", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.20" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/DigitalAssays/DigitalAssayAnalysis.py b/DigitalAssays/DigitalAssayAnalysis.py new file mode 100644 index 0000000..c189c3b --- /dev/null +++ b/DigitalAssays/DigitalAssayAnalysis.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +'''Digital Assay Analysis.py is a python module for analyzing digital assay data acquired with Qiagen QIAcuity Software''' + +__author__ = 'Josiah Levi Davidson' +__contact__ = 'Mohit S. Verma' +__email__ = 'msverma@purdue.edu' +__version__ = '1.0.0' +__status__ = 'Development' +__copyright__ = "Copyright (C) 2024 Purdue Research Foundation" +__license__ = "GNU Affero General Public License Version 3 with Commons Clause" + +#### BEGIN IMPORTS + +import pandas as pd +import numpy as np +from scipy.stats import t + +# Set partition counts based on manufacturer specifications +# (Page 102 of the QIAcuity App. Guide, +# https://www.qiagen.com/us/resources/resourcedetail?id=5d19083d-fa10-4ed2-88a0-2953d9947e0c) +partition_count = {'8.5k': 8510, '26k': 26384} + +def calc_absoluteQuant(row, rxn_dilution_factor, template_rxn_vol, plate_type): + # If there is no positive partitions, return 0 for everything + if row['Positive'] == 0: + return [0,0,0,0,0,0,0,0] + else: + # Calculate the number of hyperwells based on the approximate devision for a full well + # NOTE: This will fail if the imaging step fails to identify well based on the reference dye + numHyperwells = round(row['Total']/partition_count[plate_type]) + + # Calculate average partition volume + partitionVol = row['Volume']/(numHyperwells * partition_count[plate_type]) + + # Calculate percent positive partitions + p = row['Positive']/row['Total'] + + # Calculate lambda and confidence around lambda + lambda_center = -np.log(row['Negative']/row['Total']) + lambda_low = -np.log((1 - p + 1.96*np.sqrt(p*(1-p)/row['Total']))) + lambda_high = -np.log((1 - p - 1.96*np.sqrt(p*(1-p)/row['Total']))) + + # Determine lambda range + lambda_range = lambda_high - lambda_low + + # If lambda range is greater than lambda center, use lambda high for percentage, else use lambda range + # NOTE: I was not able to determine why this substitution was made, but it was nevertheless necessary + # to produce results identical to that of the QIAcuity software suite + if lambda_range > lambda_center: + lambda_perc = lambda_high/(2*lambda_center)*100 + else: + lambda_perc = lambda_range/(2*lambda_center) * 100 + + # Calculate concentration per µL + conc_dPCRRxn_uL = (lambda_center / partitionVol) + + # Calculate concentration per reaction and confidence bounds + conc_avg = (lambda_center / partitionVol) * rxn_dilution_factor * template_rxn_vol + conc_low = (lambda_low / partitionVol) * rxn_dilution_factor * template_rxn_vol + conc_high = (lambda_high / partitionVol) * rxn_dilution_factor * template_rxn_vol + + # Return all concentration values + return [conc_dPCRRxn_uL,conc_avg, conc_low, conc_high, lambda_perc, lambda_center, lambda_low, lambda_high] + +def calc_avgQuant(rows, rxn_dilution_factor, template_rxn_vol, plate_type, alpha_crit = 0.05): + # Calculate the number of hyperwells based on the approximate devision for a full well + # NOTE: This will fail if the imaging step fails to identify well based on the reference dye + numHyperwells = (rows['Total']/partition_count[plate_type]).round() + + # Calculate average partition volume + partVol = rows['Volume']/partition_count[plate_type] + + # Calculate ideal partition count for plate type + wellPartCount = numHyperwells * partition_count[plate_type] + + # Calculate the average concentration per microliter + a = rows['Volume'].mul(rows['Conc(cps/uL)'], axis=0).div(wellPartCount) + conc_avg_uL = a.sum()/(partVol).sum() + + # Calculate the average concentration per reaction + a = rows['Volume'].mul(rows['Conc(cps/rxn)'], axis=0).div(wellPartCount) + conc_avg_rxn = a.sum()/(partVol).sum() + + # Calculate the t-critical value based on number of replicates + t_crit = t.ppf(1-(alpha_crit/2), df=rows.shape[0]) + + # Calculate the standard deviation of the concentration per microliter based on the t-critical value + std_conc_uL = (((rows['Conc(cps/uL)'] - conc_avg_uL)**2).sum()/(rows.shape[0]-1))**0.5 + + # Calculate high and low concentration per microliter bounds for a (1-alpha)% confidence interval + conc_avg_uL_low = conc_avg_uL - t_crit*std_conc_uL/(rows.shape[0]**0.5) + conc_avg_uL_high = conc_avg_uL + t_crit*std_conc_uL/(rows.shape[0]**0.5) + + # Calculate the standard deviation of the concentration per reaction based on the t-critical value + std_conc_rxn = (((rows['Conc(cps/rxn)'] - conc_avg_rxn)**2).sum()/(rows.shape[0]-1))**0.5 + + # Calculate high and low concentration per reaction bounds for a (1-alpha)% confidence interval + conc_avg_rxn_low = conc_avg_rxn - t_crit*std_conc_rxn/(rows.shape[0]**0.5) + conc_avg_rxn_high = conc_avg_rxn + t_crit*std_conc_rxn/(rows.shape[0]**0.5) + + return [conc_avg_uL, conc_avg_uL_low, conc_avg_uL_high, conc_avg_rxn, conc_avg_rxn_low, conc_avg_rxn_high ] + +def calc_dPCRStats(fileInputPath, fileOutputPath, plate_type = '26k', rxn_dilution_factor = 4, template_rxn_vol = 5, makeSummary = True, hyperwellGroups = []) -> tuple[pd.DataFrame, pd.DataFrame]: + # Read in data file without limiting memory usage, as file is large. + """ + Reads in a Digital PCR file from QIAcuity and calculates the concentrations based on the sample name. + The calculations are done on a per well basis, and the results are then averaged over the wells within a sample + to generate a summary dataframe. The results are then written out to an excel file with the sample name and + calculated concentrations. + + Parameters: + fileInputPath (str): The path to the Digital PCR file from QIAcuity. + fileOutputPath (str): The path to the output excel file. + plate_type (str): The type of plate used. Default is '26k'. + rxn_dilution_factor (int): The dilution factor for the reaction. Default is 4. + template_rxn_vol (int): The volume of the reaction. Default is 5. + makeSummary (bool): Whether or not to make a summary dataframe. Default is True. + hyperwellGroups (list): A list of lists, where each sublist is a group of wells to be hyperwelled together. + + Returns: + tuple[pd.DataFrame, pd.DataFrame]: A tuple containing the summary dataframe and the full dataframe. + """ + df = pd.read_csv(fileInputPath, low_memory=False, header=1) + + # Loop through each group that we will hyperwell together + for hGroup in hyperwellGroups: + # Merge wells in group together based on Well identifier + groupVols = df[df['Well'].isin(hGroup)][['Well', 'Cycled volume']].drop_duplicates() + # Total yperwell volume is the sum of each well in group + totalVol = groupVols['Cycled volume'].sum() + + # Assign total volume and name to each well in hyperwell to complete "merge" + df.loc[df['Well'].isin(hGroup), 'Cycled volume'] = totalVol + df.loc[df['Well'].isin(hGroup), 'Well'] = hGroup[0] + + # Set threshold as the first unique value. Common threshold should be used. + threshold = df['Threshold'].unique()[0] + + # Create summary table based on unique sample names + sampleList = df['Sample'].unique() + + # Create rows for resulting concentration in each row. + rows = df['Well'].unique() + cols = ['Sample', 'Total', 'Positive', 'Negative', 'Conc', 'LowConc', 'HighConc', 'Volume', + 'Conc(cps/uL)', 'Conc(cps/rxn)', 'lambda_perc', 'lambda_center', + 'lambda_low', 'lambda_high'] + + # Initialize summary dataframe + resultsDf = pd.DataFrame(0, index=rows, columns=cols) + + resultsDf = resultsDf.astype({cols[0] : str}) + resultsDf = resultsDf.astype({key: int for key in cols[1:4]}) + resultsDf = resultsDf.astype({key: float for key in cols[4:]}) + + #sumDf.loc[:, ['Conc(cps/uL)', 'Conc(cps/rxn)', 'LowConc', 'HighConc', 'lambda_perc', 'lambda_center', 'lambda_low', 'lambda_high']].astype(float) + # Loop through each well and calculate stats + for well in rows: + # Select data only for current well + currentWellData = df[(df['Well'] == well) & (df['Is invalid'] == "0")] + + # Set sample name for current well. Whereas unique() should only return one value, we index in case + # any typo or edits occured so as not to introduce errors. + resultsDf.loc[well, 'Sample'] = currentWellData['Sample'].unique()[0] + + # Determine invalid well counts based on QIAcuity invalid designation, and then positive and negative annotations + # based on amplification being located above or below threshold. + resultsDf.loc[well, 'Total'] = currentWellData[currentWellData['Is invalid'] == "0"]['Is invalid'].count() + resultsDf.loc[well, 'Positive'] = currentWellData[currentWellData['RFU'] >= threshold]['RFU'].count() + resultsDf.loc[well, 'Negative'] = currentWellData[currentWellData['RFU'] < threshold]['RFU'].count() + + # Set current well volume, which should be unique but in the event mutation of data occurred, select the first value + resultsDf.loc[well, 'Volume'] = currentWellData['Cycled volume'].unique()[0] + + # Calculate concentrations and concentration range + resultsDf.loc[well, ['Conc(cps/uL)', 'Conc(cps/rxn)', 'LowConc', 'HighConc', 'lambda_perc', 'lambda_center', + 'lambda_low', 'lambda_high']] = calc_absoluteQuant(resultsDf.loc[well, :], rxn_dilution_factor, template_rxn_vol, plate_type) + + for sample in sampleList: + #currentSampleData = df[df['Sample'] == sample] + + resultsDf.loc[resultsDf[resultsDf['Sample'] == sample].index, + ['AvgConc(uL)', 'AvgConc(uL) Low', 'AvgConc(uL) High', 'AvgConc(rxn)', 'AvgConc(rxn) Low', 'AvgConc(rxn) High']] = \ + calc_avgQuant(resultsDf[resultsDf['Sample'] == sample], 4, 5, plate_type) + + resultsDf = resultsDf[['Sample', 'Conc(cps/rxn)', 'LowConc', 'HighConc', 'AvgConc(rxn)', 'AvgConc(rxn) Low', + 'AvgConc(rxn) High', 'Total', 'Positive', 'Negative', 'Conc(cps/uL)', 'lambda_perc', + 'lambda_center', 'lambda_low', 'lambda_high', 'AvgConc(uL)', 'AvgConc(uL) Low', + 'AvgConc(uL) High', 'Volume']] + + summaryDf = pd.DataFrame() + + if makeSummary: + # Create a summary dataframe that only shows whole number copies per reaction for each level + summaryDf = resultsDf[['Sample', 'AvgConc(rxn)', 'AvgConc(rxn) Low', 'AvgConc(rxn) High']].drop_duplicates() + + # For average values, round down if positive and round up if negative + summaryDf.loc[summaryDf[summaryDf['AvgConc(rxn)'] < 0].index, 'AvgConc(rxn)'] = np.ceil(summaryDf[summaryDf['AvgConc(rxn)'] < 0]['AvgConc(rxn)']) + summaryDf.loc[summaryDf[summaryDf['AvgConc(rxn)'] > 0].index, 'AvgConc(rxn)'] = np.floor(summaryDf[summaryDf['AvgConc(rxn)'] > 0]['AvgConc(rxn)']) + + # Round the high and low confidence intervals such that the intervals are being contracted not expanded + # by the rounding operation\ + summaryDf['AvgConc(rxn) Low'] = np.ceil(summaryDf['AvgConc(rxn) Low']) + summaryDf['AvgConc(rxn) High'] = np.floor(summaryDf['AvgConc(rxn) High']) + + summaryDf = summaryDf.astype({key: int for key in summaryDf.columns[1:]}) + + # Write summary data to "optimalResults" sheet in output and write full data to "data" sheet in output excel file + with pd.ExcelWriter(fileOutputPath) as writer: + summaryDf.to_excel(writer, sheet_name='Summary') + resultsDf.to_excel(writer, sheet_name='data') + else: + # Write full data to "data" sheet in output + with pd.ExcelWriter(fileOutputPath) as writer: + resultsDf.to_excel(writer, sheet_name='data') + + # Return dataframes + return summaryDf, resultsDf \ No newline at end of file diff --git a/DigitalAssays/README.md b/DigitalAssays/README.md new file mode 100644 index 0000000..6098169 --- /dev/null +++ b/DigitalAssays/README.md @@ -0,0 +1,7 @@ +# Digital Assay (dPCR, dLAMP, etc.) Computations + +This folder contains a variety of scripts for formatting and calculation of digital assay results. + +*This documentation is presently UNDER DEVELOPMENT and does not yet reflect intended usage. Please see the jupyter notebook for current intended usage while documentation is being updated.* + +

© 2024. Purdue Research Foundation. Primer Analysis Documentation by Josiah Davidson and Purdue Research Foundation is licensed under CC BY-NC 4.0

\ No newline at end of file diff --git a/PrimerAnalysis/PrimerAnalysis.ipynb b/PrimerAnalysis/PrimerAnalysis.ipynb new file mode 100644 index 0000000..686dc5d --- /dev/null +++ b/PrimerAnalysis/PrimerAnalysis.ipynb @@ -0,0 +1,518 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Execution of Primer Scoring and data analysis code for BRD publication\n", + "\n", + "## Setup and initialization\n", + "Import `PrimerAnalysis` and `matplotlib` dependencies for this module\n", + "\n", + "## License\n", + "\n", + "Copyright (C) 2024 Purdue Research Foundation. This work is protected under GNU Affero General Public License Version 3 with Commons Clause. Please see the `LICENSE` file for more information.\n", + "\n", + "## Import" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from matplotlib import pyplot as plt\n", + "\n", + "import PrimerAnalysis" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Set file and input/output directory paths" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Set list of virus names\n", + "virusName = ['BAV-3', 'BHV-1', 'bPIV-3', 'BRSV', 'BVDV-1']\n", + "\n", + "# Set path for primer scoring data\n", + "screeningPathInputPattern = \"./data/screening/input/BRD_pub/{}Screening.xls\"\n", + "coarseLODInputPath = \"/home/davids60/working/src/AnalysisScripts/PrimerScoring/data/LOD/CoarseLODs_Compiled.xls\"\n", + "fineLODGenomicInputPathPattern = \"/home/davids60/working/src/AnalysisScripts/PrimerScoring/data/LOD/fineLODs_Round{}_Compiled.xls\"\n", + "fineLODVirusInputPath = \"/home/davids60/working/src/AnalysisScripts/PrimerScoring/data/LOD/FineLOD_WholeVirus.xls\"\n", + "sensSpecInputPath = \"/home/davids60/working/src/AnalysisScripts/PrimerScoring/data/SensSpec/input/SensSpecData.xls\"\n", + "\n", + "\n", + "# Set path for primer scoring output\n", + "screeningPathOutputPattern = \"./data/screening/output/BRD_pub/{}Screening.csv\"\n", + "coarseLODOutputPath = \"/home/davids60/working/src/AnalysisScripts/PrimerScoring/data/LOD/output/CoarseLODs_Compiled.csv\"\n", + "fineLODGenomicOutputPathPattern = \"/home/davids60/working/src/AnalysisScripts/PrimerScoring/data/LOD/output/fineLODs_Round{}_Compiled.csv\"\n", + "fineLODVirusOutputPath = \"/home/davids60/working/src/AnalysisScripts/PrimerScoring/data/LOD/output/FineLOD_WholeVirus.csv\"\n", + "sensSpecOutputPath = \"/home/davids60/working/src/AnalysisScripts/PrimerScoring/data/SensSpec/output/SensSpecResults.xlsx\"\n", + "\n", + "# Define number of fine LOD rounds\n", + "numFineLODRounds = 2\n", + "\n", + "# Initialize PrimerAnalysis class\n", + "PrimerAnalysis.initialize([5,10,15,10,60], [3000, 200, 0.9, 0.2], 4, set_threshold_perc=0.2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stage 1: Primer Scoring\n", + "\n", + "Execute the `scorePrimers` function of the `PrimerAnalysis` module to score and rank primers for each virus." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Loop through each virus in our list of virus names\n", + "for virus in virusName:\n", + " # Score primers for each virus and output results to csv file using output filename pattern\n", + " PrimerAnalysis.scorePrimers(screeningPathInputPattern.format(virus), screeningPathOutputPattern.format(virus))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stage 2: Coarse LOD Analysis\n", + "\n", + "Execute the `scoreLOD` function of the `PrimerAnalysis` module to determine and rank the LOD for each primer set that has progressed to Stage 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Run coarse LOD primer screening. Result is a dataframe that is additionally written to an output csv as defined by the output path\n", + "coarseLOD_df = PrimerAnalysis.score_LOD(coarseLODInputPath, coarseLODOutputPath)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Stage 3: Fine LOD Analysis\n", + "\n", + "Execute the `scoreLOD` function of the `PrimerAnalysis` module to determine and rank the fine LOD for each primer set that has progressed to Stage 3. The fine LOD will be broken into successive rounds depending on if the fine LOD is below the minimum dilution level based on the coarse LOD of primer sets progressing to stage 3." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "fineLODGenomicResults_dfList = []\n", + "for fineLODRound in range(1, numFineLODRounds+1):\n", + " fineLODGenomicResults_dfList.append(PrimerAnalysis.score_LOD(fineLODGenomicInputPathPattern.format(fineLODRound), fineLODGenomicOutputPathPattern.format(fineLODRound)))\n", + "\n", + "fineLODVirusResutls_df = PrimerAnalysis.score_LOD(fineLODVirusInputPath, fineLODVirusOutputPath)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sensitivity and Specificity Analysis\n", + "\n", + "Carry out sensitivity and specificity analysis for all primer sets tested." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Primer SetConcentrationTtTPTNFPFNFPRFNRSensitivitySpecificityAccuracyError
0BAV-3.pV.32x3830.030.00.00.00.0000000.0000001.0000001.0000001.0000000.000000
1BHV-1.gD.42x2430.030.00.00.00.0000000.0000001.0000001.0000001.0000000.000000
2bPIV-3.L.12x3428.030.00.02.00.0000000.0666670.9333331.0000000.9666670.066667
3BRSV.M2.12x4022.027.03.08.00.1000000.2666670.7333330.9000000.8166670.284800
4BVDV-1.5UTR.32x2925.030.00.05.00.0000000.1666670.8333331.0000000.9166670.166667
5BAV-3.pV.31x4529.030.00.01.00.0000000.0333330.9666671.0000000.9833330.033333
6BHV-1.gD.41x2830.030.00.00.00.0000000.0000001.0000001.0000001.0000000.000000
7bPIV-3.L.11x5325.030.00.05.00.0000000.1666670.8333331.0000000.9166670.166667
8BRSV.M2.11x4220.025.05.010.00.1666670.3333330.6666670.8333330.7500000.372678
9BVDV-1.5UTR.31x3621.030.00.09.00.0000000.3000000.7000001.0000000.8500000.300000
\n", + "
" + ], + "text/plain": [ + " Primer Set Concentration Tt TP TN FP FN FPR FNR \\\n", + "0 BAV-3.pV.3 2x 38 30.0 30.0 0.0 0.0 0.000000 0.000000 \n", + "1 BHV-1.gD.4 2x 24 30.0 30.0 0.0 0.0 0.000000 0.000000 \n", + "2 bPIV-3.L.1 2x 34 28.0 30.0 0.0 2.0 0.000000 0.066667 \n", + "3 BRSV.M2.1 2x 40 22.0 27.0 3.0 8.0 0.100000 0.266667 \n", + "4 BVDV-1.5UTR.3 2x 29 25.0 30.0 0.0 5.0 0.000000 0.166667 \n", + "5 BAV-3.pV.3 1x 45 29.0 30.0 0.0 1.0 0.000000 0.033333 \n", + "6 BHV-1.gD.4 1x 28 30.0 30.0 0.0 0.0 0.000000 0.000000 \n", + "7 bPIV-3.L.1 1x 53 25.0 30.0 0.0 5.0 0.000000 0.166667 \n", + "8 BRSV.M2.1 1x 42 20.0 25.0 5.0 10.0 0.166667 0.333333 \n", + "9 BVDV-1.5UTR.3 1x 36 21.0 30.0 0.0 9.0 0.000000 0.300000 \n", + "\n", + " Sensitivity Specificity Accuracy Error \n", + "0 1.000000 1.000000 1.000000 0.000000 \n", + "1 1.000000 1.000000 1.000000 0.000000 \n", + "2 0.933333 1.000000 0.966667 0.066667 \n", + "3 0.733333 0.900000 0.816667 0.284800 \n", + "4 0.833333 1.000000 0.916667 0.166667 \n", + "5 0.966667 1.000000 0.983333 0.033333 \n", + "6 1.000000 1.000000 1.000000 0.000000 \n", + "7 0.833333 1.000000 0.916667 0.166667 \n", + "8 0.666667 0.833333 0.750000 0.372678 \n", + "9 0.700000 1.000000 0.850000 0.300000 " + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "[optimalResults, allResults] = PrimerAnalysis.executeSensSpecAnalysis(sensSpecInputPath, sensSpecOutputPath)\n", + "optimalResults" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAHFCAYAAAAe+pb9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABJIUlEQVR4nO3deXhU1f3H8c/MZJmEkEAC2VhCVBAQQQyCgFRADYIiCBYqyuZSKW5I0UJpVfjZYm2lrmBF2RQVQUS0kaWCgJWibIpCxQUBIWEJJAGSkGXO7w/I1CEJJMMkl+S+X88zz+OcOffe78wlMx/PuYvDGGMEAABgQ06rCwAAALAKQQgAANgWQQgAANgWQQgAANgWQQgAANgWQQgAANgWQQgAANgWQQgAANgWQQgAANgWQQiohNmzZ8vhcHgfQUFBSkhI0K9+9St9++23ZS5TWFio6dOnq3PnzoqKilJYWJhatWql8ePHKzMzs8xlPB6PXnvtNV177bVq0KCBgoODFRsbqxtvvFHvv/++PB7PWWs9ceKEXnjhBV111VWqX7++QkJC1KhRIw0aNEirV68+p8/BSs8//7wuuugihYSEyOFwKCsrq8q2dfr+djgcatiwobp3764PPvig3OUOHTqk0NBQORwObdiwwdt+8OBBhYSE6Fe/+lW5y+bk5Cg8PFw33XRTuX327Nmjm2++WRdccIHq1KmjqKgotW/fXi+88IKKior8e7OnOddaq6NGIBAIQoAfZs2apXXr1ulf//qX7rvvPi1ZskRXXXWVjhw54tMvNzdX1113ne6//361b99eb775ptLS0jR06FC9/PLLat++vb755hufZfLz89WnTx8NHz5csbGxmj59ulauXKmXXnpJiYmJ+uUvf6n333//jPUdOnRIXbt21dixY9WmTRvNnj1bH330kZ5++mm5XC5dc801+uKLLwL+uVS1LVu26IEHHlCPHj20cuVKrVu3TnXr1q3y7Zbs708//VQvv/yyXC6X+vbtW+5+eO2111RQUCBJevXVV73tDRs21E033aTFixeX+rdS4q233lJeXp7uvPPOcus5fvy4IiMj9cc//lFLlizRW2+9pauuukr333+/Ro0adQ7v9H/OtdbqqBEICAOgwmbNmmUkmc8//9ynfdKkSUaSmTlzpk/7r3/9ayPJvPXWW6XW9c0335ioqChzySWXmKKiIm/7b37zGyPJzJkzp8waduzYYb744osz1tm7d28TFBRkPvroozJf/+yzz8yuXbvOuI6Kys3NDch6KuL11183ksz69esDts7jx4+X+1p5+zs3N9eEhoaaW2+9tczl2rRpY2JjY80VV1xhoqKifD6jtLQ0I8k8//zzZS7bqVMnExcXZwoLCyv9XgYNGmSCgoJMfn5+pZctS1XUGugagXPFiBAQAB06dJAk7d+/39uWkZGhmTNnqlevXho8eHCpZVq0aKHf/e53+vrrr7V48WLvMq+88op69eqlYcOGlbmt5s2bq23btuXWsnHjRn344Ye688471bNnzzL7XHHFFWratKkk6fHHH5fD4SjVp2Ra6Mcff/S2NWvWTDfeeKMWLVqk9u3by+12a9KkSWrfvr26detWah3FxcVq1KiRBgwY4G0rKCjQE088oZYtWyo0NFQNGzbUyJEjdfDgwXLfkyR1795dt99+uySpU6dOcjgcGjFihPf1mTNnql27dnK73YqOjtbNN9+s7du3+6xjxIgRioiI0NatW5Wamqq6devqmmuuOeN2y+J2uxUSEqLg4OBSr61fv15fffWVhg4dqrvvvlvZ2dl65513vK/36tVLjRs31qxZs0otu337dq1fv17Dhg1TUFBQpetq2LChnE6nXC7XGfuV7PPNmzdrwIABioyMVFRUlG6//Xaf/VAVtVa0RqC6EISAANi5c6ekk+GmxKpVq1RUVKT+/fuXu1zJaytWrPAuU1hYeMZlzmb58uU+6w60TZs26eGHH9YDDzygpUuXauDAgRo5cqQ++eSTUsdJLV++XPv27dPIkSMlnTz2qV+/fnryySc1ZMgQ/fOf/9STTz6pFStWqHv37srLyyt3u9OmTdMf/vAHSf+bqvrjH/8oSZoyZYruvPNOXXLJJVq0aJGeffZZffnll+rcuXOpmgoKCnTTTTepZ8+eeu+99zRp0qSzvufi4mIVFRWpsLBQP/30k8aMGaPjx49ryJAhpfqWTIXdcccd+tWvfqXw8HCf6TGn06kRI0Zo06ZNpaYnSwLHHXfccdaaJMkYo6KiIh05ckTz58/X7Nmz9dvf/rbCweTmm2/WRRddpIULF+rxxx/X4sWL1atXLxUWFgas1nOtEahyVg9JATVJyVTJf/7zH1NYWGiOHj1qli5dauLj480vfvELnymCJ5980kgyS5cuLXd9eXl5RpLp3bt3hZc5m1GjRhlJ5r///W+F+j/22GOmrK+Ckve6c+dOb1tSUpJxuVzmm2++8el76NAhExISYn7/+9/7tA8aNMhn6uTNN980ksw777zj0+/zzz83ksy0adPOWGtZU1VHjhwxYWFhpk+fPj59d+/ebUJDQ82QIUO8bcOHDy9zCvNs2zv9ERoaWmatx48fN5GRkebKK6/02abD4TDfffedt+2HH34wDofDPPDAA962wsJCEx8fb7p27Vqh2owxZsqUKd6aHA6HmThxYoWWK9nnDz30kE/7vHnzjCTz+uuvB6xWf2sEqgsjQoAfrrzySgUHB6tu3bq6/vrrVb9+fb333nt+/19uWVNT56u2bdv6jHxJUkxMjPr27as5c+Z4z2g7cuSI3nvvPZ+pkw8++ED16tVT3759VVRU5H1cdtllio+P18cff1zpetatW6e8vDyfaTJJatKkiXr27KmPPvqo1DIDBw6s1Dbmzp2rzz//XJ9//rk+/PBDDR8+XPfee69eeOEFn35vv/22cnJyfEZJ7rjjDhljfKaXkpOT1aNHD82bN897UPWHH36ojIwMn2V//hkVFRXJGOOzvREjRujzzz/XsmXL9Mgjj+ivf/2r7r///gq/r9tuu83n+aBBgxQUFKRVq1ZVutbynGuNQFUjCAF+KPlhXLlype655x5t375dt956q0+fkmNwSqbNylLyWpMmTSq8zNkEYh1nkpCQUGb7HXfcob1793qn+d58802dOHHCJ6Ds379fWVlZ3uNrfv7IyMjQoUOHKl1PySUIyqorMTGx1CUKwsPDFRkZWalttGrVSh06dFCHDh10/fXX6x//+IdSU1P1yCOP+Jy+/+qrr8rtduv6669XVlaWsrKy1LZtWzVr1kyzZ89WcXGxt++dd96pzMxMLVmyRNLJqaaIiAgNGjRIkvTjjz+W+oxOv+xBfHy8OnTooNTUVD355JOaPHmyXnjhBW3evLlC7ys+Pt7neVBQkGJiYkp9Zmer9WzbOJcagapGEAL8UPLD2KNHD7300ku66667tHTpUi1cuNDbp0ePHgoKCvIeCF2Wkteuu+467zLBwcFnXOZsevXq5bPus3G73ZJOXnfo58oLJeWNXvXq1UuJiYnekY9Zs2apU6dOat26tbdPgwYNFBMT4x1dOf0xbdq0CtX8czExMZKk9PT0Uq/t27dPDRo0qFD9ldW2bVvl5eVpx44dkqQdO3bok08+UX5+vpo2bar69et7Hz/++KP27t2rZcuWeZcfMGCA6tevr5kzZ+rgwYP64IMPNHjwYEVEREg6GeJO/3xSUlLOWFPHjh29tVRERkaGz/OioiJlZmZ6P9OK1loZla0RqGoEISAAnnrqKdWvX1+PPvqod2ooPj5ed9xxh5YtW6b58+eXWmbHjh36y1/+oksuucR7YHN8fLzuuusuLVu2THPnzi1zW99//72+/PLLcmu5/PLL1bt3b7366qtauXJlmX02bNig3bt3Szp5JpikUus827WKTudyuTR06FAtXrxYa9eu1YYNG0pNndx4443KzMxUcXGxd4Tl54+LL764UtuUpM6dOyssLEyvv/66T/tPP/2klStX+nVWWEVs2bJF0smzoKT/HSQ9Y8YMrVq1yueRlpam4OBgzZw507u82+3WkCFDtHz5cv3lL39RYWGhz+cVEhJS6vM52zWTSqa0Lrroogq9h3nz5vk8f/vtt1VUVKTu3bv7tJ+t1sqobI1AlbP6ICWgJinvujLGGPPUU08ZSea1117zth07dsxcffXVJigoyIwePdp8+OGHZuXKlebPf/6ziY6ONo0bNy51UHNeXp7p1auXcTgcZsiQIWbBggVmzZo1ZtGiReY3v/mNcbvdZvHixWes8+DBgyYlJcWEhISYUaNGmffee8+sWbPGzJ8/39x+++3G5XKZLVu2GGOMyc7ONtHR0ebSSy817777rnn//ffNwIEDTXJycpkHS99www3lbvebb74xkkzjxo1NWFiYycrK8nm9qKjI9O7d20RHR5tJkyaZDz/80PzrX/8ys2fPNsOHDzeLFi064/sq7/P/85//bCSZoUOHmrS0NPPaa6+Ziy66yERFRZkdO3Z4+w0fPtzUqVPnjNsoa3uzZs0y69atM+vWrTMffPCBueOOO4wkc/PNNxtj/nfwcKtWrcpd14ABA0xwcLA5cOCAt23Tpk3eg4hbtmxZ4boeffRRc88995h58+aZjz/+2CxevNiMGjXKuFwu88tf/tKn76RJk4zL5TIff/yxt63kYOmkpCTz8MMPm+XLl5u///3vJiIiwrRr186cOHGi1DbPVOucOXOMy+XyufZVZWoErEQQAirhTEEoLy/PNG3a1DRv3tznAokFBQXmxRdfNJ06dTIR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DlWHDh3UuXNnvfzyy9q9e7d3qmvChAnau3ev5s6dK0nq27ev7r77bk2fPl29evVSenq6xowZo44dOyoxMbHS269nDuj2pCPq1vbqgL4vAABQM1gahAYPHqzMzExNnjxZ6enpatOmjdLS0pSUlCRJSk9P97mm0IgRI3T06FG98MIL+u1vf6t69eqpZ8+e+stf/lLpbf8i+qDu796BkSAAAGzMYfyaU6q5cnJyFBUVpbc27dLg9k2tLgcAAFRAye93dna2IiMjA7Zey88as8p/jxSryOOxugwAAGAh2wahLzI9uv3DQ3p921GrSwEAABaxbRCSJCPp/Z15hCEAAGzK1kGoxD935jFNBgCADRGEJHkkLfsxz+oyAABANSMInbI/lxEhAADshiB0Slw4HwUAAHbDr79Ofgi9moVZXQYAAKhmBCFJNySHKcjJRwEAgN3Y+v4STp0MQbe3rmt1KQAAwAK2DULtYpya2L0BI0EAANiYbVNAy/ouQhAAADZHEgAAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZFEAIAALZl2yBUfGynjKfY6jIAAICFbBuEcr+bowMLmylv1yKrSwEAABaxbRCSJE/uXmWtuoUwBACATdk6CElGkpSzfgzTZAAA2JDNg5AkGXly96hg/1qrCwEAANWMIHSKJy/d6hIAAEA1Iwid4gxLsLoEAABQzYKsLsB6DjnDGyskrpvVhQAAgGpm8xEhhyQpstMzcjhdFtcCAACqm62DkDO8ser1WKiwpAFWlwIAACxg26mx8IuGK7brDEaCAACwMduOCLkikglBAADYnG2D0H+PFKvI47G6DAAAYCHbBqEvMj26/cNDen3bUatLAQAAFrFtEJJO3mDj/Z15hCEAAGzK1kGoxD935jFNBgCADRGEJHkkLfsxz+oyAABANSMInbI/lxEhAADshiB0Slw4HwUAAHbDr79Ofgi9moVZXQYAAKhmBCFJNySHKcjJRwEAgN3Y9hYb0skUeENymG5vXdfqUgAAgAVsG4TaxTg1sXsDRoIAALAx26aAlvVdhCAAAGyOJAAAAGzLtkFof65HHmOsLgMAAFjItkHo433Fundlptan51tdCgAAsIhtg5AkHc73aOqmHMIQAAA2Zesg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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAHFCAYAAAAe+pb9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABE5UlEQVR4nO3deXhU1f3H8c9MtkkICSSELCwhKsgmi0EiIEVRg4AIgpWKsolWChYxP7RQLBZKi1qlaBVckE3BUhAXbBSiIKBSlE2QpGIFCWAiEkzCkn3O7w/M1DEJJGGSIbnv1/PM8zhnzr33O3NL7qfn3MVmjDECAACwILu3CwAAAPAWghAAALAsghAAALAsghAAALAsghAAALAsghAAALAsghAAALAsghAAALAsghAAALAsghBwHkuWLJHNZnO9fH19FR0drV/96lf66quvyl2mqKhICxYsUI8ePRQaGqrAwEC1a9dOU6dOVVZWVrnLOJ1OvfLKK7rhhhvUpEkT+fn5qWnTprr55pu1du1aOZ3O89ZaUFCgZ599Vtdcc40aN24sf39/NWvWTLfffrs2bdp0Qb+DN/3973/XZZddJn9/f9lsNmVnZ9fYtn6+v202myIiInTttdfqnXfeKdPfZrPp/vvvL3ddq1evls1m04cffihJ6tq1q5o1a6aSkpIKt9+rVy81adJEhYWFFfZZtmyZfvWrX+nyyy+X3W5Xq1atqvQdK2vMmDFuv0ODBg3UqlUr3XLLLVq8eLEKCgqqtd5HHnlENptNHTt29HDFQNURhIBKWrx4sbZu3ar3339f999/v95++21dc801+uGHH9z6nTlzRjfeeKN++9vfqmvXrnrttdeUnJyskSNH6sUXX1TXrl315Zdfui2Tn5+vAQMGaPTo0WratKkWLFigDRs26Pnnn1dMTIx++ctfau3atees7/jx4+rVq5eSkpLUsWNHLVmyRB988IGeeuop+fj46Prrr9fnn3/u8d+lpu3evVuTJk3Sddddpw0bNmjr1q1q2LBhjW+3dH9/8sknevHFF+Xj46NBgwaddz+cy7hx4/Ttt99q3bp15X6+f/9+ffLJJxo5cqT8/f0rXM8rr7yiffv2qXv37rr00kurXU9lBAYGauvWrdq6daveeecdzZo1Sw0aNNC9996r+Ph4HTlypErr2717t5588klFRkbWUMVAFRkA57R48WIjyXz22Wdu7TNnzjSSzKJFi9zaf/3rXxtJ5h//+EeZdX355ZcmNDTUdOjQwRQXF7vaf/Ob3xhJZunSpeXWsH//fvP555+fs87+/fsbX19f88EHH5T7+aeffmoOHTp0znVU1pkzZzyynsp49dVXjSSzbds2j63z9OnTFX5W0f4+c+aMCQgIMHfccYdbuyQzceLEcte1atUqI8ls3LjRGGPMiRMnjMPhMMOGDSu3/+9+9zsjyezZs+ec9ZeUlLj+e+DAgSY2Nvac/atr9OjRpkGDBuV+tm7dOuPn52cSEhIqvb6ioiLTpUsXM2nSJNOnTx/ToUMHT5UKVBsjQkA1devWTZL03XffudoyMzO1aNEi9evXT8OHDy+zTJs2bfS73/1O+/bt05tvvulaZuHCherXr59GjRpV7rZat26tTp06VVjLjh079O6772rcuHHq27dvuX2uuuoqtWzZUpL0xz/+UTabrUyf0mmhb775xtXWqlUr3XzzzVqzZo26du0qh8OhmTNnqmvXrurdu3eZdZSUlKhZs2YaOnSoq62wsFCzZ89W27ZtFRAQoIiICI0dO1bff/99hd9Jkq699lrdddddkqSEhATZbDaNGTPG9fmiRYvUuXNnORwOhYWF6dZbb1VaWprbOsaMGaPg4GDt3btXiYmJatiwoa6//vpzbrc8DodD/v7+8vPzq/KypRo3bqxbb71Va9euLTNFWlJSoldeeUVXXXWVrrjiinOux26/sD/d+/btU2JiooKCghQREaGJEyfqX//6l9s03vkkJibq3nvv1bZt27R58+ZKLfPYY4/pxIkT+vOf/3wB1QOeRRACqungwYOSzoabUhs3blRxcbGGDBlS4XKln6WkpLiWKSoqOucy57N+/Xq3dXvazp079dBDD2nSpEl67733NGzYMI0dO1YfffRRmfOk1q9fr2+//VZjx46VdPbcp8GDB+uxxx7TiBEj9K9//UuPPfaYUlJSdO211yovL6/C7c6fP1+PPPKIpP9NVf3hD3+QJM2ZM0fjxo1Thw4dtGbNGj399NPas2ePevToUaamwsJC3XLLLerbt6/eeustzZw587zfuaSkRMXFxSoqKtKRI0c0efJknT59WiNGjCjT1xij4uLiMq/yzusaN26cCgsL9eqrr7q1r1u3Tt9++63GjRt33touREZGhvr06aMvv/xSCxYs0LJly3Ty5MkKz3M6l1tuuUWSKhWEUlNTNXv2bC1YsEDBwcFV3hZQY7w9JAVc7EqnSv7973+boqIic/LkSfPee++ZqKgo84tf/MIUFRW5+j722GNGknnvvfcqXF9eXp6RZPr371/pZc5n/PjxRpL5z3/+U6n+jz76qCnvn3/pdz148KCrLTY21vj4+Jgvv/zSre/x48eNv7+/+f3vf+/Wfvvtt5vIyEjX7/Laa68ZSeb111936/fZZ58ZSWb+/PnnrLW8qaoffvjBBAYGmgEDBrj1TU9PNwEBAWbEiBGuttGjR5c7hXm+7f38FRAQUG6t5fX9+at0aswYY5xOp4mLizOdOnVyW8+wYcNMUFCQycnJqVSdpao6NfbQQw8Zm81m9u3b59ber1+/MrWea2rMGGPS0tKMJPOb3/zmnNssKSkxCQkJbtOKTI3hYsGIEFBJV199tfz8/NSwYUPddNNNaty4sd566y35+vpWa33lTU1drDp16uQ28iVJ4eHhGjRokJYuXeoa+fjhhx/01ltvadSoUa7f5Z133lGjRo00aNAgt9GSLl26KCoqqtJTMT+1detW5eXluU2TSVKLFi3Ut29fffDBB2WWGTZsWJW2sWzZMn322Wf67LPP9O6772r06NGaOHGinn322TJ9b7/9dlffn74ef/zxMn1tNpvGjh2rPXv2aMeOHZKkrKwsrV27VsOGDVNISIik/41InWt0qTo2bdqkjh07qn379m7td9xxR5XXZYypVL+5c+fqq6++0rx586q8DaCmEYSASio9MG7YsEH33Xef0tLSyhw8Ss/BKZ02K0/pZy1atKj0MufjiXWcS3R0dLntd999t44ePeqa5nvttddUUFDgFlC+++47ZWdnu86v+ekrMzNTx48fr3I9pefXlFdXTExMmfNvgoKCXAGjstq1a6du3bqpW7duuummm/TCCy8oMTFRDz/8cJnL9yMiIlx9f/q65JJLyl332LFjZbfbtXjxYknS8uXLVVhY6DYtdumll7r9VrNmzapS/RXJysoq94qt6lzFdejQIUlnf/OKpKena8aMGXr00Ufl7++v7OxsZWdnu8Jddnb2OadHgZpGEAIqqfTAeN111+n555/XPffco/fee0+rV6929bnuuuvk6+vrOhG6PKWf3Xjjja5l/Pz8zrnM+fTr189t3efjcDgkqcx9YCoKJRWNXvXr108xMTGuA/rixYuVkJDgNtrQpEkThYeHlzti8tlnn2n+/PmVqvmnwsPDJZ093+Xnvv32WzVp0qRS9VdVp06dlJeXp/3791/Qepo3b67ExEStWLFCBQUFWrx4sS677DL94he/cPVZu3at2+/061//+kLLl3T2t/vpCf6lMjMzq7yut99+W9LZk9orcuDAAeXl5emBBx5Q48aNXa+PP/5YaWlpaty4saZNm1blbQOeQhACqumJJ55Q48aNNWPGDNe0RVRUlO6++26tW7dOK1euLLPM/v379fjjj6tDhw6uE5ujoqJ0zz33aN26dVq2bFm52/r666+1Z8+eCmu58sor1b9/f7388svasGFDuX22b9+u9PR0SXLdgO/n66zqPXJ8fHw0cuRIvfnmm9qyZYu2b9+uu+++263PzTffrKysLJWUlJQ7anL55ZdXaZuS1KNHDwUGBpY54fjIkSPasGFDta4Kq4zdu3dLOjsCdKHGjRunH374QTNmzNDu3bs1duxYt8B2xRVXuP1O5xp1qYo+ffroiy++UGpqqlv7P/7xjyqtJyUlRQsXLlTPnj11zTXXVNivS5cu2rhxY5lX586d1apVK23cuLFaJ2oDHuPtk5SAi11F95UxxpgnnnjCSDKvvPKKq+3UqVOmT58+xtfX10yYMMG8++67ZsOGDeYvf/mLCQsLM82bNy9zUnNeXp7p16+fsdlsZsSIEWbVqlVm8+bNZs2aNeY3v/mNcTgc5s033zxnnd9//72Jj483/v7+Zvz48eatt94ymzdvNitXrjR33XWX8fHxMbt37zbGGJOTk2PCwsLMFVdcYd544w2zdu1aM2zYMBMXF1fuydIDBw6scLtffvmlkWSaN29uAgMDTXZ2ttvnxcXFpn///iYsLMzMnDnTvPvuu+b99983S5YsMaNHjzZr1qw55/eq6Pf/y1/+YiSZkSNHmuTkZPPKK6+Yyy67zISGhpr9+/e7+p3vhN+Ktrd48WKzdetWs3XrVvPOO++Yu+++20gyt956q1t/VeE+Qj9VUFBgmjRpYmw2m/Hx8TFHjhypdI379u0zq1atMqtWrTLx8fEmIiLC9f6nJ0F/+OGHxsfHx8ycOdPVdvToURMeHm5atmxplixZYt59910zcuRIExsbaySZTZs2ufqOHj3aBAYGun6HDz/80CxbtszccccdxsfHx3Ts2LFM3Xfffbfx8fEx33zzzTm/AydL42JBEALO41xBKC8vz7Rs2dK0bt3a7QaJhYWF5rnnnjMJCQkmODjYBAQEmMsvv9w8/PDD5vjx4+Vup7i42CxdutT07dvXhIWFGV9fXxMREWH69+9vVqxY4XYTvYrk5eWZZ555xvTo0cOEhIQYX19fExMTY4YOHWr+9a9/ufX99NNPTc+ePU2DBg1Ms2bNzKOPPmoWLlxY5SBkjDE9e/Y0ksydd95Z7udFRUXmySefNJ07dzYOh8MEBwebtm3bmvvuu8989dVX51z3uX7/hQsXmk6dOhl/f38TGhpqBg8eXOZqqOoGoZ++QkNDTZcuXczcuXNNfn6+W//qBiFjjHnwwQeNpDJXv51P6VV/5b0effRRV7+NGzeWaTPGmC+++MLccMMNxuFwmLCwMDNu3DizdOlSI8ntxp2lV9yVvgIDA03Lli3NoEGDzKJFi0xBQUGZ2kqX+en/hspDEMLFwmZMJU/7BwDUW7/+9a/12muvKSsr65yP9wDqm+pd9wsAqLNmzZqlmJgYXXLJJTp16pTeeecdLVy4UI888gghCJZDEAIAi/Hz89Nf//pXHTlyRMXFxWrdurXmzp2rBx54wNulAbWOqTEAAGBZXr18fvPmzRo0aJBiYmJks9kqdQ+UTZs2KT4+Xg6HQ5dccomef/75mi8UAADUS14NQqdPn1bnzp3LvWV9eQ4ePKgBAwaod+/e2rVrl37/+99r0qRJev3112u4UgAAUB9dNFNjNptNb7zxxjmfnv273/1Ob7/9ttLS0lxt48eP1+eff66tW7fWQpUAAKA+qVMnS2/dulWJiYlubf369dPLL7+soqIi+fn5lVmmoKDA7TECTqdTJ06cUHh4eJ166CUAAFZmjNHJkycVExMju91zE1p1KghlZmaWeTBgZGSkiouLdfz48XIfwDhnzhzNnDmztkoEAAA16PDhw2revLnH1lengpBU9uGJpTN7FY3uTJs2TUlJSa73OTk5atmypW5eskt+QQ3/17GkRPOvC/Z8wQAAoMpSv/lCz6Zf6npfdOak3hnTVQ0bNjzHUlVXp4JQVFRUmSckHzt2TL6+vq6nUf9cQECAAgICyrT7BTU8G4R+DFJD7W8rKvJezxcNAACqLKJJU608lqZsW4Rk+99UmKdPa6lTT5/v0aOHUlJS3NrWr1+vbt26lXt+0HmVnifudGr4AEIQAAAXCx8fX90Ve+LsG+Osse14NQidOnVKu3fv1u7duyWdvTx+9+7dSk9Pl3R2WmvUqFGu/uPHj9ehQ4eUlJSktLQ0LVq0SC+//LKmTJlS/SKcTq28pey5RQAAwLt6d+qj+1t+qUbm+xrbhleD0Pbt29W1a1d17dpVkpSUlKSuXbtqxowZkqSMjAxXKJKkuLg4JScn68MPP1SXLl30pz/9Sc8884yGDRtW9Y2XlGio/W1CEAAAF7Henfpo/oB2Srr0UI2s/6K5j1Btyc3NVWhoqDIyjyoqMsbb5QAAgEooPX7n5OQoJCTEY+utU+cIedLOj/6qwryT3i4DAAB4kWWD0ELn/fptyn+VspanLQMAYFWWDUKSlG2P1kLbNMIQAAAWZekgVHpfgtVmDNNkAABYkLWDkCTZ7Mr2aaYdW2Z7uxIAAFDLCEI/+iEv39slAACAWkYQ+lHjQIe3SwAAALWMIGScalRyVPG9H/F2JQAAoJZZOwj9+OyS22xL5B/o2afZAgCAi1+devq8pzVyZug22xLdOOhpb5cCAAC8wLJBaKTm67o+f5B/4FM6U1jsarfbbHL4+bje//Szn7uQvnmFJTIq/+kmNtkU6F+9vvlFJXKe46kpQf6+Xu8b6Ocjm80mSSooLlGJ0zN9Hb4+stvP9i0sdqrYWfHTiqvSN8DXRz7V6FtU4lRRScV9/X3s8vWxV7lvcYlThefo6+djl181+pY4jQqKSyrs62u3y9+36n2dTqN8D/X1sdsU4Hv2f+/GGOUVeaZvbf27529E5fryN+Is/kaU7VsTLBuEHvjkatl3fFym/brLI7R4bHfX+/g/vV/hH9CEuDCtvK+H6/01j2/UidOF5fbt1DxUb99/jev9DXM36Wh2Xrl9WzcNVkpSH9f7W579SF8dO1Vu32aNAvXx1L6u97e/sFV7juSU2zesgb92/uFG1/vRiz7VtoMnyu0b6OejtD/d5Hr/m1d3aOOXFT/995vHBrr+O+mfu5W8N7PCvqmz+rn+KP5+zRd6feeRCvvueOQGhQcHSJJmv5OmV/5d8UP3tjx8nVqEBUmSnlz/pV7cfKDCvusf/IXaRJ6dDn1u43/19AdfVdj3rYm91LlFI0nS4o8Pas67/6mw72v3Xq0el4af/e9P0zXjrX0V9l00ppv6to2UJL2566geWr2nwr7PjbhSAzudfUDwun3faeKKnRX2/ettnfTLbi0kSZu/+l53L9leYd9ZgztoVI9WkqRPD57QHS/9u8K+0/q31X19LpUkfXE0R4OfK/vvp9QD17fWgze2kST99/tTSvzb5gr7/voXl+j3A9pJko5m56n3Exsr7Dvy6lj9aUhHSdKJ04WKn/1+hX2HXdlcT93eWZKUV1Si9jPWVdh3wBVRmn9nvOv9ufryN+Is/kb8D38jzqqNvxE1wdrnCAEAAEuz7NPn1+89qB6tm8n+45BqKYa9a74vw95nMexd9b5MjZ3F34jq9eVvxFl19W9ETT193rJB6NZ//leRYaEa0z5YCdHcQwgAgItZTQUhS0+Nnch3au7OXG3L4K7SAABYkaWDUKmlqafOOUwLAADqJ4KQpKx8p9JOFHm7DAAAUMsIQj/Kzq/4ZDEAAFA/EYR+1MjBTwEAgNVw9JcU7rCrXZift8sAAAC1jCAkaXT74DL3EwIAAPWfZR+xIZ0dCRrNfYQAALAsywahyZ38dU2bcEaCAACwMMtOjbVp5EMIAgDA4iwbhAAAAAhCAADAsghCAADAsghCAADAsghCAADAsghCAADAsghCAADAsghCAADAsghCAADAsghCAADAsghCAADAsghCAADAsiwbhJ77936dyT/j7TIAAIAXWTYI7StsobHvn9TD63Z7uxQAAOAllg1CpQ4VRROGAACwKGsHIZtN0tkwxDQZAADWY+0gJJ0NQzabnv441duVAACAWkYQ+tH3hf7eLgEAANQygtCPIvwLvV0CAACoZb7eLsDrjJEkPdCrvZcLAQAAtc3aI0I/hqBYvwwFOYK8XAwAAKht1g5COhuCnujXxdtlAAAAL7Ds1FgH/8OadkN3BTkivV0KAADwEsuOCE28ug3TYQAAWJxlgxAAAIBlg9D+7BI5fzxZGgAAWJNlg9C8PYWauCFL2zLyvV0KAADwEssGIUk6ke/U3J25hCEAACzK0kGo1NLUU0yTAQBgQQQhSVn5TqWdKPJ2GQAAoJYRhH6Une/0dgkAAKCWEYR+1MjBTwEAgNVw9JcU7rCrXZift8sAAAC1jCAkaXT7YNltNm+XAQAAapllnzUmnR0JGt0+WAnRDm+XAgAAvMCyQWhyJ39d0yackSAAACzMslNjbRr5EIIAALA4ywYhAAAArweh+fPnKy4uTg6HQ/Hx8dqyZcs5+y9fvlydO3dWUFCQoqOjNXbsWGVlZdVStQAAoD7xahBauXKlJk+erOnTp2vXrl3q3bu3+vfvr/T09HL7f/TRRxo1apTGjRunffv2adWqVfrss890zz331HLlAACgPvBqEJo7d67GjRune+65R+3atdO8efPUokULLViwoNz+//73v9WqVStNmjRJcXFxuuaaa3Tfffdp+/bttVw5AACoD7wWhAoLC7Vjxw4lJia6tScmJuqTTz4pd5mePXvqyJEjSk5OljFG3333nVavXq2BAwdWuJ2CggLl5ua6vQAAACQvBqHjx4+rpKREkZGRbu2RkZHKzMwsd5mePXtq+fLlGj58uPz9/RUVFaVGjRrp73//e4XbmTNnjkJDQ12vFi1aePR7AACAusvrJ0vbfnYJuzGmTFup1NRUTZo0STNmzNCOHTv03nvv6eDBgxo/fnyF6582bZpycnJcr8OHD3u0fgAAUHd57YaKTZo0kY+PT5nRn2PHjpUZJSo1Z84c9erVSw899JAkqVOnTmrQoIF69+6t2bNnKzo6uswyAQEBCggI8PwXAAAAdZ7XRoT8/f0VHx+vlJQUt/aUlBT17Nmz3GXOnDkju929ZB8fH0lnR5IAAACqwqtTY0lJSVq4cKEWLVqktLQ0Pfjgg0pPT3dNdU2bNk2jRo1y9R80aJDWrFmjBQsW6MCBA/r44481adIkde/eXTExMd76GgAAoI7y6rPGhg8frqysLM2aNUsZGRnq2LGjkpOTFRsbK0nKyMhwu6fQmDFjdPLkST377LP6v//7PzVq1Eh9+/bV448/7q2vAAAA6jCbsdicUm5urkJDQ5WReVRRkYwiAQBQF5Qev3NychQSEuKx9Xr9qjFv2Z9dIqe1MiAAAPgZywaheXsKNXFDlrZl5Hu7FAAA4CWWDUKSdCLfqbk7cwlDAABYlKWDUKmlqaeYJgMAwIIIQpKy8p1KO1Hk7TIAAEAtIwj9KDvf6e0SAABALSMI/aiRg58CAACr4egvKdxhV7swP2+XAQAAahlBSNLo9sGyV/DEewAAUH959REb3hbusGt0+2AlRDu8XQoAAPACywahyZ38dU2bcEaCAACwMMtOjbVp5EMIAgDA4iwbhAAAACwbhIq+/7eMs8TbZQAAAC+ybBDK3nKXjq1upbxDa7xdCgAA8BLLBiFJcp45quyNtxGGAACwKEsHIensg1Zzt01mmgwAAAuyeBCSJCPnmcMq/G6LtwsBAAC1jCD0I2dehrdLAAAAtYwg9CN7YLS3SwAAALXMsneW/h+b7EHN5R/Z29uFAACAWmbxEaGzd5YOSZgnm93Hy7UAAIDaZukgZA9qrkbXrVZg7FBvlwIAALzAslNjjXq/qqbtBzMSBACAhVl2RMgv4mpCEAAAFmfZILQ/u0ROY7xdBgAA8CLLBqF5ewo1cUOWtmXke7sUAADgJZYNQpJ0It+puTtzCUMAAFiUpYNQqaWpp5gmAwDAgghCkrLynUo7UeTtMgAAQC0jCP0oO9/p7RIAAEAtIwj9qJGDnwIAAKvh6C8p3GFXuzA/b5cBAABqGUFI0uj2wbLbbN4uAwAA1DLLPmJDOjsSNLp9sBKiHd4uBQAAeIFlg9DkTv66pk04I0EAAFiYZafG2jTyIQQBAGBxlg1CAAAABCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZXg9C8+fPV1xcnBwOh+Lj47Vly5Zz9i8oKND06dMVGxurgIAAXXrppVq0aFEtVQsAAOoTX29ufOXKlZo8ebLmz5+vXr166YUXXlD//v2Vmpqqli1blrvM7bffru+++04vv/yyLrvsMh07dkzFxcW1XDkAAKgPbMYY462NJyQk6Morr9SCBQtcbe3atdOQIUM0Z86cMv3fe+89/epXv9KBAwcUFhZWrW3m5uYqNDRUGZlHFRUZU+3aAQBA7Sk9fufk5CgkJMRj6/Xa1FhhYaF27NihxMREt/bExER98skn5S7z9ttvq1u3bnriiSfUrFkztWnTRlOmTFFeXl6F2ykoKFBubq7bCwAAQPLi1Njx48dVUlKiyMhIt/bIyEhlZmaWu8yBAwf00UcfyeFw6I033tDx48c1YcIEnThxosLzhObMmaOZM2d6vH4AAFD3ef1kaZvN5vbeGFOmrZTT6ZTNZtPy5cvVvXt3DRgwQHPnztWSJUsqHBWaNm2acnJyXK/Dhw97/DsAAIC6yWsjQk2aNJGPj0+Z0Z9jx46VGSUqFR0drWbNmik0NNTV1q5dOxljdOTIEbVu3brMMgEBAQoICPBs8QAAoF6o1ojQmDFjtHnz5gvasL+/v+Lj45WSkuLWnpKSop49e5a7TK9evfTtt9/q1KlTrrb9+/fLbrerefPmF1QPAACwnmoFoZMnTyoxMVGtW7fWX/7yFx09erRaG09KStLChQu1aNEipaWl6cEHH1R6errGjx8v6ey01qhRo1z9R4wYofDwcI0dO1apqanavHmzHnroId19990KDAysVg0AAMC6qhWEXn/9dR09elT333+/Vq1apVatWql///5avXq1ioqKKr2e4cOHa968eZo1a5a6dOmizZs3Kzk5WbGxsZKkjIwMpaenu/oHBwcrJSVF2dnZ6tatm+68804NGjRIzzzzTHW+BgAAsDiP3Edo165dWrRokRYuXKjg4GDdddddmjBhQrnn7Hgb9xECAKDuuWjvI5SRkaH169dr/fr18vHx0YABA7Rv3z61b99ef/vb3zxRIwAAQI2oVhAqKirS66+/rptvvlmxsbFatWqVHnzwQWVkZGjp0qVav369XnnlFc2aNcvT9QIAAHhMtS6fj46OltPp1B133KFPP/1UXbp0KdOnX79+atSo0QWWBwAAUHOqFYT+9re/6Ze//KUcDkeFfRo3bqyDBw9WuzAAAICaVq2psY0bN5Z7ddjp06d19913X3BRAAAAtaFaQWjp0qXlPtIiLy9Py5Ytu+CiAAAAakOVpsZyc3NljJExRidPnnSbGispKVFycrKaNm3q8SIBAABqQpWCUKNGjWSz2WSz2dSmTZsyn9tsNp70DgAA6owqBaGNGzfKGKO+ffvq9ddfV1hYmOszf39/xcbGKiaGmxQCAIC6oUpBqE+fPpKkgwcPqmXLlrLZbDVSFAAAQG2odBDas2ePOnbsKLvdrpycHO3du7fCvp06dfJIcQAAADWp0kGoS5cuyszMVNOmTdWlSxfZbDaV95gym82mkpISjxYJAABQEyodhA4ePKiIiAjXfwMAANR1lQ5CsbGxrv+OiIhQUFBQjRRUW/Znl6hpUyM75zkBAGBZ1bqhYtOmTXXXXXdp3bp1cjqdnq6pVszbU6iJG7K0LSPf26UAAAAvqVYQWrZsmQoKCnTrrbcqJiZGDzzwgD777DNP11bjTuQ7NXdnLmEIAACLqlYQGjp0qFatWqXvvvtOc+bMUVpamnr27Kk2bdpo1qxZnq6xxi1NPSVnOSd+AwCA+q1aQahUw4YNNXbsWK1fv16ff/65GjRoUCfvLJ2V71TaibIPkQUAAPXbBQWh/Px8/fOf/9SQIUN05ZVXKisrS1OmTPFUbbUqO79unusEAACqr0p3li61fv16LV++XG+++aZ8fHx02223ad26da47T9dFjRwXlAkBAEAdVK0gNGTIEA0cOFBLly7VwIED5efn5+m6alW4w652YXX7OwAAgKqrVhDKzMxUSEiIp2vxmtHtg7mfEAAAFlTpIJSbm+sWfnJzcyvsW1dCUrjDrtHtg5UQ7fB2KQAAwAsqHYQaN26sjIwMNW3aVI0aNSr3yfPGmDrzrLHJnfx1TZtwRoIAALCwSgehDRs2KCwsTJK0cePGGiuotrRp5EMIAgDA4iodhH56RVhcXJxatGhRZlTIGKPDhw97rjoAAIAaVK1rxuPi4vT999+XaT9x4oTi4uIuuCgAAIDaUK0gVHou0M+dOnVKDgcnHgMAgLqhSpfPJyUlSZJsNpv+8Ic/KCgoyPVZSUmJtm3bpi5duni0QAAAgJpSpSC0a9cuSWdHhPbu3St/f3/XZ/7+/urcuXOdfcQGAACwnioFodKrxcaOHaunn366ztwvCAAAoDzVurP04sWLPV0HAABArat0EBo6dKiWLFmikJAQDR069Jx916xZc8GFAQAA1LRKB6HQ0FDXlWKhoaE1VhAAAEBtsRljjLeLqE25ubkKDQ1VRuZRRUXGeLscAABQCaXH75ycHI+eo1yt+wjl5eXpzJkzrveHDh3SvHnztH79eo8VBgAAUNOqFYQGDx6sZcuWSZKys7PVvXt3PfXUUxo8eLAWLFjg0QIBAABqSrWC0M6dO9W7d29J0urVqxUVFaVDhw5p2bJleuaZZzxaIAAAQE2pVhA6c+aMGjZsKElav369hg4dKrvdrquvvlqHDh3yaIEAAAA1pVpB6LLLLtObb76pw4cPa926dUpMTJQkHTt2jJssAgCAOqNaQWjGjBmaMmWKWrVqpYSEBPXo0UPS2dGhrl27erRAAACAmlLty+czMzOVkZGhzp07y24/m6c+/fRThYSEqG3bth4t0pO4fB4AgLqnpi6fr9YjNiQpKipKUVFRbm3du3e/4IIAAABqS7WC0OnTp/XYY4/pgw8+0LFjx+R0Ot0+P3DggEeKAwAAqEnVCkL33HOPNm3apJEjRyo6Otr16A0AAIC6pFpB6N1339W//vUv9erVy9P1AAAA1JpqXTXWuHFjhYWFeboWAACAWlWtIPSnP/1JM2bMcHveGAAAQF1Tramxp556Sl9//bUiIyPVqlUr+fn5uX2+c+dOjxQHAABQk6oVhIYMGeLhMgAAAGpftYLQo48+6uk6AAAAal21zhGSpOzsbC1cuFDTpk3TiRMnJJ2dEjt69KjHigMAAKhJ1RoR2rNnj2644QaFhobqm2++0b333quwsDC98cYbOnTokJYtW+bpOgEAADyuWiNCSUlJGjNmjL766is5HA5Xe//+/bV582aPFQcAAFCTqhWEPvvsM913331l2ps1a6bMzMwLLgoAAKA2VCsIORwO5ebmlmn/8ssvFRERccFFAQAA1IZqBaHBgwdr1qxZKioqkiTZbDalp6dr6tSpGjZsmEcLBAAAqCnVCkJPPvmkvv/+ezVt2lR5eXnq06ePLr30UgUHB+vPf/6zp2sEAACoEdW6aiwkJEQfffSRNmzYoJ07d8rpdCo+Pl7XX3+9p+sDAACoMVUaEdq2bZveffdd1/u+ffsqIiJC8+fP1x133KFf//rXKigo8HiRAAAANaFKQeiPf/yj9uzZ43q/d+9e3Xvvvbrxxhs1depUrV27VnPmzPF4kQAAADWhSkFo9+7dbtNf//jHP9S9e3e99NJLSkpK0jPPPKN//vOfHi8SAACgJlQpCP3www+KjIx0vd+0aZNuuukm1/urrrpKhw8f9lx1Najo+3/LOEu8XQYAAPCiKgWhyMhIHTx4UJJUWFionTt3qkePHq7PT548KT8/vyoVMH/+fMXFxcnhcCg+Pl5btmyp1HIff/yxfH191aVLlyptr1T2lrt0bHUr5R1aU63lAQBA3VelIHTTTTdp6tSp2rJli6ZNm6agoCD17t3b9fmePXt06aWXVnp9K1eu1OTJkzV9+nTt2rVLvXv3Vv/+/ZWenn7O5XJycjRq1KgLvkrNeeaosjfeRhgCAMCiqhSEZs+eLR8fH/Xp00cvvfSSXnrpJfn7+7s+X7RokRITEyu9vrlz52rcuHG655571K5dO82bN08tWrTQggULzrncfffdpxEjRriNRlWPkSTlbpvMNBkAABZUpfsIRUREaMuWLcrJyVFwcLB8fHzcPl+1apWCg4Mrta7CwkLt2LFDU6dOdWtPTEzUJ598UuFyixcv1tdff61XX31Vs2fPPu92CgoK3C7pL/toECPnmcMq/G6LAqKvrVTtAACgfqjWnaVDQ0PLhCBJCgsLcxshOpfjx4+rpKTE7eRr6ex5SBU9uPWrr77S1KlTtXz5cvn6Vi7DzZkzR6Ghoa5XixYtyu3nzMuo1PoAAED9Ua0g5Ek2m83tvTGmTJsklZSUaMSIEZo5c6batGlT6fVPmzZNOTk5rldFV7XZA6OrVjgAAKjzqvWIDU9o0qSJfHx8yoz+HDt2rMwokXT2irTt27dr165duv/++yVJTqdTxhj5+vpq/fr16tu3b5nlAgICFBAQcI5KbLIHNZd/ZO9z9AEAAPWR10aE/P39FR8fr5SUFLf2lJQU9ezZs0z/kJAQ7d27V7t373a9xo8fr8svv1y7d+9WQkJCNao4O/IUkjBPNnvZqT4AAFC/eW1ESJKSkpI0cuRIdevWTT169NCLL76o9PR0jR8/XtLZaa2jR49q2bJlstvt6tixo9vyTZs2lcPhKNNeWfag5gpJmKfA2KEX/F0AAEDd49UgNHz4cGVlZWnWrFnKyMhQx44dlZycrNjYWElSRkbGee8pVF2Ner+qpu0HMxIEAICF2YwxxttF1Kbc3FyFhoYqI/OooiJjvF0OAACohNLjd05OjkJCQjy2Xq9fNQYAAOAtBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZBCEAAGBZlg1C+7NL5DTG22UAAAAvsmwQmrenUBM3ZGlbRr63SwEAAF5i2SAkSSfynZq7M5cwBACARVk6CJVamnqKaTIAACyIICQpK9+ptBNF3i4DAADUMoLQj7Lznd4uAQAA1DKC0I8aOfgpAACwGo7+ksIddrUL8/N2GQAAoJYRhCSNbh8su83m7TIAAEAt8/V2Ad4U7rBrdPtgJUQ7vF0KAADwAssGocmd/HVNm3BGggAAsDDLTo21aeRDCAIAwOIsG4QAAAAIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLIIQgAAwLK8HoTmz5+vuLg4ORwOxcfHa8uWLRX2XbNmjW688UZFREQoJCREPXr00Lp162qxWgAAUJ94NQitXLlSkydP1vTp07Vr1y717t1b/fv3V3p6ern9N2/erBtvvFHJycnasWOHrrvuOg0aNEi7du2q5coBAEB9YDPGGG9tPCEhQVdeeaUWLFjgamvXrp2GDBmiOXPmVGodHTp00PDhwzVjxoxK9c/NzVVoaKgyMo8qKjKmWnUDAIDaVXr8zsnJUUhIiMfW67URocLCQu3YsUOJiYlu7YmJifrkk08qtQ6n06mTJ08qLCyswj4FBQXKzc11ewEAAEheDELHjx9XSUmJIiMj3dojIyOVmZlZqXU89dRTOn36tG6//fYK+8yZM0ehoaGuV4sWLS6obgAAUH94/WRpm83m9t4YU6atPK+99pr++Mc/auXKlWratGmF/aZNm6acnBzX6/DhwxdcMwAAqB98vbXhJk2ayMfHp8zoz7Fjx8qMEv3cypUrNW7cOK1atUo33HDDOfsGBAQoICDggusFAAD1j9dGhPz9/RUfH6+UlBS39pSUFPXs2bPC5V577TWNGTNGK1as0MCBA2u6TAAAUI95bURIkpKSkjRy5Eh169ZNPXr00Isvvqj09HSNHz9e0tlpraNHj2rZsmWSzoagUaNG6emnn9bVV1/tGk0KDAxUaGio174HAACom7wahIYPH66srCzNmjVLGRkZ6tixo5KTkxUbGytJysjIcLun0AsvvKDi4mJNnDhREydOdLWPHj1aS5Ysqe3yAQBAHefV+wh5A/cRAgCg7ql39xECAADwNoIQAACwLIIQAACwLIIQAACwLIIQAACwLIIQAACwLIIQAACwLIIQAACwLIIQAACwLIIQAACwLIIQAACwLIIQAACwLIIQAACwLF9vF3CxKikpUVFRkbfL8Bp/f3/Z7eRkAED9RhD6GWOMMjMzlZ2d7e1SvMputysuLk7+/v7eLgUAgBpDEPqZ0hDUtGlTBQUFyWazebukWud0OvXtt98qIyNDLVu2tORvAACwBoLQT5SUlLhCUHh4uLfL8aqIiAh9++23Ki4ulp+fn7fLAQCgRnASyE+UnhMUFBTk5Uq8r3RKrKSkxMuVAABQcwhC5WAqiN8AAGANBCEAAGBZBKEaYpwlKsj4UHkHXlNBxocyzpqdYpozZ46uuuoqNWzYUE2bNtWQIUP05Zdf1ug2AQCo6zhZugbkHVqj3G0PyHnmiKvNHtRcIQlPKzB2aI1sc9OmTZo4caKuuuoqFRcXa/r06UpMTFRqaqoaNGhQI9sEAKCuY0TIw/IOrVH2xtvcQpAkOc8cVfbG25R3aE2NbPe9997TmDFj1KFDB3Xu3FmLFy9Wenq6duzYIUn6z3/+o6CgIK1YscK1zJo1a+RwOLR3794aqQkAgIsdI0LnYYyRKT5Tub7OEuVumyTJlPepJJtytz0g/6gbZLP7nHd9Nt/q38coJydHkhQWFiZJatu2rZ588klNmDBBvXr1kp+fn+6991499thjuuKKK6q1DQAA6jqbMaa8o3a9lZubq9DQUGVkHlVUZIzbZ/n5+Tp48KDi4uLkcDgkSc6i0/puebA3SlXknadk96v6tJYxRoMHD9YPP/ygLVu2uH128803Kzc31/UIjXXr1pUbtsr7LQAA8JbS43dOTo5CQkI8tl7LjgilfvOFIpo0lY9P/fsJ7r//fu3Zs0cfffRRmc8WLVqkNm3ayG6364svvuAyeQCApdW/FFBJz6ZfqpXH0nRX7An17tSnwn423yBF3nmqUuss/G6zfnh/wHn7Nb4hWf6RvzhvP5tv1W/s+Nvf/lZvv/22Nm/erObNm5f5/PPPP9fp06dlt9uVmZmpmJiYctYCAIA1WDYISVK2LULPpkdI2lRhGLLZbLJVcnoqICZR9qDmcp45qvLPE7LJHtRcATGJlTpHqCqMMfrtb3+rN954Qx9++KHi4uLK9Dlx4oTGjBmj6dOnKzMzU3feead27typwMBAj9YCAEBdYe2rxmxnv/6rhxqrpKTYA6vzUUjC06Xvfv6pJCkkYZ7HQ5AkTZw4Ua+++qpWrFihhg0bKjMzU5mZmcrLy3P1GT9+vFq0aKFHHnlEc+fOlTFGU6ZM8XgtAADUFdYOQpJksyvbHqW9X+/0yOoCY4eq0XWrZQ9q5tZuD2quRtetrrH7CC1YsEA5OTm69tprFR0d7XqtXLlSkrRs2TIlJyfrlVdeka+vr4KCgrR8+XItXLhQycnJNVITAAAXO0tPjf3UD6crdx5QZQTGDpWjxWAVfrdFzrwM2QOj5R/Zu0ZGgkqd7+K/UaNGadSoUW5t8fHxKigoqLGaAAC42BGEftS4gWcvkbfZfRQQfa1H1wkAADyLqTHjVCNnpq649EpvVwIAAGqZtYOQcUqS7or9oV7eTwgAAJybpY/+jcwx3RX7wznvIwQAAOovywah+1t+rT7d+jISBACAhVl2aqx9q46EIAAALM6yQQgAAIAgBAAALIsgBAAALIsgBAAALIsgVEOcxmhfVqE+PpqvfVmFcp7nERgXavPmzRo0aJBiYmJks9n05ptv1uj2AACoD7hsqgZsy8jXktRTOpHvdLWFOewa0z5YCdGOGtnm6dOn1blzZ40dO1bDhg2rkW0AAFDfMCLkYdsy8jV3Z65bCJKkE/lOzd2Zq20Z+TWy3f79+2v27NkaOrTs0+3/85//KCgoSCtWrHC1rVmzRg6HQ3v37q2RegAAqAsYEToPY4wKSirX12mMFu8791Psl6Se0hVN/GW32c67vgAfyVaJfufTtm1bPfnkk5owYYJ69eolPz8/3XvvvXrsscd0xRVXXPD6AQCoqwhC51FQIo1e973H1nci36mx649Xqu/SfhFyeGgPTZgwQcnJyRo5cqT8/f0VHx+vBx54wDMrBwCgjiIIWciiRYvUpk0b2e12ffHFFx4ZbQIAoC4jCJ1HgM/ZkZnKSDtRqMc+yzlvv6lXhapdmH+ltu1Jn3/+uU6fPi273a7MzEzFxMR4dgMAANQxBKHzsNlslZ6e6hzhrzCHvcyJ0j8V7rCrc0TlzhHypBMnTmjMmDGaPn26MjMzdeedd2rnzp0KDAys1ToAALiYWPaqsf3ZJR6/t4/dZtOY9sHn7DO6fXCNhKBTp05p9+7d2r17tyTp4MGD2r17t9LT0yVJ48ePV4sWLfTII49o7ty5MsZoypQpHq8DAIC6xLIjQvP2FOq1I1kev7dPQrRDSVeqzH2Ewh12ja7B+wht375d1113net9UlKSJGn06NHq27evkpOTtWvXLvn6+srX11fLly9Xz549NXDgQA0YMKBGagIA4GJnM6aGb3l8kcnNzVVoaKhu/ed/5RfUUJKUdGWIEqIdys/P18GDBxUXFyeH48ICi9MYpZ0oUna+U40cdrUL86v16bAL4cnfAgCAC1V6/M7JyVFISIjH1mvZEaGfWpp6SldFBXh0nXabTR3Cz39CNAAA8B7LniP0U1n5TqWdKPJ2GQAAoJYRhH6UfY4rvQAAQP1EEPpRIwc/BQAAVsPRX2ev6GoX5uftMgAAQC0jCKnsvX0sdiFdufgNAABWYOmrxn5+bx8/v7OjQmfOnLH8HZcLCwslST4+Hn7OBwAAFxHLBqHJnfx1TZtwt5EgHx8fNWrUSMeOHZMkBQUFWfLBpE6nU99//72CgoLk62vZ/4kAACzAske5No18yr3BYVRUlCS5wpBV2e12tWzZ0pJBEABgHZYNQhWx2WyKjo5W06ZNVVRk3XsL+fv7y27nFDIAQP3m9SA0f/58/fWvf1VGRoY6dOigefPmqXfv3hX237Rpk5KSkrRv3z7FxMTo4Ycf1vjx46u83QkbczS7e7baX9K+3M99fHw4PwYAgHrOq/+Xf+XKlZo8ebKmT5+uXbt2qXfv3urfv7/riek/d/DgQQ0YMEC9e/fWrl279Pvf/16TJk3S66+/XvWN+/hrZmq4hr+dcYHfAgAA1FVefehqQkKCrrzySi1YsMDV1q5dOw0ZMkRz5swp0/93v/ud3n77baWlpbnaxo8fr88//1xbt26t1DbdHroaGHy20enUyluiL+zLAACAGlNTD1312ohQYWGhduzYocTERLf2xMREffLJJ+Uus3Xr1jL9+/Xrp+3bt1fvfJ7SE4HtdqUeSK368gAAoE7z2jlCx48fV0lJiSIjI93aIyMjlZmZWe4ymZmZ5fYvLi7W8ePHFR1ddlSnoKBABQUFrvc5OTmSpKIzJ936PfKpTUua5FbruwAAgJqVm3v2GO3piSyvnyz988uzjTHnvGS7vP7ltZeaM2eOZs6cWab9nTFdy7S9cd5qAQCAN2VlZSk0NNRj6/NaEGrSpIl8fHzKjP4cO3aszKhPqaioqHL7+/r6Kjw8vNxlpk2bpqSkJNf77OxsxcbGKj093aM/JKonNzdXLVq00OHDhz0654uqY19cPNgXFw/2xcUjJydHLVu2VFhYmEfX67Ug5O/vr/j4eKWkpOjWW291taekpGjw4MHlLtOjRw+tXbvWrW39+vXq1q2b6/EYPxcQEKCAgIAy7aGhofyP+iISEhLC/rhIsC8uHuyLiwf74uLh6XvcefXy+aSkJC1cuFCLFi1SWlqaHnzwQaWnp7vuCzRt2jSNGjXK1X/8+PE6dOiQkpKSlJaWpkWLFunll1/WlClTvPUVAABAHebVc4SGDx+urKwszZo1SxkZGerYsaOSk5MVGxsrScrIyHC7p1BcXJySk5P14IMP6rnnnlNMTIyeeeYZDRs2zFtfAQAA1GFeP1l6woQJmjBhQrmfLVmypExbnz59tHPnzmpvLyAgQI8++mi502WofeyPiwf74uLBvrh4sC8uHjW1L7x6Q0UAAABv4qmaAADAsghCAADAsghCAADAsghCAADAsuplEJo/f77i4uLkcDgUHx+vLVu2nLP/pk2bFB8fL4fDoUsuuUTPP/98LVVa/1VlX6xZs0Y33nijIiIiFBISoh49emjdunW1WG39V9V/G6U+/vhj+fr6qkuXLjVboIVUdV8UFBRo+vTpio2NVUBAgC699FItWrSolqqt36q6L5YvX67OnTsrKChI0dHRGjt2rLKysmqp2vpr8+bNGjRokGJiYmSz2fTmm2+edxmPHL9NPfOPf/zD+Pn5mZdeesmkpqaaBx54wDRo0MAcOnSo3P4HDhwwQUFB5oEHHjCpqanmpZdeMn5+fmb16tW1XHn9U9V98cADD5jHH3/cfPrpp2b//v1m2rRpxs/Pz+zcubOWK6+fqro/SmVnZ5tLLrnEJCYmms6dO9dOsfVcdfbFLbfcYhISEkxKSoo5ePCg2bZtm/n4449rser6qar7YsuWLcZut5unn37aHDhwwGzZssV06NDBDBkypJYrr3+Sk5PN9OnTzeuvv24kmTfeeOOc/T11/K53Qah79+5m/Pjxbm1t27Y1U6dOLbf/ww8/bNq2bevWdt9995mrr766xmq0iqrui/K0b9/ezJw509OlWVJ198fw4cPNI488Yh599FGCkIdUdV+8++67JjQ01GRlZdVGeZZS1X3x17/+1VxyySVubc8884xp3rx5jdVoRZUJQp46fterqbHCwkLt2LFDiYmJbu2JiYn65JNPyl1m69atZfr369dP27dvV1FRUY3VWt9VZ1/8nNPp1MmTJz3+gD0rqu7+WLx4sb7++ms9+uijNV2iZVRnX7z99tvq1q2bnnjiCTVr1kxt2rTRlClTlJeXVxsl11vV2Rc9e/bUkSNHlJycLGOMvvvuO61evVoDBw6sjZLxE546fnv9ztKedPz4cZWUlJR5en1kZGSZp9aXyszMLLd/cXGxjh8/rujo6Bqrtz6rzr74uaeeekqnT5/W7bffXhMlWkp19sdXX32lqVOnasuWLfL1rVd/KryqOvviwIED+uijj+RwOPTGG2/o+PHjmjBhgk6cOMF5QhegOvuiZ8+eWr58uYYPH678/HwVFxfrlltu0d///vfaKBk/4anjd70aESpls9nc3htjyrSdr3957ai6qu6LUq+99pr++Mc/auXKlWratGlNlWc5ld0fJSUlGjFihGbOnKk2bdrUVnmWUpV/G06nUzabTcuXL1f37t01YMAAzZ07V0uWLGFUyAOqsi9SU1M1adIkzZgxQzt27NB7772ngwcPuh4WjtrlieN3vfq/eU2aNJGPj0+ZJH/s2LEyqbFUVFRUuf19fX0VHh5eY7XWd9XZF6VWrlypcePGadWqVbrhhhtqskzLqOr+OHnypLZv365du3bp/vvvl3T2YGyMka+vr9avX6++ffvWSu31TXX+bURHR6tZs2YKDQ11tbVr107GGB05ckStW7eu0Zrrq+rsizlz5qhXr1566KGHJEmdOnVSgwYN1Lt3b82ePZtZhFrkqeN3vRoR8vf3V3x8vFJSUtzaU1JS1LNnz3KX6dGjR5n+69evV7du3eTn51djtdZ31dkX0tmRoDFjxmjFihXMuXtQVfdHSEiI9u7dq927d7te48eP1+WXX67du3crISGhtkqvd6rzb6NXr1769ttvderUKVfb/v37Zbfb1bx58xqttz6rzr44c+aM7Hb3Q6ePj4+k/41GoHZ47PhdpVOr64DSSyFffvllk5qaaiZPnmwaNGhgvvnmG2OMMVOnTjUjR4509S+9/O7BBx80qamp5uWXX+byeQ+p6r5YsWKF8fX1Nc8995zJyMhwvbKzs731FeqVqu6Pn+OqMc+p6r44efKkad68ubntttvMvn37zKZNm0zr1q3NPffc462vUG9UdV8sXrzY+Pr6mvnz55uvv/7afPTRR6Zbt26me/fu3voK9cbJkyfNrl27zK5du4wkM3fuXLNr1y7XrQxq6vhd74KQMcY899xzJjY21vj7+5srr7zSbNq0yfXZ6NGjTZ8+fdz6f/jhh6Zr167G39/ftGrVyixYsKCWK66/qrIv+vTpYySVeY0ePbr2C6+nqvpv46cIQp5V1X2RlpZmbrjhBhMYGGiaN29ukpKSzJkzZ2q56vqpqvvimWeeMe3btzeBgYEmOjra3HnnnebIkSO1XHX9s3HjxnMeA2rq+G0zhrE8AABgTfXqHCEAAICqIAgBAADLIggBAADLIggBAADLIggBAADLIggBAADLIggBAADLIggBAADLIggBuOiNGTNGNputzOu///2v22d+fn665JJLNGXKFJ0+fVqS9M0337gtExoaqquvvlpr16718rcCcDEgCAGoE2666SZlZGS4veLi4tw+O3DggGbPnq358+drypQpbsu///77ysjI0LZt29S9e3cNGzZMX3zxhTe+CoCLCEEIQJ0QEBCgqKgot1fpU79LP2vRooVGjBihO++8U2+++abb8uHh4YqKilLbtm315z//WUVFRdq4caMXvgmAiwlBCEC9ExgYqKKionI/Kyoq0ksvvSRJ8vPzq82yAFyEfL1dAABUxjvvvKPg4GDX+/79+2vVqlVl+n366adasWKFrr/+erf2nj17ym63Ky8vT06nU61atdLtt99e43UDuLgRhADUCdddd50WLFjget+gQQPXf5eGpOLiYhUVFWnw4MH6+9//7rb8ypUr1bZtW+3fv1+TJ0/W888/r7CwsFqrH8DFiSAEoE5o0KCBLrvssnI/Kw1Jfn5+iomJKXfKq0WLFmrdurVat26t4OBgDRs2TKmpqWratGlNlw7gIsY5QgDqvNKQFBsbW6nzfvr06aOOHTvqz3/+cy1UB+BiRhACYEn/93//pxdeeEFHjx71dikAvIggBMCSbr75ZrVq1YpRIcDibMYY4+0iAAAAvIERIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFkEIQAAYFn/D9hVQ+t6MoGMAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAHFCAYAAAAe+pb9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABLXUlEQVR4nO3deVxU9f4/8NeZjWEREGRVRCzNLTdMEuWalhiauZWWK2bd+Fm5cK2rWZle+2Ld8paZdtPUvC6Za1akcNPrUmYumKbc8qqJGoiggAKyzef3BzIyzADDODMHOK/n4zEPmTOfc8575uCcF5/PWSQhhAARERGRAqnkLoCIiIhILgxCREREpFgMQkRERKRYDEJERESkWAxCREREpFgMQkRERKRYDEJERESkWAxCREREpFgMQkRERKRYDEJENlq9ejUkSTI+NBoNgoKC8NRTT+HMmTMW5ykpKcGyZcvQq1cveHl5wdXVFe3bt8esWbOQnZ1tcR6DwYB//etfeOSRR9CsWTNotVr4+/vjsccew1dffQWDwVBrrUVFRViyZAn69OmDpk2bQqfToXnz5hg1ahT27t17V5+DnD788EPce++90Ol0kCQJOTk5DlvXm2++CUmSkJWVVWvbhx56yOR3w9XVFV26dMH7779vsr1iY2Ph4eEBALh69Sp0Oh2eeuqpapebl5cHNzc3PP7449W2uXjxIoYPH47WrVvD3d0dXl5e6NatG5YsWYLS0tJaa6/4vT5y5Eitbav6+uuvMWHCBNx///3QarWQJKnOyyByNgYhoru0atUqHDx4EP/+97/x4osvYseOHejTpw+uX79u0q6goAADBgzASy+9hG7dumHDhg1ITEzE+PHj8cknn6Bbt2749ddfTea5desWBg0ahIkTJ8Lf3x/Lli3D7t278fHHHyM4OBhPPvkkvvrqqxrry8rKQu/evREfH49OnTph9erV+O677/Dee+9BrVbj4Ycfxs8//2z3z8XRjh8/jqlTp6Jfv37YvXs3Dh48iCZNmshdllHr1q1x8OBBHDx4EBs3bkTz5s0xY8YMzJ4922J7Pz8/PP7449i+fbvZ706Fzz//HIWFhZg8eXK1683Pz4enpydef/117NixA59//jn69OmDl156CXFxcXZ5b9XZtm0bfvzxR3To0AFdunRx6LqI7EYQkU1WrVolAIjDhw+bTJ83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+PzChQt4//33kZSUZLfCiIiIiBzNpiA0dOhQrFmzBgCQk5ODnj174r333sPQoUOxbNkyuxZIRERE5Cg2BaFjx44hKioKALB582YEBgbiwoULWLNmDRYvXmzXAh3laok7DELIXQYRERHJyKYgVFBQgCZNmgAAkpKSMGLECKhUKjz44IO4cOGCXQt0lAP5bfDC7mwcSr8ldylEREQkE5uC0L333ovt27fj4sWL2LVrF6KjowEAmZmZDeoii9duGbDoWB7DEBERkULZFITeeOMNzJw5E61atUJERAR69eoFoLx3qFu3bnYt0Bk+O32Tw2REREQKZNOVpZ944gn06dMH6enp6NKli3H6ww8/jOHDh9utOGfJvmVA6rUSdPTV1d6YiIiIGg2bghAABAYGIjAw0GRaz54977ogueTcMshdAhERETmZTUEoPz8fCxcuxHfffYfMzEwYDKYh4ty5c3Ypzpm89TaNEhIREVEDZlMQevbZZ7F3716MHz8eQUFBxltvNFS+ehXa+2jlLoOIiIiczKYg9O233+Kbb75B79697V2PLCZ28ICqgYc5IiIiqjubglDTpk3h4+Nj71qczlevwsQOHogI0stdChEREcnApgNj/va3v+GNN94wud9YQ9PH/QyW9PdlCCIiIlIwm3qE3nvvPZw9exYBAQFo1aoVtFrT42uOHTtml+IcyU+bz+EwIiIihbMpCA0bNszOZRARERE5n01BaO7cufauw+mu5JehrKwUarXNl1IiIiKiBs7mi+fk5ORgxYoVmD17Nq5duwagfEjs8uXLdivOkX4oCceUxFTsP7FX7lKIiIhIJjZ1h5w4cQKPPPIIvLy88Pvvv+O5556Dj48Ptm3bhgsXLmDNmjX2rtMhciQ/LEnzA7AXUZ37yl0OEREROZlNPULx8fGIjY3FmTNnoNffOesqJiYG+/bts1txDieVv/21F5qirKxU5mKIiIjI2WwKQocPH8bzzz9vNr158+bIyMi466KcSlIhRxWIk2fr/5luREREZF82BSG9Xo+8vDyz6b/++iv8/Pzuuig5XM+/KXcJRERE5GQ2BaGhQ4di/vz5KCkpAQBIkoS0tDTMmjULI0eOtGuBztLU3UPuEoiIiMjJbApC7777Lq5evQp/f38UFhaib9++uOeee+Dh4YG33nrL3jU6ljDA25CB++/pLnclRERE5GQ2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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAHFCAYAAAAe+pb9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABaLklEQVR4nO3deVxU5f4H8M+ZnWEVZBVEM82tNDFJjVxKTM00NS1L0ezevFYuXCu99qvsdi9lZbu2KC6l5tXMNkwtzSWNXHNNyw0XUAFhkHWYeX5/IKMDAwzDLMD5vF+veck85znP+Q4HOV+e55znkYQQAkREREQypPB0AERERESewkSIiIiIZIuJEBEREckWEyEiIiKSLSZCREREJFtMhIiIiEi2mAgRERGRbDERIiIiItliIkRERESyxUSIqBYWL14MSZIsL5VKhfDwcDz88MP4888/be5jNBoxf/58dO/eHf7+/vDy8kK7du0wY8YMZGVl2dzHbDbjs88+w7333oumTZtCrVYjJCQE999/P7799luYzeYaYy0uLsYHH3yAu+66C02aNIFGo0GzZs0wcuRIbNmypU7fB096//33cfPNN0Oj0UCSJOTk5LjsWBXPtyRJCA4ORu/evfHdd99Vql+xrp+fH3r06IEVK1bYbD81NRUPPvggmjdvDq1Wi9DQUHTv3h3//Oc/AQCXL1+GRqPBww8/XGWMBoMBer0eDzzwQKVtP//8syWWxYsX29y/b9++kCQJLVq0sGrzP//5D3r37o2wsDD4+Pjg1ltvxeuvv46ioqJqvmPXLV26FA8//DBuueUWKBQKq/aJ6hMmQkQOWLRoEXbu3Ikff/wRTz/9NL755hvcdddduHLlilW9goIC9OvXD8888wxuv/12rFixAikpKRgzZgw++eQT3H777Th27JjVPkVFRRg4cCASEhIQEhKC+fPnY9OmTfjoo48QERGBhx56CN9++2218WVmZqJnz55ITExEx44dsXjxYvz000946623oFQqcc899+D33393+vfF1fbv34/JkyejT58+2LRpE3bu3AlfX1+XH7f8fO/YsQOffPIJlEolBg8ebPM8jBgxwlL3o48+gsFgwOjRo7F8+XKret9//z169OgBg8GAOXPmYMOGDXj33XfRs2dPrFy5EgAQHByMBx54AGvXrq30s1Xuiy++QGFhISZMmFBl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evSouPfee4WXl5eIjIwUiYmJoqCgwM1RN061PRfvvfeeaN++vfDy8hLh4eHi0UcfFefOnXNz1I3P5s2bq70GuOr6LQnBvjwiIiKSp0Z1jxARERFRbTARIiIiItliIkRERESyxUSIiIiIZIuJEBEREckWEyEiIiKSLSZCREREJFtMhIiIiEi2mAgRUb03btw4SJJU6fXXX39ZbVOr1bjpppswffp05OfnAwBOnz5ttY+/vz/uvPNOfPvttx7+VERUHzARIqIG4b777kN6errVq2XLllbbTp48iVdffRXz5s3D9OnTrfb/8ccfkZ6ejtTUVHTr1g3Dhw/HoUOHPPFRiKgeYSJERA2CVqtFWFiY1at81e/ybVFRURg9ejQeffRRrF271mr/oKAghIWFoW3btvjPf/4Do9GIzZs3e+CTEFF9wkSIiBodLy8vGI1Gm9uMRiM+/fRTAIBarXZnWERUD6k8HQARkT2+++47+Pj4WN4PGDAAq1atqlTvt99+w/Lly3HPPfdYlffo0QMKhQKFhYUwm81o0aIFRo4c6fK4iah+YyJERA1Cnz59MH/+fMt7b29vy9flSVJpaSmMRiOGDBmC999/32r/lStXom3btjh+/DimTp2Kjz76CIGBgW6Ln4jqJyZCRNQgeHt74+abb7a5rTxJUqvViIiIsDnkFRUVhdatW6N169bw8fHB8OHDceTIEYSEhLg6dCKqx3iPEBE1eOVJUnR0tF33/fTq1QsdO3bEf/7zHzdER0T1GRMhIpKlf/7zn/j4449x/vx5T4dCRB7ERIiIZOn+++9HixYt2CtEJHOSEEJ4OggiIiIiT2CPEBEREckWEyEiIiKSLSZCREREJFtMhIiIiEi2mAgRERGRbDERIiIiItliIkRERESyxUSIiIiIZIuJEBEREckWEyEiIiKSLSZCREREJFtMhIiIiEi2/h8euzaJHvqc+wAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkIAAAHFCAYAAAAe+pb9AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABMXElEQVR4nO3deVxU5f4H8M/sw64gqyKSaW65oSIqmVYYmmnazdLc0sqr5cLPSrOraRbeFm9ZaYvilnpNU9NChdJc0swF09TSmyZqIAIBys7M8/sDZ3ScAWGcmQOcz/v1mlfMmeec8505wXx8nuecoxBCCBARERHJkFLqAoiIiIikwiBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLLFIER13rJly6BQKMwPtVqN4OBgPPnkkzhz5ozNdUpLS7Fo0SJERUXBx8cHbm5uaNmyJaZNm4asrCyb6xiNRqxcuRIPPvggGjRoAI1Gg4CAADzyyCPYsmULjEbjbWstLi7GRx99hB49eqB+/frQarVo2LAhnnjiCezateuOPgcpffjhh7j77ruh1WqhUCiQk5PjtH3derwVCgX8/f1x//3345tvvjG369ChAxo2bAiDwVDhtrp3744GDRqgpKQEf/75p8U2NRoN/Pz80LlzZ0yZMgUnTpywWLe626/IihUr8OSTT+Kee+6BUqlEkyZNqv5hAFafhekxb948i3ajRo2Cp6dnhdvx9PTEqFGjAABNmjSpcLs3P5YtW2azBm9vb3Tr1g1r1qyp0ntYsGABunbtigYNGkCn06Fx48Z48sknrT5zInswCJFsLF26FPv378d3332HF154AZs3b0aPHj3w999/W7QrKCjAQw89hBdffBEdOnTAmjVrkJiYiOHDh+Ozzz5Dhw4d8Pvvv1usU1RUhL59+2LkyJEICAjAokWLsGPHDnzyyScICQnBP/7xD2zZsqXS+jIzM9G9e3fExcWhTZs2WLZsGb7//nu89957UKlUeOCBB/DLL784/HNxtqNHj2LixIno1asXduzYgf3798PLy8vp+zUd73379uGzzz6DSqVC//79zcdhzJgx+Ouvv7B9+3ab658+fRr79u3D8OHDodVqzctffPFF7N+/H7t27cLKlSsxcOBAbN68Ge3atcM777xjbmfv9m+1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1fnz56HT6eDr61ut7Tdt2tTic50zZ061910dTz/9NMrKynDo0CHzMrVaXemp/mVlZeb5VfZ44okncPDgQezbtw+ffvopvLy8Kr2EhS0dO3ZE165dMWzYMOzcuRNCCLz66qt210QEMAiRjJi+GHv16oVPPvkEY8eOxbZt27B+/Xpzm169ekGtVpsnQttieu2hhx4yr6PRaCpd53ZMwzVV3YZerwcA8zCBSUWhpKLeqz59+iAkJMT8Jb106VJERkaiVatW5jYNGjSAn5+fuXfl1sfChQurVPPN/Pz8AABpaWlWr/31119o0KBBleqvrrZt26KwsBCnT582L2vUqBFiYmKwevVqFBcXY+nSpbj77rtx3333VWvbly5dwuHDh9GjRw+LXsaqbH/Lli0Wn+lzzz1352+2Eqaeq5snYgcGBqKoqAjZ2dlW7bOyslBcXIzAwEC79+nv749OnTohKioKzz33HDZt2oT8/HxMmTLFru15eXmhRYsWFseSyB4MQiRbb7/9NurXr4+ZM2eahyKCgoLwzDPPYPv27Vi7dq3VOqdPn8a///1vtG7d2jyxOSgoCGPHjsX27duxYsUKm/v6448/cOzYsQpr6dixI2JjY7FkyRLs2LHDZptDhw6Z5xKZLqp36zZvd62iW6lUKgwfPhybNm3Cnj17cOjQITzzzDMWbR555BFkZWXBYDCYe1huftxzzz3V2icAREVFwc3NzWoS8cWLF7Fjxw67zgqriqNHjwK4ccaRyZgxY/D3339j5syZOHr0KEaPHl2t8FVYWIixY8eirKwML7/8stXrt9v+vffea/GZhoSE2PcGq2jlypXQaDQWw1IPPvggANj8//7LL7+0aOMI0dHRGDFiBL799lvs37+/2utnZmbi+PHjuPvuux1WE8mUpCfvE7lARdeVEUKIt99+WwAQK1euNC+7du2a6Nmzp1Cr1WL8+PFi69atYseOHeKtt94Svr6+olGjRuK3336z2E5hYaHo06ePUCgUYujQoWLdunVi9+7dYsOGDeKf//yn0Ov1YtOmTZXWeeXKFRERESG0Wq0YN26c+Prrr8Xu3bvF2rVrxdNPPy1UKpU4evSoEEKI3Nxc4evrK+69916xceNGsWXLFjF48GARHh4uAIhz586ZtxsWFib69etX4X5///13AUA0atRIuLm5iZycHIvXy8rKRGxsrPD19RWzZ88WW7duFd99951YtmyZGDlypNiwYUOl76uiz/+tt94SAMTw4cNFYmKiWLlypbj77ruFj4+POH36tLnd7a5vU9H+li5dKvbv3y/2798vvvnmG/HMM88IAOKxxx6zWqe4uFg0aNBAKBQKoVKpxMWLF63amK4j9OKLL4r9+/eLH3/8USQmJoo333xTNG3aVKjVavHee+/ZrKkq26/IiRMnxLp168S6detERESE8Pf3Nz8/ceKEud0PP/wgVCqVmD17tnnZ22+/LUaNGiVWrlwpdu7cKdauXStiYmIEAPH6669b7evRRx8VGo1GvPzyy+Lbb78V33zzjXj55ZeFRqMRjz76aIU12nMdISGESE1NFXq9XjzwwAPmZU2bNhVNmzY1P8/JyRGdO3cW//nPf8Q333wjvv/+e7Fo0SLRokUL4e7ubvP3mqg6GISozqssCBUWForGjRuLZs2aWVwgsaSkRHz88cciMjJSeHp6Cp1OJ+655x7x8ssvi8zMTJv7KSsrE8uXLxe9e/cWvr6+Qq1WC39/fxEbGytWr15tcWG8ihQWFooFCxaIqKgo4e3tLdRqtQgJCRGDBg0S3377rUXbn3/+WXTr1k14eHiIhg0bilmzZonFixdXOwgJIUS3bt0EADFs2DCbr5eWlop3331XtGvXTuj1euHp6SlatGghnn/+eXHmzJlKt13Z57948WLRtm1bodVqhY+PjxgwYIDFl7sQ9gehmx8+Pj6iffv2Yv78+aKoqMjmelOmTBEARN++fW2+bgpCpodKpRL169cXERERYvLkyVZ1V3f7FTGFDFuPWbNmmdvt3LnTatnmzZtFjx49hL+/v1Cr1cLLy0tER0eLNWvW2NxXSUmJeOutt0Tr1q2FTqcTOp1OtG7dWrz11luipKTktjVWNwgJIcRLL70kAIhdu3YJIcr/f735opFFRUVi7NixomXLlsLT01Oo1WrRqFEj8fTTT9/2MyeqCoUQt5zmQERERCQTnCNEREREssUgRERERLLFIERERESyJWkQ2r17N/r374+QkBAoFIoqXUNl165diIiIgF6vx1133YVPPvnE+YUSERFRnSRpEMrPz0e7du0sLnlfmXPnzqFv376Ijo5GSkoKXn31VUycOBFfffWVkyslIiKiuqjGnDWmUCiwcePGSu++/corr2Dz5s04deqUedm4cePwyy+/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4+NjFYIAwNfX16KHqDKZmZkwGAwWk6+B8nlIFd249cyZM5g2bRpWrVoFtbpqGS4+Ph4+Pj7mR2hoqM12xsK0Km2PiIiI6g67gpAjKRQKi+dCCKtlAGAwGDB06FDMnj0bzZs3r/L2p0+fjtzcXPOjorPalG7B1SuciIiIaj27brHhCA0aNIBKpbLq/cnIyLDqJQLKz0g7dOgQUlJS8MILLwAAjEYjhBBQq9VISkpC7969rdbT6XTQ6XSVVKKA0r0RtIHRlbQhIiKiukiyHiGtVouIiAgkJydbLE9OTka3bt2s2nt7e+P48eM4evSo+TFu3Djcc889OHr0KCIjI+2oorznyTvyfSiU1kN9REREVLdJ1iMEAHFxcRg+fDg6deqEqKgofPbZZ0hNTcW4ceMAlA9rXbp0CStWrIBSqUSbNm0s1g8ICIBer7daXlVK90bwjnwfbmGD7vi9EBERUe0jaRAaMmQIsrKyMGfOHKSlpaFNmzZITExEWFgYACAtLe221xSyl6ZBVwT0+5w9QURERDKmEEIIqYtwpby8PPj4+GBF0noMf2iw1OUQERFRFZi+v3Nzc+Ht7e2w7Up+1hgRERGRVBiEiIiISLYYhIiIiEi2GISIiIhIthiEiIiISLYYhIiIiEi2GISIiIhIthiEiIiISLYYhIiIiEi2GISIiIhIthiEiIiISLYYhIiIiEi2GISIiIhItmQbhK6UesAohNRlEBERkYRkG4T25jfDhB1ZOJBWJHUpREREJBHZBiEAyC4yYv6RPIYhIiIimZJ1EDJZfvIah8mIiIhkiEEIQFaREaeyS6Uug4iIiFyMQei6nCKj1CUQERGRizEIXVdPz4+CiIhIbvjtD8BPr0RLX43UZRAREZGLMQgBGNnKE0qFQuoyiIiIyMXUUhcgJT+9EiNbeSIyWC91KURERCQB2QahHh5nMLl3H/YEERERyZhsh8b8NfkMQURERDIn2yBERERExCBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLLFIERERESyxSBEREREssUgRERERLIl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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Generate list of color blind colors\n", + "color_list = [\n", + " ###########################################################################################\n", + " # Colors from Points of View: Color Blindness (Nature Methods, 8, 441 (2011)) by B. Wong #\n", + " # https://www.nature.com/articles/nmeth.1618 #\n", + " # RGB values extracted using ChatGPT v4o (https://chat.openai.com/) and verified by eye #\n", + " ###########################################################################################\n", + " (230, 159, 0), # Orange\n", + " (86, 180, 233), # Sky blue\n", + " (0, 158, 115), # Bluish green\n", + " (240, 228, 66), # Yellow\n", + " (0, 114, 178), # Blue\n", + " (213, 94, 0), # Vermillion\n", + " (204, 121, 167), # Reddish purple\n", + " (0, 0, 0), # Black\n", + "]\n", + "\n", + "# Create figure counter to start a new figure for each primer set\n", + "figCount = 1\n", + "\n", + "# Loop through each primer set and plot ROC curves for each concentration\n", + "for pSet in allResults['Primer Set'].unique():\n", + " # Initialize new figure for this primer set\n", + " plt.figure(figCount)\n", + "\n", + " # Create color index counter for each concentration level being tested\n", + " colorIdx = 0\n", + "\n", + " # Loop through each concentration level and plot ROC curve\n", + " for conc in allResults[allResults['Primer Set'] == pSet]['Concentration'].unique():\n", + "\n", + " # Plot ROC curve using the a color blind list. If number of concentrations levels exceeds \n", + " # number of colors in list, color will repeat\n", + " plt.plot(allResults[(allResults['Primer Set'] == pSet) & (allResults['Concentration'] == conc)]['FPR'], \n", + " allResults[(allResults['Primer Set'] == pSet) & (allResults['Concentration'] == conc)]['Sensitivity'], \n", + " linestyle='-', marker='o', label=conc, color=tuple(c / 255 for c in color_list[colorIdx % len(color_list)]))\n", + " colorIdx += 1\n", + "\n", + " # Format plot and add cutoff line of 95% sensitivity\n", + " plt.legend()\n", + " plt.xlabel('FPR')\n", + " plt.ylabel('Sensitivity')\n", + " plt.title(f\"ROC Curve for {pSet}\")\n", + " plt.plot([0,1], [0.95, 0.95], linestyle='dashed')\n", + " plt.xlim(0,1)\n", + " plt.ylim(0,1)\n", + "\n", + " # Increment figure counter for next primer set figure\n", + " figCount += 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.20" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/PrimerAnalysis/PrimerAnalysis.py b/PrimerAnalysis/PrimerAnalysis.py new file mode 100644 index 0000000..00ce31d --- /dev/null +++ b/PrimerAnalysis/PrimerAnalysis.py @@ -0,0 +1,511 @@ +#!/usr/bin/env python + +'''PrimerAnalysis.py is a python module for analyzing LAMP primer amplification data''' + +__author__ = 'Josiah Levi Davidson' +__contact__ = 'Mohit S. Verma' +__email__ = 'msverma@purdue.edu' +__version__ = '1.3.0' +__status__ = 'Development' +__copyright__ = "Copyright (C) 2024 Purdue Research Foundation" +__license__ = "GNU Affero General Public License Version 3 with Commons Clause" + +#### BEGIN IMPORTS + + +import math +import pandas as pd +import numpy as np +from os import path +from matplotlib import pyplot as plt + +# BEGIN GLOBAL VARIABLES +weights = {} +thresholds = [] +replicates = 0 +primerSetName = "" +rxnTypeDesignation = "" + +# BEGIN CONSTANTS +MAX_INST_SIGNAL = 140000 +threshold_perc = 0.1 + +# Initialization method to set weights and thresholds. +# Aruments +# set_weights := Array of length 5 which contains weights in the following order: +# Average Maximum Intensity +# Standard Deviation of Maximum Intensity +# Standard Deviation of Reaction Time +# Average Reaction Time +# False Positive +# set_thresholds := Array of threshold values to determine exponential phase beginning, +# plateau phase ending, positive reaction calculation threshold, +# and false positive threshold, respectively +# set_replicates := Number of replicates. Must be the same for all primer sets. +def initialize(set_weights = [5, 5, 10, 20, 60], set_thresholds = [3000, 200, 0.9, 0.2], set_replicates = 4, set_instrument_signal = 140000, set_threshold_perc = 0.1): + if not (len(set_weights) == 5): + raise ValueError('Weights do not contain 5 values. Refer to readme for more information.') + if not (len(set_thresholds) == 4): + raise ValueError('thresholds do not contain 2 values. Refer to readme for moe information.') + if not (set_replicates >= 3): + raise ValueError('Number of replicates is not greater than or equal to 3.') + + global weights, thresholds, replicates, primerSetName, rxnTypeDesignation, MAX_INST_SIGNAL, threshold_perc + weights = {'Intensity_Avg': set_weights[0], 'Intensity_StdDev': set_weights[1], 'RxnTime_Std':set_weights[2], + 'RxnTime_Avg': set_weights[3], 'False_Positives':set_weights[4]} + thresholds = set_thresholds + replicates = set_replicates + MAX_INST_SIGNAL = set_instrument_signal + threshold_perc = set_threshold_perc + +# Main primer scoring method. Call to generate output +# Arguments: +# primerData := Path to input file containing primer data formatted correctly. See readme for more details. +# output := Output file name containing .csv +def scorePrimers(primerData, output): + if not (len(thresholds) == 4): + raise BaseException('Not initialized. Initialize scoring') + if not path.exists(primerData): + raise ValueError('Primer Data file not found.') + + if not (len(output) > 0): + raise ValueError('Ouput file name not properly defined.') + + getPrimerSummary(primerData).to_csv(output, encoding='utf-8') + +# Function to calculate average maximum intensity across the positive replicates of a single primer set +# Arguments: +# name := String, name of primer set to calculate maximum intensity for +# df := DataFrame, dataframe containing all primer set amplification data +def calc_max_avg(name, df): + df = df[df['Primer']==name] + pos_rxns = df[df['RxnType']=='+'].drop(['Primer', 'RxnType','ObservedType', 'RxnTime', 'RxnPenalty'], axis=1) + return pos_rxns.max(axis=1).mean() + +# Function to calculate the standard deviation of the maximum intensity across the positive replicates of a single primer set +# Arguments: +# name := String, name of primer set to calculate standard deviation for +# df := DataFrame, dataframe containing all primer set amplification data +def calc_max_std(name, df): + df = df[df['Primer']==name] + pos_rxns = df[df['RxnType']=='+'].drop(['Primer', 'RxnType','ObservedType', 'RxnTime', 'RxnPenalty'], axis=1) + return pos_rxns.max(axis=1).std() + +# Function to calculate average reaction time for a single primer set. +# Arguments: +# name := String, name of primer set to calculate average reaction time +# df := DataFrame, dataframe containing all primer set amplification data +def calc_rxn_time_avg(name, df): + df = df[df['Primer']==name] + pos_rxns = df[df['RxnType']=='+'] + return pos_rxns['RxnTime'].mean() + +# Function to calculate standard deviation of the reaction time across the positive replicates of a single primer set +# Arguments: +# name := String, name of primer set to calculate maximum intensity for +# df := DataFrame, dataframe containing all primer set amplification data +def calc_rxn_time_std(name, df): + curPrimer = df[df['Primer']==name] + pos_rxns = curPrimer[curPrimer['RxnType']=='+'] + return pos_rxns['RxnTime'].to_numpy().std() + +# Function to determine if a reaction is positive or not. Function deteremines a positive according to the following algorithm: +# 1. Determine the intersection point of the reaction and then the reaction reversed. +# 2. Determine the angle from the interxection to time point 0 of both the forward and reverse season. +# 3. If the angle is sufficiently close to 0 (0.95% error in the approximation of the cosine of theta), then mark as negative +# 4. Otherwise, take the derivative and if the lower quantile is greter than 0 (i.e. the signal is not noisy), return as positive +# 5. Otherwise, return negative. +# Arguments: +# rxnTimeSeries := DataSeries, time series of reaction fluoroescent data. +def determine_pos(rxnTimeSeries): + errorRateTan = 0.95 + + data = rxnTimeSeries + revData = rxnTimeSeries[::-1] + + idxIntersect = np.where(np.greater(revData.values, data.values)==False)[0][0] + + dataVec = np.array([idxIntersect, data.iloc[idxIntersect] - data.iloc[0]]) + revDataVec = np.array([idxIntersect, revData.iloc[idxIntersect] - revData.iloc[0]]) + + magnitude = (np.linalg.norm(dataVec)*np.linalg.norm(revDataVec)) + + if magnitude == 0: + return 0 + else: + theta = math.acos(np.inner(dataVec, revDataVec)/magnitude) + + if((math.cos(theta) > errorRateTan) or math.isnan(theta)): + return 0 + else: + if(data.max() > (threshold_perc * MAX_INST_SIGNAL)): + return 1 + else: + return 0 + +# Function to determine true positives based on predicted amplification +# Arguments: +# name := String, name of primer set to calculate maximum intensity for +# df := DataFrame, dataframe containing all primer set amplification data +def calc_true_pos(name, df): + df = df[df['Primer']==name] + pos_rxns = df[df['RxnType']=='+'] + true_pos_rxns = pos_rxns['ObservedType'].sum() + + return true_pos_rxns + +# Function to determine false positives based on predicted amplification +# Arguments: +# name := String, name of primer set to calculate maximum intensity for +# df := DataFrame, dataframe containing all primer set amplification data +def calc_false_pos(name, df): + df = df[df['Primer']==name] + neg_rxns = df[df['RxnType']=='-'] + true_pos_rxns = neg_rxns['ObservedType'].sum() + + return true_pos_rxns + +# Function to calculate reaction time of a single reaction. +# Reaction time is determined as the maximum of the second derivative of the time series. +# Arguments: +# rxnTimeSeries := DataSeries, time series of reaction fluoroescent data. +def calc_rxn_time(rxnTimeSeries): + mat = rxnTimeSeries.to_numpy() + return np.argmax(np.gradient(np.gradient(mat))) + +# Function to calculate scored value for a single item +# Arguments: +# row := DataFrame, results for a single primer set +# df_results := DataFrame, dataframe for results of all primer sets +# item := The reaction characteristic that is being scored +def calc_item_score(row, df_results, item): + item_min = df_results[item].min() + item_max = df_results[item].max() + item_range = item_max - item_min + value = row[item] + if item_range == 0: + score = 1 + else: + if(item == "Intensity_Avg"): + score = 1 - ((item_max - value)/item_range) + else: + score = 1 - ((value - item_min)/item_range) + weighted_score = score * weights[item] + return weighted_score + +# Function to calculate the overall score for a given primer set in water. +# row := DataFrame, results for a single primer set +# df_results := DataFrame, dataframe for results of all primer sets +def calc_overall_score(row, df_results): + overall_score = 0 + for item in weights.keys(): + if not item=="False_Positives": + overall_score += calc_item_score(row, df_results, item) + for i in range(0, replicates): + overall_score += row['FP_{}'.format(i+1)] + return overall_score + +# Function to calculate the overall score for a given primer set in saliva. +# row := DataFrame, results for a single primer set +# df_results := DataFrame, dataframe for results of all primer sets +def calc_overall_score_saliva(row, df_results): + overall_score = 0 + weights_sal = {'Intensity_Avg': 20, 'Intensity_StdDev': 10, 'RxnTime_Std':40, 'RxnTime_Avg': 30} + for item in weights_sal.keys(): + overall_score += calc_item_score(row, df_results, item) + return overall_score + +def calc_FP_cardinal(name, df, df_results, n, retValue = 'Score'): + + # Calculate the total number of divisions given a number of replicates. This is just the sum of 1...num of replicates. + totalDivisions = 0 + for i in range(0, replicates): + totalDivisions = totalDivisions + (i + 1) + + # Allocate the total number of points for this order of false positives (i.e. 1x, 2x, etc.) + totalPoints = (weights['False_Positives'] / totalDivisions) * n + + # Select only primer sets that have at least n false positives for consideration in ranking + subjectPrimerSets = df_results[df_results['False_Positives'] >= n]['PrimerSet'] + + if(name not in subjectPrimerSets.values): + if (retValue == 'Score'): + return totalPoints + elif (retValue == 'RxnTime'): + return np.nan + else: + subjectRxnPenalty = df[(df['RxnType']=='-') & (df['ObservedType']==1) & (df['Primer'].isin(subjectPrimerSets))].groupby('Primer')[['RxnPenalty', 'RxnTime']].apply(lambda x: x.sort_values(by='RxnPenalty', ascending=False).iloc[n-1]) + maxSubjectRxnPenalty = subjectRxnPenalty['RxnPenalty'].max() + + if (retValue == 'Score'): + return (1 - (subjectRxnPenalty['RxnPenalty'][name]/maxSubjectRxnPenalty)) * totalPoints + elif (retValue == 'RxnTime'): + return subjectRxnPenalty['RxnTime'][name] + +def calc_rxn_penalty(row): + rxnTimePenalty = 60 - row['RxnTime'] + rxnIntensity = row.drop(['Primer', 'RxnType','ObservedType','RxnTime']).max() + return rxnIntensity*rxnTimePenalty + +# Function to contstruct and return the results table for a set of reactions for a given file. +# Arguments: +# fileName: String, relative path to the file of interest containing time series data for primer sets. +def getPrimerSummary(fileName): + [df, primerNames] = format_df(fileName) + results = pd.DataFrame(data=primerNames, columns=['PrimerSet']) + results['TruePos'] = results.apply(lambda row: calc_true_pos(row['PrimerSet'], df), axis=1) + results['Intensity_Avg'] = results.apply(lambda row: 0 if(row['TruePos'] < replicates) else calc_max_avg(row['PrimerSet'], df), axis=1) + results['Intensity_StdDev'] = results.apply(lambda row: 0 if(row['TruePos'] < replicates) else calc_max_std(row['PrimerSet'], df), axis=1) + results['RxnTime_Avg'] = results.apply(lambda row: 0 if(row['TruePos'] < replicates) else calc_rxn_time_avg(row['PrimerSet'], df), axis=1) + results['RxnTime_Std'] = results.apply(lambda row: 0 if(row['TruePos'] < replicates) else calc_rxn_time_std(row['PrimerSet'], df), axis=1) + results['False_Positives'] = results.apply(lambda row: 0 if(row['TruePos'] < replicates) else calc_false_pos(row['PrimerSet'], df), axis=1) + + for i in range(0, replicates): + results['FP_{}'.format(i+1)] = results.apply(lambda row: 0 if(row['TruePos'] < replicates) else calc_FP_cardinal(row['PrimerSet'], df, results, (i+1)), axis=1) + + results['Overall_Score'] = results.apply(lambda row: 0 if(row['TruePos'] < replicates) else calc_overall_score(row, results[results['TruePos']==replicates]), axis=1) + for i in range(0, replicates): + results['FP_{}_time'.format(i+1)] = results.apply(lambda row: 0 if(row['TruePos'] < replicates) else calc_FP_cardinal(row['PrimerSet'], df, results, (i+1), retValue='RxnTime'), axis=1) + return results + +# Function to return primer names and DataFrame in a dictionary +# Arguments: +# fileName: String, relative path to the file of interest containing time series data for primer sets. +def get_primer_data(fileName): + [df, primerNames] = format_df(fileName) + return {"DataFrame": df, "primerNames": primerNames} + +# Function to format time series data into DataFrame +# Arguments: +# fileName: String, relative path to the file of interest containing time series data for primer sets. +def format_df(filename): + df = pd.read_excel(filename, header=None) + primerNames = df.T[0].unique() + row_names = ['Primer', 'RxnType'] + for i in range(1, 61): + row_names.append(str(i)) + df.index = row_names + df = df.T + df['ObservedType'] = df.apply(lambda row: determine_pos(row.drop(['Primer', 'RxnType'])), axis=1) + df['RxnTime'] = df.apply(lambda row: calc_rxn_time(row.drop(['Primer', 'RxnType','ObservedType'])), axis=1) + df['RxnPenalty'] = df.apply(lambda row: calc_rxn_penalty(row), axis=1) + + return df, primerNames + +# Function to score LOD data and return average and standard deviation at each concentration +# Arguments: +# fileName: String, relative or absolute path to the file of interest containing time series data for primer sets. +# TODO: Update variable names to be more descriptive +def score_LOD(fileName, outputFile): + # Read in excel file and read sheet name + file = pd.ExcelFile(fileName) + sheets = file.sheet_names + + # Concatenate sheets together in DataFrame by assigning different sheets a unique name corresponding to the sheet name. + df = pd.concat([pd.read_excel(fileName, header=None, sheet_name=sheet).T.assign(sheet_name=sheet) for sheet in sheets]) + + # Rearrange columns and assign column headers to DataFrame + cols = df.columns.tolist() + cols = cols[-1:] + cols[:-1] + df = df[cols] + col_header = ['Primer Set', 'Conc', 'Units', 'Template'] + col_header.extend([str(x) for x in range(1, 61)]) + df.columns = col_header + + # Determine whether reactions are positive or negative and calculate reaction time + df['ObservedType'] = df.apply(lambda row: determine_pos(row.drop(['Primer Set', 'Conc', 'Units', 'Template'])), axis=1) + df['RxnTime'] = df.apply(lambda row: calc_rxn_time(row.drop(['Primer Set', 'Conc', 'Units', 'Template'])), axis=1) + + # Create list of each unique concentration and primer set + totalConcs = df['Conc'].unique() + totalPrimerSets = df['Primer Set'].unique() + + # Ensure concentration list is in descending order for assignment of LOD + totalConcs[totalConcs == "NTC"] = -1 + totalConcs = totalConcs[totalConcs[:].astype(float).argsort()[::-1]] + totalConcs[-1] = "NTC" + + # Insert columns corresponding to LOD and Pathogen + cols = np.insert(totalConcs, 0, "LOD", axis=0) + cols = np.insert(cols, 0, "Pathogen", axis=0) + + # Create new dataframe for with all NaN for all concentrations and primer sets + results_df = pd.DataFrame(np.nan, index=totalPrimerSets, columns=cols, dtype=str) + + # Loop trhough unique primer sets + for primerSet in totalPrimerSets: + # Split pathogen from primer set name + results_df.loc[primerSet, "Pathogen"] = primerSet.split(".")[0] + + #Loop through unique concentrations and initialize flag that we have not yet found LOD + primerSet_df = df[df['Primer Set'] == primerSet] + lodFound = False + + # Loop through unique concentrations + for conc in totalConcs: + # Get number of replicates for current concentration based on shape of df + # NOTE: if number of replicates is not consistent across the experiment, this could change the ability to compare across concentrations + numRep = primerSet_df[primerSet_df['Conc'] == conc].shape[0] + + # Check whether sum of Observed type is greater than num reps for conc and if so, add average reaction rate to new df + numPos = primerSet_df[primerSet_df['Conc'] == conc]['ObservedType'].sum() + + # Check if the concentration is a No Template Control (NTC) and assign number of positives. + # NOTE: STRICT RULE - If false positives are present, the LOD is indeterminant. + if conc == 'NTC': + results_df.loc[primerSet, conc] = f"{numPos} of {numRep}" + if numPos > 0: + results_df.loc[primerSet, 'LOD'] = np.nan + else: + # If number of positives is greater than number of replicates, add average reaction time to report dataframe along with standard deviation + # NOTE: Remove before public release. + # Not quite sure why I have greater than here as opposed to equal, but it seems to work... + if numPos == numRep: + results_df.loc[primerSet, conc] = "{:0.2f}".format(primerSet_df[(primerSet_df['Conc'] == conc) & (primerSet_df['ObservedType'] == 1)]['RxnTime'].mean()) + results_df.loc[primerSet, f"{conc}_STD"] = primerSet_df[(primerSet_df['Conc'] == conc) & (primerSet_df['ObservedType'] == 1)]['RxnTime'].std() + else: + # If number of positives is less than number of replicates, we have found our LOD. Assign the LOD as the last concentration up and + # flag to true + if not lodFound: + results_df.loc[primerSet, "LOD"] = totalConcs[[i for i, x in enumerate(totalConcs) if x == conc][0] - 1] + lodFound = True + + # Add number of positives out of total replicates to report dataframe + results_df.loc[primerSet, conc] = f"{numPos} of {numRep}" + + results_df.to_csv(outputFile, encoding='utf-8') + # Return report dataframe + return results_df.sort_values(by=['Pathogen', 'LOD']) + +def formatSensSpecData(fileName): + # Open and read excel sheet names (which are named after the primer sets) before reading in data + dataFile = pd.ExcelFile(fileName) + sheetNames = dataFile.sheet_names + + # Read in data, Transpose, and assign column names based on primer set information stored in the sheet name. + # Assign read and formatted data to a new DataFrame after concatenating all primer sets + df = pd.concat([pd.read_excel(fileName, header=None, sheet_name=sheet).T.assign(sheet_name=sheet) for sheet in sheetNames]) + + # Rearrange columns such that primer set name and concentraiton are first followed by data + # and assign column headers to DataFrame + cols = df.columns.tolist() + cols = cols[-1:] + cols[:-1] + df = df[cols] + + # Assign column header names + col_header = ['Primer Set', 'Conc'] + col_header.extend([str(x) for x in range(1, 61)]) + df.columns = col_header + + # Determine if each reaction is positive or negative and calculate reaction time + df['ObservedType'] = df.apply(lambda row: determine_pos(row.drop(['Primer Set', 'Conc'])), axis=1) + df['RxnTime'] = df.apply(lambda row: calc_rxn_time(row.drop(['Primer Set', 'Conc'])), axis=1) + + # Return formatted DataFrame + return df + +def calc_sens_spec(df: pd.DataFrame, concentration: str, primerSet: str) -> pd.DataFrame: + numTimePoints = 60 + # Set No Template Control (NTC) reactions as predicted negative and all other reactions as predicted positive + predPos = df[(df['Primer Set'] == primerSet) & (df['Conc'] == concentration)][['Conc', 'ObservedType', 'RxnTime']] + predNeg = df[(df['Primer Set'] == primerSet) & (df['Conc'] == 'NTC')][['Conc', 'ObservedType', 'RxnTime']] + + # Initialize DataFrame to store sensitivity, specificity, false positive rate, false negative rate, accuracy, and error + SensSpecCounts = pd.DataFrame(np.nan, index=[i for i in range(1, numTimePoints + 1)], columns=['TP', 'TN', 'FP', 'FN', 'FPR', 'FNR', 'Sensitivity', 'Specificity', 'Accuracy', 'Error']) + + # Initialize all reactions to the lenght of time points (or full length of reactions) as this will be the reaction time + # if a given reaction fails to amplify + predPos.loc[predPos['ObservedType']==0, 'RxnTime']= numTimePoints + predNeg.loc[predNeg['ObservedType']==0, 'RxnTime']= numTimePoints + + # Loop through each time point and calculate the sensitivity, specificity, false positive rate, + # false negative rate, accuracy, and error at that time + for cutoff_time in range(1, numTimePoints + 1): + # Count true/false positives/negatives + true_positives = predPos[(predPos['RxnTime'] <= cutoff_time)].shape[0] + true_negatives = predNeg[predNeg['RxnTime'] > cutoff_time].shape[0] + false_positives = predNeg[predNeg['RxnTime'] <= cutoff_time].shape[0] + false_negatives = predPos[(predPos['ObservedType'] == 0) | (predPos['RxnTime'] > cutoff_time)].shape[0] + + + # Calculate sensitivity, specificity, false positive rate, false negative rate, accuracy + sens = true_positives / (true_positives + false_negatives) + spec = true_negatives / (true_negatives + false_positives) + false_positive_rate = false_positives / (false_positives + true_negatives) + false_negative_rate = false_negatives / (false_negatives + true_positives) + accuracy = (true_positives + true_negatives) / (true_positives + true_negatives + false_positives + false_negatives) + classificationError = math.sqrt((1-sens)**2 + (1-spec)**2) + + # Add to dataframe + SensSpecCounts.loc[cutoff_time] = [true_positives, true_negatives, false_positives, false_negatives, false_positive_rate, false_negative_rate, sens, spec, accuracy, classificationError] + + return SensSpecCounts + +def find_optimum_cutoff(df: pd.DataFrame): + # Find the minimum value of the error and return the corresponding time (located by the index). If multiple maximums exist, return the first one. + return df[df['Error'] == df['Error'].min()].index[0] + +def executeSensSpecAnalysis(fileName, outputFile) -> tuple[pd.DataFrame, pd.DataFrame]: + # Open and format Sensitivity and Specificity data + sensSpecData_df = formatSensSpecData(fileName) + + # Determine unique concentrations and primer sets + lodConcs = sensSpecData_df[sensSpecData_df['Conc'] != 'NTC']['Conc'].unique() + primerSets = sensSpecData_df['Primer Set'].unique() + + # Initialize output DataFrame and set dtype of descriptor columns to string to avoid future warnings + optimalResults = pd.DataFrame(np.nan, index=[i for i in range(0, len(lodConcs) * len(primerSets))], columns=['Primer Set', 'Concentration', 'Tt', 'TP', 'TN', 'FP', 'FN', 'FPR', 'FNR', 'Sensitivity', 'Specificity', 'Accuracy', 'Error']) + optimalResults[['Primer Set', 'Concentration', 'Tt']] = optimalResults[['Primer Set', 'Concentration', 'Tt']].astype(str) + + # Initialize output DataFrame for full sensitivity and specificity analysis results + sensSpecAnalysisResults = pd.DataFrame(columns=['Primer Set', 'Concentration', 'Tt', 'TP', 'TN', 'FP', 'FN', 'FPR', 'FNR', 'Sensitivity', 'Specificity', 'Accuracy', 'Error']) + + # Initialize level counter to track row index for insertion into output DataFrame using iloc + levelCounter = 0 + + # Loop through each concentration and primer set + for concentration in lodConcs: + for primerSet in primerSets: + + # Calculate sensitivity and specificity at each time point for the current concentration and primer set (level) + levelDf = calc_sens_spec(sensSpecData_df, concentration, primerSet) + + # Calculate the optimum cutoff for the current level and the corresponding sensitivity and specificity data + run_optimumCutoff = find_optimum_cutoff(levelDf) + optimalSensSpec = levelDf.loc[run_optimumCutoff] + + # Add Primer Set, template concentration, and the optimum cutoff to the optimal sensitivity and specificity data + rowDescriptors = pd.Series(index=['Primer Set', 'Concentration', 'Tt'], data=[primerSet, concentration, run_optimumCutoff]) + optimalSensSpec = pd.concat([rowDescriptors, optimalSensSpec]) + + # Write optimal sensitivity and specificity data to output DataFrame for current level + optimalResults.iloc[levelCounter] = optimalSensSpec + + # Add Primer Set and template concentration to sensitivity and specificity data + levelDf[['Primer Set', 'Concentration']] = [primerSet, concentration] + + # Rearrange columns such that primer set name and concentraiton are first followed by data + # and assign column headers to DataFrame + cols = levelDf.columns.tolist() + cols = cols[-2:] + cols[:-2] + levelDf = levelDf[cols] + + # Write sensitivity and specificity data for current level to output DataFrame + # If sensSpecAnalysisResults is not empty, concatenate current level data to it + if sensSpecAnalysisResults.empty: + sensSpecAnalysisResults = levelDf + else: + sensSpecAnalysisResults = pd.concat([sensSpecAnalysisResults, levelDf]) + + # Increment level counter + levelCounter = levelCounter + 1 + + # Write optimal data to "optimalResults" sheet in output and write full data to "data" sheet in output excel file + with pd.ExcelWriter(outputFile) as writer: + optimalResults.to_excel(writer, sheet_name='optimalResults') + sensSpecAnalysisResults.to_excel(writer, sheet_name='data') + + # Return optimal sensitivity and sensitivity data and full sensitivity and specificity data + return (optimalResults, sensSpecAnalysisResults) + + \ No newline at end of file diff --git a/PrimerAnalysis/README.md b/PrimerAnalysis/README.md new file mode 100644 index 0000000..675240a --- /dev/null +++ b/PrimerAnalysis/README.md @@ -0,0 +1,146 @@ +# Primer Analysis +This directory contains scripts and jupyter notebooks demonstrating the use of such scripts for the analysis of designed primer sets, including primer scoring. + +*This documentation is presently UNDER DEVELOPMENT and does not yet reflect intended usage. Please see the jupyter notebook for current intended usage while documentation is being updated.* + +# Setup +## Dependencies + - Pandas + - Numpy +## Installation +Copy the PrimerScore.py file to either a valid location in the search path or to the current director. + +# Usage + +## Data formatting +The input data file must be in .xls format **NOT .XLSX**. Additionally, the file **MUST** be formmatted in the following manner, with each column representing the data for a single reaction for a specific primer set: + - First row should contain primer set IDs in the form of *{Target}*.*{SetID}*. For example, orf1ab.2. + - Second row should contain reaction type annotation. + - For negative reaction, put **'-'** in the cell. + - For positive reactions, put **'+'** in the cell. + - Rows three and onward should contain data. + + **NOTE:** + 1. The data should be rectangular; this means that all data is of the same length. This has not been tested for data of different lengths. + 2. There should be an equal amount of positive and negatives for a speific primer set. + 3. For proper scoring, each primer set should have the same number of replicates + + ## Execution + ### Importing + If the PrimerScore.py file is located in a valid path or the current directory, simply execute the following line to import the module. + ``` + import PrimerScore + ``` + + ### Initialization + To use the primer scoring method, the initialization method must first be called to set weights and tolerances. + + To initialize with default weights, simply execute the following line of code: + ``` + PrimerScore.intialize() + ``` + This will initialize weights to the following value: + + | Metric | Weight | + |:---:|:---:| + | Average Maximum Intensity | 5 | + | Max. Intensity Std. Dev. | 5 | + | Reaction Time Std. Dev. | 10| + | Average Reaction Time | 20| + | Number of False Positives | 60| + + Additionally, the thresholds will be set at: + | Threshold | Value | + |:---:|:---:| + | Exponential Phase | 3000 | + | Plateau Phase | 200 | + | Positive Reaction Threshold | 0.9 | + | False Positive Threshold | 0.2 | + +Finally, the number of replicates will be set at 4: + | Parameter | Value | + |:---:|:---:| + | Number of Replicates | 4 | + | Instrument Saturation/Maximum Intensity | 140000 | + | Positive Threshold Percentage | 0.1 | + +The thresholds above are presently non-functional, but are retained for potential future use. Reaction time is determined as the maximum of the second derivative of the intensity over time. + + + To use custom weightings, execute the following line of code with the given arguments. + + ``` + PrimerScoring.initialize(set_weights, set_thresholds, set_replicates, set_instrumentMax, set_threshold_perc) + ``` +The arguments in the above expression are defined as: +- set_weights: An array containing weights for the following metrics in the following order: + - Avg. Max. Intensity + - Max. Intensity Std. Dev. + - Reaction time Std. Dev. + - Avg. Reaction Time + - Number of False Positives + - **THE ARRAY MUST CONTAIN WEIGHTS FOR ALL OF THE ABOVE METRICS.** +- set_thresholds: An array contianing weights for the threshold tolerances of the exponential and plateau phases, positive reaction threshold, and false positive threshold, respectively. Whereas this value can be set, it is currently not in use. +- set_replicates: An integer value greater than 3 for the number of replicates. **Must be the same for all primer sets scored.** + +An example to initialize to default settings as above would be as follows: +``` +PrimerScoring.intialize([5,5,10,20,60], [3000, 200, 0.9, 0.2], 4, 140000, 0.1) +``` + +### Scoring +To calculate the scores for each primer, execute the following line of code with the given arguments: + +``` +PrimerScore.scorePrimers(primerData, output) +``` +The arguments in the above line of code are defined as follow: + - primerData: Path (relative or absolute) or file name of excel (.xls) file containing primer data formated properly as outlined above. + - output: Output excel file (.xlsx) name or path containing primer scores and metrics. Please include .xslx extension. + + An example to take an input file "WaterScore.xls" and write values to "PrimerScores_Water.xlsx" is as follows: + ``` + PrimerScore.scorePrimer('WaterScore.xls', 'PrimerScores_Water.xlsx') + ``` + + ### Output + After scoring primers as outlined above, the output file will have the following column headers: + - Primer Set: Column contains Primer Set ID (copied from input) + - TruePos: Column contains the number of true positives (completed reaction) + - Intensity_Avg: Calculated average maximum intensity. + - Intensity_StdDev: Calculated maximum intensity standard deviation. + - RxnTime_Avg: Calculated average reaction time. + - RxnTime_StdDev: Calculated reaction time standard deviation. + - False_Positives: Number of total false positives. + - FP_...: There will be a false positive column for each replicate containing the contribution of that false positive to the overall score. + - Overall Score: Calculated overall score for each primer set. + +# Methodology + +## Positive amplification detection +LAMP amplification reactions typically produce a sigmoidal amplification; however, given fluorometric methods typically have some background auto-flourescence or variable response over time, it is not sufficient to simply check for an increase in signal over time. To this end, the following methodology was used to determine a "positive amplification", regardless of designation (true positive or No Template Control (NTC)): + +1. The series containing the fluorometric reads over time was duplicated and reversed. +2. The intersection of the series and the reversed series was determined by the time point at which the forward time-series first exceeded the reverse time-series. +3. Two vectors were created, one for the forward time series and one for the reverse, using the following definition: + - $\overrightarrow{\text{Forward/Reverse Data Vector}} = <\text{Time of Intersection }, y_{Intersection} - y_0>$ +4. The cosine between to two vectors was calculated + - $\theta = \arccos(\frac{\overrightarrow{\text{Forward}}\cdot\overrightarrow{\text{Reverse}}}{\|\overrightarrow{\text{Forward}}\| \| \overrightarrow{\text{Reverse}}\|})$ +5. Using the understanding that $\cos(x) \approx 1$ if $x \approx 0 $, we check that the $\cos{\theta} > 0.95$ assuming a 95% error in the approximatation. Essentially, these steps are checking to see if our data is "flat" or relatively constant within error. + - If it is, we will return that this reaction is not a positive amplification + - If it is not, continue to step 6. +6. Check if the maximum of the time series is above some threshold percentage of the maximum fluorescent intensity of the instrument, and if it does return a positive amplification. + - Default parameters for maximum fluorescent intensity taken on an Analytik-Jena qTower 3G is approximately 140000 Relative Fluorescence Units. + - Default threshold percentage is 10%. + +## Reaction time +Reaction time is determined as the maximum of the 2nd derivative of the fluorescent time series data. This is implemented using [`numpy.gradient`](https://numpy.org/devdocs/reference/generated/numpy.gradient.html). + +## Weighting of False Positives +False positives are undesireable in the context of the developed diagnostics and hence are weighted very strongly to filter out primer sets that produce false positives. Additionally, it is possible to have a one-off or rare occurrence false positive due to operator error or contamination, rather than an inherent interaction of the primers in the primer set, which should be strongly discouraged. + +To this end, a "progressive" penalty for increasing occurrence of false positives was implemented to select for primer sets with less "persistent" false positives. + +# LICENSE + +

© 2024. Purdue Research Foundation. Primer Analysis Documentation by Josiah Davidson and Purdue Research Foundation is licensed under CC BY-NC 4.0

\ No newline at end of file diff --git a/README.md b/README.md index 8fa9131..385a8a0 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,5 @@ This public repository contains a variety of modules, scripts, jupyter notebooks, etc. used in the analysis of a variety of molecular reactions conducted by the Verma Lab. This repository also contains code used in a variety of publications. Where appropriate, releases will be made to indicate the "state" of the repository at the time of publication. + +

© 2024. Purdue Research Foundation. Reaction Analysis Library Documentation by Josiah Davidson and Purdue Research Foundation is licensed under CC BY-NC 4.0

\ No newline at end of file