Пример #1
0
def fit_population(args):
    tp_to_eval_seroprevalence = 30
    from scripts.estimate_R0 import estimate_Re
    from scripts.load_utils import cumulative_to_rolling_average
    region, json_case_data, pop_params, age_distribution, return_fit_res = args

    print(f"starting fit for {region}")
    time_range_fit = 60
    data = convert_to_vectors(json_case_data)
    weekly_data = cumulative_to_rolling_average(data)
    if weekly_data['cases'] is None or weekly_data['deaths'] is None:
        return (region, None, None) if return_fit_res else (region, None)

    weekly_data_for_fit = {
        k: v[-time_range_fit + 7:]
        for k, v in weekly_data.items()
    }

    # estimate Re and bound from above (usually a problem at the very beginning of a wave)
    res = estimate_Re(weekly_data['cases'], imports=1, cutoff=5, chop=3)
    Re = np.minimum(pop_params['r0'], res['Re'])
    Refit = fit_REblocks(weekly_data['time'][:-8], Re)
    piecewise_constant_Re = Refit.predict(weekly_data['time'].reshape(-1, 1))
    change_points = np.concatenate(
        [[-1],
         np.where(np.diff(piecewise_constant_Re) != 0)[0], [len(Re) - 1]]) + 1

    total_deaths_at_start = data['deaths'][-tp_to_eval_seroprevalence]
    IFR = get_IFR(age_distribution)
    reporting_fraction = get_reporting_fraction(data['cases'], data['deaths'],
                                                IFR)
    n_cases_at_start = total_deaths_at_start / IFR
    seroprevalence = n_cases_at_start / pop_params['size']
    if np.isnan(seroprevalence) or (type(seroprevalence)
                                    == np.ma.core.MaskedConstant
                                    and seroprevalence.mask == True):
        seroprevalence = 0

    mitigations = []
    for ci, cp in enumerate(change_points[:-1]):
        mitigations.append({
            'tMin':
            int(weekly_data['time'][cp]),
            'tMax':
            int(weekly_data['time'][change_points[ci + 1] - 1]),
            'value':
            max(
                0,
                min(
                    1,
                    float(1 - piecewise_constant_Re[cp] /
                          (1 - seroprevalence) / pop_params['r0'])))
        })

    tmin = data['time'][-time_range_fit]
    average_Re = np.mean(Re[-30:])
    fixed_params = {
        'logR0': np.log(pop_params['r0']),
        'efficacy': 1 - average_Re / pop_params['r0'],
        'containment_start': tmin,
        'seroprevalence': seroprevalence
    }
    if (weekly_data_for_fit['cases'][0]):
        guess = {
            'logInitial':
            np.log(
                (0.5 + weekly_data_for_fit['cases'][0]) / reporting_fraction),
            'reported':
            reporting_fraction
        }
    elif (weekly_data_for_fit['deaths'][0]) and reporting_fraction > 0:
        guess = {
            'logInitial':
            np.log((0.5 + weekly_data_for_fit['deaths'][0]) /
                   reporting_fraction / IFR),
            'reported':
            reporting_fraction
        }
    elif (weekly_data_for_fit['deaths'][0]):
        guess = {
            'logInitial':
            np.log((0.5 + weekly_data_for_fit['deaths'][0]) / 0.3 / IFR),
            'reported':
            reporting_fraction
        }
    else:
        guess = {'logInitial': np.log(1), 'reported': reporting_fraction}

    fit_result, success = fit_params(data['time'][-time_range_fit:],
                                     weekly_data_for_fit,
                                     guess,
                                     age_distribution,
                                     pop_params['size'],
                                     fixed_params=fixed_params)

    params = {}
    params.update(fixed_params)
    for p in guess:
        params[p] = fit_result.__getattribute__(p)
    for p in params:
        params[p] = float(params[p])

    params['mitigations'] = mitigations
    params['tMin'] = datetime.fromordinal(tmin).date().strftime('%Y-%m-%d')
    params['tMax'] = datetime.fromordinal(tmin +
                                          90).date().strftime('%Y-%m-%d')
    if return_fit_res:
        return (region, params, fit_result)
    else:
        return (region, params)
        import ipdb
        ipdb.set_trace()
Пример #2
0
    from matplotlib import pyplot as plt

    case_counts = parse_tsv()
    scenario_data = load_population_data()
    age_distributions = load_distribution()
    # region = 'JPN-Kagawa'
    region = 'United States of America'
    # region = 'Germany'
    region = 'Switzerland'
    region = 'USA-Texas'
    age_dis = age_distributions[scenario_data[region]['ages']]
    region, p, fit_params = fit_population(
        (region, case_counts[region], scenario_data[region], age_dis, True))

    model_data = generate_data(fit_params)
    model_cases = model_data['cases'][7:] - model_data['cases'][:-7]
    model_deaths = model_data['deaths'][7:] - model_data['deaths'][:-7]
    model_time = fit_params.time[7:]

    cases = cumulative_to_rolling_average(
        convert_to_vectors(case_counts[region]))

    print(fit_params.reported, np.exp(fit_params.logInitial))
    print(get_IFR(age_dis))

    plt.plot(model_time, model_cases)
    plt.plot(model_time, model_deaths)
    plt.plot(cases['time'], cases['cases'])
    plt.plot(cases['time'], cases['deaths'])
    plt.yscale('log')