Esempio n. 1
0
def obtain_t(x, y):
    """
    Compute the Student's t value between two datasets
    :param x:
    :param y:
    :return: (t, df)
    t = Student's t value
    df = degrees of freedom
    """
    nx = length(x)
    ny = length(y)
    if nx == 0 or ny == 0:
        raise ValueError('obtain_t: datasets cannot have zero elements')
    xbar = np.mean(x)
    ybar = np.mean(y)
    numerator = np.abs(xbar - ybar)
    sx = ((np.sum(x**2) / nx) - (xbar**2)) / (nx - 1.0)
    sy = ((np.sum(y**2) / ny) - (ybar**2)) / (ny - 1.0)
    if sx < 0:
        sx = 0
    if sy < 0:
        sy = 0
    denominator = np.sqrt(sx + sy)
    if denominator == 0.0:
        t = 0
    else:
        t = numerator / denominator
    df_numerator = (sx + sy)**2
    df_denominator = ((sx**2) / (nx - 1.0)) + ((sy**2) / (ny - 1.0))
    if df_denominator == 0.0:
        df = 0.0
    else:
        df = numerator / denominator
    return t, df
Esempio n. 2
0
def dp_model_recomp_heating_cooling_trim(fs,
                                         q,
                                         k,
                                         t,
                                         th,
                                         dT_known,
                                         r0,
                                         get_gamma4=False):
    """
    Run the DP model, but take into consideration a trimmed curve that can be:
    (1) heating and cooling
    (2) cooling only
    DO NOT use this function for heating only.  Use the dp_model_recomp_heating() function below if
    only the heating curve is passed in.
    :param fs:                      as the sampling rate
    :param q:                       as the heat input into the soil
    :param k:                       as the thermal conductivity
    :param t:                       as the time vector
    :param th:                      as the threshold time
    :param dT_known:                as the known change in temperature
    :param r0:                      as the initial radius
    :param get_gamma4:              True to return gamma4 as well
    :return: r_t or (r_t, gamma4)
    """
    n = length(t)
    if length(dT_known) != n:
        raise ValueError(
            'dp_model_recomp_heating_cooling: the length of t must be the same as dT'
        )
    term = -(4 * pi * k) / q
    dt = 1 / fs
    if t[0] >= th:  # cooling only
        tvec_heat = []
        tvec_cool = t
        dT_known_heat = []
        dT_known_cool = dT_known
        gamma4_heat = []
    else:  # heating and cooling
        nheat = int(np.ceil(fs * (th - t[0])))
        tvec_heat = t[:nheat]
        tvec_cool = t[nheat:]
        dT_known_heat = dT_known[:nheat]
        dT_known_cool = dT_known[nheat:]
        gamma2_heat = term * dT_known_heat
        gamma3_heat = ei_inv_neg_array(gamma2_heat) * tvec_heat
        gamma4_heat = -gamma3_heat
    # COOLING
    dT_cool_strip = -term * dT_known_cool
    gamma4_cool = ei_inv_cooling(dT_cool_strip, th, tvec_cool)
    gamma4 = np.abs(np.concatenate((gamma4_heat, gamma4_cool)))
    r_t = dp_model_recomp_shared(k, t, q, gamma4, dt, r0)
    if get_gamma4:
        return r_t, gamma4
    return r_t
Esempio n. 3
0
def cut_to_zero(x, t):
    """
    Helper function to cut a sequence to zero
    :param x:       as the sequence
    :param t:       as the associated timestep
    :return:
    """
    n = length(x)
    if n != length(t):
        raise ValueError('cut_to_zero: x and t must have the same length')
    elem = x >= 0
    xout = x[elem]
    tout = t[elem]
    return xout, tout
Esempio n. 4
0
def dp_model_recomp_heating_cooling(fs,
                                    q,
                                    k,
                                    t,
                                    th,
                                    dT_known,
                                    r0,
                                    get_gamma4=False):
    """
    DP inverse model for heating and cooling.
    USE THIS FUNCTION ONLY FOR THE FULL CURVE THAT IS NOT TRIMMED.

    NOTE that the dT_known has to be sufficiently smooth for the derivative operation
    to not be contaminated by noise

    :param fs:                      as the sampling rate
    :param q:                       as the heat input into the soil
    :param k:                       as the thermal conductivity
    :param t:                       as the time vector
    :param th:                      as the time of heating
    :param dT_known:                as the change in temperature
    :param r0:                      as an assumed change in temperature
    :param get_gamma4:              True to obtain the gamma4
    :return:
    """
    n = length(t)
    if length(dT_known) != n:
        raise ValueError(
            'dp_model_recomp_heating_cooling: the length of t must be the same as dT'
        )
    term = -(4 * pi * k) / q
    dt = 1 / fs
    nn = int(np.ceil(fs * th))
    tvec_heat = t[:nn]
    tvec_cool = t[nn:]
    dT_known_heat = dT_known[:nn]
    dT_known_cool = dT_known[nn:]
    # HEATING
    gamma2_heat = term * dT_known_heat
    gamma3_heat = ei_inv_neg_array(gamma2_heat) * tvec_heat
    gamma4_heat = -gamma3_heat
    # COOLING
    dT_cool_strip = -term * dT_known_cool
    gamma4_cool = ei_inv_cooling(dT_cool_strip, th, tvec_cool)
    gamma4 = np.concatenate((gamma4_heat, gamma4_cool))
    r_t = dp_model_recomp_shared(k, t, q, gamma4, dt, r0)
    if get_gamma4:
        return r_t, gamma4
    return r_t
Esempio n. 5
0
def safe_div(x, y, replace=None):
    if replace is None:
        replace = float('NaN')
    n = length(x)
    out = np.zeros(n)
    if n != length(y):
        raise ValueError('save_div: cannot divide')
    for k in range(n):
        xx = x[k]
        yy = y[k]
        if yy == 0:
            out[k] = replace
        else:
            out[k] = xx / yy
    return out
def run_plot_output(alpha, fs, k, q, r0, run_full, t_heat, t, r):
    """
    Function required to generate the plot outputs for the demonstration
    :param alpha:
    :param fs:
    :param k:
    :param q:
    :param r0:
    :param run_full:
    :param t_heat:
    :param t:
    :param r:
    :return:
    """
    # Note that Ei(x=0) is not defined, so the time vector must be trimmed
    # The forward model is not defined at t = 0.
    tt = np.copy(t)
    tt = tt[1:]
    dt = 1 / fs
    n = length(tt)
    if run_full:  # run the complete algorithm for heating and cooling
        dT_dual = compute_delta_T_dual_heating_cooling(q, k, alpha, r, tt, t_heat, split=False)
        dT_dual_fixed = compute_delta_T_dual_heating_cooling(q, k, alpha, r0, tt, t_heat, split=False)
        r_t_det = dp_model_recomp_heating_cooling(fs, q, k, tt, t_heat, dT_dual, r0, get_gamma4=False)
    else:
        # only run the algorithm for heating
        dT_dual = compute_delta_T_dual_infinite_line_heating(q, k, alpha, r, tt)
        dT_dual_fixed = compute_delta_T_dual_infinite_line_heating(q, k, alpha, r0, tt)
        r_t_det = dp_model_recomp_heating(fs, q, k, tt, dT_dual, r0, get_gamma4=False)
    r_t_det_diff = r - r_t_det
    r_mm = r / 1.0e-3
    r_det_mm = r_t_det / 1.0e-3
    return dT_dual, dT_dual_fixed, r_det_mm, r_mm, r_t_det_diff, tt
    def inverse_warmup_curve_dp(self,
                                k,
                                dT_dual,
                                q,
                                t,
                                r0,
                                typ,
                                lowpass=False,
                                epsilon=0.0):
        """
        Obtain the inverse of the curve data
        Note that the inverse solution cannot be used for t = 0 since the solution is undefined at this point
        The first element is therefore sampled at timestep t = delta_t

        :param k:           as the thermal conductivity determined from the SP model (or assumed)
        :param dT_dual:     dual-probe warmup curve at distance of r(t) (Celcius or K)
        :param q:           inferred heat input (W/m)
        :param t:           vector of regular timestamps (t > 0) for DP
        :param r0:          initial single-probe radius

        :param typ:         'iterative' to use an iterative solution
                            'matrix' to use a matrix solution
                            'regularized' to use Tikhonov regularization

        :param epsilon:     regularization parameter to use in the Tikhanov solution

        :return: (alpha, r_t)
        alpha = thermal diffusivity (m^2 / s)
        r_t = time series showing change in r with respect to time t
        """
        n = length(t)
        dt = t[1] - t[0]  # timestep must be regular
        gamma2 = -dT_dual * ((4 * pi * k) / q)
        gamma3 = expi_inv_vect_neg(gamma2)
        gamma4 = -gamma3
        gamma5 = np.sqrt(gamma4 * t)
        gamma6 = np.log(gamma5)
        gamma7 = forward_first_derivative(gamma6, dt)
        log_r = np.log(r0)
        if typ == 'iterative':
            gamma8 = inverse_first_derivative(gamma7, dt, log_r)
        elif typ == 'matrix':
            self._set_ds(n)
            gamma8 = self.ds.solve_system_normal(gamma7, dt, log_r)
        elif typ == 'regularized':
            self._set_ds(n)
            gamma8 = self.ds.solve_system_tikreg_sparse(
                gamma7, dt, log_r, epsilon)
        else:
            raise ValueError(
                'inverse_warmup_curve: the type of inverse has not been specified'
            )
        gamma9 = np.exp(gamma8)
        r_t = gamma9
        alpha = obtain_alpha(q, k, r_t, t, gamma3)
        return alpha, r_t
Esempio n. 8
0
def ei_inv_neg_array(known):
    """
    Take the inverse of Ei(x) with x < 0
    :param known:
    :return:
    """
    n = length(known)
    out = np.zeros(n)
    for k in range(n):
        out[k] = ei_inv_neg(known[k])
    return out
Esempio n. 9
0
def test_small_argument():
    from ei import ei
    from get_alpha import get_alpha_k_C
    from get_volumetric_heat_capacity import get_volumetric_heat_capacity
    from gen_time_vec import gen_time_vec

    q = 50
    k = 4
    r0 = 5.0e-3
    r1 = 50e-3
    theta_o = 1.0e-3
    theta_w = 0.49
    theta_m = 1 - theta_o - theta_w
    C = get_volumetric_heat_capacity(theta_m, theta_o, theta_w)
    fs = 120
    dt = 1 / fs
    T = 30
    t = gen_time_vec(fs, T)
    t = t[1:]  # cannot start with zero
    n = length(t)
    r = np.linspace(r0, r1, n)
    alpha = get_alpha_k_C(k, C)
    print('alpha = ', alpha)
    gamma4 = r**2 / (4 * alpha)

    gamma5 = np.log(np.sqrt(gamma4))
    gamma5_comp = np.log(r) - np.log(2 * np.sqrt(alpha))
    gamma5_diff = gamma5 - gamma5_comp

    # take the average
    gamma6 = np.average(gamma5)
    N = length(gamma5)
    gamma6_comp = (1.0 / N) * np.sum(np.log(r)) - np.log(2 * np.sqrt(alpha))
    print('gamma6 = ', gamma6)
    print('gamma6_comp = ', gamma6_comp)
    print('diff = ', gamma6 - gamma6_comp)

    # subtract from original
    gamma7 = gamma5 - gamma6
    gamma7_comp = np.log(r) - (1 / N) * (np.sum(np.log(r)))
    gamma7_diff = gamma7 - gamma7_comp
Esempio n. 10
0
 def load_r0(self, path):
     """
     Load the radius r0
     :return:
     """
     array = np.load(path)
     q_range = array[QRANGE_IDENT]
     r0 = array[R0_IDENT]
     check_same_size(q_range, r0, self.ERR_STR)
     n = length(q_range)
     for k in range(n):
         s = str(q_range[k])
         self.lookup[s] = r0[k]
