Esempio n. 1
0
    def healthcare(self, region: covid.Region):
        """
        Return a dictionary with hospital and icu capacities from user input.

        Returns:
            icu_capacity, hospital_capacity (float): maximum system capacity
        """
        st.sidebar.header(_("Hospital capacity"))

        def get(msg, capacity, rate, key=None):
            st.sidebar.subheader(msg)
            msg = _(
                "Location has {n} beds, but only {rate} are typically available in a given day."
            )
            st.sidebar.markdown(msg.format(n=fmt(int(capacity)), rate=pc(1 - rate)))
            total = st.sidebar.number_input(
                _("Beds dedicated exclusively to COVID-19"),
                min_value=0,
                value=int((1 - rate) * capacity),
                key=key + "_total",
            )
            return (1 - rate) * total

        h_total = region.hospital_total_capacity
        h_rate = max(region.hospital_occupancy_rate, 0.75)
        c_total = region.icu_total_capacity
        c_rate = max(region.icu_occupancy_rate, 0.75)
        return {
            "hospital_capacity": get(_("Clinical beds"), h_total, h_rate, key="hospital"),
            "icu_capacity": get(_("ICU beds"), c_total, c_rate, key="icu"),
        }
Esempio n. 2
0
    def write_population_info(self, model: SEICHAR):
        """Write additional information about the model."""

        # Demography
        st.subheader(_("Population"))
        seniors = model.demography.loc["60-69":].sum()
        total = model.population
        entries = {_("Total"): fmt(total), _("Age 60+"): f"{fmt(seniors)} ({pc(seniors / total)})"}
        cards(entries)
Esempio n. 3
0
 def write_fatalities_chart(self, model):
     st.subheader(" ")
     st.subheader(_("Anticipated age distribution of COVID deaths"))
     data = model.data.loc[model.time, "fatalities"]
     data = pd.DataFrame(
         {
             "fatalities": data.astype(int),
             "pc": (1e5 * data.values / model.demography.values).astype(int),
         }
     )
     data.columns = ["left", "right"]
     double_bar_chart(data, _("Total deaths"), _("Mortality per 100k"))
Esempio n. 4
0
 def get(msg, capacity, rate, key=None):
     st.sidebar.subheader(msg)
     msg = _(
         "Location has {n} beds, but only {rate} are typically available in a given day."
     )
     st.sidebar.markdown(msg.format(n=fmt(int(capacity)), rate=pc(1 - rate)))
     total = st.sidebar.number_input(
         _("Beds dedicated exclusively to COVID-19"),
         min_value=0,
         value=int((1 - rate) * capacity),
         key=key + "_total",
     )
     return (1 - rate) * total
Esempio n. 5
0
 def run(self):
     """
     Run streamlit app.
     """
     components.icon(_("COVID-19"),
                     _("Epidemic Calculator"),
                     where=st.sidebar)
     with self.info(_("Loading region...")):
         region = self.input.region()
         self.input.pause()
         self._title = f"{self.title} - {region}"
     with self.info(_("Loading simulation parameters...")):
         kwargs = {"region": region, **self.input.params(region)}
     with self.info(_("Performing simulation...")):
         self.run_simulation(**kwargs)
Esempio n. 6
0
    def write_protection_equipment_demand(self, model):
        st.markdown("---")
        st.subheader(_("Protection equipment"))
        df = model.health_resources(translate=_)

        df[df.columns[1]] = df[df.columns[1]].apply(fmt)
        st.table(df)
Esempio n. 7
0
    def write_footnotes(self, *args):
        """Write footnotes"""

        template = '<a href="{href}">{name}</a>'
        institutions = [
            template.format(href=_("https://www.paho.org/hq/index.php?lang=en"), name=_("PAHO")),
            template.format(href="https://saude.gov.br/", name="MS/SVS"),
            template.format(href="https://lappis.rocks", name="UnB/LAPPIS"),
            template.format(href="http://medicinatropical.unb.br/", name="UnB/NMT"),
            template.format(href="http://fce.unb.br/", name="UnB/FCE"),
            template.format(href="http://www.butantan.gov.br/", name="Butantã"),
            template.format(href="http://www.matogrossodosul.fiocruz.br/", name="Fiocruz"),
            template.format(href="https://famed.ufms.br/", name="FAMED"),
        ]
        links = _("Support: {institutions}").format(institutions=", ".join(institutions))
        styles = "text-align: center; margin: 5rem 0 -5rem 0;"
        html(f'<div style="{styles}">{links}</div>')
