#!/usr/bin/env python3

import os
import numpy as np
import pandas
import matplotlib.pyplot as plt
from scipy.optimize import minimize, Bounds
from scipy.signal import medfilt
from datetime import datetime
from collections import defaultdict

def savefig(figid, directory="./"):
    if directory != "./":
        if not os.path.exists(directory):
            os.makedirs(directory)
    print("Saving figure", figid, "in %s/%s" % (directory, figid))
    plt.tight_layout()
    plt.savefig(directory + "/%s.pdf" % (figid), dpi=600)


def add_time_col(a_pd):
    time_col = [(datetime.strptime(a, '%d.%m.%Y %H:%M:%S.%f') -
                 datetime.strptime(a_pd.date[0], '%d.%m.%Y %H:%M:%S.%f')).total_seconds() for a in a_pd.date]
    a_pd['time'] = time_col


def add_tid_col(a_pd, flux):
    a_pd['fluence'] = a_pd.time*flux
    a_pd['tid'] = a_pd.fluence/1.69e9


def read_csv_psu(fileName, timeOffset, flux):
    a_pd = pandas.read_csv(fileName, header=None,
                           names=['date', 'v1', 'i1', 'v2', 'i2'], sep=',')
    add_time_col(a_pd)
    a_pd.time = [a+timeOffset for a in a_pd.time]
    add_tid_col(a_pd, flux)
    return a_pd


def read_csv_mm(fileName, flux):
    a_pd = pandas.read_csv(fileName, header=None,
                           names=['date', 'mm', 'N', 'TMR_ERR', 'I2C_ERR',
                                  'v1', 'v2', 'v3', 'i1', 'i2', 'i3',
                                  't1', 't2', 't3', 'f1', 'f2', 'err'], sep=',')
    add_time_col(a_pd)
    add_tid_col(a_pd, flux)
    return a_pd


def concat_runs(runs):
    res = pandas.concat(runs, ignore_index=True)
    prev_time = 0
    timediff = 0
    extra_tid = 0
    extra_fluence = 0
    extra_time = 0
    for i in range(len(res)):
        if i:
            timediff = prev_time - res.time.iloc[i]
            if timediff > 0:
                extra_time += timediff
                extra_tid += prev_tid - res.tid.iloc[i]
                extra_fluence += prev_fluence - res.fluence.iloc[i]
                print('adding extra time and TID while concatenating runs: {:0.2f}, TID: {:0.2f}'.format(extra_time, extra_tid))
        prev_time = res.time.iloc[i]
        prev_tid = res.tid.iloc[i]
        prev_fluence = res.fluence.iloc[i]
        res.time.iloc[i] += extra_time
        res.tid.iloc[i] += extra_tid
        res.fluence.iloc[i] += extra_fluence
    return res


def f_time(a_pd, time):
    rows = a_pd[a_pd['time'] < time]
    pos = len(rows)-1

    # check if the table is made of row pairs that are very close
    # together in time, assuming there are more than two elements
    double_measurements = bool(abs(a_pd['time'][1] - a_pd['time'][0]) < 0.5)

    # the requested time doesn't exist, return the lowest set of data
    if len(rows) == 0:
        return a_pd.loc[0:double_measurements]

    # check if we're at the end of the list
    if len(rows) == len(a_pd):
        res = rows.loc[len(rows)-1-double_measurements:len(rows)-1]
    else:
        if abs(a_pd.loc[pos]['time'] - time) < abs(a_pd.loc[pos+1]['time'] - time):
            res = rows.loc[len(rows)-1-double_measurements:len(rows)-1]
        else:
            res = a_pd.loc[pos+1:pos+1+double_measurements]

    return res


def psu_volt_drop(v, i, R):
    return v-R*(np.array(i)/1000.0)


def mm_fit_func(v, c, s):
    return c + s*v


def fit_v_square_func(mm_pd, psu_pd, ch, R, c, s):
    vstr = 'v' + str(ch)
    istr = 'i' + str(ch)
    mm_index = np.array(mm_pd.index)
    mm_fit = mm_fit_func(medfilt(mm_pd[vstr]), c, s)
    vi_array = [f_time(psu_pd, mm_pd.time[idx])[[vstr, istr]]
                for idx in mm_index]
    v_array = [float(vi_array[idx][vstr]) for idx in range(len(vi_array))]
    i_array = [float(vi_array[idx][istr]) for idx in range(len(vi_array))]
    psu_withvoltdrop = psu_volt_drop(v_array, i_array, R)
    a1ma2 = np.array(mm_fit - psu_withvoltdrop)
    return np.sum(np.square(a1ma2))


def fit_v_square_func_wrap(x, mm_pd, psu_pd, ch):
    return fit_v_square_func(mm_pd, psu_pd, ch, x[0], x[1], x[2])


def fit_v_measurements(mm_pd, psu_pd, is_mm0, is_mm1, fixmm0=True, fixmm1=True):
    # multivariate fit for computing the R of the cable and the monimod
    # offset and scaling factors:

    consts_ret = []

    x0 = [0.8, 0, 1.0]
    bounds = Bounds([0.5, -1, 0.9], [1.2, 1, 1.1])

    print("V1, MM0 fit:")
    res = minimize(fit_v_square_func_wrap, x0=x0, bounds=bounds,
                   args=(mm_pd[is_mm0 & fixmm0], psu_pd, 1))
    consts_ret += [res['x']]
    print(res)
    print()

    bounds = Bounds([0.5, -3, 0.9], [1.5, 3, 1.7])
    print("V2, MM0 fit:")
    res = minimize(fit_v_square_func_wrap, x0=x0, bounds=bounds,
                   args=(mm_pd[is_mm0 & fixmm1], psu_pd, 2))
    consts_ret += [res['x']]
    print(res)
    print()

    return consts_ret


