diff --git a/caimira/apps/calculator/static/js/report.js b/caimira/apps/calculator/static/js/report.js index 6cfd96a1..956c0dd6 100644 --- a/caimira/apps/calculator/static/js/report.js +++ b/caimira/apps/calculator/static/js/report.js @@ -59,7 +59,7 @@ function draw_plot(svg_id) { .attr('class', 'y label') .attr('fill', 'black') .attr('text-anchor', 'middle') - .text('Mean concentration (virions/m³)'); + .text('Mean concentration (IRP/m³)'); // Y cumulative concentration axis declaration. var yAxisCumEl = vis.append('svg:g') @@ -71,7 +71,7 @@ function draw_plot(svg_id) { .attr('class', 'y label') .attr('fill', 'black') .attr('text-anchor', 'middle') - .text('Mean cumulative dose (infectious virus)'); + .text('Mean cumulative dose (IRP)'); // Legend for the plot elements - line and area. @@ -82,8 +82,7 @@ function draw_plot(svg_id) { .style('fill', '#1f77b4'); // Concentration line text var legendLineText = vis.append('text') - .text('Mean concentration') - .style('font-size', '15px'); + .text('Mean concentration (Infectious Respiratory Particles)') // Cumulative dose line icon var legendCumulativeIcon = vis.append('line') @@ -92,8 +91,7 @@ function draw_plot(svg_id) { .style("stroke", '#1f77b4'); // Cumulative dose line text var legendCumutiveText = vis.append('text') - .text('Cumulative dose') - .style('font-size', '15px'); + .text('Cumulative dose (Infectious Respiratory Particles)') // Area line icon var legendAreaIcon = vis.append('rect') @@ -104,7 +102,6 @@ function draw_plot(svg_id) { // Area line text var legendAreaText = vis.append('text') .text('Presence of exposed person(s)') - .style('font-size', '15px'); sr_unique_activities = [...new Set(short_range_expirations)] if (show_sr_legend) { @@ -142,7 +139,7 @@ function draw_plot(svg_id) { if (show_sr_legend) legendBBox_height = 68 + 20 * sr_unique_activities.length; else legendBBox_height = 68; var legendBBox = vis.append('rect') - .attr('width', 255) + .attr('width', 420) .attr('height', legendBBox_height) .attr('stroke', 'lightgrey') .attr('stroke-width', '2') @@ -310,9 +307,9 @@ function draw_plot(svg_id) { graph_width = div_width; graph_height = div_height var margins = { top: 30, right: 20, bottom: 50, left: 60 }; - if (div_width >= 900) { // For screens with width > 900px legend can be on the graph's right side. - div_width = 900; - graph_width = div_width * (2/3); + if (div_width >= 1100) { // For screens with width > 1100px legend can be on the graph's right side. + div_width = 1100; + graph_width = 600; const svg_margins = {'margin-left': '0rem'}; Object.entries(svg_margins).forEach(([prop,val]) => vis.style(prop,val)); } @@ -361,7 +358,7 @@ function draw_plot(svg_id) { yAxisCumLabelEl.attr('transform', 'rotate(-90, 0,' + graph_height + ')') .attr('x', (graph_height + margins.bottom) / 2.1); - if (plot_div.clientWidth >= 900) { + if (plot_div.clientWidth >= 1100) { yAxisCumLabelEl.attr('y', graph_width * 1.7); } else { @@ -373,7 +370,7 @@ function draw_plot(svg_id) { const space_between_text_icon = 30; const text_height = 6; // Legend on right side. - if (plot_div.clientWidth >= 900) { + if (plot_div.clientWidth >= 1100) { legendLineIcon.attr('x', graph_width + legend_x_start) .attr('y', margins.top + size); legendLineText.attr('x', graph_width + legend_x_start + space_between_text_icon) @@ -746,9 +743,9 @@ function draw_generic_concentration_plot( graph_width = div_width; graph_height = div_height; var margins = { top: 30, right: 20, bottom: 50, left: 60 }; - if (window_width >= 900) { // For screens with width > 900px legend can be on the graph's right side. - div_width = 900; - graph_width = div_width * (2/3); + if (window_width >= 1100) { // For screens with width > 1100px legend can be on the graph's right side. + div_width = 1100; + graph_width = 600; const svg_margins = {'margin-left': '0rem'}; Object.entries(svg_margins).forEach(([prop,val]) => vis.style(prop,val)); } @@ -799,7 +796,7 @@ function draw_generic_concentration_plot( var scenario_index = Object.keys(data_for_scenarios).indexOf(scenario_name) // Legend on right side. var size = 20 * (scenario_index + 1); - if (window_width >= 900) { + if (window_width >= 1100) { label_icons[scenario_name].attr('x', graph_width + legend_x_start) .attr('y', margins.top + size); label_text[scenario_name].attr('x', graph_width + legend_x_start + space_between_text_icon) @@ -817,7 +814,7 @@ function draw_generic_concentration_plot( if (h_lines) { h_lines.map((line, index) => { size = 21 * (scenario_index + index + 2); // account for previous legend elements - if (window_width >= 900) { + if (window_width >= 1100) { h_line_label_icon[line.label].attr("x1", graph_width + legend_x_start) .attr("x2", graph_width + legend_x_start + 20) .attr("y1", margins.top + size) @@ -839,7 +836,7 @@ function draw_generic_concentration_plot( } // Legend on right side. - if (window_width >= 900) { + if (window_width >= 1100) { legendBBox.attr('x', graph_width * 1.02) .attr('y', margins.top * 1.15); @@ -899,10 +896,10 @@ function draw_histogram(svg_id, prob, prob_sd) { var vis = d3.select(plot_div).append('svg'); // set the dimensions and margins of the graph - if (div_width > 900) { - div_width = 900; + if (div_width > 1100) { + div_width = 1100; var margins = { top: 30, right: 20, bottom: 50, left: 60 }; - var graph_width = div_width * (2/3); + var graph_width = 600; const svg_margins = {'margin-left': '0rem'}; Object.entries(svg_margins).forEach(([prop,val]) => vis.style(prop,val)); } diff --git a/caimira/apps/expert.py b/caimira/apps/expert.py index 5162d8f0..8a14e76a 100644 --- a/caimira/apps/expert.py +++ b/caimira/apps/expert.py @@ -131,13 +131,13 @@ class ExposureModelResult(View): ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) ax.set_xlabel('Time (hours)') - ax.set_ylabel('Mean concentration ($virions/m^{3}$)') - ax.set_title('Concentration of virions \nand Cumulative dose') + ax.set_ylabel('Mean concentration ($IRP/m^{3}$)') + ax.set_title('Concentration and Cumulative\ndose of Infectious Respiratory Particles') ax2 = ax.twinx() ax2.spines['left'].set_visible(False) ax2.spines['top'].set_visible(False) - ax2.set_ylabel('Mean cumulative dose (infectious virus)') + ax2.set_ylabel('Mean cumulative dose (IRP)') ax2.spines['right'].set_linestyle((0,(1,4))) return ax, ax2 @@ -193,8 +193,8 @@ class ExposureModelResult(View): self.ax.set_xlim(left = min(min(infected_presence.boundaries()[0]), min(exposed_presence.boundaries()[0])), right = max(max(infected_presence.boundaries()[1]), max(exposed_presence.boundaries()[1]))) - figure_legends = [mlines.Line2D([], [], color='#3530fe', markersize=15, label='Mean concentration'), - mlines.Line2D([], [], color='#0000c8', markersize=15, ls="dotted", label='Cumulative dose'), + figure_legends = [mlines.Line2D([], [], color='#3530fe', markersize=15, label='Mean concentration (Infectious Respiratory Particles)'), + mlines.Line2D([], [], color='#0000c8', markersize=15, ls="dotted", label='Cumulative dose (Infectious Respiratory Particles)'), patches.Patch(edgecolor="#96cbff", facecolor='#96cbff', label='Presence of exposed person(s)')] self.ax.legend(handles=figure_legends) @@ -236,15 +236,15 @@ class ExposureComparisonResult(View): ax.spines['top'].set_visible(False) ax.set_xlabel('Time (hours)') - ax.set_ylabel('Mean concentration ($virions/m^{3}$)') - ax.set_title('Concentration of virions \nand Cumulative dose') + ax.set_ylabel('Mean concentration ($IRP/m^{3}$)') + ax.set_title('Concentration and Cumulative\ndose of Infectious Respiratory Particles') ax2 = ax.twinx() ax2.spines['left'].set_visible(False) ax2.spines['top'].set_visible(False) ax2.spines['right'].set_linestyle((0,(1,4))) - ax2.set_ylabel('Mean cumulative dose (infectious virus)') + ax2.set_ylabel('Mean cumulative dose (IRP)') return ax, ax2 diff --git a/caimira/apps/templates/base/calculator.report.html.j2 b/caimira/apps/templates/base/calculator.report.html.j2 index 58bf8f68..94343afe 100644 --- a/caimira/apps/templates/base/calculator.report.html.j2 +++ b/caimira/apps/templates/base/calculator.report.html.j2 @@ -277,7 +277,7 @@ var alternative_scenarios = {{ alternative_scenarios.stats | JSONify }} draw_generic_concentration_plot( "alternative_scenario_plot", - "Mean concentration (virions/m³)", + "Mean concentration (IRP/m³)", );
diff --git a/caimira/tests/test_full_algorithm.py b/caimira/tests/test_full_algorithm.py index a26f3555..ff5f3843 100644 --- a/caimira/tests/test_full_algorithm.py +++ b/caimira/tests/test_full_algorithm.py @@ -56,8 +56,8 @@ class SimpleConcentrationModel: #: Number of infected people num_infected: int = 1 - #: Fraction of infected viruses - finf: _VectorisedFloat = 0.5 + #: Fraction of infected viruses (viable to RNA ratio) + viable_to_RNA: _VectorisedFloat = 0.5 #: Host immunity factor (0. for not immune) HI: _VectorisedFloat = 0. @@ -182,7 +182,8 @@ class SimpleConcentrationModel: return ( ( (0 if not self.infected_presence.triggered(t) else self.f(lambda_rate,0)) + result * np.exp(-lambda_rate*(t-ti)) ) - * self.num_infected * self.finf * (1. - self.HI) / self.room_volume) + * self.num_infected * self.viable_to_RNA + * (1. - self.HI) / self.room_volume) @dataclass(frozen=True) @@ -410,7 +411,8 @@ class SimpleExposureModel(SimpleConcentrationModel): else self.f_with_fdep(lambda_rate,0,evaporation)*(t2-t1)) + (primitive(t2) * np.exp(-lambda_rate*(t2-ti)) - primitive(t1) * np.exp(-lambda_rate*(t1-ti)) ) ) - * self.num_infected * self.finf * (1. - self.HI) / self.room_volume) + * self.num_infected * self.viable_to_RNA + * (1. - self.HI) / self.room_volume) @method_cache def integrated_shortrange_concentration(self) -> _VectorisedFloat: @@ -528,7 +530,7 @@ def simple_c_model() -> SimpleConcentrationModel: room_volume = 50., lambda_ventilation= 1., BLO_factors = expiration_BLO_factors['Breathing'], - finf = models.Virus.types['SARS_CoV_2_DELTA'].viable_to_RNA_ratio, + viable_to_RNA = models.Virus.types['SARS_CoV_2_DELTA'].viable_to_RNA_ratio, HI = 0., ) @@ -576,7 +578,7 @@ def simple_expo_sr_model(simple_sr_models) -> SimpleExposureModel: room_volume = 50., lambda_ventilation= 1., BLO_factors = expiration_BLO_factors['Breathing'], - finf = models.Virus.types['SARS_CoV_2_DELTA'].viable_to_RNA_ratio, + viable_to_RNA = models.Virus.types['SARS_CoV_2_DELTA'].viable_to_RNA_ratio, HI = 0., ID50 = models.Virus.types['SARS_CoV_2_DELTA'].infectious_dose, transmissibility = models.Virus.types['SARS_CoV_2_DELTA'].transmissibility_factor, @@ -624,7 +626,7 @@ def simple_expo_sr_model_distr() -> SimpleExposureModel: room_volume = 50., lambda_ventilation= 1., BLO_factors = expiration_BLO_factors['Breathing'], - finf = virus_distributions['SARS_CoV_2_DELTA' + viable_to_RNA = virus_distributions['SARS_CoV_2_DELTA' ].build_model(SAMPLE_SIZE).viable_to_RNA_ratio, HI = 0., ID50 = virus_distributions['SARS_CoV_2_DELTA' @@ -685,7 +687,7 @@ def test_longrange_exposure(c_model): room_volume = 50., lambda_ventilation= 1., BLO_factors = expiration_BLO_factors['Breathing'], - finf = models.Virus.types['SARS_CoV_2_DELTA'].viable_to_RNA_ratio, + viable_to_RNA = models.Virus.types['SARS_CoV_2_DELTA'].viable_to_RNA_ratio, HI = 0., ID50 = models.Virus.types['SARS_CoV_2_DELTA'].infectious_dose, transmissibility = models.Virus.types['SARS_CoV_2_DELTA'].transmissibility_factor, @@ -726,7 +728,7 @@ def test_longrange_concentration_with_distributions(c_model_distr,time): room_volume = 50., lambda_ventilation= 1., BLO_factors = expiration_BLO_factors['Breathing'], - finf = virus_distributions['SARS_CoV_2_DELTA' + viable_to_RNA = virus_distributions['SARS_CoV_2_DELTA' ].build_model(SAMPLE_SIZE).viable_to_RNA_ratio, HI = 0., ) @@ -746,7 +748,7 @@ def test_longrange_exposure_with_distributions(c_model_distr): room_volume = 50., lambda_ventilation= 1., BLO_factors = expiration_BLO_factors['Breathing'], - finf = virus_distributions['SARS_CoV_2_DELTA' + viable_to_RNA = virus_distributions['SARS_CoV_2_DELTA' ].build_model(SAMPLE_SIZE).viable_to_RNA_ratio, HI = 0., ID50 = virus_distributions['SARS_CoV_2_DELTA'