Merge branch 'cara_update_activity' into 'master'

Modified activity parameters and updated calculator scenarios

See merge request cara/cara!92
This commit is contained in:
Philip James Elson 2020-11-17 20:09:59 +00:00
commit 659404ae05
8 changed files with 57 additions and 35 deletions

View file

@ -103,12 +103,16 @@ There are three predefined activities in the tool at present.
**Call Centre** = All persons seated, all talking simultaneously, all the time. This is a conservative profile (i.e. will show in increased ``P(i)`` compared to office/meeting) if used for office activity.
**Workshop** = Based on a mechanical assembly workshop, all persons are doing light exercise (standing, moving around, using tools) and talking. Everyone (occupants and infected occupants) is treated the same in this model.
**Lab** = Based on a typical lab or technical working area, all persons are doing light activity and talking 50% of the time. Everyone (occupants and infected occupants) is treated the same in this model.
**Workshop** = Based on a mechanical assembly workshop or equipment installation scenario, all persons are doing moderate activity and talking 50% of the time. Everyone (occupants and infected occupants) is treated the same in this model. This model is equally applicable to bicycling, or walking on a gradient, in the LHC tunnels.
**Training** = Based on a typical training course scenario.
One individual (the trainer) is doing light exercise (standing) and talking, with all other individuals seated and talking quietly (whispering).
In this case it is assumed that the infected person is the trainer, because this is the worst case in terms of viral sheeding.
One individual (the trainer) is standing and talking, with all other individuals seated and talking quietly (whispering).
In this case it is assumed that the infected person is the trainer, because this is the worst case in terms of viral sheding.
**Gym** = Included for comparison purposes only, all persons are doing heavy exercise and breathing (no talking). Everyone (occupants and infected occupants) is treated the same in this model.
### Timings

View file

@ -185,8 +185,16 @@ class FormData:
{'Talking': 1, 'Breathing': self.total_people - 1}
),
'callcentre': ('Seated', 'Talking'),
'training': ('Light exercise', 'Talking'),
'workshop': ('Light exercise', 'Talking'),
'training': ('Standing', 'Talking'),
'lab': (
'Light activity',
#Model 1/2 of time spent talking in a lab.
{'Talking': 1, 'Breathing': 1}),
'workshop': (
'Moderate activity',
#Model 1/2 of time spent talking in a workshop.
{'Talking': 1, 'Breathing': 1}),
'gym':('Heavy exercise', 'Breathing'),
}
[activity_defn, expiration_defn] = scenario_activity_and_expiration[self.activity_type]
@ -210,8 +218,10 @@ class FormData:
'office': 'Seated',
'meeting': 'Seated',
'callcentre': 'Seated',
'training': 'Light exercise',
'workshop': 'Light exercise',
'training': 'Seated',
'workshop': 'Moderate activity',
'lab':'Light activity',
'gym':'Heavy exercise',
}
activity_defn = scenario_activity[self.activity_type]
@ -388,7 +398,7 @@ def baseline_raw_form_data():
}
ACTIVITY_TYPES = {'office', 'meeting', 'training', 'callcentre', 'workshop'}
ACTIVITY_TYPES = {'office', 'meeting', 'training', 'callcentre', 'workshop', 'lab', 'gym'}
EVENT_TYPES = {'single_event', 'recurrent_event'}
MECHANICAL_VENTILATION_TYPES = {'air_changes', 'air_supply', 'not-applicable'}
MASK_TYPES = {'Type I', 'FFP2'}

View file