def fix_voltages(pd, fit_consts):
    pd.v1 = fit_consts[0][1]+fit_consts[0][2]*pd.v1
    pd.v2 = fit_consts[1][1]+fit_consts[1][2]*pd.v2
    return pd


def find_power_cycles(pd):
    cycle_col = pandas.Series(index=pd.N[pd['N'] == 0].index, dtype='float64')
    for i in pd.N[pd['N'] == 0].index:
        cycle_col[i] = 1
    pd['cycle'] = cycle_col


def plot_voltages_currents(mm_pd, psu_pd, file_prefix, is_mm0, is_mm1, fit_consts, onlymm1=False):
    # PSU 12V voltage at POL vs measured voltages
    plt.figure(figsize=(8, 6))
    plt.xlabel('TID [Gy]', fontsize=18)
    plt.ylabel('12V rail voltage [V]', fontsize=18)
    plt.plot(psu_pd.tid, psu_pd.v1-fit_consts[0][0]*(psu_pd.i1/1000), label='PSU at POL (w/cable resistance)')
    if not onlymm1:
        plt.plot(mm_pd.tid[is_mm0], mm_pd.v1[is_mm0], label='MM0 measurement')
    plt.plot(mm_pd.tid[is_mm1], mm_pd.v1[is_mm1], label='MM1 measurement')
    for idx in mm_pd.cycle[mm_pd['cycle'] == 1].index:
        plt.axvline(mm_pd.tid[idx], ymin=0, ymax=1, linewidth=1, linestyle=':')
    if not onlymm1:
        for idx in mm_pd.I2C_ERR[(is_mm0) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]-0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='red')
    for idx in mm_pd.I2C_ERR[(is_mm1) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]+0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='orange')
    # plt.xlim((0, 1900))
    plt.ylim((5, 15))
    plt.legend(loc='upper center', fontsize=18)
    savefig(file_prefix+'_v12', 'plots')
    plt.close()

    # PSU 5V voltage at POL vs measured voltages
    plt.figure(figsize=(8, 6))
    plt.xlabel('TID [Gy]', fontsize=18)
    plt.ylabel('5V rail voltage [V]', fontsize=18)
    plt.plot(psu_pd.tid, psu_pd.v2-fit_consts[1][0]*(psu_pd.i2/1000), label='PSU at POL (w/cable resistance)')
    if not onlymm1:
        plt.plot(mm_pd.tid[is_mm0], mm_pd.v2[is_mm0], label='MM0 measurement')
    plt.plot(mm_pd.tid[is_mm1], mm_pd.v2[is_mm1], label='MM1 measurement')
    for idx in mm_pd.cycle[mm_pd['cycle'] == 1].index:
        plt.axvline(mm_pd.tid[idx], ymin=0, ymax=1, linewidth=1, linestyle=':')
    if not onlymm1:
        for idx in mm_pd.I2C_ERR[(is_mm0) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]-0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='red')
    for idx in mm_pd.I2C_ERR[(is_mm1) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]+0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='orange')
    # plt.xlim((0, 1900))
    plt.ylim((3, 7))
    plt.legend(loc='upper center', fontsize=18)
    savefig(file_prefix+'_v5', 'plots')
    plt.close()

    # PSU 12V current vs measured current sum
    plt.figure(figsize=(8, 6))
    plt.xlabel('TID [Gy]', fontsize=18)
    plt.ylabel('12V rail current [mA]', fontsize=18)
    plt.plot(psu_pd.tid, psu_pd.i1, label='PSU-reported values')
    if not onlymm1:
        plt.plot(mm_pd.tid[is_mm0],
                 mm_pd.i1[is_mm0].values + mm_pd.i1[is_mm1].values, label='MM0 + MM1 measurements')
    else:
        plt.plot(mm_pd.tid[is_mm1], mm_pd.i1[is_mm1], label='MM1 measurements')
    for idx in mm_pd.cycle[mm_pd['cycle'] == 1].index:
        plt.axvline(mm_pd.tid[idx], ymin=0, ymax=1, linewidth=1, linestyle=':')
    if not onlymm1:
        for idx in mm_pd.I2C_ERR[(is_mm0) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]-0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='red')
    for idx in mm_pd.I2C_ERR[(is_mm1) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]+0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='orange')
    # plt.xlim((0, 1900))
    plt.ylim((0, 4000))
    plt.legend(loc='lower center', fontsize=18)
    savefig(file_prefix+'_i12', 'plots')
    plt.close()

    # PSU 5V current vs measured current sum
    plt.figure(figsize=(8, 6))
    plt.xlabel('TID [Gy]', fontsize=18)
    plt.ylabel('5V rail current [mA]', fontsize=18)
    plt.plot(psu_pd.tid, psu_pd.i2, label='PSU-reported values')
    if not onlymm1:
        plt.plot(mm_pd.tid[is_mm0],
                 mm_pd.i2[is_mm0].values + mm_pd.i2[is_mm1].values, label='MM0 + MM1 measurements')
    else:
        plt.plot(mm_pd.tid[is_mm0], mm_pd.i2[is_mm1], label='MM1 measurements')
    for idx in mm_pd.cycle[mm_pd['cycle'] == 1].index:
        plt.axvline(mm_pd.tid[idx], ymin=0, ymax=1, linewidth=1, linestyle=':')
    if not onlymm1:
        for idx in mm_pd.I2C_ERR[(is_mm0) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]-0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='red')
    for idx in mm_pd.I2C_ERR[(is_mm1) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]+0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='orange')
    # plt.xlim((0, 1900))
    plt.ylim((0, 60))
    plt.legend(loc='lower center', fontsize=18)
    savefig(file_prefix+'_i5', 'plots')
    plt.close()


