Merge branch 'feature/HI_data' into 'master'
Host Immunity Data See merge request cara/caimira!401
This commit is contained in:
commit
20b65b6081
13 changed files with 355 additions and 18 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.xlsx filter=lfs diff=lfs merge=lfs -text
|
||||
|
|
@ -33,7 +33,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.4"
|
||||
__version__ = "4.5"
|
||||
|
||||
|
||||
class BaseRequestHandler(RequestHandler):
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@ class FormData:
|
|||
room_volume: float
|
||||
simulation_name: str
|
||||
total_people: int
|
||||
vaccine_option: bool
|
||||
vaccine_booster_option: bool
|
||||
vaccine_type: str
|
||||
vaccine_booster_type: str
|
||||
ventilation_type: str
|
||||
virus_type: str
|
||||
volume_type: str
|
||||
|
|
@ -133,6 +137,10 @@ class FormData:
|
|||
'room_volume': 0.,
|
||||
'simulation_name': _NO_DEFAULT,
|
||||
'total_people': _NO_DEFAULT,
|
||||
'vaccine_option': False,
|
||||
'vaccine_booster_option': False,
|
||||
'vaccine_type': 'AZD1222_(AstraZeneca)',
|
||||
'vaccine_booster_type': 'AZD1222_(AstraZeneca)',
|
||||
'ventilation_type': 'no_ventilation',
|
||||
'virus_type': 'SARS_CoV_2',
|
||||
'volume_type': _NO_DEFAULT,
|
||||
|
|
@ -270,8 +278,9 @@ class FormData:
|
|||
('window_opening_regime', WINDOWS_OPENING_REGIMES),
|
||||
('window_type', WINDOWS_TYPES),
|
||||
('event_month', MONTH_NAMES),
|
||||
('ascertainment_bias', CONFIDENCE_LEVEL_OPTIONS),]
|
||||
|
||||
('ascertainment_bias', CONFIDENCE_LEVEL_OPTIONS),
|
||||
('vaccine_type', VACCINE_TYPE),
|
||||
('vaccine_booster_type', VACCINE_BOOSTER_TYPE),]
|
||||
for attr_name, valid_set in validation_tuples:
|
||||
if getattr(self, attr_name) not in valid_set:
|
||||
raise ValueError(f"{getattr(self, attr_name)} is not a valid value for {attr_name}")
|
||||
|
|
@ -517,7 +526,7 @@ class FormData:
|
|||
mask=self.mask(),
|
||||
activity=activity,
|
||||
expiration=expiration,
|
||||
host_immunity=0.,
|
||||
host_immunity=0., # Vaccination status does not affect the infected population (for now)
|
||||
)
|
||||
return infected
|
||||
|
||||
|
|
@ -545,12 +554,22 @@ class FormData:
|
|||
# minus the number of infected occupants.
|
||||
exposed_occupants = self.total_people - infected_occupants
|
||||
|
||||
if (self.vaccine_option):
|
||||
if (self.vaccine_booster_option and self.vaccine_booster_type != 'Other'):
|
||||
host_immunity = [vaccine['VE'] for vaccine in data.vaccine_booster_host_immunity if
|
||||
vaccine['primary series vaccine'] == self.vaccine_type and
|
||||
vaccine['booster vaccine'] == self.vaccine_booster_type][0]
|
||||
else:
|
||||
host_immunity = data.vaccine_primary_host_immunity[self.vaccine_type]
|
||||
else:
|
||||
host_immunity = 0.
|
||||
|
||||
exposed = mc.Population(
|
||||
number=exposed_occupants,
|
||||
presence=self.exposed_present_interval(),
|
||||
activity=activity,
|
||||
mask=self.mask(),
|
||||
host_immunity=0.,
|
||||
host_immunity=host_immunity,
|
||||
)
|
||||
return exposed
|
||||
|
||||
|
|
@ -790,6 +809,10 @@ def baseline_raw_form_data() -> typing.Dict[str, typing.Union[str, float]]:
|
|||
'room_volume': '75',
|
||||
'simulation_name': 'Test',
|
||||
'total_people': '10',
|
||||
'vaccine_option': '0',
|
||||
'vaccine_booster_option': '0',
|
||||
'vaccine_type': 'Ad26.COV2.S_(Janssen)',
|
||||
'vaccine_booster_type': 'AZD1222_(AstraZeneca)',
|
||||
'ventilation_type': 'natural_ventilation',
|
||||
'virus_type': 'SARS_CoV_2',
|
||||
'volume_type': 'room_volume_explicit',
|
||||
|
|
@ -820,7 +843,12 @@ MONTH_NAMES = [
|
|||
'January', 'February', 'March', 'April', 'May', 'June', 'July',
|
||||
'August', 'September', 'October', 'November', 'December',
|
||||
]
|
||||
|
||||
VACCINE_TYPE = ['Ad26.COV2.S_(Janssen)', 'Any_mRNA_-_heterologous', 'AZD1222_(AstraZeneca)', 'AZD1222_(AstraZeneca)_and_any_mRNA_-_heterologous', 'AZD1222_(AstraZeneca)_and_BNT162b2_(Pfizer)',
|
||||
'BBIBP-CorV_(Beijing_CNBG)', 'BNT162b2_(Pfizer)', 'BNT162b2_(Pfizer)_and_mRNA-1273_(Moderna)', 'CoronaVac_(Sinovac)', 'CoronaVac_(Sinovac)_and_AZD1222_(AstraZeneca)', 'Covishield',
|
||||
'mRNA-1273_(Moderna)', 'Sputnik_V_(Gamaleya)', 'CoronaVac_(Sinovac)_and_BNT162b2_(Pfizer)']
|
||||
VACCINE_BOOSTER_TYPE = ['AZD1222_(AstraZeneca)', 'Ad26.COV2.S_(Janssen)', 'BNT162b2_(Pfizer)', 'BNT162b2_(Pfizer)_(4th_dose)', 'BNT162b2_(Pfizer)_and_mRNA-1273_(Moderna)',
|
||||
'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)', 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)_(4th_dose)', 'CoronaVac_(Sinovac)', 'Coronavac_(Sinovac)', 'Sinopharm',
|
||||
'mRNA-1273_(Moderna)', 'mRNA-1273_(Moderna)_(4th_dose)', 'Other']
|
||||
|
||||
def _hours2timestring(hours: float):
|
||||
# Convert times like 14.5 to strings, like "14:30"
|
||||
|
|
|
|||
|
|
@ -214,6 +214,10 @@ def readable_minutes(minutes: int) -> str:
|
|||
return time_str + unit
|
||||
|
||||
|
||||
def percentage(absolute: float) -> float:
|
||||
return absolute * 100
|
||||
|
||||
|
||||
def non_zero_percentage(percentage: int) -> str:
|
||||
if percentage < 0.01:
|
||||
return "<0.01%"
|
||||
|
|
@ -389,6 +393,7 @@ class ReportGenerator:
|
|||
env.filters['minutes_to_time'] = minutes_to_time
|
||||
env.filters['float_format'] = "{0:.2f}".format
|
||||
env.filters['int_format'] = "{:0.0f}".format
|
||||
env.filters['percentage'] = percentage
|
||||
env.filters['JSONify'] = json.dumps
|
||||
return env
|
||||
|
||||
|
|
|
|||
|
|
@ -328,6 +328,49 @@ function on_wearing_mask_change() {
|
|||
})
|
||||
}
|
||||
|
||||
function update_booster_warning() {
|
||||
// Check if "Other" is selected
|
||||
$("#vaccine_booster_type").find(":selected").val() == "Other" ? $("#booster_warning").show() : $("#booster_warning").hide();
|
||||
}
|
||||
|
||||
function update_booster_dropdown(url) {
|
||||
let primary_vaccine_option = $("#vaccine_type").find(":selected").val();
|
||||
$("#vaccine_booster_type option").remove();
|
||||
vaccine_booster_host_immunity.forEach(booster => {
|
||||
if (booster['primary series vaccine'] == primary_vaccine_option)
|
||||
$("#vaccine_booster_type").append(`<option data-primary-vaccine=${primary_vaccine_option} value=${booster['booster vaccine']}>${booster['booster vaccine'].replaceAll('_', ' ')}</option>`);
|
||||
});
|
||||
$("#vaccine_booster_type").append(`<option value='Other'>Other</option>`);
|
||||
|
||||
let booster_vaccine = url.searchParams.has('vaccine_booster_type') ? url.searchParams.get('vaccine_booster_type') : null;
|
||||
$(`#vaccine_booster_type > option[value="${booster_vaccine}"`).attr('selected', true);
|
||||
|
||||
update_booster_warning();
|
||||
}
|
||||
|
||||
function on_vaccination_change(url) {
|
||||
vaccination_option = $('input[type=radio][name=vaccine_option]');
|
||||
vaccination_option.each(function (index) {
|
||||
if (this.checked) {
|
||||
getChildElement($(this)).show();
|
||||
require_fields(this);
|
||||
}
|
||||
else {
|
||||
getChildElement($(this)).hide();
|
||||
require_fields(this);
|
||||
}
|
||||
});
|
||||
update_booster_dropdown(url);
|
||||
}
|
||||
|
||||
function on_vaccination_booster_change() {
|
||||
vaccination_booster_option = $('input[type=radio][name=vaccine_booster_option]');
|
||||
vaccination_booster_option.each(function (index) {
|
||||
if (this.checked) getChildElement($(this)).show();
|
||||
else getChildElement($(this)).hide();
|
||||
});
|
||||
}
|
||||
|
||||
function populate_temp_hum_values(data, index) {
|
||||
$("#sensor_temperature").text(Math.round(data[index].Details.T) + '°C');
|
||||
$("#sensor_humidity").text(Math.round(data[index].Details.RH) + '%');
|
||||
|
|
@ -818,6 +861,7 @@ window.onpagehide = function(){
|
|||
$(document).ready(function () {
|
||||
var url = new URL(decodeURIComponent(window.location.href));
|
||||
//Pre-fill form with known values
|
||||
|
||||
url.searchParams.forEach((value, name) => {
|
||||
//If element exists
|
||||
if(document.getElementsByName(name).length > 0) {
|
||||
|
|
@ -852,8 +896,8 @@ $(document).ready(function () {
|
|||
$("#sr_interactions").text(index - 1);
|
||||
}
|
||||
|
||||
else if (name == 'sensor_in_use') {
|
||||
// TODO - Validate if sensor exists
|
||||
else if (name == 'sensor_in_use' || name == 'vaccine_type' || name == 'vaccine_booster_type') {
|
||||
// Validation after
|
||||
}
|
||||
|
||||
//Ignore 0 (default) values from server side
|
||||
|
|
@ -865,6 +909,14 @@ $(document).ready(function () {
|
|||
});
|
||||
|
||||
// Handle default URL values if they are not explicitly defined.
|
||||
|
||||
// Populate primary vaccine dropdown
|
||||
$("#vaccine_type option").remove();
|
||||
let primary_vaccine = url.searchParams.has('vaccine_type') ? url.searchParams.get('vaccine_type') : null;
|
||||
vaccine_primary_host_immunity.forEach(vaccine => $("#vaccine_type").append(`<option value=${vaccine}>${vaccine.replaceAll('_', ' ')}</option>`));
|
||||
$(`#vaccine_type > option[value="${primary_vaccine}"]`).attr('selected', true);
|
||||
|
||||
// Handle geographic location input
|
||||
if (Array.from(url.searchParams).length > 0) {
|
||||
if (!url.searchParams.has('location_name')) {
|
||||
$('[name="location_name"]').val('Geneva')
|
||||
|
|
@ -878,7 +930,6 @@ $(document).ready(function () {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// When the document is ready, deal with the fact that we may be here
|
||||
// as a result of a forward/back browser action. If that is the case, update
|
||||
// the visibility of some of our inputs.
|
||||
|
|
@ -931,6 +982,23 @@ $(document).ready(function () {
|
|||
// Call the function now to handle forward/back button presses in the browser.
|
||||
on_wearing_mask_change();
|
||||
|
||||
// When the vaccinated_option_option changes we want to make its respective
|
||||
// children show/hide.
|
||||
$("input[type=radio][name=vaccine_option]").change(() => on_vaccination_change(url));
|
||||
// Call the function now to handle forward/back button presses in the browser.
|
||||
on_vaccination_change(url);
|
||||
|
||||
// When the vaccine_type dropdown selected option changes we want to update
|
||||
// the booster vaccine dropdown.
|
||||
$("#vaccine_type").change(() => update_booster_dropdown(url));
|
||||
$("#vaccine_booster_type").change(update_booster_warning);
|
||||
|
||||
// When the vaccinated_booster_option changes we want to make its respective
|
||||
// children show/hide.
|
||||
$("input[type=radio][name=vaccine_booster_option]").change(on_vaccination_booster_change);
|
||||
// Call the function now to handle forward/back button presses in the browser.
|
||||
on_vaccination_booster_change();
|
||||
|
||||
// When the short_range_option changes we want to make its respective
|
||||
// children show/hide.
|
||||
$("input[type=radio][name=short_range_option]").change(on_short_range_option_change);
|
||||
|
|
@ -1216,3 +1284,47 @@ function objectifyForm(formArray) {
|
|||
returnArray[formArray[i]['name']] = formArray[i]['value'];
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
// ------- VACCINATION DATA -------
|
||||
|
||||
// From data available in Results of COVID-19 Vaccine Effectiveness
|
||||
// Studies: An Ongoing Systematic Review - Updated September 8, 2022.
|
||||
// https://view-hub.org/resources
|
||||
vaccine_primary_host_immunity = [
|
||||
'AZD1222_(AstraZeneca)',
|
||||
'AZD1222_(AstraZeneca)_and_BNT162b2_(Pfizer)',
|
||||
'AZD1222_(AstraZeneca)_and_any_mRNA_-_heterologous',
|
||||
'Ad26.COV2.S_(Janssen)',
|
||||
'Any_mRNA_-_heterologous',
|
||||
'BBIBP-CorV_(Beijing_CNBG)',
|
||||
'BNT162b2_(Pfizer)',
|
||||
'BNT162b2_(Pfizer)_and_mRNA-1273_(Moderna)',
|
||||
'CoronaVac_(Sinovac)',
|
||||
'CoronaVac_(Sinovac)_and_AZD1222_(AstraZeneca)',
|
||||
'CoronaVac_(Sinovac)_and_AZD1222_(AstraZeneca)_-_heterologous',
|
||||
'CoronaVac_(Sinovac)_and_BNT162b2_(Pfizer)',
|
||||
'Covishield',
|
||||
'Sputnik_V_(Gamaleya)',
|
||||
'mRNA-1273_(Moderna)',
|
||||
]
|
||||
|
||||
vaccine_booster_host_immunity = [
|
||||
{'primary series vaccine': 'AZD1222_(AstraZeneca)', 'booster vaccine': 'AZD1222_(AstraZeneca)',},
|
||||
{'primary series vaccine': 'AZD1222_(AstraZeneca)', 'booster vaccine': 'BNT162b2_(Pfizer)',},
|
||||
{'primary series vaccine': 'AZD1222_(AstraZeneca)', 'booster vaccine': 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)',},
|
||||
{'primary series vaccine': 'AZD1222_(AstraZeneca)', 'booster vaccine': 'mRNA-1273_(Moderna)',},
|
||||
{'primary series vaccine': 'Ad26.COV2.S_(Janssen)', 'booster vaccine': 'Ad26.COV2.S_(Janssen)',},
|
||||
{'primary series vaccine': 'Ad26.COV2.S_(Janssen)', 'booster vaccine': 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)',},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)', 'booster vaccine': 'AZD1222_(AstraZeneca)',},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)', 'booster vaccine': 'BNT162b2_(Pfizer)',},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)', 'booster vaccine': 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)',},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)', 'booster vaccine': 'mRNA-1273_(Moderna)',},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)_and_mRNA-1273_(Moderna)', 'booster vaccine': 'BNT162b2_(Pfizer)_and_mRNA-1273_(Moderna)',},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)_(3_doses)', 'booster vaccine': 'BNT162b2_(Pfizer)_(4th_dose)',},
|
||||
{'primary series vaccine': 'CoronaVac_(Sinovac)', 'booster vaccine': 'AZD1222_(AstraZeneca)',},
|
||||
{'primary series vaccine': 'CoronaVac_(Sinovac)', 'booster vaccine': 'BNT162b2_(Pfizer)',},
|
||||
{'primary series vaccine': 'CoronaVac_(Sinovac)', 'booster vaccine': 'CoronaVac_(Sinovac)',},
|
||||
{'primary series vaccine': 'mRNA-1273_(Moderna)', 'booster vaccine': 'BNT162b2_(Pfizer)',},
|
||||
{'primary series vaccine': 'mRNA-1273_(Moderna)', 'booster vaccine': 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)',},
|
||||
{'primary series vaccine': 'mRNA-1273_(Moderna)', 'booster vaccine': 'mRNA-1273_(Moderna)',}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
<b>Virus data:</b>
|
||||
|
||||
<div data-tooltip="Choose the SARS-CoV-2 Variant of Concern (VOC).">
|
||||
<div data-tooltip="Choose the SARS-CoV-2 Variant of Concern (VOC) and select the vaccine type taken by the majority of the exposed population.">
|
||||
<span class="tooltip_text">?</span>
|
||||
</div><br>
|
||||
|
||||
|
|
@ -76,6 +76,49 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-4">Vaccinated? 💉</div>
|
||||
<div class="col-sm-6 ml-0">
|
||||
<input type="radio" id="vaccinated_no" name="vaccine_option" value="0" checked="checked">
|
||||
<label class="mb-0" for="vaccinated_no">No</label>
|
||||
<input class="ml-2" type="radio" id="vaccinated_yes" name="vaccine_option" value="1" data-enables="#DIVvaccine_booster">
|
||||
<label class="mb-0" for="vaccinated_yes">Yes</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="DIVvaccine_booster" class="mt-3">
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-4"><label class="col-form-label">Primary vaccine:</label></div>
|
||||
<div class="col-sm-6 align-self-center">
|
||||
<select id="vaccine_type" name="vaccine_type" class="form-control form-control-sm">
|
||||
{# Updated with JS #}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<div class="d-flex flex-row col-sm-4"><div class="ml-4" style="border: 1px solid #2f4858"></div><p class="ml-2">With booster?</p></div>
|
||||
<div class="col-sm-6 ml-0">
|
||||
<input type="radio" id="vaccinated_booster_no" name="vaccine_booster_option" value="0" checked="checked">
|
||||
<label class="mb-0" for="vaccinated_booster_no">No</label>
|
||||
<input class="ml-2" type="radio" id="vaccinated_booster_yes" name="vaccine_booster_option" value="1" data-enables="#DIVvaccine_booster_yes">
|
||||
<label class="mb-0" for="vaccinated_booster_yes">Yes</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="DIVvaccine_booster_yes" class="mt-3">
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-4"><label class="col-form-label">Booster:</label></div>
|
||||
<div class="col-sm-6 align-self-center">
|
||||
<select id="vaccine_booster_type" name="vaccine_booster_type" class="form-control form-control-sm">
|
||||
{# Updated with JS #}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<p id="booster_warning" class="red_text" style="display: none; max-width: 85%">Due to the lack of data, only the efficiency of the primary dose(s) is considered</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr width="80%">
|
||||
|
||||
<b>Room data:</b>
|
||||
|
|
@ -325,7 +368,7 @@
|
|||
<input type="radio" id="p_deterministic_exposure" name="exposure_option" value="p_deterministic_exposure" checked="checked" data-enables="#DIVp_deterministic_exposure">
|
||||
<label for="p_deterministic_exposure">Deterministic exposure</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group mb-1">
|
||||
<input type="radio" id="p_probabilistic_exposure" name="exposure_option" value="p_probabilistic_exposure" data-enables="#DIVp_probabilistic_exposure">
|
||||
<label for="p_probabilistic_exposure">Probabilistic exposure (incidence rate)</label>
|
||||
</div>
|
||||
|
|
@ -359,6 +402,7 @@
|
|||
</div>
|
||||
|
||||
<span id="training_limit_error" class="red_text" hidden>Conference/Training activities limited to 1 infected<br></span>
|
||||
|
||||
<hr width="80%">
|
||||
|
||||
<div class="form-group row">
|
||||
|
|
@ -381,7 +425,6 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div style=" margin-right:2rem;">
|
||||
<div class="boxMargin pb-0">
|
||||
<div class='sub_title'>Exposed person(s) presence:</div>
|
||||
|
|
@ -427,7 +470,7 @@
|
|||
</div>
|
||||
<p id="short_range_warning" class="red_text" style="margin-right: 2rem">The use of masks mitigates exposure at short-range. The analytical model with short-range interactions does not take mask wearing into account.</p>
|
||||
|
||||
<div id="DIVsr_interactions" class="none">
|
||||
<div id="DIVsr_interactions">
|
||||
<div class="d-flex">
|
||||
<button type="button" id="set_interactions_button" class="btn btn-primary btn-sm" data-toggle="modal" data-target="#short_range_dialog" data-keyboard="false" data-backdrop="static">Set interactions</button>
|
||||
<p class="align-self-center pl-4"><b id="sr_interactions">0</b> short-range interactions.</p>
|
||||
|
|
@ -604,8 +647,6 @@
|
|||
|
||||
<br style="clear:both;">
|
||||
<i>Coffee breaks are spread evenly throughout the day.</i><br>
|
||||
|
||||
|
||||
<br><br>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -375,6 +375,24 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<div class="card">
|
||||
<div class="card-header"><strong>Vaccination data:</strong></div>
|
||||
<div class="card-body">
|
||||
{% if form.vaccine_option %}
|
||||
<ul>
|
||||
<li>Primary vaccine: {{ form.vaccine_type | replace("_", " ") }}
|
||||
{% if form.vaccine_booster_option %}
|
||||
<li>Booster vaccine: {{ form.vaccine_booster_type | replace("_", " ")}} </li>
|
||||
{% endif %}
|
||||
<li>Vaccine effectiveness: {{ model.exposed.host_immunity | percentage | non_zero_percentage }} </li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<p>No vaccination selected.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="card">
|
||||
<div class="card-header"><strong>Ventilation data:</strong></div>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ The local population in Manaus had very high levels of Covid-19 antibodies (>
|
|||
This factor has been taken into account by the authors of the study, via statistical adjustments to the transmission value (i.e. it has been increased, to account for spread in a population with significant acquired Covid-19 immunity).
|
||||
However, this value may be revised in the future as more studies of the Gamma VOC transmission in different geographical locations become available.</p>
|
||||
<br>
|
||||
<h4>Vaccine effectiveness</h4>
|
||||
<br>
|
||||
<p>The vaccination input corresponds to the vaccine type(s) administrated to the exposed population, assuming every exposed (or the occupant in question) has received the vaccine cocktail selected by the user.
|
||||
The respective vaccine effectiveness values were extracted from data available in <a href="https://view-hub.org/resources">Results of COVID-19 Vaccine Effectiveness Studies: An Ongoing Systematic Review - Updated September 8, 2022</a>, using <a href="https://gitlab.cern.ch/cara/caimira/-/tree/master/caimira/scripts/data/vaccine_effectiveness.py">this script</a>.</p>
|
||||
<br>
|
||||
<h3>Room Data</h3>
|
||||
<br>
|
||||
<p>Please enter either the room volume (in m³) or both the floor area (m²) and the room height (m).
|
||||
|
|
|
|||
|
|
@ -40,3 +40,48 @@ GenevaTemperatures = {
|
|||
month: GenevaTemperatures_hourly[month].refine(refine_factor=10)
|
||||
for month, temperatures in local_hourly_temperatures_celsius_per_hour.items()
|
||||
}
|
||||
|
||||
|
||||
# ------- VACCINATION DATA -------
|
||||
|
||||
# From data available in Results of COVID-19 Vaccine Effectiveness
|
||||
# Studies: An Ongoing Systematic Review - Updated September 8, 2022.
|
||||
# https://view-hub.org/resources
|
||||
vaccine_primary_host_immunity = {
|
||||
'AZD1222_(AstraZeneca)': 0.589293,
|
||||
'AZD1222_(AstraZeneca)_and_BNT162b2_(Pfizer)': 0.7865,
|
||||
'AZD1222_(AstraZeneca)_and_any_mRNA_-_heterologous': 0.81,
|
||||
'Ad26.COV2.S_(Janssen)': 0.551278,
|
||||
'Any_mRNA_-_heterologous': 0.93875,
|
||||
'BBIBP-CorV_(Beijing_CNBG)': 0.4325,
|
||||
'BNT162b2_(Pfizer)': 0.660272,
|
||||
'BNT162b2_(Pfizer)_and_mRNA-1273_(Moderna)': 0.586319,
|
||||
'CoronaVac_(Sinovac)': 0.317333,
|
||||
'CoronaVac_(Sinovac)_and_AZD1222_(AstraZeneca)': 0.472,
|
||||
'CoronaVac_(Sinovac)_and_AZD1222_(AstraZeneca)_-_heterologous': 0.74,
|
||||
'CoronaVac_(Sinovac)_and_BNT162b2_(Pfizer)': 0.7965,
|
||||
'Covishield': 0.98,
|
||||
'Sputnik_V_(Gamaleya)': 0.696,
|
||||
'mRNA-1273_(Moderna)': 0.730148,
|
||||
}
|
||||
|
||||
vaccine_booster_host_immunity = [
|
||||
{'primary series vaccine': 'AZD1222_(AstraZeneca)', 'booster vaccine': 'AZD1222_(AstraZeneca)', 'VE': 0.500429},
|
||||
{'primary series vaccine': 'AZD1222_(AstraZeneca)', 'booster vaccine': 'BNT162b2_(Pfizer)', 'VE': 0.537818},
|
||||
{'primary series vaccine': 'AZD1222_(AstraZeneca)', 'booster vaccine': 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)', 'VE': 0.284},
|
||||
{'primary series vaccine': 'AZD1222_(AstraZeneca)', 'booster vaccine': 'mRNA-1273_(Moderna)', 'VE': 0.709143},
|
||||
{'primary series vaccine': 'Ad26.COV2.S_(Janssen)', 'booster vaccine': 'Ad26.COV2.S_(Janssen)', 'VE': 0.492667},
|
||||
{'primary series vaccine': 'Ad26.COV2.S_(Janssen)', 'booster vaccine': 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)', 'VE': 0.79},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)', 'booster vaccine': 'AZD1222_(AstraZeneca)', 'VE': 0.801},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)', 'booster vaccine': 'BNT162b2_(Pfizer)', 'VE': 0.60712},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)', 'booster vaccine': 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)', 'VE': 0.632633},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)', 'booster vaccine': 'mRNA-1273_(Moderna)', 'VE': 0.716786},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)_and_mRNA-1273_(Moderna)', 'booster vaccine': 'BNT162b2_(Pfizer)_and_mRNA-1273_(Moderna)', 'VE': 0.645},
|
||||
{'primary series vaccine': 'BNT162b2_(Pfizer)_(3_doses)', 'booster vaccine': 'BNT162b2_(Pfizer)_(4th_dose)', 'VE': 0.962},
|
||||
{'primary series vaccine': 'CoronaVac_(Sinovac)', 'booster vaccine': 'AZD1222_(AstraZeneca)', 'VE': 0.9405},
|
||||
{'primary series vaccine': 'CoronaVac_(Sinovac)', 'booster vaccine': 'BNT162b2_(Pfizer)', 'VE': 0.690563},
|
||||
{'primary series vaccine': 'CoronaVac_(Sinovac)', 'booster vaccine': 'CoronaVac_(Sinovac)', 'VE': 0.52225},
|
||||
{'primary series vaccine': 'mRNA-1273_(Moderna)', 'booster vaccine': 'BNT162b2_(Pfizer)', 'VE': 0.842143},
|
||||
{'primary series vaccine': 'mRNA-1273_(Moderna)', 'booster vaccine': 'BNT162b2_(Pfizer)_or_mRNA-1273_(Moderna)', 'VE': 0.632633},
|
||||
{'primary series vaccine': 'mRNA-1273_(Moderna)', 'booster vaccine': 'mRNA-1273_(Moderna)', 'VE': 0.633238}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2aef0605c3668b4884b815f71c0eae93eaaa7b88d6b6c17ff97f6a86a38674a5
|
||||
size 76179581
|
||||
56
caimira/scripts/data/vaccine_effectiveness.py
Normal file
56
caimira/scripts/data/vaccine_effectiveness.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import pandas as pd
|
||||
from tabulate import tabulate
|
||||
|
||||
'''
|
||||
Script file to generate the vaccine effectiveness values.
|
||||
To generate the primary vaccine effectiveness values, uncoment lines 16-21.
|
||||
To generate the booster effectiveness values, uncoment lines 26-56.
|
||||
'''
|
||||
|
||||
# Data from 08 Sep. 2022
|
||||
file_loc = "./WeeklySummary_COVID19_VE_Studies_08Sep2022_adapted.xlsx"
|
||||
|
||||
|
||||
# ------- PRIMARY VACCINATION ------ #
|
||||
|
||||
# df = pd.read_excel(file_loc, sheet_name="Primary_filtered", usecols="A, B, E")
|
||||
|
||||
# calculate the VE value
|
||||
# df = df.drop(df[df['VE'] < 0].index)
|
||||
# ve_data = df.groupby(['vaccine'])['VE'].mean().divide(100).reset_index()
|
||||
# print(tabulate(ve_data, headers='keys', tablefmt='psql'))
|
||||
|
||||
|
||||
# ------- BOOSTER VACCINATION ------ #
|
||||
|
||||
# df = pd.read_excel(file_loc, sheet_name="Booster_filtered", usecols="A, B, C, F")
|
||||
|
||||
# # create df without the ' or ' substring in primary vaccines
|
||||
# rows_with_or = df[df['primary series vaccine'].str.contains(' or ')]
|
||||
# rows_indexes = list(rows_with_or.index)
|
||||
# df_without_or = df.drop(labels=rows_indexes, axis=0)
|
||||
|
||||
# # copy of all the rows that contain ' or '
|
||||
# new_rows_with_or = rows_with_or.reset_index().copy()
|
||||
|
||||
# # create new dataframe empty
|
||||
# rows_to_add = pd.DataFrame(columns=rows_with_or.columns)
|
||||
|
||||
# # duplicate each row and add it into the new dataframe
|
||||
# for index, row in new_rows_with_or.iterrows():
|
||||
# new_rows_with_or.at[index, 'primary series vaccine'] = row['primary series vaccine'].split(' or ')[0]
|
||||
# rows_to_add.loc[index] = new_rows_with_or.loc[index]
|
||||
# new_rows_with_or.at[index, 'primary series vaccine'] = row['primary series vaccine'].split(' or ')[1]
|
||||
# rows_to_add.loc[len(rows_indexes)+index] = new_rows_with_or.loc[index]
|
||||
|
||||
# # merge the dataframe without the ' or ' with the new dataframe that has the rows divided in two
|
||||
# final_df = pd.concat([df_without_or, rows_to_add]).reset_index().drop(columns=['index'])
|
||||
|
||||
# # calculate the VE value
|
||||
# final_df = final_df.drop(final_df[final_df['VE'] < 0].index)
|
||||
|
||||
# ve_data = final_df.groupby(['primary series vaccine', 'booster vaccine'])['VE'].mean().divide(100).reset_index()
|
||||
|
||||
# result = ve_data.to_dict('records')
|
||||
|
||||
# print(tabulate(ve_data, headers='keys', tablefmt='psql'))
|
||||
|
|
@ -297,13 +297,13 @@ def test_prob_meet_infected_person(pop, cases, AB, exposed, infected, prob_meet_
|
|||
[30, known_concentrations(lambda t: 1.2),
|
||||
100000, 68, 5, 55.93154502],
|
||||
])
|
||||
def test_probabilistic_exposure_probability(exposed_population, cm,
|
||||
def test_probabilistic_exposure_probability(sr_model, exposed_population, cm,
|
||||
pop, AB, cases, probabilistic_exposure_probability):
|
||||
|
||||
population = models.Population(
|
||||
exposed_population, models.PeriodicInterval(120, 60), models.Mask.types['Type I'],
|
||||
models.Activity.types['Standing'], host_immunity=0.,)
|
||||
model = ExposureModel(cm, (), population, models.Cases(geographic_population=pop,
|
||||
model = ExposureModel(cm, sr_model, population, models.Cases(geographic_population=pop,
|
||||
geographic_cases=cases, ascertainment_bias=AB),)
|
||||
np.testing.assert_allclose(
|
||||
model.total_probability_rule(), probabilistic_exposure_probability, rtol=0.05
|
||||
|
|
@ -390,4 +390,25 @@ def test_diameter_vectorisation_room(diameter_dependent_model, sr_model, cases_m
|
|||
ventilation = models.HVACMechanical(active=models.SpecificInterval(((0., 24.), )), q_air_mech=100.))
|
||||
with pytest.raises(ValueError, match=error_message):
|
||||
models.ExposureModel(concentration, sr_model, populations[0], cases_model)
|
||||
|
||||
|
||||
|
||||
@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.])],
|
||||
]
|
||||
)
|
||||
def test_host_immunity_vectorisation(sr_model, cases_model, cm, host_immunity, expected_probability):
|
||||
population = models.Population(
|
||||
10, halftime, models.Mask(np.array([0.3, 0.35])),
|
||||
models.Activity.types['Standing'], host_immunity=host_immunity
|
||||
)
|
||||
model = ExposureModel(cm, sr_model, population, cases_model)
|
||||
inf_probability = model.infection_probability()
|
||||
|
||||
np.testing.assert_almost_equal(
|
||||
inf_probability, expected_probability, decimal=1
|
||||
)
|
||||
assert isinstance(inf_probability, np.ndarray)
|
||||
assert inf_probability.shape == (2, )
|
||||
|
|
|
|||
|
|
@ -29,3 +29,5 @@ ignore_missing_imports = True
|
|||
[mypy-timezonefinder.*]
|
||||
ignore_missing_imports = True
|
||||
|
||||
[mypy-pandas.*]
|
||||
ignore_missing_imports = True
|
||||
|
|
|
|||
Loading…
Reference in a new issue