Esempio n. 8
0
    def write_healthcare_parameters(self, model):
        st.markdown("---")
        st.subheader(_("Healthcare system"))

        r = model.region
        md_description(
            {
                _("COVID ICUs"): fmt(int(model.icu_capacity)),
                _("COVID hospital beds"): fmt(int(model.hospital_capacity)),
                _("ICUs"): _("{n} (source: CNES)").format(n=fmt(r.icu_total_capacity)),
                _("Hospital beds"): _("{n} (source: CNES)").format(
                    n=fmt(r.hospital_total_capacity)
                ),
            }
        )

        if model.region.icu_total_capacity == 0:
            msg = _(
                """
The location does not have any ICU beds. At peak demand, it needs to reserve {n}
beds from neighboring cities.
"""
            )
            msg = msg.format(n=fmt(model.peak_icu_demand))
        elif model.icu_overflow_date:
            msg = _(
                """
The location will **run out of ICU beds at {date}**. At peak demand, it will need **{n}
new ICUs**. This demand corresponds to **{surge} times** the number of beds dedicated
to COVID-19 and {total} of the total number of ICU beds.
"""
            )
            msg = msg.format(
                date=naturaldate(model.icu_overflow_date),
                n=fmt(int(model.peak_icu_demand - model.icu_capacity)),
                surge=fmt(model.peak_icu_demand / model.icu_capacity),
                total=fmt(model.peak_icu_demand / model.icu_total_capacity),
            )
        else:
            msg = _(
                """
The number of ICU beds is sufficient for the expected demand in this scenario.
"""
            )

        st.markdown(msg)
Esempio n. 9
0
    def hospitalizations_chart(self, model):
        """
        Write plot of hospitalization
        """
        st.subheader(_("Hospital demand"))

        hospitalized = model["hospitalized:total"]
        icu = model["critical:total"]
        fatalities = fatality_rate(model["fatalities:total"], model.dt)
        columns = {
            _("Deaths/day"): fatalities,
            _("Required hospital beds"): hospitalized.astype(int),
            _("Required ICU beds"): icu.astype(int),
        }
        df = model.get_dates(pd.DataFrame(columns))

        st.area_chart(df)
Esempio n. 10
0
    def intervention(self, region: covid.Region):
        """
        Return a dictionary with intervention parameters.

        Returns:
            icu_capacity, hospital_capacity (float): maximum system capacity
        """

        st.sidebar.header(_("Intervention"))
        baseline, social_distance = interventions = [_("None"), _("Social distancing")]
        intervention = st.sidebar.selectbox(_("Scenario"), interventions)
        if intervention == baseline:
            return {}
        elif intervention == social_distance:
            st.sidebar.markdown(
                _(
                    """
This intervention simulates a situation in which everyone reduces
the average number of encounters throughout the day. Small reductions (~15%) are
possible through small behavioral changes. Larger reductions require implementation
of many non-pharmacological measures.
"""
                )
            )
            week = TODAY + datetime.timedelta(days=7)
            date = st.sidebar.date_input(_("Date of intervention"), value=week)
            rate = st.sidebar.slider(_("Reduction in the number of contacts"), value=15)
            return {"intervention": social_distance_intervention(date, 1 - rate / 100)}