def plot_temperatures(mm_pd, file_prefix, is_mm0, is_mm1, onlymm1=False):
    plt.figure(figsize=(8, 6))
    plt.xlabel('TID [Gy]', fontsize=18)
    plt.ylabel('LM45-measured temperatures [V]', fontsize=18)
    if not onlymm1:
        plt.plot(mm_pd.tid[is_mm0], mm_pd.t1[is_mm0], label='MM0 measurement')
    plt.plot(mm_pd.tid[is_mm1], mm_pd.t1[is_mm1], label='MM1 measurement')
    for idx in mm_pd.cycle[mm_pd['cycle'] == 1].index:
        plt.axvline(mm_pd.tid[idx], ymin=0, ymax=1, linewidth=1, linestyle=':')
    if not onlymm1:
        for idx in mm_pd.I2C_ERR[(is_mm0) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]-0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='red')
    for idx in mm_pd.I2C_ERR[(is_mm1) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]+0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='orange')
    # plt.xlim((0, 1900))
    plt.ylim((10, 40))
    plt.legend(loc='upper center', fontsize=18)
    savefig(file_prefix+'_t1', 'plots')
    plt.close()

    plt.figure(figsize=(8, 6))
    plt.xlabel('TID [Gy]', fontsize=18)
    plt.ylabel('PT100-measured temperatures [V]', fontsize=18)
    if not onlymm1:
        plt.plot(mm_pd.tid[is_mm0], mm_pd.t2[is_mm0], label='MM0 measurement')
    plt.plot(mm_pd.tid[is_mm1], mm_pd.t3[is_mm1], label='MM1 measurement')
    for idx in mm_pd.cycle[mm_pd['cycle'] == 1].index:
        plt.axvline(mm_pd.tid[idx], ymin=0, ymax=1, linewidth=1, linestyle=':')
    if not onlymm1:
        for idx in mm_pd.I2C_ERR[(is_mm0) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]-0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='red')
    for idx in mm_pd.I2C_ERR[(is_mm1) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]+0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='orange')
    # plt.xlim((0, 1900))
    plt.ylim((10, 40))
    plt.legend(loc='upper center', fontsize=18)
    savefig(file_prefix+'_t2', 'plots')
    plt.close()


def plot_fan_speeds(mm_pd, file_prefix, is_mm0, is_mm1, onlymm1=False):
    plt.figure(figsize=(8, 6))
    plt.xlabel('TID [Gy]', fontsize=18)
    plt.ylabel('Fan speeds [RPM]', fontsize=18)
    if not onlymm1:
        plt.plot(mm_pd.tid[is_mm0], mm_pd.f1[is_mm0], label='MM0 fan 1')
        plt.plot(mm_pd.tid[is_mm0], mm_pd.f2[is_mm0], label='MM0 fan 2')
    plt.plot(mm_pd.tid[is_mm1], mm_pd.f1[is_mm1], label='MM1 fan 1')
    plt.plot(mm_pd.tid[is_mm1], mm_pd.f2[is_mm1], label='MM1 fan 2')
    for idx in mm_pd.cycle[mm_pd['cycle'] == 1].index:
        plt.axvline(mm_pd.tid[idx], ymin=0, ymax=1, linewidth=1, linestyle=':')
    if not onlymm1:
        for idx in mm_pd.I2C_ERR[(is_mm0) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]-0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='red')
    for idx in mm_pd.I2C_ERR[(is_mm1) & (mm_pd['I2C_ERR'] != 0)].index:
            plt.axvline(mm_pd.tid[idx]+0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='orange')
    # plt.xlim((0, 1900))
    plt.ylim((0, 10000))
    plt.legend(loc='upper center', fontsize=18)
    savefig(file_prefix+'_f', 'plots')
    plt.close()


def plot_i2c_err_hist(mm_pd, file_prefix, is_mm0, is_mm1, onlymm1=False):
    plt.figure(figsize=(8, 6))
    plt.xlabel('I2C error code', fontsize=18)
    plt.ylabel('Occurrences', fontsize=18)
    if onlymm1:
        myhist = np.histogram(mm_pd.I2C_ERR[is_mm1], bins=list(range(-9, 0)) + [-0.01])
    else:
        myhist = np.histogram(mm_pd.I2C_ERR, bins=list(range(-9, 0)) + [-0.01])
    plt.bar(x = np.arange(-9, 0), height = myhist[0])
    for i, j in enumerate(myhist[0]):
        if j:
            plt.annotate(str(int(j)), xy=(-9+i, j), ha='center', va='bottom')
    plt.xticks(np.arange(-9, 0), np.arange(-9, 0))
    # plt.xlim((0, 1900))
    # plt.ylim((5, 15))
    savefig(file_prefix+'_i2c_errs', 'plots')
    plt.close()


def add_defaultdicts(d1, d2):
    res = defaultdict(int)
    for k1 in d1:
        if k1 in d2:
            res[k1] = d1[k1] + d2[k1]
        else:
            res[k1] = d1[k1]
    for k2 in d2:
        if k2 not in d1:
            res[k2] = d2[k2]
    return res


def histo_count_nonzero(h):
    for a in h:
        if a:
            return True
    return False


def plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, file_prefix, onlymm1=False):
    if onlymm1:
        total_sefi = sefi_types[1]
        total_err = err_types[1]
        total_inbetween = inbetween_types[1]
    else:
        total_sefi = add_defaultdicts(sefi_types[0], sefi_types[1])
        total_err = add_defaultdicts(err_types[0], err_types[1])
        total_inbetween = add_defaultdicts(inbetween_types[0], inbetween_types[1])

    hist_sefi = []
    hist_err = []
    hist_inbetween = []
    for k in range(-9, 0):
        if k in total_sefi:
            hist_sefi += [total_sefi[k]]
        else:
            hist_sefi += [0]

        if k in total_err:
            hist_err += [total_err[k]]
        else:
            hist_err += [0]

        if k in total_inbetween:
            hist_inbetween += [total_inbetween[k]]
        else:
            hist_inbetween += [0]

    n_nz_histos = histo_count_nonzero(hist_sefi) + histo_count_nonzero(hist_err) + \
        histo_count_nonzero(hist_inbetween)

    if n_nz_histos == 3:
        x_start = -0.3
        x_step = 0.3
        x_width = 0.3
    elif n_nz_histos == 2:
        x_start = -0.2
        x_step = 0.4
        x_width = 0.4
    else:
        x_start = 0
        x_step = 0
        x_width = 0.5

    plt.figure(figsize=(8, 6))
    plt.xlabel('I2C error code', fontsize=18)
    plt.ylabel('Occurrences', fontsize=18)

    histo_colors = ['steelblue', 'lightskyblue', 'cadetblue']
    histo_labels = ['SEFIs', 'Isolated errors', 'Interference errors']
    x_histo = x_start
    for hi, histo in enumerate([hist_sefi, hist_err, hist_inbetween]):
        if histo_count_nonzero(histo):
            plt.bar(x=[a + x_histo for a in np.arange(-9, 0)], height=histo, width=x_width, color=histo_colors[hi], label=histo_labels[hi])
            for i, j in enumerate(histo):
                if j:
                    plt.annotate(str(int(j)), xy=(-9+i+x_histo, j), ha='center', va='bottom')
            x_histo += x_step
    plt.xticks(np.arange(-9, 0), ['PEC', 'NA', 'NA', 'BUSY', 'BUS', 'ADDR', 'NA', 'NACK', 'COMB'], ha='center')
    plt.legend(loc='upper center', fontsize=18)
    # plt.xlim((0, 1900))
    # plt.ylim((5, 15))
    savefig(file_prefix+'_i2c_errs_detail', 'plots')
    plt.close()


def count_seus_v(mm_pd, psu_pd, ch, R):
    vstr = 'v' + str(ch)
    istr = 'i' + str(ch)
    mm_index = np.array(mm_pd.index)
    mm_fit = mm_pd[vstr]
    vi_array = [f_time(psu_pd, mm_pd.time[idx])[[vstr, istr]]
                for idx in mm_index]
    v_array = [float(vi_array[idx][vstr]) for idx in range(len(vi_array))]
    i_array = [float(vi_array[idx][istr]) for idx in range(len(vi_array))]
    psu_withvoltdrop = psu_volt_drop(v_array, i_array, R)
    a1ma2 = np.array(mm_fit - psu_withvoltdrop)
    return np.sum([bool(abs(a) > 0.25) for a in a1ma2])


def calc_print_sefis(mm_pd, onlymm1=False):
    # indices of all the entries that feature an error
    err_tbl = [a for a in mm_pd.I2C_ERR[mm_pd['I2C_ERR'] != 0].index]
    # isolated error counts
    err_cnt = [0, 0]
    # types of isolated errors
    err_types = [defaultdict(int), defaultdict(int)]
    # sefi error counts
    sefi_cnt = [0, 0]
    # types of errors in SEFIs
    sefi_types = [defaultdict(int), defaultdict(int)]
    # interference errors
    inbetween_cnt = [0, 0]
    # types of interference errors
    inbetween_types = [defaultdict(int), defaultdict(int)]
    # consecutive error counts
    cons_cnt = [0, 0]
    # "stack" of types in consecutive errors, to remove from type
    # histograms when turning into SEFIs
    cons_types = [[], []]
    # when MM0 started a string of errors
    started_0 = False
    # when MM1 started a string of errors
    started_1 = False
    # current index
    curr = 0
    # previous index
    prev = -3
    if onlymm1:
        for (i, a) in enumerate(filter(lambda x: x%2 != 0, err_tbl)):
            curr = a
            if (curr - prev <= 2) and (mm_pd.cycle[curr] != 1):
                err_cnt[1] += 1
                cons_cnt[1] += 1
                err_types[1][mm_pd.I2C_ERR[a]] += 1
                cons_types[1] += [mm_pd.I2C_ERR[a]]
            if (curr - prev > 2) or (mm_pd.cycle[curr] == 1):
                err_cnt[1] += 1
                cons_cnt[1] = 1
                err_types[1][mm_pd.I2C_ERR[a]] += 1
                cons_types[1] = [mm_pd.I2C_ERR[a]]
            if cons_cnt[1] == 3:
                cons_cnt[1] = 0
                err_cnt[1] -= 3
                sefi_cnt[1] += 1
                for err in cons_types[1]:
                    err_types[1][err] -= 1
                    sefi_types[1][err] += 1
                cons_types[1] = []
            prev = curr

        print(f"MM1 SEFIs: {sefi_cnt[1]}, MM1 ERRs: {err_cnt[1]}")
        print(f"MM1 SEFI types: {sefi_types[1]}, ERR types: {err_types[1]}")
        return sefi_types, err_types, inbetween_types

    for (i, a) in enumerate(err_tbl):
        curr = err_tbl[i]
        if (curr - prev <= 2) and (mm_pd.cycle[curr] != 1) and started_0:
            if curr % 2 == 0:   # MM0
                err_cnt[0] += 1
                err_types[0][mm_pd.I2C_ERR[a]] += 1
                cons_cnt[0] += 1
                cons_types[0] += [mm_pd.I2C_ERR[a]]
            else:               # MM1
                inbetween_cnt[1] += 1
                inbetween_types[1][mm_pd.I2C_ERR[a]] += 1
        if (curr - prev <= 2) and (mm_pd.cycle[curr] != 1) and started_1:
            if curr % 2 == 0:   # MM0
                inbetween_cnt[0] += 1
                inbetween_types[0][mm_pd.I2C_ERR[a]] += 1
            else:               # MM1
                err_cnt[1] += 1
                err_types[1][mm_pd.I2C_ERR[a]] += 1
                cons_cnt[1] += 1
                cons_types[1] += [mm_pd.I2C_ERR[a]]
        if (curr - prev > 2) or (mm_pd.cycle[curr] == 1):
            if curr % 2 == 0:  # MM0
                started_0 = True
                started_1 = False
                err_cnt[0] += 1
                err_types[0][mm_pd.I2C_ERR[a]] += 1
                cons_cnt[0] = 1
                cons_types[0] = [mm_pd.I2C_ERR[a]]
                cons_cnt[1] = 0
                cons_types[1] = []
            else:               # MM1
                started_0 = False
                started_1 = True
                err_cnt[1] += 1
                err_types[1][mm_pd.I2C_ERR[a]] += 1
                cons_cnt[0] = 0
                cons_types[0] = []
                cons_cnt[1] = 1
                cons_types[1] = [mm_pd.I2C_ERR[a]]
        if cons_cnt[0] == 3:
            err_cnt[0] -= 3
            for err in cons_types[0]:
                err_types[0][err] -= 1
                sefi_types[0][err] += 1
            cons_cnt[0] = 0
            cons_types[0] = []
            sefi_cnt[0] += 1
        if cons_cnt[1] == 3:
            err_cnt[1] -= 3
            for err in cons_types[1]:
                err_types[1][err] -= 1
                sefi_types[1][err] += 1
            cons_cnt[1] = 0
            cons_types[1] = []
            sefi_cnt[1] += 1
        prev = err_tbl[i]

    print(f"MM0 SEFIs: {sefi_cnt[0]}, MM0 ERRs: {err_cnt[0]}, MM0 IBTWs: {inbetween_cnt[0]}")
    print(f"MM0 SEFI types: {sefi_types[0]}, MM0 ERR types: {err_types[0]}, MM0 IBTW types: {inbetween_types[0]}")
    print(f"MM1 SEFIs: {sefi_cnt[1]}, MM1 ERRs: {err_cnt[1]}, MM1 IBTWs: {inbetween_cnt[1]}")
    print(f"MM1 SEFI types: {sefi_types[1]}, MM1 ERR types: {err_types[1]}, MM1 IBTW types: {inbetween_types[1]}")

    return sefi_types, err_types, inbetween_types


