generate initial CO2 plot

This commit is contained in:
Luis Aleixo 2023-05-17 17:29:37 +02:00
parent 2faeabf05c
commit e75846a3b2
5 changed files with 35 additions and 40 deletions

View file

@ -325,11 +325,8 @@ class FormData:
humidity = float(self.humidity)
inside_temp = self.inside_temp
return models.Room(volume=volume, inside_temp=models.PiecewiseConstant((0, 24), (inside_temp,)), humidity=humidity)
def build_mc_model(self) -> mc.ExposureModel:
room = self.initialize_room()
room = models.Room(volume=volume, inside_temp=models.PiecewiseConstant((0, 24), (inside_temp,)), humidity=humidity)
ventilation: models._VentilationBase = self.ventilation()
infected_population = self.infected_population()
short_range = []
@ -342,11 +339,10 @@ class FormData:
distance=short_range_distances,
))
# Initializes and returns a model with the attributes defined above
return mc.ExposureModel(
concentration_model=mc.ConcentrationModel(
room=room,
ventilation=self.ventilation(),
ventilation=ventilation,
infected=infected_population,
evaporation_factor=0.3,
),
@ -357,6 +353,14 @@ class FormData:
geographic_cases=self.geographic_cases,
ascertainment_bias=CONFIDENCE_LEVEL_OPTIONS[self.ascertainment_bias],
),
CO2_profile=models.CO2Data(
room_volume=self.room_volume,
number=self.total_people,
presence=self.population_present_interval(),
ventilation_transition_times=tuple(ventilation.transition_times(room=room)),
times=self.CO2_data['times'],
CO2_concentrations=self.CO2_data['CO2']
) if self.CO2_data_option else (),
)
def build_model(self, sample_size=DEFAULT_MC_SAMPLE_SIZE) -> models.ExposureModel:
@ -754,6 +758,12 @@ class FormData:
self.infected_start, self.infected_finish,
breaks=breaks,
)
def population_present_interval(self) -> models.Interval:
state_change_times = set(self.infected_present_interval().transition_times())
state_change_times.update(self.exposed_present_interval().transition_times())
all_state_changes = sorted(state_change_times)
return models.SpecificInterval(tuple(zip(all_state_changes[:-1], all_state_changes[1:])))
def short_range_interval(self, interaction) -> models.SpecificInterval:
start_time = time_string_to_minutes(interaction['start_time'])

View file

@ -150,6 +150,11 @@ def calculate_report_data(form: FormData, model: models.ExposureModel) -> typing
zip(('viral_loads', 'pi_means', 'lower_percentiles', 'upper_percentiles'),
manufacture_conditional_probability_data(model, prob))}
CO2_times = list(form.CO2_data['times']) if form.CO2_data_option else []
CO2_values = list(form.CO2_data['CO2']) if form.CO2_data_option else []
ex, airs = model.CO2_profile.CO2_fit_params()
co2_plot = img2base64(_figure2bytes(CO2_plot(CO2_times, CO2_values))) if form.CO2_data_option else None
return {
"model_repr": repr(model),
"times": list(times),

View file

@ -181,6 +181,9 @@
let short_range_expirations = {{ short_range_expirations | JSONify }};
draw_plot("concentration_plot");
</script>
<img src= "{{ CO2_plot }}" />
<p>Emission rate = {{ ex }}</p>
<p>Ventilation = {{ airs }}</p>
</p>
</div>
</div>

View file

@ -1584,6 +1584,9 @@ class ExposureModel:
c_model.ventilation.air_exchange(c_model.room, time)) for time in c_model.state_change_times()))):
raise ValueError("If the diameter is an array, none of the ventilation parameters "
"or virus decay constant can be arrays at the same time.")
if not isinstance(self.exposed.number, int):
raise NotImplementedError("Cannot use dynamic occupancy for"
" the exposed population")
@method_cache
def population_state_change_times(self) -> typing.List[float]:

View file

@ -27,7 +27,7 @@ def full_exposure_model():
short_range=(),
exposed=models.Population(
number=10,
presence=models.SpecificInterval(((8, 12), (13, 17), )),
presence=models.SpecificInterval(((8, 12), (13, 17), )),
mask=models.Mask.types['No mask'],
activity=models.Activity.types['Seated'],
host_immunity=0.
@ -51,37 +51,11 @@ def baseline_infected_population_number():
@pytest.fixture
def baseline_exposed_population_number():
return models.Population(
number=models.IntPiecewiseConstant(
(8, 12, 13, 17), (10, 0, 10)),
presence=None,
mask=models.Mask.types['No mask'],
activity=models.Activity.types['Seated'],
host_immunity=0.,
)
@pytest.fixture
def dynamic_infected_single_exposure_model(full_exposure_model, baseline_infected_population_number):
def dynamic_single_exposure_model(full_exposure_model, baseline_infected_population_number):
return dc_utils.nested_replace(full_exposure_model,
{'concentration_model.infected': baseline_infected_population_number, })
@pytest.fixture
def dynamic_exposed_single_exposure_model(full_exposure_model, baseline_exposed_population_number):
return dc_utils.nested_replace(full_exposure_model,
{'exposed': baseline_exposed_population_number, })
@pytest.fixture
def dynamic_population_exposure_model(full_exposure_model, baseline_infected_population_number ,baseline_exposed_population_number):
return dc_utils.nested_replace(full_exposure_model, {
'concentration_model.infected': baseline_infected_population_number,
'exposed': baseline_exposed_population_number,
})
@pytest.mark.parametrize(
"time",
[4., 8., 10., 12., 13., 14., 16., 20., 24.],
@ -117,16 +91,16 @@ def test_population_number(full_exposure_model: models.ExposureModel,
[4., 8., 10., 12., 13., 14., 16., 20., 24.],
)
def test_concentration_model_dynamic_population(full_exposure_model: models.ExposureModel,
dynamic_infected_single_exposure_model: models.ExposureModel,
dynamic_single_exposure_model: models.ExposureModel,
time: float):
assert full_exposure_model.concentration(time) == dynamic_infected_single_exposure_model.concentration(time)
assert full_exposure_model.concentration(time) == dynamic_single_exposure_model.concentration(time)
@pytest.mark.parametrize("number_of_infected",[1, 2, 3, 4, 5])
@pytest.mark.parametrize("time",[9., 12.5, 16.])
def test_linearity_with_number_of_infected(full_exposure_model: models.ExposureModel,
dynamic_infected_single_exposure_model: models.ExposureModel,
dynamic_single_exposure_model: models.ExposureModel,
time: float,
number_of_infected: int):
@ -138,8 +112,8 @@ def test_linearity_with_number_of_infected(full_exposure_model: models.ExposureM
}
)
npt.assert_almost_equal(static_multiple_exposure_model.concentration(time), dynamic_infected_single_exposure_model.concentration(time) * number_of_infected)
npt.assert_almost_equal(static_multiple_exposure_model.deposited_exposure(), dynamic_infected_single_exposure_model.deposited_exposure() * number_of_infected)
npt.assert_almost_equal(static_multiple_exposure_model.concentration(time), dynamic_single_exposure_model.concentration(time) * number_of_infected)
npt.assert_almost_equal(static_multiple_exposure_model.deposited_exposure(), dynamic_single_exposure_model.deposited_exposure() * number_of_infected)
@pytest.mark.parametrize(