def forward_first_derivative(x, dx):
    """
    Take the first derivative using a two-point stencil
    :param x:       as the vector
    :param dx:      as the step between elements
    :return:
    """
    n = length(x)
    nsub1 = n - 1
    out = np.zeros(nsub1)
    cnt = 0
    for i in range(1, n):
        out[cnt] = (x[i] - x[i - 1]) / dx
        cnt += 1
    return out
Esempio n. 12
0
def normalize_open_interval(x, normalized=False, s=0.5):
    """
    Function to normalize data on the open interval (0,1)
    INPUTS
    x = data vector
    normalized = True if the function has already been normalized
    s = Bayesian estimator = 0.5 (see paper [3] for details)
    REFERENCES: [2],[3]
    """
    if (normalized is False):
        x0 = normalize_regular(x)
    else:
        x0 = x
    N = length(x0)
    y = (x0 * (N - 1) + s) / N
    return y
Esempio n. 13
0
def compute_delta_T_dual_heating_q_H(q, k, H, t):
    """
    Compute the synthetic curve using the heating and cooling with only H
    :param q:           quantity of heat liberated
    :param k:           thermal conductivity
    :param H:           H parameter
    :param t:           time vector
    :param t_heating:   time at which heating ends
    :return:
    """
    n = length(t)
    out = np.zeros(n)
    first = term1(q, k)
    second = ei(-H / t)
    out = first * second
    return out
def inverse_first_derivative(xprime, dt, a0):
    """
    Take the inverse of the first derivative using recursion
    :param xprime:          as the derivative vector
    :param dt:              as the timestep between vectors
    :param a0:              as the known first element (boundary condition)
    :return:
    """
    n = length(xprime)
    n1 = n + 1
    out = np.zeros(n1)
    out[0] = a0
    cnt = 0
    for i in range(1, n1):
        out[i] = xprime[cnt] * dt + out[cnt]
        cnt += 1
    return out
def expi_inv_vect_neg(known):
    """
    Take the inverse of expi over a vector.  Here it is known that
    x < 0.

    NOTE that this function cannot be applied if x > 0.

    :param known:
    :param neg:
    :param radius:
    :return:
    """
    n = length(known)
    out = np.zeros(n)
    for k in range(n):
        out[k] = exp_integral.Eid_inv_negative(known[k])
    return out
Esempio n. 16
0
def ei_inv_cooling(fxy, th, tc):
    """
    Function to compute the inverse of f(x, y) = Ei(-x) - Ei(-y)
    NOTE that Nelder-Mead function works well, and that an operation can cause underflow.
    :param fxy:     as the function
    :param th:      as the time of heating
    :param tc:      as the cooling time vector
    :return:
    """
    def _func(x, *args):
        hh = x[0]
        known = args[0]
        th_known = args[1]
        t_known = args[2]
        upper = args[3]
        xx = hh / (t_known - th_known)
        yy = hh / t_known
        first = ei(-xx)
        second = ei(-yy)
        calc = first - second  # this operation can be subject to invalid floating point math
        if calc < 0:
            calc = eps
        elif calc > upper:
            calc = upper - eps
        out = known - calc
        if out < 0:  # compute absolute value (do this directly in case multiple precision math is required)
            out = -out
        return out

    nn = length(fxy)
    recon = np.zeros(nn)
    hstart = 80
    xstart = (hstart, )
    th_known = th
    for k in range(nn):
        t_known = tc[k]
        term = t_known - th_known
        known = fxy[k]
        z = np.sqrt(term / t_known)
        upper = term * (((1 + z) / z) * (1 / known))**2
        args = (known, th, t_known, upper)
        res = minimize(_func, xstart, args, method='Nelder-Mead',
                       tol=1.0e-30)  # NOTE THE TOLERANCE REQUIRED
        recon[k] = res.x[0]
    return recon
Esempio n. 17
0
def _deriv_3pt_common(x, dx, t, typ):
    if typ == 'first':
        f = _first
        dx2 = 2.0 * dx
    elif typ == 'second':
        f = _second
        dx2 = dx**2
    else:
        raise ValueError('Type of derivative not recognized')
    n = length(x)
    nn = n - 2
    out = np.zeros(nn)
    cnt = 0
    tt = t[1:-1]
    for k in range(1, n-1):
        out[cnt] = f(x, k, dx2)
        cnt += 1
    return tt, out
Esempio n. 18
0
def test_full_inverse_heating():
    q = 50
    k = 4
    r0 = 5.7e-3
    r1 = 15e-3
    theta_o = 1.0e-3
    theta_w = 0.49
    theta_m = 1 - theta_o - theta_w
    C = get_volumetric_heat_capacity(theta_m, theta_o, theta_w)
    fs = 12
    dt = 1 / fs
    T = 30
    t = gen_time_vec(fs, T)
    t = t[1:]  # cannot start with zero
    n = length(t)
    r = np.linspace(r0, r1, n)
    alpha = get_alpha_k_C(k, C)
    t_heating = 8
    th = t_heating

    # dT = compute_delta_T_dual_infinite_line_heating(q, k, alpha, r, t)  # obtain the forward model
    # r0_found, r_t = recomp_radius(fs, q, k, t, dT)
    # print('r0 = ', r0)
    # print('r0_found = ', r0_found)

    gamma4 = (r**2) / (4 * alpha)

    gamma5 = np.sqrt(gamma4)
    gamma5_comp = r / (2 * np.sqrt(alpha))

    gamma6 = np.log(gamma5)
    gamma7 = forward_first_derivative(gamma6, dt)
    gamma7_comp = forward_first_derivative(np.log(r), dt)

    r0_in = r0
    gamma8 = np.exp(inverse_first_derivative(gamma7, dt, np.log(r0_in)))
    gamma8 = gamma8 - gamma8[0]
    print('delta_r = ', r[2] - r[1])
    print('delta_r = ', gamma8[2] - gamma8[1])

    plt.figure()
    plt.plot(gamma8)
    plt.plot(r)
    plt.show()
Esempio n. 19
0
def sp_model_late_time_inv(dT, t, dt, q, entire_heating_time=False, return_all=False):
    """
    Obtain the k value from the late-time inverse
    :param dT:                          change in temperature
    :param t:                           time vector
    :param dt:                          time step
    :param q:                           heat input into soil
    :param entire_heating_time:         True to not search for when the curve becomes linear
    :return: (tlinear, kdet)
    tlinear         = time at which the curve becomes linear
    kdet            = determined k
    """
    TADD = 1.0          # time additional to take when the curve is linear (ensures linearity)
    log_t = np.log(t)   # t cannot be zero since we are taking the logarithm
    if not entire_heating_time:
        tt, sd = second_derivative_3pt(dT, dt, log_t)
        nn = length(sd)
        kk = 0
        for k in range(1, nn):      # zero-crossing detector to determine when the curve is linear
            check = sd[k]           # start at the first element
            if check < 0:
                kk = k
                break
        k2 = kk-2
        if k2 < 0:                  # ensure that the element selected is not less than 0
            k2 = 0
        tlinear = t[k2] + TADD      # time at which the curve becomes linear
        fs = 1.0/dt                 # sampling frequency used to compute the cut time
        tlinear_cut_elem = int(np.ceil(tlinear*fs))
        t_tlinear = t[tlinear_cut_elem:]
        dT_tlinear = dT[tlinear_cut_elem:]
    else:  # bypass cutting the curve
        t_tlinear = t
        dT_tlinear = dT
        tlinear = 0

    # take the curve with the late time since this is fit over the late time section of the curve
    t_tlinear0 = t_tlinear
    dT_tlinear0 = dT_tlinear

    kdet, bdet = sp_model_late_time_inv_optim(dT_tlinear0, t_tlinear0, q)
    if not return_all:
        return tlinear, kdet
    return tlinear, kdet, bdet, t_tlinear0, dT_tlinear0
Esempio n. 20
0
def gen_radius(r0, r1, t, th, sd, heat_cool=False):
    """
    Generate a radius suitable for demonstrating the inverse
    :param r0:              as the starting radius
    :param r1:              as the ending radius
    :param t:               as the total time vector
    :param th:              as the time of heating
    :param sd:              as the standard deviation
    :param heat_cool:       True to generate heating and cooling curves
    :return:
    """
    n = length(t)               # obtain the length of t
    if heat_cool:               # run over the heating and cooling curve
        a = r1                  # height of the peak at the maximum radius
        b = th                  # height of the peak time
        c = sd                  # standard deviation
        rout = r0 + gaussian(a, b, c, t)
    else:
        rout = np.linspace(r0, r1, n)
    return rout
Esempio n. 21
0
def compute_delta_T_dual_heating_cooling(q,
                                         k,
                                         alpha,
                                         r,
                                         t,
                                         t_heating,
                                         split=False):
    """
    Compute the synthetic curve using the heating and cooling
    :param q:           quantity of heat liberated
    :param k:           thermal conductivity
    :param alpha:       thermal diffusivity
    :param r:           probe radius
    :param t:           time vector
    :param t_heating:   time at which heating ends
    :return:
    """
    n = length(t)
    out = np.zeros(n)
    first = term1(q, k)
    second = -first
    dt = t[1] - t[0]
    fs = 1.0 / dt
    nn = int(np.ceil(fs * t_heating))
    tvec_heat = t[:nn]
    tvec_cool = t[nn:]
    if is_numpy(r):  # variable r
        rheat = r[:nn]
        rcool = r[nn:]
    else:  # fixed r
        rheat = r
        rcool = r
    heating = compute_delta_T_dual_infinite_line_heating(
        q, k, alpha, rheat, tvec_heat)
    ei_term3 = ei(term3(rcool, alpha, tvec_cool, t_heating))
    ei_term2 = ei(term2(rcool, alpha, tvec_cool))
    cooling = second * (ei_term3 - ei_term2)
    out = np.append(heating, cooling)
    if split:
        return out, heating, cooling, first, second, tvec_heat, tvec_cool, rheat, rcool, ei_term3, ei_term2
    return out
Esempio n. 22
0
 def find_curve_changes(self, x):
     nx = length(x)
     n = nx - 2 * self.ws
     start = 0
     end = self.ws
     mid = int(np.floor(0.5 * (start + end)))
     out = np.zeros(nx)  # output is same size as the initial input
     for k in range(n):
         first = x[start:mid]
         second = x[mid + 1:end]
         mid += 1
         if first.size == 0 or second.size == 0:
             break
         test = self.st.run(first, second)
         if test:
             out[mid] = CURVE_CHANGE_TRUE_VAL
         else:
             out[mid] = CURVE_CHANGE_FALSE_VAL
         # switch out the endpoints
         start += 1
         end += 1
     return out
Esempio n. 23
0
def compute_delta_T_dual_heating_cooling_q_H(q, k, H, t, t_heating):
    """
    Compute the synthetic curve using the heating and cooling with only H
    :param q:           quantity of heat liberated
    :param k:           thermal conductivity
    :param H:           H parameter
    :param t:           time vector
    :param t_heating:   time at which heating ends
    :return:
    """
    n = length(t)
    out = np.zeros(n)
    first = term1(q, k)
    for k in range(n):
        tk = t[k]
        if tk > t_heating:
            second = ei(-H / (tk - t_heating)) - ei(-H / tk)
            second = -second
        else:
            second = ei(-H / tk)
        out[k] = first * second
    return out
def average_downsample(fsample, fwanted, v):
    """
    Downsample a signal over a series of windows
    :param fsample:     as the actual sampling rate
    :param fwanted:     as the wanted sampling rate
    :param v:
    :return:
    """
    n = int(np.ceil(fsample / fwanted))  # number of points in the window
    nlen = length(v)
    nwin = int(nlen / n)  # number of windows
    begin = 0
    end = n
    out = np.zeros(
        nwin)  # the output has the same length as the number of windows
    for k in range(nwin):
        win = v[begin:end]
        av = np.average(win)
        out[k] = av
        begin = end
        end += n
    return out
