def fit_doubling_time():
    """
    fit time series for doubling time
    """
    global d_countries_timeseries
    global d_selected_countries
    # TODO!
    # l = []
    # l.append('South Korea')
    # for country in l:
    for country in tqdm(d_countries_timeseries.keys()):
        # for country in d_selected_countries.keys():
        # print(country)
        # country_code = d_selected_countries[country]['Code']
        l_country_data = d_countries_timeseries[country]
        # pop_in_Mill = d_selected_countries[country]['Population'] / 1000000

        # for fits of doubling time
        data_t = []
        data_cases = []
        data_deaths = []

        for i in range(len(l_country_data)):
            entry = l_country_data[i]

            # for fits of doubling time
            data_t.append(entry['Days_Past'])
            data_cases.append(entry['Cases'])
            data_deaths.append(entry['Deaths'])

            l_country_data[i] = entry

        # fit the doubling time each day
        data = list(zip(data_t, data_cases))
        fit_series_res_cases = helper.series_of_fits(data,
                                                     fit_range=7,
                                                     max_days_past=28)
        data = list(zip(data_t, data_deaths))
        fit_series_res_deaths = helper.series_of_fits(data,
                                                      fit_range=7,
                                                      max_days_past=28)

        for i in range(len(l_country_data)):
            entry = l_country_data[i]
            entry['Cases_Doubling_Time'] = ""
            entry['Deaths_Doubling_Time'] = ""
            this_DaysPast = entry['Days_Past']
            if this_DaysPast in fit_series_res_cases:
                entry['Cases_Doubling_Time'] = fit_series_res_cases[
                    this_DaysPast]
            if this_DaysPast in fit_series_res_deaths:
                entry['Deaths_Doubling_Time'] = fit_series_res_deaths[
                    this_DaysPast]
            l_country_data[i] = entry

        if args["sleep"]:
            time.sleep(1)
        d_countries_timeseries[country] = l_country_data
def fit_doubling_or_halftime() -> dict:
    for code, l_time_series in d_states_data.items():
        print(f'fitting doubling time for {code}')

        # if code != 'DE-total':  # TODO
        #     continue

        # # fit cases data V2: based on CasesNew instead of Cases and interpreting T<0 -> halftime
        dataCases = []
        for i in range(1, len(l_time_series)):  # TODO
            # for i in range(10, 60):
            # x= day , y = cases
            dataCases.append((
                l_time_series[i]['Days_Past'],
                l_time_series[i]['Cases_Last_Week_Per_100000']
                # l_time_series[i]['Cases_New_Per_Million']
                # this set to very noisy results, so using Last_week data instead
            ))

        fit_series_res = helper.series_of_fits(dataCases,
                                               fit_range=14,
                                               max_days_past=365,
                                               mode='exp')
        for i in range(0, len(l_time_series)):
            this_Doubling_Time = ""
            this_days_past = l_time_series[i]['Days_Past']
            if this_days_past in fit_series_res:
                this_Doubling_Time = fit_series_res[this_days_past]
            l_time_series[i][
                'Cases_Last_Week_Doubling_Time'] = this_Doubling_Time
            # debugging
            # print(l_time_series[i]['Days_Past'], this_Doubling_Time)

        d_states_data[code] = l_time_series
    return d_states_data