@ -113,9 +113,11 @@
<option value="office">Office</option>
<option value="meeting">Meeting</option>
<option value="callcentre">Call Centre</option>
<option value="lab">Laboratory</option>
<option value="workshop">Workshop</option>
<option value="training">Training</option>
</select><br>
<option value="gym">Gym</option>
</select><br>
Start: <input type="time" id="activity_start" class="start_time" name="activity_start" value="09:00" required> &nbsp;&nbsp;
Finish: <input type="time" id="activity_finish" class="finish_time" name="activity_finish" value="18:00" required>
<span id="activity_time_error" class="red_text" hidden>Finish time must be after start</span><br>
@ -196,7 +198,7 @@
<b>Ventilation data:</b> <br>
<ul>
<li>Mechanical ventilation = check the rates with a specialist.</li>
<li>Natural ventilation = the window opening distance is between the fixed frame and movable part when open.</li>
<li>Natural ventilation = the window opening distance is between the fixed frame and movable part when open.</li>
<li>HEPA filtration = the air flow of the device. The following values are based on the different fan velocities of a specific commercial device proposed by the HSE Unit:</li>
<ul>
<li>Level 6 (max) = 430 m^3/h (noisy)</li>
@ -208,11 +210,13 @@
<b>Activity types:</b><br>
The type of activity that includes both the infected and exposed persons:
<ul>
<li>Office = typical scenario all persons seated, in conversation (talking 33% of the time, otherwise breathing normally).</li>
<li>Meeting = typical scenario all persons seated, in conversation.</li>
<li>Workshop = assembly workshop environment, all persons doing light exercise, talking.</li>
<li>Office = Typical office scenario with all persons seated, in conversation (talking 33% of the time, otherwise breathing normally).</li>
<li>Meeting = Typical meeting scenario with all persons seated, in conversation (talking time is shared equally between all persons).</li>
<li>Call Centre = A conservative assumption for office spaces, assumes all occupants are seated and talking continuously.</li>
<li>Training = one person (the trainer) standing, talking, all others seated, talking quietly (whispering). It is assumed the trainer is the infected person, for the worst case scenario.</li>
<li>Laboratory = Typical lab scenario with all persons doing light physical activity and talking 50% of the time.</li>
<li>Workshop = Typical mechanical assembly workshop or equipment installation scenario with all persons doing moderate activity and talking 50% of the time.</li>
<li>Training = Training course scenario. One person (Trainer) standing, talking, all others seated, talking quietly (whispering). It is assumed the Trainer is the infected person, for the worst case scenario.</li>
<li>Gym = Included for comparison purposes only, all persons are doing heavy exercise and breathing (no talking).</li>
</ul>
<b>Activity breaks:</b><br>
<ul>

View file

@ -70,15 +70,19 @@
<li><p class="data_text">
Activity type:
{% if form.activity_type == "office" %}
Office typical scenario with all persons seated, talking occasionally.
Office typical scenario with all persons seated, talking occasionally (talking assumed for 1/3rd of the time).
{% elif form.activity_type == "meeting" %}
Meeting typical scenario with all persons seated, one person talking at a time.
{% elif form.activity_type == "callcentre" %}
Call Centre = typical office scenario with all persons seated, all talking continuously.
{% elif form.activity_type == "workshop" %}
Workshop = assembly workshop environment, all persons doing light exercise, talking.
Workshop = assembly workshop environment, all persons doing moderate physical activity, talking 50% of the time.
{% elif form.activity_type == "training" %}
Training one person (the trainer) standing, talking, all others seated, talking quietly (whispering). It is assumed the trainer is the infected person, for the worst case scenario.
{% elif form.activity_type == "lab" %}
Laboratory = Lab or technical environment, all persons doing light physical activity, talking 50% of the time.
{% elif form.activity_type == "gym" %}
Gym = For comparison only, all persons doing heavy physical exercise, breathing and not talking.
{% endif %}
</p></li>
<ul>

View file

@ -369,14 +369,14 @@ baseline_model = models.ExposureModel(
virus=models.Virus.types['SARS_CoV_2'],
presence=models.SpecificInterval(((8, 12), (13, 17))),
mask=models.Mask.types['No mask'],
activity=models.Activity.types['Light exercise'],
activity=models.Activity.types['Light activity'],
expiration=models.Expiration.types['Unmodulated Vocalization'],
),
),
exposed=models.Population(
number=10,
presence=models.SpecificInterval(((8, 12), (13, 17))),
activity=models.Activity.types['Light exercise'],
activity=models.Activity.types['Light activity'],
mask=models.Mask.types['No mask'],
),
)

View file

@ -390,10 +390,10 @@ class Activity:
Activity.types = {
'Resting': Activity(0.49, 0.49),
'Seated': Activity(0.54, 0.54),
'Light exercise': Activity(1.38, 1.38),
'Moderate exercise': Activity(2.35, 2.35),
'Seated': Activity(0.51, 0.51),
'Standing': Activity(0.57, 0.57),
'Light activity': Activity(1.25, 1.25),
'Moderate activity': Activity(1.78, 1.78),
'Heavy exercise': Activity(3.30, 3.30),
}

View file

@ -18,7 +18,7 @@ def baseline_model():
virus=models.Virus.types['SARS_CoV_2'],
presence=models.SpecificInterval(((0, 4), (5, 8))),
mask=models.Mask.types['No mask'],
activity=models.Activity.types['Light exercise'],
activity=models.Activity.types['Light activity'],
expiration=models.Expiration.types['Unmodulated Vocalization'],
),
)