def print_tmr(mm_pd, is_mm1):
    None
    # tmr_errors = mm_pd.TMR_ERR[is_mm1 & (mm_pd.TMR_ERR != 0)]
    # print('TMR_ERRORS: {}'.format(tmr_errors))
    # print('TMR_ERRORS: {}'.format(tmr_errors.shape[0]))


def print_tid(mm_pd):
    print('This run: fluence={:e}, tid={:.2f} over {:.0f}s'.format(mm_pd.fluence.iloc[-1], mm_pd.tid.iloc[-1], mm_pd.time.iloc[-1]))


def plot_run1_ierrs(mm_pd, psu_pd, is_mm0, is_mm1):
    # PSU 12V voltage at POL vs measured voltages
    plt.figure(figsize=(12, 9))
    plt.xlabel('TID [Gy]', fontsize=18)
    plt.ylabel('12V rail voltage [V]', fontsize=18)
    psu_tid_lim = ((psu_pd['tid'] > 75) & (psu_pd['tid'] < 90))
    mm_tid_lim = ((mm_pd['tid'] > 75) & (mm_pd['tid'] < 90))
    plt.plot(psu_pd.tid[psu_tid_lim], psu_pd.v1[psu_tid_lim]-fit_consts[0][0]*(psu_pd.i1[psu_tid_lim]/1000), label='PSU at POL (w/cable resistance)')
    plt.plot(mm_pd.tid[is_mm0 & mm_tid_lim], mm_pd.v1[is_mm0 & mm_tid_lim], label='MM0 measurement')
    plt.plot(mm_pd.tid[is_mm1 & mm_tid_lim], mm_pd.v1[is_mm1 & mm_tid_lim], label='MM1 measurement')
    for idx in mm_pd.cycle[(mm_pd['cycle'] == 1) & (mm_tid_lim)].index:
        plt.axvline(mm_pd.tid[idx], ymin=0, ymax=1, linewidth=1, linestyle=':')
    for idx in mm_pd.I2C_ERR[(is_mm0) & (mm_pd['I2C_ERR'] != 0) & (mm_tid_lim)].index:
        plt.axvline(mm_pd.tid[idx]-0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='red')
    for idx in mm_pd.I2C_ERR[(is_mm1) & (mm_pd['I2C_ERR'] != 0) & (mm_tid_lim)].index:
            plt.axvline(mm_pd.tid[idx]+0.05, ymin=0, ymax=1, linewidth=0.5, linestyle=':', color='orange')
    # plt.xlim((0, 1900))
    plt.ylim((5, 15))
    plt.legend(loc='upper center', fontsize=18)
    savefig('run1_ierrs_zoom', 'plots')
    plt.close()



plt.style.use('seaborn-whitegrid')
plt.rc('text', usetex=True)
plt.rc('font', size=16)
plt.rc('axes.grid', axis='y')

doplots = True


# load run 1 ###################################
print("Processing run 1...")

pd1 = read_csv_mm('logs/log_run1_mm.txt', 1e8)
pd_p1 = read_csv_psu('logs/log_run1_psu.txt', 5, 1e8)

is_mm0 = pd1['mm'] == 0
is_mm1 = pd1['mm'] == 1

# fit_consts = fit_v_measurements(pd1, pd_p1)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -1, 1.042],
#               [1.0, -2.95, 1.66]]
fit_consts = [[0.5, 0.0, 1.0],
              [0.5, 0.0, 1.0]]

# fix voltage data
pd1 = fix_voltages(pd1, fit_consts)

