Merge branch 'feature/f_inf_in_emission_rate' into 'master'
Including viable-to-RNA ratio (f_inf) at the level of the emission rate See merge request caimira/caimira!473
This commit is contained in:
commit
18456f4efa
8 changed files with 87 additions and 85 deletions
|
|
@ -37,7 +37,7 @@ from .user import AuthenticatedUser, AnonymousUser
|
|||
# calculator version. If the calculator needs to make breaking changes (e.g. change
|
||||
# form attributes) then it can also increase its MAJOR version without needing to
|
||||
# increase the overall CAiMIRA version (found at ``caimira.__version__``).
|
||||
__version__ = "4.14.0"
|
||||
__version__ = "4.14.1"
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
@ -83,7 +83,6 @@ function draw_plot(svg_id) {
|
|||
// Concentration line text
|
||||
var legendLineText = vis.append('text')
|
||||
.text('Mean concentration')
|
||||
.style('font-size', '15px');
|
||||
|
||||
// Cumulative dose line icon
|
||||
var legendCumulativeIcon = vis.append('line')
|
||||
|
|
@ -93,7 +92,6 @@ function draw_plot(svg_id) {
|
|||
// Cumulative dose line text
|
||||
var legendCumutiveText = vis.append('text')
|
||||
.text('Cumulative dose')
|
||||
.style('font-size', '15px');
|
||||
|
||||
// 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) {
|
||||
|
|
@ -116,7 +113,6 @@ function draw_plot(svg_id) {
|
|||
.attr('opacity', 0);
|
||||
var legendLongCumutiveText = vis.append('text')
|
||||
.text('Long-range cumulative dose')
|
||||
.style('font-size', '15px')
|
||||
.attr('opacity', 0);
|
||||
// Short-range area icon
|
||||
var legendShortRangeAreaIcon = {};
|
||||
|
|
@ -133,8 +129,7 @@ function draw_plot(svg_id) {
|
|||
var legendShortRangeText = {};
|
||||
sr_unique_activities.forEach((b, index) => {
|
||||
legendShortRangeText[index] = vis.append('text')
|
||||
.text('Short-range - ' + sr_unique_activities[index])
|
||||
.style('font-size', '15px');
|
||||
.text('Short-range - ' + sr_unique_activities[index]);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +137,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', 270)
|
||||
.attr('height', legendBBox_height)
|
||||
.attr('stroke', 'lightgrey')
|
||||
.attr('stroke-width', '2')
|
||||
|
|
@ -310,9 +305,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 >= 1000) { // For screens with width > 1000px legend can be on the graph's right side.
|
||||
div_width = 1000;
|
||||
graph_width = 600;
|
||||
const svg_margins = {'margin-left': '0rem'};
|
||||
Object.entries(svg_margins).forEach(([prop,val]) => vis.style(prop,val));
|
||||
}
|
||||
|
|
@ -361,7 +356,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 >= 1000) {
|
||||
yAxisCumLabelEl.attr('y', graph_width * 1.7);
|
||||
}
|
||||
else {
|
||||
|
|
@ -373,7 +368,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 >= 1000) {
|
||||
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)
|
||||
|
|
@ -610,7 +605,7 @@ function draw_generic_concentration_plot(
|
|||
|
||||
max_key_length = Math.max(Math.max(...(Object.keys(data_for_scenarios).map(el => el.length))), h_line_max_key);
|
||||
var legendBBox = vis.append('rect')
|
||||
.attr('width', 9 * max_key_length )
|
||||
.attr('width', 10 * max_key_length )
|
||||
.attr('height', 25 * ((Object.keys(data_for_scenarios).length) + h_lines_lenght))
|
||||
.attr('stroke', 'lightgrey')
|
||||
.attr('stroke-width', '2')
|
||||
|
|
@ -646,8 +641,7 @@ function draw_generic_concentration_plot(
|
|||
.style('fill', colors[scenario_index]);
|
||||
|
||||
label_text[scenario_name] = vis.append('text')
|
||||
.text(scenario_name)
|
||||
.style('font-size', '15px');
|
||||
.text(scenario_name);
|
||||
}
|
||||
if (h_lines) {
|
||||
var h_lines_draw = {}, h_line_label_icon = {}, h_line_label_text = {};
|
||||
|
|
@ -664,8 +658,7 @@ function draw_generic_concentration_plot(
|
|||
.attr('stroke-width', '2')
|
||||
.style("stroke", line.color);
|
||||
h_line_label_text[line.label] = vis.append('text')
|
||||
.text(line.label)
|
||||
.style('font-size', '15px');
|
||||
.text(line.label);
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -746,9 +739,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 >= 1000) { // For screens with width > 1000px legend can be on the graph's right side.
|
||||
div_width = 1000;
|
||||
graph_width = 600;
|
||||
const svg_margins = {'margin-left': '0rem'};
|
||||
Object.entries(svg_margins).forEach(([prop,val]) => vis.style(prop,val));
|
||||
}
|
||||
|
|
@ -799,7 +792,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 >= 1000) {
|
||||
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 +810,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 >= 1000) {
|
||||
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 +832,7 @@ function draw_generic_concentration_plot(
|
|||
}
|
||||
|
||||
// Legend on right side.
|
||||
if (window_width >= 900) {
|
||||
if (window_width >= 1000) {
|
||||
legendBBox.attr('x', graph_width * 1.02)
|
||||
.attr('y', margins.top * 1.15);
|
||||
|
||||
|
|
@ -899,10 +892,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 > 1000) {
|
||||
div_width = 1000;
|
||||
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));
|
||||
}
|
||||
|
|
@ -1035,7 +1028,6 @@ function draw_histogram(svg_id, prob, prob_sd) {
|
|||
// CDF line text
|
||||
vis.append('text')
|
||||
.text('CDF')
|
||||
.style('font-size', '15px')
|
||||
.attr('x', graph_width + legend_x_start + space_between_text_icon)
|
||||
.attr('y', margins.top + size + text_height);
|
||||
// Hist icon
|
||||
|
|
@ -1048,7 +1040,6 @@ function draw_histogram(svg_id, prob, prob_sd) {
|
|||
// Hist text
|
||||
vis.append('text')
|
||||
.text('Histogram')
|
||||
.style('font-size', '15px')
|
||||
.attr('x', graph_width + legend_x_start + space_between_text_icon)
|
||||
.attr('y', margins.top + 2 * size + text_height*2);
|
||||
// Mean text
|
||||
|
|
@ -1063,7 +1054,6 @@ function draw_histogram(svg_id, prob, prob_sd) {
|
|||
// Mean line text
|
||||
vis.append('text')
|
||||
.text('Mean')
|
||||
.style('font-size', '15px')
|
||||
.attr('x', graph_width + legend_x_start + space_between_text_icon)
|
||||
.attr('y', margins.top + 3 * size + text_height*3);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@
|
|||
let short_range_expirations = {{ short_range_expirations | JSONify }};
|
||||
draw_plot("concentration_plot");
|
||||
</script>
|
||||
<i>IRP - Infectious Respiratory Particles.</i>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -277,7 +278,7 @@
|
|||
var alternative_scenarios = {{ alternative_scenarios.stats | JSONify }}
|
||||
draw_generic_concentration_plot(
|
||||
"alternative_scenario_plot",
|
||||
"Mean concentration (virions/m³)",
|
||||
"Mean concentration (IRP/m³)",
|
||||
);
|
||||
</script>
|
||||
<br>
|
||||
|
|
|
|||
|
|
@ -979,6 +979,7 @@ class InfectedPopulation(_PopulationWithVirus):
|
|||
|
||||
ER = (self.virus.viral_load_in_sputum *
|
||||
self.activity.exhalation_rate *
|
||||
self.fraction_of_infectious_virus() *
|
||||
10 ** 6)
|
||||
return ER
|
||||
|
||||
|
|
@ -1641,7 +1642,6 @@ class ExposureModel:
|
|||
emission_rate_per_aerosol_per_person = \
|
||||
self.concentration_model.infected.emission_rate_per_aerosol_per_person_when_present()
|
||||
aerosols = self.concentration_model.infected.aerosols()
|
||||
f_inf = self.concentration_model.infected.fraction_of_infectious_virus()
|
||||
fdep = self.long_range_fraction_deposited()
|
||||
|
||||
diameter = self.concentration_model.infected.particle.diameter
|
||||
|
|
@ -1667,7 +1667,7 @@ class ExposureModel:
|
|||
(1 - self.exposed.mask.inhale_efficiency()))
|
||||
|
||||
# In the end we multiply the final results by the fraction of infectious virus of the vD equation.
|
||||
return deposited_exposure * f_inf
|
||||
return deposited_exposure
|
||||
|
||||
def deposited_exposure_between_bounds(self, time1: float, time2: float) -> _VectorisedFloat:
|
||||
"""
|
||||
|
|
@ -1716,9 +1716,8 @@ class ExposureModel:
|
|||
|
||||
# Then we multiply by diameter-independent quantities: viral load
|
||||
# and fraction of infected virions
|
||||
f_inf = self.concentration_model.infected.fraction_of_infectious_virus()
|
||||
deposited_exposure *= (f_inf
|
||||
* self.concentration_model.virus.viral_load_in_sputum
|
||||
deposited_exposure *= (
|
||||
self.concentration_model.virus.viral_load_in_sputum
|
||||
* (1 - self.exposed.mask.inhale_efficiency()))
|
||||
# Long-range concentration
|
||||
deposited_exposure += self.long_range_deposited_exposure_between_bounds(time1, time2)
|
||||
|
|
|
|||
|
|
@ -75,19 +75,19 @@ def known_concentrations(func):
|
|||
|
||||
@pytest.mark.parametrize(
|
||||
"population, cm, expected_exposure, expected_probability", [
|
||||
[populations[1], known_concentrations(lambda t: 36.),
|
||||
[populations[1], known_concentrations(lambda t: 18.),
|
||||
np.array([64.02320633, 59.45012016]), np.array([67.9503762594, 65.2366759251])],
|
||||
|
||||
[populations[2], known_concentrations(lambda t: 36.),
|
||||
[populations[2], known_concentrations(lambda t: 18.),
|
||||
np.array([40.91708675, 45.73086166]), np.array([51.6749232285, 55.6374622042])],
|
||||
|
||||
[populations[0], known_concentrations(lambda t: np.array([36., 72.])),
|
||||
[populations[0], known_concentrations(lambda t: np.array([18., 36.])),
|
||||
np.array([45.73086166, 91.46172332]), np.array([55.6374622042, 80.3196524031])],
|
||||
|
||||
[populations[1], known_concentrations(lambda t: np.array([36., 72.])),
|
||||
[populations[1], known_concentrations(lambda t: np.array([18., 36.])),
|
||||
np.array([64.02320633, 118.90024032]), np.array([67.9503762594, 87.9151129926])],
|
||||
|
||||
[populations[2], known_concentrations(lambda t: np.array([36., 72.])),
|
||||
[populations[2], known_concentrations(lambda t: np.array([18., 36.])),
|
||||
np.array([40.91708675, 91.46172332]), np.array([51.6749232285, 80.3196524031])],
|
||||
])
|
||||
def test_exposure_model_ndarray(population, cm,
|
||||
|
|
@ -113,7 +113,7 @@ def test_exposure_model_ndarray(population, cm,
|
|||
])
|
||||
def test_exposure_model_ndarray_and_float_mix(population, expected_deposited_exposure, sr_model, cases_model):
|
||||
cm = known_concentrations(
|
||||
lambda t: 0. if np.floor(t) % 2 else np.array([1.2, 1.2]))
|
||||
lambda t: 0. if np.floor(t) % 2 else np.array([0.6, 0.6]))
|
||||
model = ExposureModel(cm, sr_model, population, cases_model)
|
||||
|
||||
np.testing.assert_almost_equal(
|
||||
|
|
@ -130,7 +130,7 @@ def test_exposure_model_ndarray_and_float_mix(population, expected_deposited_exp
|
|||
[populations[2], np.array([1.36390289, 1.52436206])],
|
||||
])
|
||||
def test_exposure_model_vector(population, expected_deposited_exposure, sr_model, cases_model):
|
||||
cm_array = known_concentrations(lambda t: np.array([1.2, 1.2]))
|
||||
cm_array = known_concentrations(lambda t: np.array([0.6, 0.6]))
|
||||
model_array = ExposureModel(cm_array, sr_model, population, cases_model)
|
||||
np.testing.assert_almost_equal(
|
||||
model_array.deposited_exposure(), np.array(expected_deposited_exposure)
|
||||
|
|
@ -138,7 +138,7 @@ def test_exposure_model_vector(population, expected_deposited_exposure, sr_model
|
|||
|
||||
|
||||
def test_exposure_model_scalar(sr_model, cases_model):
|
||||
cm_scalar = known_concentrations(lambda t: 1.2)
|
||||
cm_scalar = known_concentrations(lambda t: 0.6)
|
||||
model_scalar = ExposureModel(cm_scalar, sr_model, populations[0], cases_model)
|
||||
expected_deposited_exposure = 1.52436206
|
||||
np.testing.assert_almost_equal(
|
||||
|
|
@ -234,7 +234,7 @@ def test_infectious_dose_vectorisation(sr_model, cases_model):
|
|||
expiration=models.Expiration.types['Speaking'],
|
||||
host_immunity=0.,
|
||||
)
|
||||
cm = known_concentrations(lambda t: 1.2)
|
||||
cm = known_concentrations(lambda t: 0.6)
|
||||
cm = replace(cm, infected=infected_population)
|
||||
|
||||
presence_interval = models.SpecificInterval(((0., 1.),))
|
||||
|
|
@ -289,13 +289,13 @@ def test_prob_meet_infected_person(pop, cases, AB, exposed, infected, prob_meet_
|
|||
|
||||
@pytest.mark.parametrize(
|
||||
"exposed_population, cm, pop, cases, AB, probabilistic_exposure_probability",[
|
||||
[10, known_concentrations(lambda t: 36.),
|
||||
[10, known_concentrations(lambda t: 18.),
|
||||
100000, 68, 5, 41.50971131],
|
||||
[10, known_concentrations(lambda t: 0.2),
|
||||
[10, known_concentrations(lambda t: 0.1),
|
||||
100000, 68, 5, 2.185785075],
|
||||
[20, known_concentrations(lambda t: 72.),
|
||||
[20, known_concentrations(lambda t: 36.),
|
||||
100000, 68, 5, 64.09068488],
|
||||
[30, known_concentrations(lambda t: 1.2),
|
||||
[30, known_concentrations(lambda t: 0.6),
|
||||
100000, 68, 5, 55.93154502],
|
||||
])
|
||||
def test_probabilistic_exposure_probability(sr_model, exposed_population, cm,
|
||||
|
|
@ -396,8 +396,8 @@ def test_diameter_vectorisation_room(diameter_dependent_model, sr_model, cases_m
|
|||
@pytest.mark.parametrize(
|
||||
["cm", "host_immunity", "expected_probability"],
|
||||
[
|
||||
[known_concentrations(lambda t: 36.), np.array([0.25, 0.5]), np.array([57.40415859, 41.03956914])],
|
||||
[known_concentrations(lambda t: 36.), np.array([0., 1.]), np.array([67.95037626, 0.])],
|
||||
[known_concentrations(lambda t: 18.), np.array([0.25, 0.5]), np.array([57.40415859, 41.03956914])],
|
||||
[known_concentrations(lambda t: 18.), np.array([0., 1.]), np.array([67.95037626, 0.])],
|
||||
]
|
||||
)
|
||||
def test_host_immunity_vectorisation(sr_model, cases_model, cm, host_immunity, expected_probability):
|
||||
|
|
|
|||
|
|
@ -56,6 +56,12 @@ class SimpleConcentrationModel:
|
|||
#: Number of infected people
|
||||
num_infected: int = 1
|
||||
|
||||
#: Fraction of infected viruses (viable to RNA ratio)
|
||||
viable_to_RNA: _VectorisedFloat = 0.5
|
||||
|
||||
#: Host immunity factor (0. for not immune)
|
||||
HI: _VectorisedFloat = 0.
|
||||
|
||||
#: Relative humidity RH
|
||||
humidity: float = 0.3
|
||||
|
||||
|
|
@ -176,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.room_volume)
|
||||
* self.num_infected * self.viable_to_RNA
|
||||
* (1. - self.HI) / self.room_volume)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
|
|
@ -295,12 +302,6 @@ class SimpleExposureModel(SimpleConcentrationModel):
|
|||
interaction intervals are within presence intervals of the infected.
|
||||
"""
|
||||
|
||||
#: Fraction of infected viruses
|
||||
finf: _VectorisedFloat = 0.5
|
||||
|
||||
#: Host immunity factor (0. for not immune)
|
||||
HI: _VectorisedFloat = 0.
|
||||
|
||||
#: Infectious dose (ID50)
|
||||
ID50: _VectorisedFloat = 50.
|
||||
|
||||
|
|
@ -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.room_volume)
|
||||
* self.num_infected * self.viable_to_RNA
|
||||
* (1. - self.HI) / self.room_volume)
|
||||
|
||||
@method_cache
|
||||
def integrated_shortrange_concentration(self) -> _VectorisedFloat:
|
||||
|
|
@ -448,7 +450,7 @@ class SimpleExposureModel(SimpleConcentrationModel):
|
|||
|
||||
result += self.integrated_shortrange_concentration()
|
||||
|
||||
return result * self.finf * (1. - self.HI)
|
||||
return result
|
||||
|
||||
def probability_infection(self):
|
||||
"""
|
||||
|
|
@ -528,6 +530,8 @@ def simple_c_model() -> SimpleConcentrationModel:
|
|||
room_volume = 50.,
|
||||
lambda_ventilation= 1.,
|
||||
BLO_factors = expiration_BLO_factors['Breathing'],
|
||||
viable_to_RNA = models.Virus.types['SARS_CoV_2_DELTA'].viable_to_RNA_ratio,
|
||||
HI = 0.,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -574,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,
|
||||
|
|
@ -622,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'
|
||||
|
|
@ -683,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,
|
||||
|
|
@ -724,6 +728,9 @@ def test_longrange_concentration_with_distributions(c_model_distr,time):
|
|||
room_volume = 50.,
|
||||
lambda_ventilation= 1.,
|
||||
BLO_factors = expiration_BLO_factors['Breathing'],
|
||||
viable_to_RNA = virus_distributions['SARS_CoV_2_DELTA'
|
||||
].build_model(SAMPLE_SIZE).viable_to_RNA_ratio,
|
||||
HI = 0.,
|
||||
)
|
||||
npt.assert_allclose(
|
||||
c_model_distr.build_model(SAMPLE_SIZE).concentration(time).mean(),
|
||||
|
|
@ -741,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'
|
||||
|
|
|
|||
|
|
@ -311,17 +311,22 @@ def waiting_room_mc():
|
|||
)
|
||||
|
||||
|
||||
# In the following tests all the initial expected values for emission
|
||||
# rate were multiplied by the average of the distribution of fraction
|
||||
# of infected viruses (0.305, for a uniform distribution from 0.01 to 0.6)
|
||||
# following the change of convention that this ratio should be
|
||||
# applied at the emission level.
|
||||
@retry(tries=10)
|
||||
@pytest.mark.parametrize(
|
||||
"mc_model, expected_pi, expected_new_cases, expected_dose, expected_ER_per_person",
|
||||
[
|
||||
["shared_office_mc", 5.38, 0.16, 3.350, 1056],
|
||||
["classroom_mc", 8.21, 1.56, 11.356, 7416],
|
||||
["ski_cabin_mc", 12.92, 0.39, 21.796, 10231],
|
||||
["skagit_chorale_mc",61.01, 36.53, 84.730, 190422],
|
||||
["bus_ride_mc", 10.59, 7.06, 6.650, 5419],
|
||||
["gym_mc", 0.52, 0.14, 0.249, 1450/2.], # there are two infected in this case
|
||||
["waiting_room_mc", 1.53, 0.21, 0.844, 929],
|
||||
["shared_office_mc", 5.38, 0.16, 3.350, 1056*0.305],
|
||||
["classroom_mc", 8.21, 1.56, 11.356, 7416*0.305],
|
||||
["ski_cabin_mc", 12.92, 0.39, 21.796, 10231*0.305],
|
||||
["skagit_chorale_mc",61.01, 36.53, 84.730, 190422*0.305],
|
||||
["bus_ride_mc", 10.59, 7.06, 6.650, 5419*0.305],
|
||||
["gym_mc", 0.52, 0.14, 0.249, 1450*0.305/2.], # there are two infected in this case
|
||||
["waiting_room_mc", 1.53, 0.21, 0.844, 929*0.305],
|
||||
]
|
||||
)
|
||||
def test_report_models(mc_model, expected_pi, expected_new_cases,
|
||||
|
|
@ -343,12 +348,12 @@ def test_report_models(mc_model, expected_pi, expected_new_cases,
|
|||
@pytest.mark.parametrize(
|
||||
"mask_type, month, expected_pi, expected_dose, expected_ER",
|
||||
[
|
||||
["No mask", "Jul", 7.689, 10.050, 1034.435],
|
||||
["Type I", "Jul", 1.663, 0.938, 193.52],
|
||||
["FFP2", "Jul", 0.523, 0.253, 193.52],
|
||||
["Type I", "Feb", 0.659, 0.325, 193.52],
|
||||
["Cloth", "Feb", 2.653, 1.741, 673.10],
|
||||
["Cloth", "Jul", 5.322, 5.064, 673.10],
|
||||
["No mask", "Jul", 7.689, 10.050, 1034.435*0.305],
|
||||
["Type I", "Jul", 1.663, 0.938, 193.52*0.305],
|
||||
["FFP2", "Jul", 0.523, 0.253, 193.52*0.305],
|
||||
["Type I", "Feb", 0.659, 0.325, 193.52*0.305],
|
||||
["Cloth", "Feb", 2.653, 1.741, 673.10*0.305],
|
||||
["Cloth", "Jul", 5.322, 5.064, 673.10*0.305],
|
||||
],
|
||||
)
|
||||
def test_small_shared_office_Geneva(mask_type, month, expected_pi,
|
||||
|
|
|
|||
Loading…
Reference in a new issue