def read_csv_to_dict() -> dict:
    """
    read and convert the source csv file, containing: federalstate,infections,deaths,date,newinfections,newdeaths
    re-calc _New
    add _Per_Million
    add Fitted Doubling time
    """

    global d_states_ref
    # Preparations
    d_states_data = {'BW': [], 'BY': [], 'BE': [], 'BB': [], 'HB': [], 'HH': [], 'HE': [], 'MV': [
    ], 'NI': [], 'NW': [], 'RP': [], 'SL': [], 'SN': [], 'ST': [], 'SH': [], 'TH': []}
    # add German sum
    d_states_data['DE-total'] = []
    d_german_sums = {}  # date -> 'infections', 'deaths', 'new infections', 'new deaths'

    # data body
    with open(download_file, mode='r', encoding='utf-8') as f:
        csv_reader = csv.DictReader(f, delimiter=",")
        for row in csv_reader:
            d = {}
            s = row['date']
            l = s.split("-")
            d['Date'] = helper.date_format(
                int(l[0]), int(l[1]), int(l[2]))
            d['Cases'] = int(row["infections"])
            d['Deaths'] = int(row["deaths"])

            if row["federalstate"] == 'Baden-Württemberg':
                d_states_data['BW'].append(d)
            elif row["federalstate"] == 'Bavaria':
                d_states_data['BY'].append(d)
            elif row["federalstate"] == 'Berlin':
                d_states_data['BE'].append(d)
            elif row["federalstate"] == 'Brandenburg':
                d_states_data['BB'].append(d)
            elif row["federalstate"] == 'Bremen':
                d_states_data['HB'].append(d)
            elif row["federalstate"] == 'Hamburg':
                d_states_data['HH'].append(d)
            elif row["federalstate"] == 'Hesse':
                d_states_data['HE'].append(d)
            elif row["federalstate"] == 'Lower Saxony':
                d_states_data['NI'].append(d)
            elif row["federalstate"] == 'North Rhine-Westphalia':
                d_states_data['NW'].append(d)
            elif row["federalstate"] == 'Mecklenburg-Western Pomerania':
                d_states_data['MV'].append(d)
            elif row["federalstate"] == 'Rhineland-Palatinate':
                d_states_data['RP'].append(d)
            elif row["federalstate"] == 'Saarland':
                d_states_data['SL'].append(d)
            elif row["federalstate"] == 'Saxony':
                d_states_data['SN'].append(d)
            elif row["federalstate"] == 'Saxony-Anhalt':
                d_states_data['ST'].append(d)
            elif row["federalstate"] == 'Schleswig-Holstein':
                d_states_data['SH'].append(d)
            elif row["federalstate"] == 'Thuringia':
                d_states_data['TH'].append(d)
            else:
                print("ERROR: unknown state")
                quit()

            # add to German sum
            if d['Date'] not in d_german_sums:
                d2 = {}
                d2['Cases'] = d['Cases']
                d2['Deaths'] = d['Deaths']
            else:
                d2 = d_german_sums[d['Date']]
                d2['Cases'] += d['Cases']
                d2['Deaths'] += d['Deaths']
            d_german_sums[d['Date']] = d2
            del d2

    # for German sum -> same dict
    for datum in d_german_sums.keys():
        d = d_german_sums[datum]
        d['Date'] = datum  # add date field
        d_states_data['DE-total'].append(d)
    del d_german_sums, d

    # check if DE sum of lastdate and per-last date has changed, if so: remove last date
    if d_states_data['DE-total'][-1]['Cases'] == d_states_data['DE-total'][-2]['Cases']:
        print("WARNING: DE cases sum is unchanged")
        for code in d_states_data:
            d_states_data[code].pop()
    print(f"DE-States Last Date: {d_states_data['DE-total'][-1]['Date']}")

    for code in d_states_data.keys():
        l_time_series = d_states_data[code]

        l_time_series = helper.prepare_time_series(l_time_series)

        # add days past and per million
        for i in range(len(l_time_series)):
            d = l_time_series[i]
            # add per Million rows
            d = helper.add_per_million_via_lookup(d, d_states_ref, code)

        # fit cases data
        # Cases
        dataCases = []
        dataDeaths = []
        for i in range(1, len(l_time_series)):
            # x= day , y = cases
            dataCases.append(
                (
                    l_time_series[i]['Days_Past'],
                    l_time_series[i]['Cases']
                )
            )
            dataDeaths.append(
                (
                    l_time_series[i]['Days_Past'],
                    l_time_series[i]['Deaths']
                )
            )

        fit_series_res = helper.series_of_fits(
            dataCases, fit_range=7, max_days_past=28)
        for i in range(0, len(l_time_series)):
            this_Doubling_Time = ""
            this_days_past = l_time_series[i]['Days_Past']
            if this_days_past in fit_series_res:
                this_Doubling_Time = fit_series_res[this_days_past]
            l_time_series[i]['Cases_Doubling_Time'] = this_Doubling_Time

        fit_series_res = helper.series_of_fits(
            dataDeaths, fit_range=7, max_days_past=28)
        for i in range(0, len(l_time_series)):
            this_Doubling_Time = ""
            this_days_past = l_time_series[i]['Days_Past']
            if this_days_past in fit_series_res:
                this_Doubling_Time = fit_series_res[this_days_past]
            l_time_series[i]['Deaths_Doubling_Time'] = this_Doubling_Time

        d_states_data[code] = l_time_series

        if args["sleep"]:
            time.sleep(1)

    return d_states_data