# mark power cycles
find_power_cycles(pd1)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd1)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run1')
    plot_voltages_currents(pd1, pd_p1, 'run1', is_mm0, is_mm1, fit_consts)
    plot_temperatures(pd1, 'run1', is_mm0, is_mm1)
    plot_fan_speeds(pd1, 'run1', is_mm0, is_mm1)
    plot_i2c_err_hist(pd1, 'run1', is_mm0, is_mm1)
    plot_run1_ierrs(pd1, pd_p1, is_mm0, is_mm1)

mm0_v1_seus = count_seus_v(pd1[is_mm0], pd_p1, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd1[is_mm1 & ((pd1['v1'] > 6))], pd_p1, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))

print_tmr(pd1, is_mm1)
print_tid(pd1)
print()


# load run 2 ###################################
print("Processing run 2...")

pd2 = read_csv_mm('logs/log_run2_mm.txt', 1e8)
pd_p2 = read_csv_psu('logs/log_run2_psu.txt', 5, 1e8)

is_mm0 = pd2['mm'] == 0
is_mm1 = pd2['mm'] == 1

# fit_consts = fit_v_measurements(pd2, pd_p2)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -1, 1.042],
#               [1.0, -2.95, 1.66]]

# fix voltage data
pd2 = fix_voltages(pd2, fit_consts)

# mark power cycles
find_power_cycles(pd2)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd2)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run2')
    plot_voltages_currents(pd2, pd_p2, 'run2', is_mm0, is_mm1, fit_consts)
    plot_temperatures(pd2, 'run2', is_mm0, is_mm1)
    plot_fan_speeds(pd2, 'run2', is_mm0, is_mm1)
    plot_i2c_err_hist(pd2, 'run2', is_mm0, is_mm1)

mm0_v1_seus = count_seus_v(pd2[is_mm0], pd_p2, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd2[is_mm1], pd_p2, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd2, is_mm1)
print_tid(pd2)
print()


# load run 3 ###################################
print("Processing run 3...")

pd3 = read_csv_mm('logs/log_run3_mm.txt', 5e7)
pd_p3 = read_csv_psu('logs/log_run3_psu.txt', 5, 5e7)

is_mm0 = pd3['mm'] == 0
is_mm1 = pd3['mm'] == 1

# fit_consts = fit_v_measurements(pd3, pd_p3)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -1, 1.042],
#               [1.0, -2.95, 1.66]]

# fix voltage data
pd3 = fix_voltages(pd3, fit_consts)

# mark power cycles
find_power_cycles(pd3)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd3)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run3')
    plot_voltages_currents(pd3, pd_p3, 'run3', is_mm0, is_mm1, fit_consts)
    plot_temperatures(pd3, 'run3', is_mm0, is_mm1)
    plot_fan_speeds(pd3, 'run3', is_mm0, is_mm1)
    plot_i2c_err_hist(pd3, 'run3', is_mm0, is_mm1)

mm0_v1_seus = count_seus_v(pd3[is_mm0], pd_p3, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd3[is_mm1], pd_p3, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd3, is_mm1)
print_tid(pd3)
print()


# load run 4 ###################################
print("Processing run 4...")

pd4 = read_csv_mm('logs/log_run4_mm.txt', 2.5e8)
pd_p4 = read_csv_psu('logs/log_run4_psu.txt', 5, 2.5e8)

is_mm0 = pd4['mm'] == 0
is_mm1 = pd4['mm'] == 1

# fit_consts = fit_v_measurements(pd4, pd_p4)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -3.35, 1.66]]

# fix voltage data
pd4 = fix_voltages(pd4, fit_consts)

# mark power cycles
find_power_cycles(pd4)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd4)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run4')
    plot_voltages_currents(pd4, pd_p4, 'run4', is_mm0, is_mm1, fit_consts)
    plot_temperatures(pd4, 'run4', is_mm0, is_mm1)
    plot_fan_speeds(pd4, 'run4', is_mm0, is_mm1)
    plot_i2c_err_hist(pd4, 'run4', is_mm0, is_mm1)

mm0_v1_seus = count_seus_v(pd4[is_mm0], pd_p4, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd4[is_mm1], pd_p4, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd4, is_mm1)
print_tid(pd4)
print()


# load run 5 ###################################
print("Processing run 5...")

pd5 = read_csv_mm('logs/log_run5_mm.txt', 2.7e8)
pd_p5 = read_csv_psu('logs/log_run5_psu.txt', 5, 2.7e8)

is_mm0 = pd5['mm'] == 0
is_mm1 = pd5['mm'] == 1

# fit_consts = fit_v_measurements(pd5, pd_p5)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pd5 = fix_voltages(pd5, fit_consts)

# mark power cycles
find_power_cycles(pd5)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd5)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run5')
    plot_voltages_currents(pd5, pd_p5, 'run5', is_mm0, is_mm1, fit_consts)
    plot_temperatures(pd5, 'run5', is_mm0, is_mm1)
    plot_fan_speeds(pd5, 'run5', is_mm0, is_mm1)
    plot_i2c_err_hist(pd5, 'run5', is_mm0, is_mm1)

mm0_v1_seus = count_seus_v(pd5[is_mm0], pd_p5, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd5[is_mm1], pd_p5, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd5, is_mm1)
print_tid(pd5)
print()


# load run 6-1 ###################################
print("Processing run 6-1...")

pd61 = read_csv_mm('logs/log_run6_1_mm.txt', 2.3e8)
pd_p61 = read_csv_psu('logs/log_run6_1_psu.txt', 5, 2.3e8)

is_mm0 = pd61['mm'] == 0
is_mm1 = pd61['mm'] == 1

# fit_consts = fit_v_measurements(pd61, pd_p61)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pd61 = fix_voltages(pd61, fit_consts)

# mark power cycles
find_power_cycles(pd61)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd61, True)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run6-1')
    plot_voltages_currents(pd61, pd_p61, 'run6-1', is_mm0, is_mm1, fit_consts, True)
    plot_temperatures(pd61, 'run6-1', is_mm0, is_mm1, True)
    plot_fan_speeds(pd61, 'run6-1', is_mm0, is_mm1, True)
    plot_i2c_err_hist(pd61, 'run6-1', is_mm0, is_mm1, True)