Esempio n. 25
0
def data_analysis_for_trials():
    """
    Perform the data analysis for all trials
    :return:
    """
    print('Loading data...')
    experiments = pickle.load(open(DATA_PICKLE_FILE_VEC, "rb"))

    theta_nom_sand, rho_nom_sand, theta_sig_sand, rho_sig_sand, \
    alpha_det_sand, alpha_sig_sand, k_det_sand, kdet_sig_sand, kdet_linear_sand, qav_vec_sand, qknown_vec_sand\
        = experiments[SAND_NAME]

    theta_nom_peat, rho_nom_peat, theta_sig_peat, rho_sig_peat, \
    alpha_det_peat, alpha_sig_peat, k_det_peat, kdet_sig_peat, kdet_linear_peat, qav_vec_peat, qknown_vec_peat\
        = experiments[PEAT_NAME]
    print('Done loading data...')

    ################################################################

    # compute the RMSD, MB and PD for sand and peat q (the heat input into the soil)
    print('Computing q comparisons')
    rmsd_sand_q = compute_rmse(qknown_vec_sand, qav_vec_sand)
    rmsd_peat_q = compute_rmse(qknown_vec_peat, qav_vec_peat)
    mb_sand_q = compute_mb(qknown_vec_sand, qav_vec_sand)
    mb_peat_q = compute_mb(qknown_vec_peat, qav_vec_peat)
    pd_sand_q = compute_pd(qknown_vec_sand, qav_vec_sand)
    pd_peat_q = compute_pd(qknown_vec_peat, qav_vec_peat)
    comp_list = [('sand',  rmsd_sand_q, mb_sand_q,  pd_sand_q),
                 ('peat', rmsd_peat_q, mb_peat_q, pd_peat_q)]
    labels = ['soil', 'rmsd', 'mb', 'pd']
    df_q = pd.DataFrame.from_records(comp_list, columns=labels)
    df_q.to_html(TABLE_PATH + TABLE_NAME_Q_COMP + HTML_EXT)
    print('DONE saving out HTML comparisons for q')

    ################################################################

    # first sequence of experiments
    ns = length(theta_nom_sand)
    xs = np.linspace(1, ns, ns)

    # second sequence of experiments
    nnp = length(theta_nom_peat)
    xp = np.linspace(xs[-1]+1, xs[-1]+nnp, nnp)

    # break the sequences up for each set so that the stats can be run

    ########################
    # NUMBERS SAND
    ########################
    start_num = 1
    end_num = 5
    calc_sand_theta_nom_sand_num_1_5 = cut_seq_trial(theta_nom_sand, start_num, end_num)
    calc_sand_rho_nom_sand_num_1_5 = cut_seq_trial(rho_nom_sand, start_num, end_num)
    calc_sand_theta_sig_sand_num_1_5 = cut_seq_trial(theta_sig_sand, start_num, end_num)
    calc_sand_rho_sig_sand_num_1_5 = cut_seq_trial(rho_sig_sand, start_num, end_num)

    # theta nominal for sand 1-5
    rmse__calc_sand_theta_nom_sand_num_1_5 = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_1_5)
    mb__calc_sand_theta_nom_sand_num_1_5 = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_1_5)
    pd__calc_sand_theta_nom_sand_num_1_5 = compute_percentage_diff(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_1_5)
    variance__calc_sand_theta_nom_sand_num_1_5 = compute_variance(calc_sand_theta_nom_sand_num_1_5)
    sd__calc_sand_theta_nom_sand_num_1_5 = compute_sd(calc_sand_theta_nom_sand_num_1_5)

    # rho nominal for sand 1-5
    rmse__calc_sand_rho_nom_sand_num_1_5 = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_1_5)
    mb__calc_sand_rho_nom_sand_num_1_5 = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_1_5)
    pd__calc_sand_rho_nom_sand_num_1_5 = compute_percentage_diff(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_1_5)
    variance__calc_rho_theta_nom_sand_num_1_5 = compute_variance(calc_sand_rho_nom_sand_num_1_5)
    sd__calc_sand_rho_nom_sand_num_1_5 = compute_sd(calc_sand_rho_nom_sand_num_1_5)

    # theta signal for sand 1-5
    rmse__calc_sand_theta_sig_sand_num_1_5 = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_1_5)
    mb__calc_sand_theta_sig_sand_num_1_5 = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_1_5)
    pd__calc_sand_theta_sig_sand_num_1_5 = compute_percentage_diff(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_1_5)
    variance__calc_sand_theta_sig_sand_num_1_5 = compute_variance(calc_sand_theta_sig_sand_num_1_5)
    sd__calc_sand_theta_sig_sand_num_1_5 = compute_sd(calc_sand_theta_sig_sand_num_1_5)

    # rho signal for sand 1-5
    rmse__calc_sand_rho_sig_sand_num_1_5 = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_1_5)
    mb__calc_sand_rho_sig_sand_num_1_5 = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_1_5)
    pd__calc_sand_rho_sig_sand_num_1_5 = compute_percentage_diff(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_1_5)
    variance__calc_rho_sig_nom_sand_num_1_5 = compute_variance(calc_sand_rho_sig_sand_num_1_5)
    sd__calc_sand_rho_sig_sand_num_1_5 = compute_sd(calc_sand_rho_sig_sand_num_1_5)

    ##########################################################################################

    start_num = 6
    end_num = 10
    calc_sand_theta_nom_sand_num_6_10 = cut_seq_trial(theta_nom_sand, start_num, end_num)
    calc_sand_rho_nom_sand_num_6_10 = cut_seq_trial(rho_nom_sand, start_num, end_num)
    calc_sand_theta_sig_sand_num_6_10 = cut_seq_trial(theta_sig_sand, start_num, end_num)
    calc_sand_rho_sig_sand_num_6_10 = cut_seq_trial(rho_sig_sand, start_num, end_num)

    # theta nominal for sand 6-10
    rmse__calc_sand_theta_nom_sand_num_6_10 = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_6_10)
    mb__calc_sand_theta_nom_sand_num_6_10 = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_6_10)
    pd__calc_sand_theta_nom_sand_num_6_10 = compute_percentage_diff(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_6_10)
    variance__calc_sand_theta_nom_sand_num_6_10 = compute_variance(calc_sand_theta_nom_sand_num_6_10)
    sd__calc_sand_theta_nom_sand_num_6_10 = compute_sd(calc_sand_theta_nom_sand_num_6_10)

    # rho nominal for sand 6-10
    rmse__calc_sand_rho_nom_sand_num_6_10 = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_6_10)
    mb__calc_sand_rho_nom_sand_num_6_10 = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_6_10)
    pd__calc_sand_rho_nom_sand_num_6_10 = compute_percentage_diff(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_6_10)
    variance__calc_rho_theta_nom_sand_num_6_10 = compute_variance(calc_sand_rho_nom_sand_num_6_10)
    sd__calc_sand_rho_nom_sand_num_6_10 = compute_sd(calc_sand_rho_nom_sand_num_6_10)

    # theta signal for sand 6-10
    rmse__calc_sand_theta_sig_sand_num_6_10 = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_6_10)
    mb__calc_sand_theta_sig_sand_num_6_10 = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_6_10)
    pd__calc_sand_theta_sig_sand_num_6_10 = compute_percentage_diff(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_6_10)
    variance__calc_sand_theta_sig_sand_num_6_10 = compute_variance(calc_sand_theta_sig_sand_num_6_10)
    sd__calc_sand_theta_sig_sand_num_6_10 = compute_sd(calc_sand_theta_sig_sand_num_6_10)

    # rho signal for sand 6-10
    rmse__calc_sand_rho_sig_sand_num_6_10 = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_6_10)
    mb__calc_sand_rho_sig_sand_num_6_10 = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_6_10)
    pd__calc_sand_rho_sig_sand_num_6_10 = compute_percentage_diff(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_6_10)
    variance__calc_rho_sig_nom_sand_num_6_10 = compute_variance(calc_sand_rho_sig_sand_num_6_10)
    sd__calc_sand_rho_sig_sand_num_6_10 = compute_sd(calc_sand_rho_sig_sand_num_6_10)

    ##########################################################################################

    start_num = 11
    end_num = 15
    calc_sand_theta_nom_sand_num_11_15 = cut_seq_trial(theta_nom_sand, start_num, end_num)
    calc_sand_rho_nom_sand_num_11_15 = cut_seq_trial(rho_nom_sand, start_num, end_num)
    calc_sand_theta_sig_sand_num_11_15 = cut_seq_trial(theta_sig_sand, start_num, end_num)
    calc_sand_rho_sig_sand_num_11_15 = cut_seq_trial(rho_sig_sand, start_num, end_num)

    # theta nominal for sand 11-15
    rmse__calc_sand_theta_nom_sand_num_11_15 = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_11_15)
    mb__calc_sand_theta_nom_sand_num_11_15 = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_11_15)
    pd__calc_sand_theta_nom_sand_num_11_15 = compute_percentage_diff(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_11_15)
    variance__calc_sand_theta_nom_sand_num_11_15 = compute_variance(calc_sand_theta_nom_sand_num_11_15)
    sd__calc_sand_theta_nom_sand_num_11_15 = compute_sd(calc_sand_theta_nom_sand_num_11_15)

    # rho nominal for sand 11-15
    rmse__calc_sand_rho_nom_sand_num_11_15 = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_11_15)
    mb__calc_sand_rho_nom_sand_num_11_15 = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_11_15)
    pd__calc_sand_rho_nom_sand_num_11_15 = compute_percentage_diff(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_11_15)
    variance__calc_rho_theta_nom_sand_num_11_15 = compute_variance(calc_sand_rho_nom_sand_num_11_15)
    sd__calc_sand_rho_nom_sand_num_11_15 = compute_sd(calc_sand_rho_nom_sand_num_11_15)

    # theta signal for sand 11-15
    rmse__calc_sand_theta_sig_sand_num_11_15 = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_11_15)
    mb__calc_sand_theta_sig_sand_num_11_15 = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_11_15)
    pd__calc_sand_theta_sig_sand_num_11_15 = compute_percentage_diff(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_11_15)
    variance__calc_sand_theta_sig_sand_num_11_15 = compute_variance(calc_sand_theta_sig_sand_num_11_15)
    sd__calc_sand_theta_sig_sand_num_11_15 = compute_sd(calc_sand_theta_sig_sand_num_11_15)

    # rho signal for sand 11-15
    rmse__calc_sand_rho_sig_sand_num_11_15 = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_11_15)
    mb__calc_sand_rho_sig_sand_num_11_15 = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_11_15)
    pd__calc_sand_rho_sig_sand_num_11_15 = compute_percentage_diff(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_11_15)
    variance__calc_rho_sig_nom_sand_num_11_15 = compute_variance(calc_sand_rho_sig_sand_num_11_15)
    sd__calc_sand_rho_sig_sand_num_11_15 = compute_sd(calc_sand_rho_sig_sand_num_11_15)

    #################################################################################################

    start_num = 16
    end_num = 20
    calc_sand_theta_nom_sand_num_16_20 = cut_seq_trial(theta_nom_sand, start_num, end_num)
    calc_sand_rho_nom_sand_num_16_20 = cut_seq_trial(rho_nom_sand, start_num, end_num)
    calc_sand_theta_sig_sand_num_16_20 = cut_seq_trial(theta_sig_sand, start_num, end_num)
    calc_sand_rho_sig_sand_num_16_20 = cut_seq_trial(rho_sig_sand, start_num, end_num)

    # theta nominal for sand 16-20
    rmse__calc_sand_theta_nom_sand_num_16_20 = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_16_20)
    mb__calc_sand_theta_nom_sand_num_16_20 = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_num_16_20)
    pd__calc_sand_theta_nom_sand_num_16_20 = compute_percentage_diff(THETA_NOMINAL_SAND,
                                                                     calc_sand_theta_nom_sand_num_16_20)
    variance__calc_sand_theta_nom_sand_num_16_20 = compute_variance(calc_sand_theta_nom_sand_num_16_20)
    sd__calc_sand_theta_nom_sand_num_16_20 = compute_sd(calc_sand_theta_nom_sand_num_16_20)

    # rho nominal for sand 16-20
    rmse__calc_sand_rho_nom_sand_num_16_20 = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_16_20)
    mb__calc_sand_rho_nom_sand_num_16_20 = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_num_16_20)
    pd__calc_sand_rho_nom_sand_num_16_20 = compute_percentage_diff(DENSITY_NOMINAL_SAND,
                                                                   calc_sand_rho_nom_sand_num_16_20)
    variance__calc_rho_theta_nom_sand_num_16_20 = compute_variance(calc_sand_rho_nom_sand_num_16_20)
    sd__calc_sand_rho_nom_sand_num_16_20 = compute_sd(calc_sand_rho_nom_sand_num_16_20)

    # theta signal for sand 16-20
    rmse__calc_sand_theta_sig_sand_num_16_20 = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_16_20)
    mb__calc_sand_theta_sig_sand_num_16_20 = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_num_16_20)
    pd__calc_sand_theta_sig_sand_num_16_20 = compute_percentage_diff(THETA_NOMINAL_SAND,
                                                                     calc_sand_theta_sig_sand_num_16_20)
    variance__calc_sand_theta_sig_sand_num_16_20 = compute_variance(calc_sand_theta_sig_sand_num_16_20)
    sd__calc_sand_theta_sig_sand_num_16_20 = compute_sd(calc_sand_theta_sig_sand_num_16_20)

    # rho signal for sand 16-20
    rmse__calc_sand_rho_sig_sand_num_16_20 = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_16_20)
    mb__calc_sand_rho_sig_sand_num_16_20 = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_num_16_20)
    pd__calc_sand_rho_sig_sand_num_16_20 = compute_percentage_diff(DENSITY_NOMINAL_SAND,
                                                                   calc_sand_rho_sig_sand_num_16_20)
    variance__calc_rho_sig_nom_sand_num_16_20 = compute_variance(calc_sand_rho_sig_sand_num_16_20)
    sd__calc_sand_rho_sig_sand_num_16_20 = compute_sd(calc_sand_rho_sig_sand_num_16_20)

    ########################
    # NUMBERS PEAT
    ########################

    start_num = 1
    end_num = 5
    calc_peat_theta_nom_peat_num_21_25 = cut_seq_trial(theta_nom_peat, start_num, end_num)
    calc_peat_rho_nom_peat_num_21_25 = cut_seq_trial(rho_nom_peat, start_num, end_num)
    calc_peat_theta_sig_peat_num_21_25 = cut_seq_trial(theta_sig_peat, start_num, end_num)
    calc_peat_rho_sig_peat_num_21_25 = cut_seq_trial(rho_sig_peat, start_num, end_num)

    # theta nominal for peat 21-25
    rmse__calc_peat_theta_nom_peat_num_21_25 = compute_rmse(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_21_25)
    mb__calc_peat_theta_nom_peat_num_21_25 = compute_mb(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_21_25)
    pd__calc_peat_theta_nom_peat_num_21_25 = compute_percentage_diff(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_21_25)
    variance__calc_peat_theta_nom_peat_num_21_25 = compute_variance(calc_peat_theta_nom_peat_num_21_25)
    sd__calc_peat_theta_nom_peat_num_21_25 = compute_sd(calc_peat_theta_nom_peat_num_21_25)

    # rho nominal for peat 21-25
    rmse__calc_peat_rho_nom_sand_num_21_25 = compute_rmse(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_21_25)
    mb__calc_peat_rho_nom_sand_num_21_25 = compute_mb(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_21_25)
    pd__calc_peat_rho_nom_sand_num_21_25 = compute_percentage_diff(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_21_25)
    variance__calc_peat_rho_theta_nom_sand_num_21_25 = compute_variance(calc_peat_rho_nom_peat_num_21_25)
    sd__calc_peat_rho_nom_sand_num_21_25 = compute_sd(calc_peat_rho_nom_peat_num_21_25)

    # theta signal for peat 21-25
    rmse__calc_peat_theta_sig_sand_num_21_25 = compute_rmse(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_21_25)
    mb__calc_peat_theta_sig_sand_num_21_25 = compute_mb(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_21_25)
    pd__calc_peat_theta_sig_sand_num_21_25 = compute_percentage_diff(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_21_25)
    variance__calc_peat_theta_sig_sand_num_21_25 = compute_variance(calc_peat_theta_sig_peat_num_21_25)
    sd__calc_peat_theta_sig_sand_num_21_25 = compute_sd(calc_peat_theta_sig_peat_num_21_25)

    # rho signal for peat 21-25
    rmse__calc_peat_rho_sig_peat_num_21_25 = compute_rmse(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_21_25)
    mb__calc_peat_rho_sig_peat_num_21_25 = compute_mb(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_21_25)
    pd__calc_peat_rho_sig_peat_num_21_25 = compute_percentage_diff(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_21_25)
    variance__calc_peat_rho_sig_nom_peat_num_21_25 = compute_variance(calc_peat_rho_sig_peat_num_21_25)
    sd__calc_peat_rho_sig_peat_num_21_25 = compute_sd(calc_peat_rho_sig_peat_num_21_25)

    #########################################################################################################

    start_num = 6
    end_num = 10
    calc_peat_theta_nom_peat_num_26_30 = cut_seq_trial(theta_nom_peat, start_num, end_num)
    calc_peat_rho_nom_peat_num_26_30 = cut_seq_trial(rho_nom_peat, start_num, end_num)
    calc_peat_theta_sig_peat_num_26_30 = cut_seq_trial(theta_sig_peat, start_num, end_num)
    calc_peat_rho_sig_peat_num_26_30 = cut_seq_trial(rho_sig_peat, start_num, end_num)

    # theta nominal for peat 26-30
    rmse__calc_peat_theta_nom_peat_num_26_30 = compute_rmse(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_26_30)
    mb__calc_peat_theta_nom_peat_num_26_30 = compute_mb(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_26_30)
    pd__calc_peat_theta_nom_peat_num_26_30 = compute_percentage_diff(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_26_30)
    variance__calc_peat_theta_nom_peat_num_26_30 = compute_variance(calc_peat_theta_nom_peat_num_26_30)
    sd__calc_peat_theta_nom_peat_num_26_30 = compute_sd(calc_peat_theta_nom_peat_num_26_30)

    # rho nominal for peat 26-30
    rmse__calc_peat_rho_nom_peat_num_26_30 = compute_rmse(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_26_30)
    mb__calc_peat_rho_nom_peat_num_26_30 = compute_mb(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_26_30)
    pd__calc_peat_rho_nom_peat_num_26_30 = compute_percentage_diff(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_26_30)
    variance__calc_peat_rho_theta_nom_peat_num_26_30 = compute_variance(calc_peat_rho_nom_peat_num_26_30)
    sd__calc_peat_rho_nom_peat_num_26_30 = compute_sd(calc_peat_rho_nom_peat_num_26_30)

    # theta signal for peat 26-30
    rmse__calc_peat_theta_sig_peat_num_26_30 = compute_rmse(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_26_30)
    mb__calc_peat_theta_sig_peat_num_26_30 = compute_mb(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_26_30)
    pd__calc_peat_theta_sig_peat_num_26_30 = compute_percentage_diff(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_26_30)
    variance__calc_peat_theta_sig_peat_num_26_30 = compute_variance(calc_peat_theta_sig_peat_num_26_30)
    sd__calc_peat_theta_sig_peat_num_26_30 = compute_sd(calc_peat_theta_sig_peat_num_26_30)

    # rho signal for peat 26-30
    rmse__calc_peat_rho_sig_peat_num_26_30 = compute_rmse(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_26_30)
    mb__calc_peat_rho_sig_peat_num_26_30 = compute_mb(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_26_30)
    pd__calc_peat_rho_sig_peat_num_26_30 = compute_percentage_diff(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_26_30)
    variance__calc_peat_rho_sig_nom_peat_num_26_30 = compute_variance(calc_peat_rho_sig_peat_num_26_30)
    sd__calc_peat_rho_sig_peat_num_26_30 = compute_sd(calc_peat_rho_sig_peat_num_26_30)

    #########################################################################################################

    start_num = 11
    end_num = 15
    calc_peat_theta_nom_peat_num_31_35 = cut_seq_trial(theta_nom_peat, start_num, end_num)
    calc_peat_rho_nom_peat_num_31_35 = cut_seq_trial(rho_nom_peat, start_num, end_num)
    calc_peat_theta_sig_peat_num_31_35 = cut_seq_trial(theta_sig_peat, start_num, end_num)
    calc_peat_rho_sig_peat_num_31_35 = cut_seq_trial(rho_sig_peat, start_num, end_num)

    # theta nominal for peat 31-25
    rmse__calc_peat_theta_nom_peat_num_31_35 = compute_rmse(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_31_35)
    mb__calc_peat_theta_nom_peat_num_31_35 = compute_mb(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_31_35)
    pd__calc_peat_theta_nom_peat_num_31_35 = compute_percentage_diff(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_num_31_35)
    variance__calc_peat_theta_nom_peat_num_31_35 = compute_variance(calc_peat_theta_nom_peat_num_31_35)
    sd__calc_peat_theta_nom_peat_num_31_35 = compute_sd(calc_peat_theta_nom_peat_num_31_35)

    # rho nominal for peat 31-25
    rmse__calc_peat_rho_nom_peat_num_31_35 = compute_rmse(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_31_35)
    mb__calc_peat_rho_nom_peat_num_31_35 = compute_mb(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_31_35)
    pd__calc_peat_rho_nom_peat_num_31_35 = compute_percentage_diff(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_num_31_35)
    variance__calc_peat_rho_theta_nom_peat_num_31_35 = compute_variance(calc_peat_rho_nom_peat_num_31_35)
    sd__calc_peat_rho_nom_peat_num_31_35 = compute_sd(calc_peat_rho_nom_peat_num_31_35)

    # theta signal for peat 31-25
    rmse__calc_peat_theta_sig_peat_num_31_35 = compute_rmse(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_31_35)
    mb__calc_peat_theta_sig_peat_num_31_35 = compute_mb(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_31_35)
    pd__calc_peat_theta_sig_peat_num_31_35 = compute_percentage_diff(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_num_31_35)
    variance__calc_peat_theta_sig_peat_num_31_35 = compute_variance(calc_peat_theta_sig_peat_num_31_35)
    sd__calc_peat_theta_sig_peat_num_31_35 = compute_sd(calc_peat_theta_sig_peat_num_31_35)

    # rho signal for peat 31-25
    rmse__calc_peat_rho_sig_peat_num_31_35 = compute_rmse(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_31_35)
    mb__calc_peat_rho_sig_peat_num_31_35 = compute_mb(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_31_35)
    pd__calc_peat_rho_sig_peat_num_31_35 = compute_percentage_diff(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_num_31_35)
    variance__calc__peat_rho_sig_nom_peat_num_31_35 = compute_variance(calc_peat_rho_sig_peat_num_31_35)
    sd__calc_peat_rho_sig_peat_num_31_35 = compute_sd(calc_peat_rho_sig_peat_num_31_35)

    #########################################################################################################

    ###########################
    # ALL SAND
    ###########################

    calc_sand_theta_nom_sand_all = theta_nom_sand
    calc_sand_rho_nom_sand_all = rho_nom_sand
    calc_sand_theta_sig_sand_all = theta_sig_sand
    calc_sand_rho_sig_sand_all = rho_sig_sand

    rmse__calc_sand_theta_nom_sand_all = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_all)
    mb__calc_sand_theta_nom_sand_all = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_all)
    pd__calc_sand_theta_nom_sand_all = compute_percentage_diff(THETA_NOMINAL_SAND, calc_sand_theta_nom_sand_all)
    variance__calc_sand_theta_nom_sand_all = compute_variance(calc_sand_theta_nom_sand_all)
    sd__calc_sand_theta_nom_sand_trial_all = compute_sd(calc_sand_theta_nom_sand_all)

    rmse__calc_sand_rho_nom_sand_all = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_all)
    mb__calc_sand_rho_nom_sand_all = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_all)
    pd__calc_sand_rho_nom_sand_all = compute_percentage_diff(DENSITY_NOMINAL_SAND, calc_sand_rho_nom_sand_all)
    variance__calc_sand_rho_nom_sand_all = compute_variance(calc_sand_rho_nom_sand_all)
    sd__calc_sand_rho_nom_sand_all = compute_sd(calc_sand_rho_nom_sand_all)

    rmse__calc_sand_theta_sig_sand_all = compute_rmse(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_all)
    mb__calc_sand_theta_sig_sand_all = compute_mb(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_all)
    pd__calc_sand_theta_sig_sand_all = compute_percentage_diff(THETA_NOMINAL_SAND, calc_sand_theta_sig_sand_all)
    variance__calc_sand_theta_sig_sand_all = compute_variance(calc_sand_theta_sig_sand_all)
    sd__calc_sand_theta_sig_sand_all = compute_sd(calc_sand_theta_sig_sand_all)

    rmse__calc_sand_rho_sig_sand_all = compute_rmse(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_all)
    mb__calc_sand_rho_sig_sand_all = compute_mb(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_all)
    pd__calc_sand_rho_sig_sand_all = compute_percentage_diff(DENSITY_NOMINAL_SAND, calc_sand_rho_sig_sand_all)
    variance__calc_sand_rho_sig_sand_all = compute_variance(calc_sand_rho_sig_sand_all)
    sd__calc_sand_rho_sig_sand_all = compute_sd(calc_sand_rho_sig_sand_all)

    ###########################
    # ALL PEAT
    ###########################
    calc_peat_theta_nom_peat_all = theta_nom_peat
    calc_peat_rho_nom_peat_all = rho_nom_peat
    calc_peat_theta_sig_peat_all = theta_sig_peat
    calc_peat_rho_sig_peat_all = rho_sig_peat

    rmse__calc_peat_theta_nom_peat_all = compute_rmse(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_all)
    mb__calc_peat_theta_nom_peat_all = compute_mb(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_all)
    pd__calc_peat_theta_nom_peat_all = compute_percentage_diff(THETA_NOMINAL_PEAT, calc_peat_theta_nom_peat_all)
    variance__calc_peat_theta_nom_peat_all = compute_variance(calc_peat_theta_nom_peat_all)
    sd__calc_peat_theta_nom_peat_trial_all = compute_sd(calc_peat_theta_nom_peat_all)

    rmse__calc_peat_rho_nom_peat_all = compute_rmse(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_all)
    mb__calc_peat_rho_nom_peat_all = compute_mb(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_all)
    pd__calc_peat_rho_nom_peat_all = compute_percentage_diff(DENSITY_NOMINAL_PEAT, calc_peat_rho_nom_peat_all)
    variance__calc_peat_rho_nom_peat_all = compute_variance(calc_peat_rho_nom_peat_all)
    sd__calc_peat_rho_nom_peat_all = compute_sd(calc_peat_rho_nom_peat_all)

    rmse__calc_peat_theta_sig_peat_all = compute_rmse(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_all)
    mb__calc_peat_theta_sig_peat_all = compute_mb(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_all)
    pd__calc_peat_theta_sig_peat_all = compute_percentage_diff(THETA_NOMINAL_PEAT, calc_peat_theta_sig_peat_all)
    variance__calc_peat_theta_sig_peat_all = compute_variance(calc_peat_theta_sig_peat_all)
    sd__calc_peat_theta_sig_peat_all = compute_sd(calc_peat_theta_sig_peat_all)

    rmse__calc_peat_rho_sig_peat_all = compute_rmse(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_all)
    mb__calc_peat_rho_sig_peat_all = compute_mb(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_all)
    pd__calc_peat_rho_sig_peat_all = compute_percentage_diff(DENSITY_NOMINAL_PEAT, calc_peat_rho_sig_peat_all)
    variance__calc_peat_rho_sig_peat_all = compute_variance(calc_peat_rho_sig_peat_all)
    sd__calc_peat_rho_sig_peat_all = compute_sd(calc_peat_rho_sig_peat_all)

    # EXPORT ALL OF THE ABOVE IN AN HTML TABLE
    tabd = PrettyTableWrapper(DEC_PLACES_TAB)
    # 22 columns (list vertically)
    tabd.field_names(["Soil Type",
                        "Identifier",

                        "theta_nominal RMSE",
                        "theta_nominal MB",
                        "theta_nominal PD (%)",
                        "theta_nominal Variance",
                        "theta_nominal SD",

                        "rho_nominal RMSE",
                        "rho_nominal MB",
                        "rho_nominal PD (%)",
                        "rho_nominal Variance",
                        "rho_nominal SD",

                        "theta_sig RMSE",
                        "theta_sig MB",
                        "theta_sig PD (%)",
                        "theta_sig Variance",
                        "theta_sig SD",

                        "rho_sig RMSE",
                        "rho_sig MB",
                        "rho_sig PD (%)",
                        "rho_sig Variance",
                        "rho_sig SD"
                        ])

    tabd.add_row(['sand',
                  '1-5',
                  rmse__calc_sand_theta_nom_sand_num_1_5,
                  mb__calc_sand_theta_nom_sand_num_1_5,
                  pd__calc_sand_theta_nom_sand_num_1_5,
                  variance__calc_sand_theta_nom_sand_num_1_5,
                  sd__calc_sand_theta_nom_sand_num_1_5,

                  rmse__calc_sand_rho_nom_sand_num_1_5,
                  mb__calc_sand_rho_nom_sand_num_1_5,
                  pd__calc_sand_rho_nom_sand_num_1_5,
                  variance__calc_rho_theta_nom_sand_num_1_5,
                  sd__calc_sand_rho_nom_sand_num_1_5,

                  rmse__calc_sand_theta_sig_sand_num_1_5,
                  mb__calc_sand_theta_sig_sand_num_1_5,
                  pd__calc_sand_theta_sig_sand_num_1_5,
                  variance__calc_sand_theta_sig_sand_num_1_5,
                  sd__calc_sand_theta_sig_sand_num_1_5,

                  rmse__calc_sand_rho_sig_sand_num_1_5,
                  mb__calc_sand_rho_sig_sand_num_1_5,
                  pd__calc_sand_rho_sig_sand_num_1_5,
                  variance__calc_rho_sig_nom_sand_num_1_5,
                  sd__calc_sand_rho_sig_sand_num_1_5
                  ])

    tabd.add_row(['sand',
                  '6-10',
                  rmse__calc_sand_theta_nom_sand_num_6_10,
                  mb__calc_sand_theta_nom_sand_num_6_10,
                  pd__calc_sand_theta_nom_sand_num_6_10,
                  variance__calc_sand_theta_nom_sand_num_6_10,
                  sd__calc_sand_theta_nom_sand_num_6_10,

                  rmse__calc_sand_rho_nom_sand_num_6_10,
                  mb__calc_sand_rho_nom_sand_num_6_10,
                  pd__calc_sand_rho_nom_sand_num_6_10,
                  variance__calc_rho_theta_nom_sand_num_6_10,
                  sd__calc_sand_rho_nom_sand_num_6_10,

                  rmse__calc_sand_theta_sig_sand_num_6_10,
                  mb__calc_sand_theta_sig_sand_num_6_10,
                  pd__calc_sand_theta_sig_sand_num_6_10,
                  variance__calc_sand_theta_sig_sand_num_6_10,
                  sd__calc_sand_theta_sig_sand_num_6_10,

                  rmse__calc_sand_rho_sig_sand_num_6_10,
                  mb__calc_sand_rho_sig_sand_num_6_10,
                  pd__calc_sand_rho_sig_sand_num_6_10,
                  variance__calc_rho_sig_nom_sand_num_6_10,
                  sd__calc_sand_rho_sig_sand_num_6_10
                  ])

    tabd.add_row(['sand',
                  '11-15',
                  rmse__calc_sand_theta_nom_sand_num_11_15,
                  mb__calc_sand_theta_nom_sand_num_11_15,
                  pd__calc_sand_theta_nom_sand_num_11_15,
                  variance__calc_sand_theta_nom_sand_num_11_15,
                  sd__calc_sand_theta_nom_sand_num_11_15,

                  rmse__calc_sand_rho_nom_sand_num_11_15,
                  mb__calc_sand_rho_nom_sand_num_11_15,
                  pd__calc_sand_rho_nom_sand_num_11_15,
                  variance__calc_rho_theta_nom_sand_num_11_15,
                  sd__calc_sand_rho_nom_sand_num_11_15,

                  rmse__calc_sand_theta_sig_sand_num_11_15,
                  mb__calc_sand_theta_sig_sand_num_11_15,
                  pd__calc_sand_theta_sig_sand_num_11_15,
                  variance__calc_sand_theta_sig_sand_num_11_15,
                  sd__calc_sand_theta_sig_sand_num_11_15,

                  rmse__calc_sand_rho_sig_sand_num_11_15,
                  mb__calc_sand_rho_sig_sand_num_11_15,
                  pd__calc_sand_rho_sig_sand_num_11_15,
                  variance__calc_rho_sig_nom_sand_num_11_15,
                  sd__calc_sand_rho_sig_sand_num_11_15
                  ])

    tabd.add_row(['sand',
                  '16-20',
                  rmse__calc_sand_theta_nom_sand_num_16_20,
                  mb__calc_sand_theta_nom_sand_num_16_20,
                  pd__calc_sand_theta_nom_sand_num_16_20,
                  variance__calc_sand_theta_nom_sand_num_16_20,
                  sd__calc_sand_theta_nom_sand_num_16_20,

                  rmse__calc_sand_rho_nom_sand_num_16_20,
                  mb__calc_sand_rho_nom_sand_num_16_20,
                  pd__calc_sand_rho_nom_sand_num_16_20,
                  variance__calc_rho_theta_nom_sand_num_16_20,
                  sd__calc_sand_rho_nom_sand_num_16_20,

                  rmse__calc_sand_theta_sig_sand_num_16_20,
                  mb__calc_sand_theta_sig_sand_num_16_20,
                  pd__calc_sand_theta_sig_sand_num_16_20,
                  variance__calc_sand_theta_sig_sand_num_16_20,
                  sd__calc_sand_theta_sig_sand_num_16_20,

                  rmse__calc_sand_rho_sig_sand_num_16_20,
                  mb__calc_sand_rho_sig_sand_num_16_20,
                  pd__calc_sand_rho_sig_sand_num_16_20,
                  variance__calc_rho_sig_nom_sand_num_16_20,
                  sd__calc_sand_rho_sig_sand_num_16_20
                  ])

    tabd.add_row(['peat',
                  '21-25',

                  rmse__calc_peat_theta_nom_peat_num_21_25,
                  mb__calc_peat_theta_nom_peat_num_21_25,
                  pd__calc_peat_theta_nom_peat_num_21_25,
                  variance__calc_peat_theta_nom_peat_num_21_25,
                  sd__calc_peat_theta_nom_peat_num_21_25,

                  rmse__calc_peat_rho_nom_sand_num_21_25,
                  mb__calc_peat_rho_nom_sand_num_21_25,
                  pd__calc_peat_rho_nom_sand_num_21_25,
                  variance__calc_peat_rho_theta_nom_sand_num_21_25,
                  sd__calc_peat_rho_nom_sand_num_21_25,

                  rmse__calc_peat_theta_sig_sand_num_21_25,
                  mb__calc_peat_theta_sig_sand_num_21_25,
                  pd__calc_peat_theta_sig_sand_num_21_25,
                  variance__calc_peat_theta_sig_sand_num_21_25,
                  sd__calc_peat_theta_sig_sand_num_21_25,

                  rmse__calc_peat_rho_sig_peat_num_21_25,
                  mb__calc_peat_rho_sig_peat_num_21_25,
                  pd__calc_peat_rho_sig_peat_num_21_25,
                  variance__calc_peat_rho_sig_nom_peat_num_21_25,
                  sd__calc_peat_rho_sig_peat_num_21_25,
                  ])

    tabd.add_row(['peat',
                  '26-30',

                  rmse__calc_peat_theta_nom_peat_num_26_30,
                  mb__calc_peat_theta_nom_peat_num_26_30,
                  pd__calc_peat_theta_nom_peat_num_26_30,
                  variance__calc_peat_theta_nom_peat_num_26_30,
                  sd__calc_peat_theta_nom_peat_num_26_30,

                  rmse__calc_peat_rho_nom_peat_num_26_30,
                  mb__calc_peat_rho_nom_peat_num_26_30,
                  pd__calc_peat_rho_nom_peat_num_26_30,
                  variance__calc_peat_rho_theta_nom_peat_num_26_30,
                  sd__calc_peat_rho_nom_peat_num_26_30,

                  rmse__calc_peat_theta_sig_peat_num_26_30,
                  mb__calc_peat_theta_sig_peat_num_26_30,
                  pd__calc_peat_theta_sig_peat_num_26_30,
                  variance__calc_peat_theta_sig_peat_num_26_30,
                  sd__calc_peat_theta_sig_peat_num_26_30,

                  rmse__calc_peat_rho_sig_peat_num_26_30,
                  mb__calc_peat_rho_sig_peat_num_26_30,
                  pd__calc_peat_rho_sig_peat_num_26_30,
                  variance__calc_peat_rho_sig_nom_peat_num_26_30,
                  sd__calc_peat_rho_sig_peat_num_26_30
                  ])

    tabd.add_row(['peat',
                  '31-35',

                  rmse__calc_peat_theta_nom_peat_num_31_35,
                  mb__calc_peat_theta_nom_peat_num_31_35,
                  pd__calc_peat_theta_nom_peat_num_31_35,
                  variance__calc_peat_theta_nom_peat_num_31_35,
                  sd__calc_peat_theta_nom_peat_num_31_35,

                  rmse__calc_peat_rho_nom_peat_num_31_35,
                  mb__calc_peat_rho_nom_peat_num_31_35,
                  pd__calc_peat_rho_nom_peat_num_31_35,
                  variance__calc_peat_rho_theta_nom_peat_num_31_35,
                  sd__calc_peat_rho_nom_peat_num_31_35,

                  rmse__calc_peat_theta_sig_peat_num_31_35,
                  mb__calc_peat_theta_sig_peat_num_31_35,
                  pd__calc_peat_theta_sig_peat_num_31_35,
                  variance__calc_peat_theta_sig_peat_num_31_35,
                  sd__calc_peat_theta_sig_peat_num_31_35,

                  rmse__calc_peat_rho_sig_peat_num_31_35,
                  mb__calc_peat_rho_sig_peat_num_31_35,
                  pd__calc_peat_rho_sig_peat_num_31_35,
                  variance__calc__peat_rho_sig_nom_peat_num_31_35,
                  sd__calc_peat_rho_sig_peat_num_31_35
                  ])

    tabd.add_row(['SAND ALL',
                  '',
                  rmse__calc_sand_theta_nom_sand_all,
                  mb__calc_sand_theta_nom_sand_all,
                  pd__calc_sand_theta_nom_sand_all,
                  variance__calc_sand_theta_nom_sand_all,
                  sd__calc_sand_theta_nom_sand_trial_all,

                  rmse__calc_sand_rho_nom_sand_all,
                  mb__calc_sand_rho_nom_sand_all,
                  pd__calc_sand_rho_nom_sand_all,
                  variance__calc_sand_rho_nom_sand_all,
                  sd__calc_sand_rho_nom_sand_all,

                  rmse__calc_sand_theta_sig_sand_all,
                  mb__calc_sand_theta_sig_sand_all,
                  pd__calc_sand_theta_sig_sand_all,
                  variance__calc_sand_theta_sig_sand_all,
                  sd__calc_sand_theta_sig_sand_all,

                  rmse__calc_sand_rho_sig_sand_all,
                  mb__calc_sand_rho_sig_sand_all,
                  pd__calc_sand_rho_sig_sand_all,
                  variance__calc_sand_rho_sig_sand_all,
                  sd__calc_sand_rho_sig_sand_all
                  ])

    tabd.add_row(['PEAT ALL',
                  '',
                  rmse__calc_peat_theta_nom_peat_all,
                  mb__calc_peat_theta_nom_peat_all,
                  pd__calc_peat_theta_nom_peat_all,
                  variance__calc_peat_theta_nom_peat_all,
                  sd__calc_peat_theta_nom_peat_trial_all,

                  rmse__calc_peat_rho_nom_peat_all,
                  mb__calc_peat_rho_nom_peat_all,
                  pd__calc_peat_rho_nom_peat_all,
                  variance__calc_peat_rho_nom_peat_all,
                  sd__calc_peat_rho_nom_peat_all,

                  rmse__calc_peat_theta_sig_peat_all,
                  mb__calc_peat_theta_sig_peat_all,
                  pd__calc_peat_theta_sig_peat_all,
                  variance__calc_peat_theta_sig_peat_all,
                  sd__calc_peat_theta_sig_peat_all,

                  rmse__calc_peat_rho_sig_peat_all,
                  mb__calc_peat_rho_sig_peat_all,
                  pd__calc_peat_rho_sig_peat_all,
                  variance__calc_peat_rho_sig_peat_all,
                  sd__calc_peat_rho_sig_peat_all
                  ])

    print('Saving stat table...')
    html = tabd.get_html_string()
    fn = TABLE_PATH + TABLE_NAME_ALL + HTML_EXT
    with open(fn, 'w') as f:
        f.write(html)
        f.close()
    print('DONE saving out HTML table')

    # load in the HTML table text and transpose cols
    print('Converting to CSV')
    fn_csv = TABLE_PATH + TABLE_NAME_ALL + CSV_EXT
    df_list = pd.read_html(fn)
    for i, df in enumerate(df_list):
        df.to_csv(fn_csv)
    print('Done conversion to CSV')

    # load in the CSV file
    frame = np.genfromtxt(fn_csv, delimiter=',', dtype=str)
    frame1 = np.delete(frame, 0, 1)         # delete the first column
    frame2 = np.delete(frame1, 0, 0)        # delete the first row
    c0 = frame2[:, 0]
    c1 = frame2[:, 1]
    c2 = frame2[:, 2]
    c3 = frame2[:, 3]
    c4 = frame2[:, 4]
    c5 = frame2[:, 5]
    c6 = frame2[:, 6]
    c7 = frame2[:, 7]
    c8 = frame2[:, 8]
    c9 = frame2[:, 9]
    c10 = frame2[:, 10]
    c11 = frame2[:, 11]
    c12 = frame2[:, 12]
    c13 = frame2[:, 13]
    c14 = frame2[:, 14]
    c15 = frame2[:, 15]
    c16 = frame2[:, 16]
    c17 = frame2[:, 17]
    c18 = frame2[:, 18]
    c19 = frame2[:, 19]
    c20 = frame2[:, 20]
    c21 = frame2[:, 21]
    frame_out = np.column_stack((c0, c1,
                                 c2, c12,
                                 c3, c13,
                                 c4, c14,
                                 c5, c15,
                                 c6, c16,
                                 c7, c17,
                                 c8, c18,
                                 c9, c19,
                                 c10, c20,
                                 c11, c21))

    print('Saving sorted cols out as CSV file...')
    fn_csv_col_sorted = TABLE_PATH + TABLE_NAME_ALL + "-col-sorted" + CSV_EXT
    df = pd.DataFrame(frame_out)
    df.to_csv(fn_csv_col_sorted)

    fn_csv_col_sorted_html = TABLE_PATH + TABLE_NAME_ALL + "-col-sorted" + HTML_EXT
    print('Save to HTML file')
    df.to_html(fn_csv_col_sorted_html)
    print('DONE')
