def task_plot_combined_rapid_test_demand_params(depends_on, func, produces): params = pd.read_pickle(depends_on["params"]) params = func(params) with warnings.catch_warnings(): warnings.filterwarnings( "ignore", message="indexing past lexsort depth may impact performance.") educ_workers_params = params.loc[("rapid_test_demand", "educ_worker_shares")] students_params = params.loc[("rapid_test_demand", "student_shares")] work_offer_params = params.loc[("rapid_test_demand", "share_workers_receiving_offer")] private_demand_params = params.loc[("rapid_test_demand", "private_demand")] work_accept_params = params.loc[("rapid_test_demand", "share_accepting_work_offer")] # educ demand share_educ_workers = get_piecewise_linear_interpolation( educ_workers_params) share_educ_workers = share_educ_workers.loc[PLOT_START_DATE:PLOT_END_DATE] share_students = get_piecewise_linear_interpolation(students_params) share_students = share_students.loc[PLOT_START_DATE:PLOT_END_DATE] # worker demand share_workers_receiving_offer = get_piecewise_linear_interpolation( work_offer_params) share_workers_receiving_offer = share_workers_receiving_offer.loc[ PLOT_START_DATE:PLOT_END_DATE] share_workers_accepting_offer = get_piecewise_linear_interpolation( work_accept_params) share_workers = share_workers_receiving_offer * share_workers_accepting_offer # private demand private_demand_shares = get_piecewise_linear_interpolation( private_demand_params) private_demand_shares = private_demand_shares.loc[ PLOT_START_DATE:PLOT_END_DATE] fig = _plot_rapid_test_demand_shares( share_educ_workers=share_educ_workers, share_students=share_students, share_workers=share_workers, private_demand_shares=private_demand_shares, ) fig.savefig(produces["figure"]) plt.close() if "data" in produces.keys(): df = pd.DataFrame({ "share_educ_workers": share_educ_workers, "share_students": share_students, "share_workers": share_workers, "private_demand_shares": private_demand_shares, }) df.round(3).to_csv(produces["data"])
def _check_no_work_rapid_tests(new_params): accept_params = new_params.loc[ ("rapid_test_demand", "share_accepting_work_offer"), "value" ] accept_time_series = get_piecewise_linear_interpolation(params_slice=accept_params) assert (accept_time_series == 0).all() offer_params = new_params.loc[ ("rapid_test_demand", "share_workers_receiving_offer"), "value" ] offer_time_series = get_piecewise_linear_interpolation(params_slice=offer_params) assert (offer_time_series == 0).all()
def _check_school_demand_is_zero(new_params): teacher_params = new_params.loc[ ("rapid_test_demand", "educ_worker_shares"), "value" ] teacher_time_series = get_piecewise_linear_interpolation( params_slice=teacher_params ) assert (teacher_time_series == 0).all() student_params = new_params.loc[("rapid_test_demand", "student_shares"), "value"] student_time_series = get_piecewise_linear_interpolation( params_slice=student_params ) assert (student_time_series == 0).all()
def test_mandatory_work_rapid_tests_after_easter(params): new_params = params_scenarios.mandatory_work_rapid_tests_after_easter(params) accept_params = new_params.loc[ ("rapid_test_demand", "share_accepting_work_offer"), "value" ] accept_time_series = get_piecewise_linear_interpolation(params_slice=accept_params) assert (accept_time_series[:"2021-04-05"] < 0.95).all() assert (accept_time_series["2021-04-06":] == 0.95).all() offer_params = new_params.loc[ ("rapid_test_demand", "share_workers_receiving_offer"), "value" ] offer_time_series = get_piecewise_linear_interpolation(params_slice=offer_params) assert (offer_time_series[:"2021-04-05"] < 0.95).all() assert (offer_time_series["2021-04-06":] == 0.95).all()
def task_plot_share_of_workers_receiving_test_offer(depends_on, produces): params = pd.read_pickle(depends_on["params"]) with warnings.catch_warnings(): warnings.filterwarnings( "ignore", message="indexing past lexsort depth may impact performance." ) params_slice = params.loc[ ("rapid_test_demand", "share_workers_receiving_offer") ] share_workers_receiving_offer = get_piecewise_linear_interpolation(params_slice) share_workers_receiving_offer = share_workers_receiving_offer.loc[ PLOT_START_DATE:PLOT_END_DATE ] fig, ax = plt.subplots(figsize=PLOT_SIZE) sns.lineplot( x=share_workers_receiving_offer.index, y=share_workers_receiving_offer, ax=ax, ) ax.set_title("Share Workers With Work Contacts With Rapid Test Offer At Work") fig, ax = style_plot(fig, ax) fig.tight_layout() fig.savefig(produces) plt.close()
def task_plot_private_test_demand_shares(depends_on, produces): params = pd.read_pickle(depends_on["params"]) with warnings.catch_warnings(): warnings.filterwarnings( "ignore", message="indexing past lexsort depth may impact performance.") params_slice = params.loc[("rapid_test_demand", "private_demand")] private_demand_shares = get_piecewise_linear_interpolation(params_slice) private_demand_shares = private_demand_shares.loc[ PLOT_START_DATE:PLOT_END_DATE] fig, ax = plt.subplots(figsize=PLOT_SIZE) sns.lineplot( x=private_demand_shares.index, y=private_demand_shares, ax=ax, ) ax.set_title( "Private Rapid Test Demand\n" "(Share of Individuals who Do a Rapid Test \n" "When a Household Member Tests Positive Or Becomes Symptomatic Or \n" "When Developing Symptoms but not Receiving a Rapid Test Or \n" "When Participating in Some Private Events)") fig, ax = style_plot(fig, ax) fig.tight_layout() fig.savefig(produces) plt.close()
def test_no_rapid_tests_at_schools_and_private(params): new_params = params_scenarios.no_rapid_tests_at_schools_and_private(params) _check_school_demand_is_zero(new_params) private_slice = new_params.loc[("rapid_test_demand", "private_demand"), "value"] private_series = get_piecewise_linear_interpolation(params_slice=private_slice) assert (private_series == 0).all()
def test_keep_work_offer_share_at_23_pct_after_easter(params): new_params = params_scenarios.keep_work_offer_share_at_23_pct_after_easter(params) offer_params = new_params.loc[ ("rapid_test_demand", "share_workers_receiving_offer"), "value" ] time_series = get_piecewise_linear_interpolation(params_slice=offer_params) assert time_series["2021-04-06"] == 0.23 assert (time_series["2021-04-06":] == 0.23).all()
def task_plot_overall_share_known_cases(depends_on, produces): df_old = pd.read_csv(depends_on["old"]) old_share_known = _calculate_share_known_cases( df_old)[PLOT_START_DATE:"2020-12-24"] df_new = pd.read_csv(depends_on["new"]) new_share_known = _calculate_share_known_cases(df_new)["2020-12-25":] share_known = pd.concat([old_share_known, new_share_known]) share_known.index = share_known.index.normalize() assert not share_known.index.duplicated().any() dates = share_known.index expected_dates = pd.date_range(dates.min(), dates.max()) missing_dates = [str(x.date()) for x in expected_dates if x not in dates] assert (len(missing_dates) == 0 ), f"There are missing dates in the share_known: {missing_dates}" share_known = share_known.loc[PLOT_START_DATE:"2020-12-28"] params = pd.read_pickle(depends_on["params"]) with warnings.catch_warnings(): warnings.filterwarnings( "ignore", message="indexing past lexsort depth may impact performance.") params_slice = params.loc[("share_known_cases", "share_known_cases")] share_known_from_params = get_piecewise_linear_interpolation(params_slice) share_known_from_params = share_known_from_params.loc[ PLOT_START_DATE:PLOT_END_DATE] fig, ax = plt.subplots(figsize=PLOT_SIZE) sns.lineplot( x=share_known.index, y=share_known, ax=ax, label="Dunkelzifferradar", alpha=0.6, linewidth=3.0, color=BLUE, ) sns.lineplot( x=share_known_from_params.index, y=share_known_from_params, ax=ax, label="Interpolated and Extrapolated", alpha=0.6, linewidth=3.0, color=RED, ) fig, ax = style_plot(fig, ax) ax.set_ylabel("share of cases that are detected") fig.tight_layout() ax.axvline(pd.Timestamp("2020-12-24"), alpha=0.6, color="k") fig.savefig(produces["share_known_cases_fig"]) plt.close()
def task_plot_share_of_educ_participants_with_rapid_test(depends_on, produces): params = pd.read_pickle(depends_on["params"]) with warnings.catch_warnings(): warnings.filterwarnings( "ignore", message="indexing past lexsort depth may impact performance.") educ_workers_params = params.loc[("rapid_test_demand", "educ_worker_shares")] students_params = params.loc[("rapid_test_demand", "student_shares")] share_educ_workers = get_piecewise_linear_interpolation( educ_workers_params) share_educ_workers = share_educ_workers.loc[PLOT_START_DATE:PLOT_END_DATE] share_students = get_piecewise_linear_interpolation(students_params) share_students = share_students.loc[PLOT_START_DATE:PLOT_END_DATE] fig, ax = plt.subplots(figsize=PLOT_SIZE) sns.lineplot( x=share_educ_workers.index, y=share_educ_workers, ax=ax, label="Teachers (School, Preschool, Nursery)", ) sns.lineplot( x=share_students.index, y=share_students, ax=ax, label="School Students", ) ax.set_title("Share of Students and Teachers Receiving Rapid Tests") fig, ax = style_plot(fig, ax) fig.tight_layout() fig.savefig(produces) plt.close()
def test_start_all_rapid_tests_after_easter(params): new_params = params_scenarios.start_all_rapid_tests_after_easter(params) slice_tuples = [ ("rapid_test_demand", "private_demand"), ("rapid_test_demand", "educ_worker_shares"), ("rapid_test_demand", "student_shares"), ("rapid_test_demand", "share_accepting_work_offer"), ("rapid_test_demand", "share_workers_receiving_offer"), ] for loc in slice_tuples: params_slice = new_params.loc[loc, "value"] time_series = get_piecewise_linear_interpolation(params_slice=params_slice) assert (time_series[:"2021-04-05"] == 0).all() assert (time_series["2021-04-06":] > 0).all()
def _build_new_date_params(before_params_slice, change_date, new_val): before = get_piecewise_linear_interpolation(before_params_slice) day_before = change_date - pd.Timedelta(days=1) if day_before in before: val_before_change = before.loc[day_before] else: val_before_change = before.iloc[-1] new_params_slice = before_params_slice.copy(deep=True) new_params_slice.index = pd.DatetimeIndex(new_params_slice.index) # remove old change points after change date new_params_slice = new_params_slice[:day_before] # implement the switch on the change date new_params_slice.loc[day_before] = val_before_change new_params_slice.loc[change_date] = new_val # maintain the new value over time new_params_slice.loc[pd.Timestamp("2025-12-31")] = new_val new_params_slice = new_params_slice.sort_index() return new_params_slice
def test_no_private_test_demand(params): new_params = params_scenarios.no_private_rapid_test_demand(params) comparison = create_comparison_df(new_params=new_params, old_params=params) loc = ("rapid_test_demand", "private_demand") private_demand_params = params.loc[loc, "value"] should_have_changed = private_demand_params[private_demand_params != 0] expected = pd.DataFrame() expected["before"] = should_have_changed expected["name"] = should_have_changed.index expected["after"] = 0.0 expected["category"] = "rapid_test_demand" expected["subcategory"] = "private_demand" expected = expected.set_index(["category", "subcategory", "name"]) assert comparison.equals(expected) private_series = get_piecewise_linear_interpolation( params_slice=new_params.loc[loc, "value"] ) assert (private_series == 0).all()
def load_simulation_inputs( scenario, start_date, end_date, debug, group_share_known_case_path=None, period_outputs=False, return_last_states=False, initial_states_path=None, is_resumed=False, rapid_test_statistics_path=None, ): """Load the simulation inputs. Does **not** include: params, path, seed. Args: scenario (str): string specifying the scenario. A function with the same name must exist in src.simulation.scenario_simulation_inputs. start_date (str): date on which the simulation starts. Data must be available for at least a month before the start date for the burn in period. end_date (str): date on which the simulation ends. debug (bool): Whether to use the debug or the full initial states. group_share_known_case_path (pathlib.Path, str or None): if not None, the group share known cases are loaded from this path and used for the creation of the initial conditions. period_outputs (bool, optional): whether to use period_outputs instead of saving the time series. Default is False. return_last_states (bool, optional): if True, the last states are returned as part of the simulation result. initial_states_path (pathlib.Path, optional): Path to the initial states. If not given the standard initial states are used. is_resumed (bool, optional): if True, the initial_states_path must be given. In that case no initial conditions are created rapid_test_statistics_path (Path, optional): where to save rapid test statistics. Returns: dict: Dictionary with most arguments of get_simulate_func. Keys are: - initial_states - contact_models - duration - events - saved_columns - virus_strains - derived_state_variables - seasonality_factor_model - initial_conditions - susceptibility_factor_model - testing_demand_models - testing_allocation_models - testing_processing_models - period_outputs - return_last_states - return_time_series - contact_policies - vaccination_models - rapid_test_models - rapid_test_reaction_models """ if is_resumed: assert ( initial_states_path is not None ), "You must specify the path to the initial states if you resume a simulation." start_date = pd.Timestamp(start_date) end_date = pd.Timestamp(end_date) paths = get_simulation_dependencies( debug=debug, is_resumed=is_resumed, ) if rapid_test_statistics_path is not None: paths["rapid_test_statistics_path"] = rapid_test_statistics_path if initial_states_path is None: initial_states_path = paths["initial_states"] if initial_states_path.suffix == ".pkl": initial_states = pd.read_pickle(initial_states_path) elif initial_states_path.suffix == ".parquet": initial_states = pd.read_parquet(paths["initial_states"]) contact_models = get_all_contact_models() # process dates one_day = pd.Timedelta(1, unit="D") init_start = start_date - pd.Timedelta(31, unit="D") init_end = start_date - one_day duration = {"start": start_date, "end": end_date} # testing models share_of_tests_for_symptomatics_series = pd.read_pickle( paths["share_of_tests_for_symptomatics_series"] ) test_start = init_start - one_day test_end = end_date + one_day test_demand_func = partial( demand_test, share_of_tests_for_symptomatics_series=share_of_tests_for_symptomatics_series, ) testing_demand_models = { "symptoms": { "model": test_demand_func, "start": test_start, "end": test_end, } } testing_allocation_models = { "direct_allocation": { "model": allocate_tests, "start": test_start, "end": test_end, } } testing_processing_models = { "direct_processing": { "model": process_tests, "start": test_start, "end": test_end, } } saved_columns = { "initial_states": ["age_group_rki"], "disease_states": ["newly_infected", "newly_deceased", "ever_infected"], "time": ["date"], "other": [ "new_known_case", "virus_strain", "n_has_infected", "channel_infected_by_contact", "state", "knows_currently_infected", "currently_infected", ], } if not is_resumed: virus_shares = pd.read_pickle(paths["virus_shares"]) rki_infections = pd.read_pickle(paths["rki"]) group_weights = pd.read_pickle(paths["rki_age_groups"])["weight"] if group_share_known_case_path is not None: group_share_known_cases = pd.read_pickle(group_share_known_case_path) else: group_share_known_cases = None params = pd.read_pickle(paths["params"]) with warnings.catch_warnings(): warnings.filterwarnings( "ignore", message="indexing past lexsort depth may impact performance." ) params_slice = params.loc[("share_known_cases", "share_known_cases")] overall_share_known_cases = get_piecewise_linear_interpolation(params_slice) initial_conditions = create_initial_conditions( start=init_start, end=init_end, seed=3930, reporting_delay=5, synthetic_data=initial_states[["county", "age_group_rki"]], empirical_infections=rki_infections, virus_shares=virus_shares, overall_share_known_cases=overall_share_known_cases, group_share_known_cases=group_share_known_cases, group_weights=group_weights, ) else: initial_conditions = None seasonality_factor_model = partial(seasonality_model, contact_models=contact_models) def _currently_infected(df): return df["infectious"] | df["symptomatic"] | (df["cd_infectious_true"] >= 0) def _knows_currently_infected(df): return df["knows_immune"] & df["currently_infected"] derived_state_variables = { "currently_infected": _currently_infected, "knows_currently_infected": _knows_currently_infected, } events = { "introduce_b117": {"model": introduce_b117}, "introduce_delta": {"model": introduce_delta}, } fixed_inputs = { "initial_states": initial_states, "contact_models": contact_models, "duration": duration, "events": events, "testing_demand_models": testing_demand_models, "testing_allocation_models": testing_allocation_models, "testing_processing_models": testing_processing_models, "saved_columns": saved_columns, "initial_conditions": initial_conditions, "susceptibility_factor_model": calculate_susceptibility, "virus_strains": ["base_strain", "b117", "delta"], "seasonality_factor_model": seasonality_factor_model, "derived_state_variables": derived_state_variables, "return_last_states": return_last_states, } if period_outputs: fixed_inputs["period_outputs"] = create_period_outputs() fixed_inputs["return_time_series"] = False scenario_func = getattr(scenario_simulation_inputs, scenario) scenario_inputs = scenario_func(paths, fixed_inputs) simulation_inputs = combine_dictionaries([fixed_inputs, scenario_inputs]) return simulation_inputs
def _get_school_multipliers(start_date): share_age_for_emergency_care = 0.5 share_in_graduating_classes = 0.25 # 16, 17 and 18 year olds share_in_primary = 0.3 a_b_multiplier = 0.5 share_getting_strict_emergency_care = 0.2 share_getting_generous_emergency_care = 0.3 strict_emergency_care_multiplier = ( share_age_for_emergency_care * share_getting_strict_emergency_care * HYGIENE_MULTIPLIER ) generous_emergency_care_multiplier = ( share_in_graduating_classes * a_b_multiplier + share_age_for_emergency_care * share_getting_generous_emergency_care ) * HYGIENE_MULTIPLIER feb_to_march_a_b_share = ( share_in_primary + share_in_graduating_classes ) * a_b_multiplier feb_to_march_emergency_share = ( share_age_for_emergency_care * share_getting_generous_emergency_care * a_b_multiplier ) feb_to_march_multiplier = ( feb_to_march_a_b_share + feb_to_march_emergency_share ) * HYGIENE_MULTIPLIER a_b_for_most_multiplier = ( a_b_multiplier + feb_to_march_emergency_share * a_b_multiplier ) school_multiplier_without_vacations = pd.Series( { start_date: 1.0, "2020-11-01": 1.0, "2020-11-02": HYGIENE_MULTIPLIER, "2020-12-15": HYGIENE_MULTIPLIER, # strict emergency care "2020-12-16": strict_emergency_care_multiplier, "2021-01-10": strict_emergency_care_multiplier, # generous emergency care "2021-01-11": generous_emergency_care_multiplier, "2021-02-21": generous_emergency_care_multiplier, # primary and graduating in A / B "2021-02-22": feb_to_march_multiplier, "2021-03-14": feb_to_march_multiplier, # mid March until Easter: A / B for most "2021-03-15": a_b_for_most_multiplier, "2021-04-05": a_b_for_most_multiplier, # easter until may: "2021-04-06": generous_emergency_care_multiplier, "2021-04-30": generous_emergency_care_multiplier, # may "2021-05-01": a_b_for_most_multiplier, "2021-05-31": a_b_for_most_multiplier, } ) school_multiplier_without_vacations = get_piecewise_linear_interpolation( school_multiplier_without_vacations ) school_multiplier_with_vacations = pd.Series( { start_date: 1.0, # fall vacation: # first start on 2020-10-05. last end 2020-11-06 # on average from 2020-10-13 to 2020-10-23 # there was no overlap in the fall vacation dates between states. "2020-10-05": 1.0, "2020-10-13": 0.3, # number to cover that many states had fall vacation "2020-10-23": 0.3, "2020-11-06": HYGIENE_MULTIPLIER, # strict emergency care started in the week before Christmas "2020-12-15": HYGIENE_MULTIPLIER, "2020-12-16": strict_emergency_care_multiplier, # Christmas vacations started on 2002-12-21 in most states. # Christmas vacations ended between 2021-01-02 and 2021-01-10. "2020-12-20": strict_emergency_care_multiplier, "2020-12-21": 0.0, "2021-01-02": 0.0, "2021-01-10": strict_emergency_care_multiplier, # generous emergency care # winter vacations were from 2021-01-25 until 2021-03-12 depending on the # state and only short so we ignore them here. "2021-01-11": generous_emergency_care_multiplier, "2021-02-21": generous_emergency_care_multiplier, # primary and graduating in A / B "2021-02-22": feb_to_march_multiplier, "2021-03-14": feb_to_march_multiplier, # mid March until Easter: A / B for most "2021-03-15": a_b_for_most_multiplier, "2021-03-26": a_b_for_most_multiplier, # Easter vacations started on 2021-03-29 in most states # and ended between 2021-04-05 and 2021-04-16, for most on 2021-04-10 "2021-03-29": 0.0, "2021-04-06": 0.0, "2021-04-10": 0.1, # some states started school before 2021-04-10 # easter until may: "2021-04-11": generous_emergency_care_multiplier, "2021-04-30": generous_emergency_care_multiplier, # may # we ignore Pentecoast vacation because it was <4 days on average "2021-05-01": a_b_for_most_multiplier, "2021-05-31": a_b_for_most_multiplier, } ) school_multiplier_with_vacations = get_piecewise_linear_interpolation( school_multiplier_with_vacations ) return school_multiplier_without_vacations, school_multiplier_with_vacations