mm0_v1_seus = count_seus_v(pd61[is_mm0], pd_p61, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd61[is_mm1], pd_p61, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd61, is_mm1)
print_tid(pd61)
print()


# load run 6-2 ###################################
print("Processing run 6-2...")

pd62 = read_csv_mm('logs/log_run6_2_mm.txt', 2.3e8)
pd_p62 = read_csv_psu('logs/log_run6_2_psu.txt', 5, 2.3e8)

is_mm0 = pd62['mm'] == 0
is_mm1 = pd62['mm'] == 1

# fit_consts = fit_v_measurements(pd62, pd_p62)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pd62 = fix_voltages(pd62, fit_consts)

# mark power cycles
find_power_cycles(pd62)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd62, True)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run6-2')
    plot_voltages_currents(pd62, pd_p62, 'run6-2', is_mm0, is_mm1, fit_consts, True)
    plot_temperatures(pd62, 'run6-2', is_mm0, is_mm1, True)
    plot_fan_speeds(pd62, 'run6-2', is_mm0, is_mm1, True)
    plot_i2c_err_hist(pd62, 'run6-2', is_mm0, is_mm1, True)

mm0_v1_seus = count_seus_v(pd62[is_mm0], pd_p62, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd62[is_mm1], pd_p62, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd62, is_mm1)
print_tid(pd62)
print()


# load run 7 ###################################
print("Processing run 7...")

pd7 = read_csv_mm('logs/log_run7_mm.txt', 2.3e8)
pd_p7 = read_csv_psu('logs/log_run7_psu.txt', 5, 2.3e8)

is_mm0 = pd7['mm'] == 0
is_mm1 = pd7['mm'] == 1

# fit_consts = fit_v_measurements(pd7, pd_p7)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pd7 = fix_voltages(pd7, fit_consts)

# mark power cycles
find_power_cycles(pd7)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd7, True)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run7')
    plot_voltages_currents(pd7, pd_p7, 'run7', is_mm0, is_mm1, fit_consts, True)
    plot_temperatures(pd7, 'run7', is_mm0, is_mm1, True)
    plot_fan_speeds(pd7, 'run7', is_mm0, is_mm1, True)
    plot_i2c_err_hist(pd7, 'run7', is_mm0, is_mm1, True)

mm0_v1_seus = count_seus_v(pd7[is_mm0], pd_p7, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd7[is_mm1], pd_p7, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd7, is_mm1)
print_tid(pd7)
print()


# load run 6-1 (clean) ###########################
print("Processing run 6-1 (clean)...")

pd61c = read_csv_mm('logs/log_run6_1_c_mm.txt', 2.3e8)
pd_p61c = read_csv_psu('logs/log_run6_1_c_psu.txt', 5, 2.3e8)

is_mm0 = pd61c['mm'] == 0
is_mm1 = pd61c['mm'] == 1

# fit_consts = fit_v_measurements(pd61, pd_p61)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pd61c = fix_voltages(pd61c, fit_consts)

# mark power cycles
find_power_cycles(pd61c)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd61c, True)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run6-1-c')
    plot_voltages_currents(pd61c, pd_p61c, 'run6-1-c', is_mm0, is_mm1, fit_consts, True)
    plot_temperatures(pd61c, 'run6-1-c', is_mm0, is_mm1, True)
    plot_fan_speeds(pd61c, 'run6-1-c', is_mm0, is_mm1, True)
    plot_i2c_err_hist(pd61c, 'run6-1-c', is_mm0, is_mm1, True)

mm0_v1_seus = count_seus_v(pd61c[is_mm0], pd_p61c, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd61c[is_mm1], pd_p61c, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd61c, is_mm1)
print_tid(pd61c)
print()


# load run 6-2 (clean) ###########################
print("Processing run 6-2 (clean)...")

pd62c = read_csv_mm('logs/log_run6_2_c_mm.txt', 2.3e8)
pd_p62c = read_csv_psu('logs/log_run6_2_c_psu.txt', 5, 2.3e8)

is_mm0 = pd62c['mm'] == 0
is_mm1 = pd62c['mm'] == 1

# fit_consts = fit_v_measurements(pd62c, pd_p62c)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pd62c = fix_voltages(pd62c, fit_consts)

# mark power cycles
find_power_cycles(pd62c)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd62c, True)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run6-2-c')
    plot_voltages_currents(pd62c, pd_p62c, 'run6-2-c', is_mm0, is_mm1, fit_consts, True)
    plot_temperatures(pd62c, 'run6-2-c', is_mm0, is_mm1, True)
    plot_fan_speeds(pd62c, 'run6-2-c', is_mm0, is_mm1, True)
    plot_i2c_err_hist(pd62c, 'run6-2-c', is_mm0, is_mm1, True)

mm0_v1_seus = count_seus_v(pd62c[is_mm0], pd_p62c, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd62c[is_mm1], pd_p62c, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd62c, is_mm1)
print_tid(pd62c)
print()


# load run 7 (clean) #############################
print("Processing run 7 (clean)...")

pd7c = read_csv_mm('logs/log_run7_c_mm.txt', 2.3e8)
pd_p7c = read_csv_psu('logs/log_run7_c_psu.txt', 5, 2.3e8)

is_mm0 = pd7c['mm'] == 0
is_mm1 = pd7c['mm'] == 1

# fit_consts = fit_v_measurements(pd7c, pd_p7c)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pd7c = fix_voltages(pd7c, fit_consts)

# mark power cycles
find_power_cycles(pd7c)