def run_dp_model_inv_test(show_plot=False, run_full=False):
    """
    Run the SP model inverse test to show an example of the reconstruction
    :param  show_plot:          True to show the plot
    :param  run_full:           True to run the reconstruction over the heating and cooling curve
                                False to run the reconstruction over only the heating curve
    :return:
    """

    ################################################
    # MAIN
    ################################################
    q = 45
    k = 5.2
    theta_m = 0.59
    theta_o = 9.2e-3
    theta_w = 0.40
    C = get_volumetric_heat_capacity(theta_m, theta_o, theta_w)
    alpha = get_alpha_k_C(k, C)
    r0 = 6e-3
    fs = 12
    t0 = 0
    max_delta_r = 5.0e-3
    timestep = 1 / fs

    t_heat = 8      # 8 seconds for heating (when working with the full curve)
    if run_full:
        t1 = 60*3   # 3 minutes for heating and cooling
    else:
        t1 = 8      # 8 seconds for heating

    # create the time vector
    t = np.arange(t0, t1, timestep)
    # required since t0 = 0 and this cannot be used since Ei(x=0) is not defined
    rstep = length(t)-1

    ###########################################################
    # LINEAR CHANGE (INCREASE)
    ###########################################################
    print('Computing for linear increase in r(t)...')
    r = r0 + np.linspace(0, max_delta_r, rstep)
    dT_dual, dT_dual_fixed, r_det_mm, r_mm, r_t_det_diff, tt = \
        run_plot_output(alpha, fs, k, q, r0, run_full, t_heat, t, r)

    ###########################################################
    #  LINEAR CHANGE (DECREASE)
    ###########################################################
    print('Computing for linear decrease in r(t)...')
    rdec = r[::-1]
    r0_dec = rdec[0]
    dT_dual_dec, dT_dual_fixed_dec, r_det_mm_dec, r_mm_dec, r_t_det_diff_dec, tt = \
        run_plot_output(alpha, fs, k, q, r0_dec, run_full, t_heat, t, rdec)

    ###########################################################
    # RANDOM WALK
    ###########################################################
    print('Computing for Brownian random walk in r(t)...')
    nr = length(r)
    rb = brownian_noise_norm(nr, r0, r0 + max_delta_r)
    rb0 = rb[0]
    dT_dual_bn, dT_dual_fixed_bn, r_det_mm_bn, r_mm_bn, r_t_det_diff_bn, tt = \
        run_plot_output(alpha, fs, k, q, rb0, run_full, t_heat, t, rb)

    ###########################################################
    # FIGURES
    ###########################################################
    print('DONE COMPUTING, RUNNING FIGURES')
    fig = plt.figure(num=None, figsize=LARGE_SQUARE_FIGSIZE)

    # INCREASE
    # (a)
    ax = fig.add_subplot(3, 3, 1)
    ax.plot(tt, dT_dual_fixed, label='DP Fixed Radius', color='orange')
    ax.plot(tt, dT_dual, label='DP Variable Radius', color="cornflowerblue")
    # ax.set_xlabel('Time (s)')
    ticklabels_off_x()
    ax.set_ylabel(create_label('$\Delta T \hspace{1}$', 'K'))
    ax.legend()
    ax.set_title('(a)', loc='center')

    # (b)
    ax = fig.add_subplot(3, 3, 2)
    ax.plot(tt, r_mm, color=MODELLED_COLOR, linewidth=4, label='Forward')
    ax.plot(tt, r_det_mm, color='grey', ls='dashed', label='Inverse')
    ax.set_ylabel(create_label('$r\hspace{0.3}(\hspace{0.3}t\hspace{0.3})$', 'mm'))
    # ax.set_xlabel('Time (s)')
    ticklabels_off_x()
    ax.legend()
    ax.set_title('(b)', loc='center')

    # (c)
    ax = fig.add_subplot(3, 3, 3)
    ax.plot(tt, r_t_det_diff, color='grey', label='difference')
    ax.set_ylabel(create_label('$r\hspace{0.3}(\hspace{0.3}t\hspace{0.3})\hspace{1}$ Forward -\n Inverse', 'mm'))
    # ax.set_xlabel('Time (s)')
    ticklabels_off_x()
    ax.set_title('(c)', loc='center')

    # DECREASE
    # (d)
    ax = fig.add_subplot(3, 3, 4)
    ax.plot(tt, dT_dual_fixed_dec, label='DP Fixed Radius', color='orange')
    ax.plot(tt, dT_dual_dec, label='DP Variable Radius', color="cornflowerblue")
    ticklabels_off_x()
    # ax.set_xlabel('Time (s)')
    ax.set_ylabel(create_label('$\Delta T \hspace{1}$', 'K'))
    # ax.legend()
    ax.set_title('(d)', loc='center')

    # (e)
    ax = fig.add_subplot(3, 3, 5)
    ax.plot(tt, r_mm_dec, color=MODELLED_COLOR, linewidth=4, label='Forward')
    ax.plot(tt, r_det_mm_dec, color='grey', ls='dashed', label='Inverse')
    ax.set_ylabel(create_label('$r\hspace{0.3}(\hspace{0.3}t\hspace{0.3})$', 'mm'))
    ticklabels_off_x()
    # ax.set_xlabel('Time (s)')
    # ax.legend()
    ax.set_title('(e)', loc='center')

    # (f)
    ax = fig.add_subplot(3, 3, 6)
    ax.plot(tt, r_t_det_diff_dec, color='grey', label='difference')
    ax.set_ylabel(create_label('$r\hspace{0.3}(\hspace{0.3}t\hspace{0.3})\hspace{1}$ Forward -\n Inverse', 'mm'))
    ticklabels_off_x()
    # ax.set_xlabel('Time (s)')
    ax.set_title('(f)', loc='center')

    # RANDOM WALK
    # (g)
    ax = fig.add_subplot(3, 3, 7)
    ax.plot(tt, dT_dual_fixed_bn, label='DP Fixed Radius', color='orange')
    ax.plot(tt, dT_dual_bn, label='DP Variable Radius', color="cornflowerblue")
    ax.set_xlabel('Time (s)')
    ax.set_ylabel(create_label('$\Delta T \hspace{1}$', 'K'))
    # ax.legend()
    ax.set_title('(g)', loc='center')

    # (h)
    ax = fig.add_subplot(3, 3, 8)
    ax.plot(tt, r_mm_bn, color=MODELLED_COLOR, linewidth=4, label='Forward')
    ax.plot(tt, r_det_mm_bn, color='grey', ls='dashed', label='Inverse')
    ax.set_ylabel(create_label('$r\hspace{0.3}(\hspace{0.3}t\hspace{0.3})$', 'mm'))
    ax.set_xlabel('Time (s)')
    ylim = list(ax.get_ylim())
    ylim[1] += 0.20*(ylim[1]-ylim[0])
    ax.set_ylim(ylim)
    ax.legend()
    ax.set_title('(h)', loc='center')

    # (i)
    ax = fig.add_subplot(3, 3, 9)
    ax.plot(tt, r_t_det_diff_bn, color='grey', label='difference')
    ax.set_ylabel(create_label('$r\hspace{0.3}(\hspace{0.3}t\hspace{0.3})\hspace{1}$ Forward -\n Inverse', 'mm'))
    ax.set_xlabel('Time (s)')
    ax.set_title('(i)', loc='center')

    # SHOW AND SAVE FIGURE
    plt.tight_layout()
    plt.savefig(FIG_PATH + DP_SYNTH_FILENAME_EXAMPLE + PLOT_EXTENSION)
    if show_plot:
        plt.show()