View file

@ -16,7 +16,7 @@ def test_no_mask_aerosols(baseline_model):
def test_no_mask_emission_rate(baseline_model):
rate = 167.74011998223307
rate = 151.938514
npt.assert_allclose(
[baseline_model.infected.emission_rate(t) for t in [0, 1, 4, 4.5, 5, 8, 9]],
[0, rate, rate, 0, 0, rate, 0],
@ -52,7 +52,7 @@ def test_concentrations(baseline_model):
concentrations = [baseline_model.concentration(t) for t in ts]
npt.assert_allclose(
concentrations,
[0.000000e+00, 2.891970e-01, 1.266287e-04, 2.891969e-01, 5.544607e-08],
[0.000000e+00, 2.619538e-01, 1.146999e-04, 2.619537e-01, 5.022289e-08],
rtol=1e-5
)
@ -79,7 +79,7 @@ def build_model(interval_duration):
virus=models.Virus.types['SARS_CoV_2'],
presence=models.SpecificInterval(((0, 4), (5, 8))),
mask=models.Mask.types['No mask'],
activity=models.Activity.types['Light exercise'],
activity=models.Activity.types['Light activity'],
expiration=models.Expiration.types['Unmodulated Vocalization'],
),
)
@ -97,7 +97,7 @@ def test_concentrations_startup(baseline_model):
def test_r0(baseline_exposure_model):
p = baseline_exposure_model.infection_probability()
npt.assert_allclose(p, 93.196908)
npt.assert_allclose(p, 88.977694)
def test_periodic_window(baseline_periodic_window, baseline_room):
@ -300,7 +300,7 @@ def build_hourly_dependent_model(month, intervals_open=((7.5, 8.5),),
virus=models.Virus.types['SARS_CoV_2'],
presence=models.SpecificInterval(intervals_presence_infected),
mask=models.Mask.types['No mask'],
activity=models.Activity.types['Light exercise'],
activity=models.Activity.types['Light activity'],
expiration=models.Expiration.types['Unmodulated Vocalization'],
),
)
@ -321,7 +321,7 @@ def build_constant_temp_model(outside_temp, intervals_open=((7.5, 8.5),)):
virus=models.Virus.types['SARS_CoV_2'],
presence=models.SpecificInterval(((0, 4), (5, 7.5))),
mask=models.Mask.types['No mask'],
activity=models.Activity.types['Light exercise'],
activity=models.Activity.types['Light activity'],
expiration=models.Expiration.types['Unmodulated Vocalization'],
),
)
@ -348,7 +348,7 @@ def build_hourly_dependent_model_multipleventilation(month, intervals_open=((7.5
virus=models.Virus.types['SARS_CoV_2'],
presence=models.SpecificInterval(((0, 4), (5, 7.5))),
mask=models.Mask.types['No mask'],
activity=models.Activity.types['Light exercise'],
activity=models.Activity.types['Light activity'],
expiration=models.Expiration.types['Unmodulated Vocalization'],
),
)
@ -364,7 +364,7 @@ def build_hourly_dependent_model_multipleventilation(month, intervals_open=((7.5
[0.5, 1.2, 2., 3.5, 5., 6.5, 7.5, 7.9, 8.],
)
def test_concentrations_hourly_dep_temp_vs_constant(month, temperatures, time):
# The concentrations should be the same up to 8 AM (time when the
# The concentrations should be the same up to 8 AM (time when the
# temperature changes DURING the window opening).
m1 = build_hourly_dependent_model(month)
m2 = build_constant_temp_model(temperatures[7]+273.15)
@ -435,8 +435,8 @@ def build_exposure_model(concentration_model):
@pytest.mark.parametrize(
"month, expected_r0",
[
['Jan', 91.06953],
['Jun', 99.995335],
['Jan', 86.220749],
['Jun', 99.972046],
],
)
def test_r0_hourly_dep(month,expected_r0):
@ -453,8 +453,8 @@ def test_r0_hourly_dep(month,expected_r0):
@pytest.mark.parametrize(
"month, expected_r0",
[
['Jan', 91.19912],
['Jun', 99.997324],
['Jan', 86.385018],
['Jun', 99.982281],
],
)
def test_r0_hourly_dep_refined(month,expected_r0):