sefi_types, err_types, inbetween_types = calc_print_sefis(pd7c, True)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run7-c')
    plot_voltages_currents(pd7c, pd_p7c, 'run7-c', is_mm0, is_mm1, fit_consts, True)
    plot_temperatures(pd7c, 'run7-c', is_mm0, is_mm1, True)
    plot_fan_speeds(pd7c, 'run7-c', is_mm0, is_mm1, True)
    plot_i2c_err_hist(pd7c, 'run7-c', is_mm0, is_mm1, True)

mm0_v1_seus = count_seus_v(pd7c[is_mm0], pd_p7c, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pd7c[is_mm1], pd_p7c, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pd7c, is_mm1)
print_tid(pd7c)


# load log w/short ###############################
print("Processing log w/short...")

pds = read_csv_mm('logs/log_day1_short_mm.txt', 2.3e8)
pd_ps = read_csv_psu('logs/log_day1_short_psu.txt', 5, 2.3e8)

is_mm0 = pds['mm'] == 0
is_mm1 = pds['mm'] == 1

# fit_consts = fit_v_measurements(pds, pd_ps)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pds = fix_voltages(pds, fit_consts)

# mark power cycles
find_power_cycles(pds)

sefi_types, err_types, inbetween_types = calc_print_sefis(pds)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run_s')
    plot_voltages_currents(pds, pd_ps, 'run_s', is_mm0, is_mm1, fit_consts)
    plot_temperatures(pds, 'run_s', is_mm0, is_mm1)
    plot_fan_speeds(pds, 'run_s', is_mm0, is_mm1)
    plot_i2c_err_hist(pds, 'run_s', is_mm0, is_mm1)

mm0_v1_seus = count_seus_v(pds[is_mm0], pd_ps, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pds[is_mm1], pd_ps, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pds, is_mm1)
print_tid(pds)
print()


# load log after the short #######################
print("Processing log after the short...")

pdas = read_csv_mm('logs/log_day1_aftershort_mm.txt', 2.3e8)
pd_pas = read_csv_psu('logs/log_day1_aftershort_psu.txt', 5, 2.3e8)

is_mm0 = pdas['mm'] == 0
is_mm1 = pdas['mm'] == 1

# fit_consts = fit_v_measurements(pdas, pd_pas)
# fit_consts = [[0.9, -1.0, 1.04],
# fit_consts = [[1.0, -0.7, 1.042],
#               [1.0, -2.65, 1.66]]

# fix voltage data
pdas = fix_voltages(pdas, fit_consts)

# mark power cycles
find_power_cycles(pdas)

sefi_types, err_types, inbetween_types = calc_print_sefis(pdas)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'run_as')
    plot_voltages_currents(pdas, pd_pas, 'run_as', is_mm0, is_mm1, fit_consts)
    plot_temperatures(pdas, 'run_as', is_mm0, is_mm1)
    plot_fan_speeds(pdas, 'run_as', is_mm0, is_mm1)
    plot_i2c_err_hist(pdas, 'run_as', is_mm0, is_mm1)

mm0_v1_seus = count_seus_v(pdas[is_mm0], pd_pas, 1, fit_consts[0][0])
mm1_v1_seus = count_seus_v(pdas[is_mm1], pd_pas, 1, fit_consts[1][0])

# print("MM0 v1 SEUs: {}".format(mm0_v1_seus))
# print("MM1 v1 SEUs: {}".format(mm1_v1_seus))
print_tmr(pdas, is_mm1)
print_tid(pdas)
print()


# any cumulative stuff goes here

pd_day1 = concat_runs([pd1, pd2, pd3, pd4])
pd_p_day1 = concat_runs([pd_p1, pd_p2, pd_p3, pd_p4])
is_mm0 = pd_day1['mm'] == 0
is_mm1 = pd_day1['mm'] == 1
sefi_types, err_types, inbetween_types = calc_print_sefis(pd_day1)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'day1')
    plot_voltages_currents(pd_day1, pd_p_day1, 'day1', is_mm0, is_mm1, fit_consts)
    plot_temperatures(pd_day1, 'day1', is_mm0, is_mm1)
    plot_fan_speeds(pd_day1, 'day1', is_mm0, is_mm1)
    plot_i2c_err_hist(pd_day1, 'day1', is_mm0, is_mm1)


pd_day2 = concat_runs([pd61, pd62, pd7])
pd_p_day2 = concat_runs([pd_p61, pd_p62, pd_p7])
is_mm0 = pd_day2['mm'] == 0
is_mm1 = pd_day2['mm'] == 1
sefi_types, err_types, inbetween_types = calc_print_sefis(pd_day2, True)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'day2')
    plot_voltages_currents(pd_day2, pd_p_day2, 'day2', is_mm0, is_mm1, fit_consts, True)
    plot_temperatures(pd_day2, 'day2', is_mm0, is_mm1, True)
    plot_fan_speeds(pd_day2, 'day2', is_mm0, is_mm1, True)
    plot_i2c_err_hist(pd_day2, 'day2', is_mm0, is_mm1, True)


pd_day2c = concat_runs([pd61c, pd62c, pd7c])
pd_p_day2c = concat_runs([pd_p61c, pd_p62c, pd_p7c])
is_mm0 = pd_day2['mm'] == 0
is_mm1 = pd_day2['mm'] == 1
sefi_types, err_types, inbetween_types = calc_print_sefis(pd_day2c, True)

if doplots:
    plot_complex_i2c_err_hist(sefi_types, err_types, inbetween_types, 'day2c')
    plot_voltages_currents(pd_day2c, pd_p_day2c, 'day2c', is_mm0, is_mm1, fit_consts, True)
    plot_temperatures(pd_day2c, 'day2c', is_mm0, is_mm1, True)
    plot_fan_speeds(pd_day2c, 'day2c', is_mm0, is_mm1, True)
    plot_i2c_err_hist(pd_day2c, 'day2c', is_mm0, is_mm1, True)