Esempio n. 27
0
def test_full_inverse_heating_determine_r():
    q = 50
    k = 4
    r0 = 5.7e-3
    r1 = 15e-3
    theta_o = 1.0e-3
    theta_w = 0.49
    theta_m = 1 - theta_o - theta_w
    C = get_volumetric_heat_capacity(theta_m, theta_o, theta_w)
    fs = 12
    dt = 1 / fs
    T = 30
    t = gen_time_vec(fs, T)
    t = t[1:]  # cannot start with zero
    n = length(t)
    r = np.linspace(r0, r1, n)
    alpha = get_alpha_k_C(k, C)
    t_heating = 8
    th = t_heating

    # this is the known curve
    print('Running for different starting r0 values')
    dT = compute_delta_T_dual_infinite_line_heating(q, k, alpha, r, t)
    r0v = [4e-3, 5e-3, 5.7e-3, 6e-3]
    dT_inv_vec = []
    for r0_elem in r0v:
        print('r0_elem = ', r0_elem)
        r_t_det = dp_model_recomp_heating(fs,
                                          q,
                                          k,
                                          t,
                                          dT,
                                          r0_elem,
                                          get_gamma4=False)
        dT_inv = compute_delta_T_dual_infinite_line_heating(
            q, k, alpha, r_t_det, t)
        dT_inv_vec.append(dT_inv)

    print('Starting optimization to find the known r')
    rstart = 1.0e-3

    # def _f_obtain_r_from_curve(x, *args):
    #     # UNKNOWN
    #     r0_in = x[0]
    #     # KNOWN
    #     q_in = args[0]
    #     k_in = args[1]
    #     alpha_in = args[2]
    #     t_in = args[3]
    #     fs_in = args[4]
    #     known_in = args[5]
    #     r_t_det = dp_model_recomp_heating(fs, q_in, k_in, t_in, known_in, r0_in, get_gamma4=False)
    #     dT_inv = compute_delta_T_dual_infinite_line_heating(q_in, k_in, alpha_in, r_t_det, t_in)
    #     diff = (known_in - dT_inv)**2
    #     dsum = np.sum(diff)
    #     return dsum
    # # use optimization for the starting r
    # xstart = (rstart,)
    # args = (q, k, alpha, t, fs, dT)
    # res = minimize(_f_obtain_r_from_curve, xstart, args, method='Nelder-Mead')
    # rout = res.x[0]
    # print('rout = ', rout)
    # print('r0 = ', r0)
    #
    block = True
    plt.figure()
    plt.plot(t, dT, linewidth=8)
    for dT_i in dT_inv_vec:
        plt.plot(t, dT_i)
    plt.show(block)