Esempio n. 11
0
    def simulation(self, region: covid.Region):
        """
        Return a dictionary with basic simulation parameters from user input.

        Returns:
              period (int): Simulation period in days.
              start_date (date): Initial date.
              seed (int): Initial number of cases.
        """
        st.sidebar.header(_("Simulation options"))
        seed = int(max(5e-6 * region.population_size, 1))
        return {
            "period": st.sidebar.slider(_("Duration (weeks)"), 1, 30, value=10) * 7,
            "start_date": st.sidebar.date_input(_("Simulation date")),
            "seed": st.sidebar.number_input(
                _("Number of detected cases"), 1, int(region.population_size), value=seed
            ),
        }
Esempio n. 12
0
    def write_epidemiological_parameters(self, model):
        st.markdown("---")
        st.subheader(_("Advanced epidemiological information"))

        mortality = fmt(1e5 * model.fatalities / model.population)
        fatality = pc(model.CFR())
        infected = pc(model.total_exposed / model.population)
        symptomatic = pc(model.prob_symptomatic)

        md_description(
            {
                _("Number of cases generated by a single case"): fmt(model.R0_average),
                _("Mortality (deaths per 100k population)"): mortality,
                _("Letality ({pc} of deaths among the ill)").format(pc="%"): fatality,
            }
        )
        lang = os.environ.get("LANGUAGE", "en_US")
        footnote_disclaimer(**locals())
Esempio n. 13
0
    def available_beds_chart(self, model):
        """
        Write plot of available beds.
        """
        st.subheader(_("Available hospital beds"))

        hospitalized = model["hospitalized:total"]
        icu = model["critical:total"]

        available_beds = model.hospital_capacity - hospitalized
        available_beds[available_beds < 0] = 0

        available_icu = model.icu_capacity - icu
        available_icu[available_icu < 0] = 0

        columns = {_("Regular"): available_beds, _("ICU"): available_icu}
        df = model.get_dates(pd.DataFrame(columns))

        st.line_chart(df)
Esempio n. 14
0
    def summary_cards(self, model: SEICHAR):
        """
        Show list of summary cards for the results of simulation.
        """

        # Which one?
        df = model.data["infectious"] * model.gamma_i * model.prob_hospitalization
        hospitalized = df.apply(model.integral).sum()

        h_date = model.hospital_overflow_date
        c_date = model.icu_overflow_date
        missing_icu = max(int(model.peak_icu_demand - model.icu_capacity), 0)
        missing_hospital = max(int(model.peak_hospitalization_demand - model.hospital_capacity), 0)
        fatalities_pc = pc(model.fatalities / model.initial_population)
        hospitalized_pc = pc(hospitalized / model.initial_population)

        entries = {
            _("Deaths"): f"{fmt(int(model.fatalities))} ({fatalities_pc})",
            _("Hospitalizations"): f"{fmt(int(hospitalized))} ({hospitalized_pc})",
            _("Required extra ICU beds"): f"{fmt(missing_icu)}",
            _("Required extra hospital beds"): f"{fmt(missing_hospital)}",
            _("No more ICU beds available by"): f"{naturaldate(c_date)}",
            _("No more hospital beds available by"): f"{naturaldate(h_date)}",
        }
        cards(entries)
Esempio n. 15
0
    def fn(model):
        if date < model.start_date:
            st.warning(_("Intervention starts prior to simulation"))
            model.R0 *= rate
            return model
        else:
            delta = date - model.start_date
            R0_initial = model.R0
            R0_final = model.R0 * rate
            t_intervention = delta.days

            def Rt(t):
                return R0_initial if t < t_intervention else R0_final

            model.R0 = Rt
            return model
Esempio n. 16
0
    def region(self):
        """
        Return a region instance from user input.
        """

        # Select a state
        st.sidebar.header(_("Location"))
        df = states(self.country)
        choices = [self.display_country, *df["name"]]
        choice = st.sidebar.selectbox(_("State"), choices)
        if choice == choices[0]:
            return get_region(self.country)
        state_id = state_code(self.country, choice)

        # State selected, now ask for sub-region
        df = sub_regions(self.country, state_id)
        if len(df) == 1:
            choice = df["name"].iloc[0]
        else:
            choices = [_("All"), *df["name"]]
            choice = st.sidebar.selectbox(_("Region"), choices)
            if choice == choices[0]:
                return get_region(f"{self.country}/{state_id}")
        sub_region_id = sub_region_code(self.country, state_id, choice)

        # Sub-region selected, now ask for a city
        df = cities(self.country, sub_region_id)
        if len(df) == 1:
            choice = df["name"].iloc[0]
        else:
            choices = [_("All"), *df["name"]]
            choice = st.sidebar.selectbox(_("City"), choices)
            if choice == choices[0]:
                return get_region(f"{self.country}/{sub_region_id}")
        city_id = df[df["name"] == choice].index[0]
        return get_region(f"{self.country}/{city_id}")
Esempio n. 17
0
    cities = countries.cities(country.lower())
    return cities[cities["sub_region"] == sub_region]


@st.cache
def state_code(country, state):
    names = states(country)["name"]
    return names[names == state].index[0]


@st.cache
def sub_region_code(country, state_code, sub_region):
    regions = sub_regions(country, state_code)
    return regions[regions["name"] == sub_region].index[0]


@st.cache(allow_output_mutation=True)
def get_region(ref):
    region = covid.region(ref)
    if ref.lower().startswith("brazil/"):
        region.demography = DEMOGRAPHY_CORRECTION
    return region


if __name__ == "__main__":
    from pprint import pformat

    app = Input("brazil", _("Brazil"), st.sidebar)
    res = app.run()
    st.text(pformat(res))
Esempio n. 18
0
class CalcUI:
    """
    Renders Streamlit UI.
    """

    simulation_class = SEICHAR
    title = _("COVID-19 Hospital Pressure")

    def __init__(self, country=COUNTRY, display_country=DISPLAY_COUNTRY):
        st.write(asset("custom.html"), unsafe_allow_html=True)
        self._title = st.title(self.title)
        self._info = st.text("")
        self.country = country
        self.input = Input(self.country, display_country=DISPLAY_COUNTRY)

    @contextmanager
    def info(self, st):
        """
        Context manager that displays info text while code inside the with
        block is being executed and clear it afterwards.
        """
        self._info.text(st)
        yield
        self._info.text("")

    def run(self):
        """
        Run streamlit app.
        """
        components.icon(_("COVID-19"),
                        _("Epidemic Calculator"),
                        where=st.sidebar)
        with self.info(_("Loading region...")):
            region = self.input.region()
            self.input.pause()
            self._title = f"{self.title} - {region}"
        with self.info(_("Loading simulation parameters...")):
            kwargs = {"region": region, **self.input.params(region)}
        with self.info(_("Performing simulation...")):
            self.run_simulation(**kwargs)

    def run_simulation(
        self,
        period,
        hospital_capacity,
        icu_capacity,
        hospitalization_bias=2.0,
        intervention=None,
        **kwargs,
    ):
        """
        Initialize class with given arguments and run simulation.
        """
        kwargs = {
            "prob_symptomatic": 0.14,
            "hospital_prioritization": 0.0,
            **kwargs
        }
        model = self.simulation_class(**kwargs)

        # FIXME: should be able to setup on the constructor
        model.hospital_capacity = hospital_capacity
        model.icu_capacity = icu_capacity
        model.prob_hospitalization *= hospitalization_bias
        if intervention:
            model = intervention(model)
        model.run(period)

        out = Output(model)
        out.run()
Esempio n. 19
0
from contextlib import contextmanager

import streamlit as st

import covid
from covid import gettext as _
from covid.models import SEICHARDemographic as SEICHAR
from covid.ui import components
from covid.ui.components import asset
from covid.ui.input import Input
from covid.ui.output import Output

COUNTRY = "Brazil"
DISPLAY_COUNTRY = _("Brazil")

SEIR_HUMANIZED_NAMES = {
    "susceptible": _("susceptible"),
    "exposed": _("exposed"),
    "infectious": _("infectious"),
    "critical": _("critical"),
    "hospitalized": _("hospitalized"),
    "asymptomatic": _("asymptomatic"),
    "recovered": _("recovered"),
    "fatalities": _("fatalities"),
}
e = 1e-50