Esempio n. 28
0
def run_find_hpp_nominal():
    """
    Do experiment to obtain nominal HPP data
    :return:
    """
    from calibration_processing import initial_compute_hpp
    from comparisons import compute_rmse, compute_mb
    from inverse_model_nominal import obtain_sp_vars_from_curve_min, compute_single_probe_forward_model_min
    # path = '../hpp-data/hpp-formatted-data/calibration/July-12-2017/'
    path = '../hpp-data/hpp-formatted-data/sand/July-20-2017/'
    # path = '../hpp-data/hpp-formatted-data/sand/July-21-2017/'
    # path = '../hpp-data/hpp-formatted-data/sand/July-26-2017/'
    # path = '../hpp-data/hpp-formatted-data/peat/July-26-2017/'
    # path = '../hpp-data/hpp-formatted-data/peat/July-27-2017/'
    # path = '../hpp-data/hpp-formatted-data/peat/July-30-2017/'
    # path = '../hpp-data/hpp-formatted-data/peat/July-30-2017/'
    # path = '../hpp-data/hpp-formatted-data/peat/July-31-2017/'
    start_string = 'sand-'
    # start_string = 'cal-'
    # start_string = 'peat-'
    downsample = 'dp'
    filt = 'both'
    filt_cutoff = 10  # cutoff filter frequency (Hz)
    fs = 120  # sample rate of device (Hz)
    fs_down = 12  # downsample frequency (Hz)
    t_cold = 1  # time of cold sampling at beginning (s)
    additional_text = '-rep1'
    r0 = 6e-3  # starting radius (m)

    # Tikhonov regularization parameter
    epsilon = 0.0

    #############################################################################

    q = 45
    t_heat = 8
    t_total = 3 * SECONDS_IN_MIN

    # q = 10
    # t_heat = 10 * SECONDS_IN_MIN
    # t_total = 12 * SECONDS_IN_MIN

    ################################################

    # LOAD IN THE COEFFICIENTS USED FOR CALIBRATION AND OBTAIN r_nominal
    # NOTE that the calibrated r0 is stored in mm, so we need to convert to m to be able to use the data
    from obtain_load_r0 import SaveLoadR0
    sr = SaveLoadR0()
    sr.load_r0(CONST_PATH + CAL_R0_FILENAME + SAVEZ_EXT)
    r_nominal = sr.get_r0(q) * 1.0e-3
    # r_nominal = 6e-3

    # We always use assumed q and use the step detector q
    use_assumed_q = False
    use_step_detector_q = True

    I, Rw, T1, T2, Vout, dV, dac_code, delta_T1, delta_T1_trim, delta_T1_trim_heating, \
    delta_T2, delta_T2_trim, num, qav, qprime, step_q_tfirst, step_q_tsecond, t1, t1_trim, \
    t1_trim_heating, t2, t2_trim, ypk, t, rmse_q_calc, mb_q_calc, pd_q_calc, t2_trim_heating, \
    delta_T2_trim_heating = \
        initial_compute_hpp(start_string, additional_text,
        downsample, filt, filt_cutoff, fs, fs_down, path, q, t_cold, t_heat, t_total, use_assumed_q,
        use_step_detector_q)

    dt_sp = t1_trim_heating[1] - t1_trim_heating[0]
    dt_dp = t2_trim_heating[1] - t2_trim_heating[0]

    from sp_model_signal import sp_model_signal_inv
    from curve_time_trim import curve_time_trim
    from sp_model_signal import sp_model_late_time_inv
    from inverse_model_nominal import obtain_k_alpha_from_dual_probe
    from inverse_model_dp_radius import InverseWarmupCurveDP
    from get_theta_rho import get_theta_rho

    # heating only for SP
    t1_trim_heating1, delta_T1_trim_heating1 = curve_time_trim(
        t1_trim_heating, delta_T1_trim_heating)
    # heating only for DP
    t2_trim_heating1, delta_T2_trim_heating1 = curve_time_trim(
        t2_trim_heating, delta_T2_trim_heating)
    # heating and cooling for DP
    t2_trim1, delta_T2_trim1 = curve_time_trim(t2_trim, delta_T2_trim)

    # SP SIGNAL PROCESSING INVERSE MODEL
    kdet_sig, bdet = sp_model_signal_inv(delta_T1_trim_heating1,
                                         t1_trim_heating1,
                                         dt_sp,
                                         q,
                                         output_model_array=False)
    # SP inverse model to obtain k via a late-time model
    tlinear, kout_sp_late_time = sp_model_late_time_inv(
        delta_T1_trim_heating1, t1_trim_heating1, dt_sp, qav)

    # Calculate the time at which the heat pulse goes linear relative to the start of the experiment.
    # This also includes the cold time at the beginning of the experiment (used for graphing).
    tlinear_from_begin = t_cold + tlinear

    # SP FORWARD MODELS
    kd_signal, bd_signal, cd_signal, dd_signal = obtain_sp_vars_from_curve(
        qav, t1_trim_heating1, delta_T1_trim_heating1, kout_sp_late_time)
    kd_lt, bd_lt, cd_lt, dd_lt = obtain_sp_vars_from_curve(
        qav, t1_trim_heating1, delta_T1_trim_heating1, kout_sp_late_time)

    # SP SYNTHETIC MODELS
    delta_T_single_synth_signal = compute_single_probe_forward_model(
        qav, kd_signal, t1_trim_heating1, bd_signal, cd_signal, dd_signal)
    delta_T_single_synth_late_time = compute_single_probe_forward_model(
        qav, kd_lt, t1_trim_heating1, bd_lt, cd_lt, dd_lt)

    # OBTAIN {k, alpha} FROM THE NOMINAL DP MODEL (HEATING AND COOLING)
    # NOTE THAT THIS REQUIRES AN ESTIMATE OF THE PROBE SPACING RADIUS as r_nominal READ FROM A COEFFICIENT FILE
    kstart = kd_signal
    Hstart = 80
    k_nom_heat, alpha_nom_heat = obtain_k_alpha_from_dual_probe(
        q,
        t2_trim_heating1,
        t_heat,
        delta_T2_trim_heating1,
        kstart,
        Hstart,
        r_nominal,
        full=False)  # heat only
    k_nom_heat_and_cool, alpha_nom_heat_and_cool = obtain_k_alpha_from_dual_probe(
        qav,
        t2_trim1,
        t_heat,
        delta_T2_trim1,
        kstart,
        Hstart,
        r_nominal,
        full=True)  # heat and cool
    # OBTAIN {r(t), alpha} FROM THE SIGNAL PROCESSING MODEL
    # r(t) = r_t_sig as the time-variable radius
    InvDP = InverseWarmupCurveDP()
    typ = 'iterative'
    from scipy.interpolate import spline
    from scipy.interpolate import UnivariateSpline
    # s = spline(t2_trim_heating1, delta_T2_trim_heating1, t2_trim_heating1, order=5, kind='smoothest')
    spl = UnivariateSpline(t2_trim_heating1, delta_T2_trim_heating1)
    s = spl(t2_trim_heating1)  # spline (apply to inverse warmup curve)
    from deriv_forward_inv import forward_first_derivative
    sderiv = forward_first_derivative(s, 1 / fs_down)

    # run a zero crossing detector to determine when sderiv is zero and then cut at that point
    nn = length(sderiv)
    ncut = 0
    for k in range(nn):
        if sderiv[k] > 0:
            ncut = k
            break
    ncut += 1
    print('ncut = ', ncut)
    tt_ncut = t2_trim_heating1[ncut + 1:]
    sderiv_ncut = sderiv[ncut:]
    tt_cut = tt_ncut[0]

    # block = True
    # plt.figure()
    # # plt.plot(tt_ncut, sderiv_ncut)
    # plt.plot(t2_trim_heating1[1:], sderiv)
    # plt.axvline(x=tt_cut)
    # plt.show(block)

    scut = s[ncut:]
    tcut = t2_trim_heating1[ncut:]

    # scut = s
    # tcut = t2_trim_heating1
    # compute from the inverse warmup curve
    r0 = 6e-3
    alpha_sig, r_t_sig = InvDP.inverse_warmup_curve_dp(kdet_sig,
                                                       scut,
                                                       qav,
                                                       tcut,
                                                       r_nominal,
                                                       typ,
                                                       lowpass=False,
                                                       epsilon=0.0)

    # average over r_t_sig
    from integrate_average import integrate_average
    r_av = integrate_average(r_t_sig, tcut, 'simpson')
    # r_av = np.mean(r_t_sig)
    print('r_av = ', r_av)

    #############################################################################
    # OBTAIN {k, alpha} FROM THE NOMINAL DP MODEL (HEATING AND COOLING)
    # USE THE r_av FROM SIGNAL PROCESSING
    kstart = kd_signal
    Hstart = 80
    # r_av = r_nominal
    print('r_nominal = ', r_nominal)
    k_sig_heat, alpha_sig_heat = obtain_k_alpha_from_dual_probe(
        q,
        t2_trim_heating1,
        t_heat,
        delta_T2_trim_heating1,
        kstart,
        Hstart,
        r_av,
        full=False)  # heat only
    k_sig_heat_and_cool, alpha_sig_heat_and_cool = obtain_k_alpha_from_dual_probe(
        qav, t2_trim1, t_heat, delta_T2_trim1, kstart, Hstart, r_av,
        full=True)  # heat and cool
    #############################################################################

    # DP SYNTHETICS NOMINAL
    deltaT_dual_synth_nominal_heat_cool = compute_delta_T_dual_heating_cooling(
        qav, k_nom_heat, alpha_nom_heat, r_nominal, t2_trim1, t_heat)
    deltaT_dual_synth_nominal_heating = compute_delta_T_dual_infinite_line_heating(
        qav, k_nom_heat_and_cool, alpha_nom_heat_and_cool, r_nominal,
        t2_trim_heating1)

    # DP SYNTHETIC WITH RADIUS DETERMINED FROM SIGNAL PROCESSING
    deltaT_dual_syth_variable_radius_heating = compute_delta_T_dual_infinite_line_heating(
        qav, kdet_sig, alpha_sig, r_av, t2_trim_heating1)
    # set the organic content
    theta_o = 9.2e-3

    # COMPUTATIONS
    # {theta_w, rho} for DP (heating)
    theta_w_heat, rho_heat = get_theta_rho(k_nom_heat, alpha_nom_heat, theta_o)
    # {theta_w, rho} for DP (heating and cooling)
    theta_w_heat_cool, rho_heat_cool = get_theta_rho(k_nom_heat_and_cool,
                                                     alpha_nom_heat_and_cool,
                                                     theta_o)

    # SIGNAL PROCESSING (HEAT AND COOL)
    theta_w_heat_sig, rho_heat_sig = get_theta_rho(kdet_sig, alpha_sig,
                                                   theta_o)
    theta_w_heat_cool_sig, rho_heat_cool_sig = get_theta_rho(
        kdet_sig, alpha_sig, theta_o)

    # DUAL PROBE
    # RMSE, MB asnd PD for DP model actual vs synthetic (heating)
    # RMSE, MB and PD for DP model actual vs synthetic (heating and cooling)
    # RMSE, MB and PD for DP model actual vs synthetic variable radius (heating only) SIGNAL PROCESSING
    # SINGLE PROBE
    # RMSE, MB and PD for SP model actual vs synthetic (late-time)
    # RMSE, MB and PD for SP model actual vs synthetic (signal processing)

    # from butterworth_low import butter_lowpass_filter
    # y = butter_lowpass_filter(delta_T2_trim_heating1, 1, fs, order=5, both=True)

    # block = False
    # plt.figure()
    # plt.plot(t2_trim_heating1, y)
    # plt.xlabel('Time (s)')
    # plt.ylabel('delta T2 heating')
    # plt.legend()
    # plt.show(block)

    print('OUTPUTS:')
    print('kdet_sig (signal processing) = ', kdet_sig)
    print('tlinear (late-time) = ', tlinear)
    print('kout_sp_late_time (late-time) = ', kout_sp_late_time)
    print('')
    print('k_nom_heat = ', k_nom_heat)
    print('alpha_nom_heat = ', alpha_nom_heat)
    print('')
    print('k_nom_heat_and_cool = ', k_nom_heat_and_cool)
    print('alpha_nom_heat_and_cool = ', alpha_nom_heat_and_cool)
    print('')
    print('alpha_sig (from signal processing with variable radius) = ',
          alpha_sig)
    print('THETA AND RHO')
    print('-----')
    print('theta_w_heat = ', theta_w_heat)
    print('rho_heat = ', rho_heat)
    print('-----')
    print('theta_w_heat_cool = ', theta_w_heat_cool)
    print('rho_heat_cool = ', rho_heat_cool)

    print('----SIGNAL PROCESSING----')
    print('theta_w_heat_sig = ', theta_w_heat_sig)
    print('rho_heat_sig = ', rho_heat_sig)
    print('-----')
    print('---HEAT AND COOL:---')
    print('theta_w_heat_cool_sig = ', theta_w_heat_cool_sig)
    print('rho_heat_cool_sig = ', rho_heat_cool_sig)
    print('--------------------------')

    block = False
    plt.figure()
    plt.plot(t1_trim_heating1, delta_T1_trim_heating1, label='data')
    plt.plot(t1_trim_heating1, delta_T_single_synth_signal, label='signal')
    plt.plot(t1_trim_heating1,
             delta_T_single_synth_late_time,
             label='late time')
    plt.xlabel('Time (s)')
    plt.ylabel('delta T1 heating SP')
    plt.legend()
    plt.show(block)

    # plt.plot(t2_trim1, delta_T2_trim1, label='data heating and cooling')
    # plt.plot(t2_trim_heating1, deltaT_dual_synth_nominal_heating, label='heating')
    # plt.plot(t2_trim1, deltaT_dual_synth_nominal_heat_cool, label='heating and cooling')
    block = False
    plt.figure()
    plt.plot(t2_trim_heating1, delta_T2_trim_heating1, label='data heating')
    # plt.plot(t2_trim_heating1, deltaT_dual_syth_variable_radius_heating, label='heating (variable radius)')
    plt.plot(t2_trim_heating1, s, label='heating (variable radius) smooth')
    plt.legend()
    plt.xlabel('Time (s)')
    plt.ylabel('delta T2 heating DP')
    plt.show(block)

    block = True
    plt.figure()
    plt.plot(tcut, r_t_sig, label='r(t)')
    plt.legend()
    plt.xlabel('Time (s)')
    plt.ylabel('r(t)')
    plt.show(block)