class CalcUI:
    """
    Renders Streamlit UI.
Esempio n. 20
0
from babel.dates import format_date

import covid
from covid import gettext as _
from covid.models import SEICHARDemographic as SEICHAR
from covid.ui.components import (
    cards,
    md_description,
    asset,
    double_bar_chart,
    html,
    footnote_disclaimer,
)
from covid.utils import fmt, pc

naturaldate = lambda d: format_date(d, format="short") if d else _("Not soon...")


class Output:
    def __init__(self, model):
        self.model = model

    def run(self):
        """
        Show all outputs for the given simulated model.
        """
        model = self.model
        self.summary_cards(model)
        self.hospitalizations_chart(model)
        self.available_beds_chart(model)
        self.write_population_info(model)
Esempio n. 21
0
 def write_age_distribution_chart(self, model):
     st.subheader(" ")
     st.subheader(_("Population pyramid"))
     data = model.region.detailed_demography
     data.columns = ["left", "right"]
     double_bar_chart(data, _("Female"), _("Male"))
Esempio n. 22
0
    def epidemiology(self, region: covid.Region):
        """
        Return a dictionary with additional simulation parameters from user input.
        Those parameters are related to basic epidemiology assumptions such as
        the value of R0, incubation period, etc.
        """

        e = 1e-50
        st.sidebar.header(_("Epidemiology"))
        std, fast, slow, custom = scenarios = [_("Standard"), _("Fast"), _("Slow"), _("Advanced")]
        scenario = st.sidebar.selectbox(_("Scenario"), scenarios)

        if scenario == std:
            return {"R0": 2.74}
        if scenario == fast:
            return {"R0": 3.5}
        elif scenario == slow:
            return {"R0": 2.0}

        # Custom
        st.sidebar.subheader(_("Epidemiological parameters"))
        R0 = SEICHAR.R0
        msg = _("Newly infected people for each infection (R0)")
        R0 = st.sidebar.slider(msg, min_value=0.0, max_value=5.0, value=R0)

        incubation_period = 1 / SEICHAR.sigma
        msg = _("Virus incubation period")
        incubation_period = st.sidebar.slider(
            msg, min_value=1.0, max_value=10.0, value=incubation_period
        )

        infectious_period = 1 / SEICHAR.gamma_i
        msg = _("Infectious period")
        infectious_period = st.sidebar.slider(
            msg, min_value=1.0, max_value=14.0, value=infectious_period
        )

        prob_symptomatic = 100 * SEICHAR.prob_symptomatic
        msg = _("Fraction of symptomatic cases")
        prob_symptomatic = 0.01 * st.sidebar.slider(
            msg, min_value=0.0, max_value=100.0, value=prob_symptomatic
        )

        st.sidebar.subheader(_("Clinical parameters"))
        prob_hospitalization = 200 * region.prob_hospitalization
        prob_hospitalization = st.sidebar.slider(
            _("Fraction of hospitalized cases"),
            min_value=0.0,
            max_value=100.0,
            value=prob_hospitalization,
        )
        hospitalization_bias = prob_hospitalization / (100 * region.prob_hospitalization)

        hospitalization_period = 1 / SEICHAR.gamma_h
        msg = _("Hospitalization period (days)")
        hospitalization_period = st.sidebar.slider(
            msg, min_value=0.0, max_value=30.0, value=hospitalization_period
        )

        icu_period = 1 / SEICHAR.gamma_c
        msg = _("Hospitalization period for ICU patients (days)")
        icu_period = st.sidebar.slider(msg, min_value=0.0, max_value=30.0, value=icu_period)

        return {
            "R0": R0,
            "sigma": 1.0 / (incubation_period + e),
            "gamma_i": 1.0 / (infectious_period + e),
            "gamma_h": 1.0 / (hospitalization_period + e),
            "gamma_c": 1.0 / (icu_period + e),
            "prob_symptomatic": prob_symptomatic,
            "hospitalization_bias": hospitalization_bias,
        }