Esempio n. 29
0
def check_same_size(a, b, err=''):
    if length(a) != length(b):
        raise ValueError(err)
Esempio n. 30
0
def plot_ei_test():
    from ei import ei
    from get_alpha import get_alpha_k_C
    from get_volumetric_heat_capacity import get_volumetric_heat_capacity
    from gen_time_vec import gen_time_vec

    q = 50
    k = 4
    r0 = 6.7e-3
    r1 = 15e-3
    theta_o = 1.0e-3
    theta_w = 0.49
    theta_m = 1 - theta_o - theta_w
    C = get_volumetric_heat_capacity(theta_m, theta_o, theta_w)
    fs = 12
    dt = 1 / fs
    T = 30
    t = gen_time_vec(fs, T)
    t = t[1:]  # cannot start with zero
    n = length(t)
    r = np.linspace(r0, r1, n)
    alpha = get_alpha_k_C(k, C)
    print('alpha = ', alpha)
    t_heating = 8
    th = t_heating
    dT, heating, cooling, first, second, tvec_heat, tvec_cool, rheat, rcool, ei_term3, ei_term2 = \
        compute_delta_T_dual_heating_cooling(q, k, alpha, r, t, t_heating, split=True)

    # check the recomposition
    from dp_model_recomp import dp_model_recomp_heating_cooling, dp_model_recomp_heating
    r_t = dp_model_recomp_heating_cooling(fs, q, k, t, th, dT, r0)
    r_t_heat = dp_model_recomp_heating(fs, q, k, tvec_heat, heating, r0)

    block = True
    plt.figure()
    plt.plot(t, r_t)
    plt.plot(t, r)
    plt.plot(tvec_heat, r_t_heat)
    plt.show(block)

    # dT_known = dT
    # from numpy import pi
    # from dp_model_recomp import ei_inv_neg_array, ei_inv_cooling
    # from deriv_forward_inv import forward_first_derivative, inverse_first_derivative
    # out = np.zeros(n)
    # term = -(4*pi*k)/q
    # dt = 1 / fs
    # nn = int(np.ceil(fs*th))
    # tvec_heat = t[:nn]
    # tvec_cool = t[nn:]
    # dT_known_heat = dT_known[:nn]
    # dT_known_cool = dT_known[nn:]
    # # HEATING
    # gamma2_heat = term*dT_known_heat
    # gamma3_heat = ei_inv_neg_array(gamma2_heat) * tvec_heat
    # gamma4_heat = -gamma3_heat
    # # COOLING
    # dT_cool_strip = -term*dT_known_cool
    # gamma4_cool = ei_inv_cooling(dT_cool_strip, th, tvec_cool)
    # gamma4 = np.concatenate((gamma4_heat, gamma4_cool))   # AFTER HERE
    # gamma5 = np.sqrt(gamma4)
    # gamma6 = np.log(gamma5)
    # gamma7 = forward_first_derivative(gamma6, dt)
    #
    # gamma7_comp = forward_first_derivative(np.log(r), dt)
    # gamma7_diff = gamma7 - gamma7_comp
    #
    # # check the inverse
    # r0_wanted = 6e-3
    # log_r_inv = inverse_first_derivative(gamma7, dt, np.log(r0_wanted))
    # r_inv = np.exp(log_r_inv)
    #
    #
    # block = False
    # plt.figure()
    # plt.plot(t[1:], gamma7)
    # plt.plot(t[1:], gamma7_comp)
    # plt.show(block)
    #
    # block = False
    # plt.figure()
    # plt.plot(t[1:], gamma7_diff)
    # plt.show(block)

    # block = True
    # plt.figure()
    # plt.plot(t[1:], linear_test_vec_log_deriv)
    # plt.plot(t[1:], gamma7)
    # plt.show(block)

    # block = True
    # plt.figure()
    # plt.plot(t, r_inv)
    # plt.show(block)

    from dp_model_recomp import dp_model_recomp_heating_cooling