def InflectPoints(TP, Frac, TotalConc, DerEp=1e-3, D1Cut=1e-1):
    try:
        Valid = ValidbyTotalConc(TotalConc)
        TP = TP[Valid]
        Frac = Frac[Valid]
        LogTP = np.log10(TP)
        s5 = InterpolatedUnivariateSpline(LogTP, Frac, k=5)
        #s5.set_smoothing_factor(1e-3)
        D2 = s5.derivative(2)
        R2 = D2.roots()

        s4 = InterpolatedUnivariateSpline(LogTP, Frac, k=4)
        #s4.set_smoothing_factor(1e-3)
        D1 = s4.derivative(1)
        #R1 = D1.roots()

        ITest = R2[D1(R2) >= D1Cut]

        DevCheck1 = np.sign(D1(ITest - DerEp)) == np.sign(D1(ITest + DerEp))
        DevCheck2 = np.sign(D2(ITest - DerEp)) != np.sign(D2(ITest + DerEp))
        DevCheck = np.logical_and(DevCheck1, DevCheck2)
        #DevCheck = DevCheck1
        #DevCheck = DevCheck2
        # print "Radius of Curvature: {}".format(np.abs((1+D1(R2)**1.5)/D2(R2)))

        return ITest[DevCheck]
    except:
        print "Inflection Point Error!!!!"
        return []
Exemple #2
0
def find_sub_pixel_max_value(inp, k=4, ignore_border=50):
    """
    To find the highest point in a 2D array, with subpixel accuracy based on 1D spline interpolation.
    The algorithm is based on a matlab script "tom_peak.m"

    @param inp: A 2D numpy array containing the data points.
    @type inp: numpy array 2D
    @param k: The smoothing factor used in the spline interpolation, must be 1 <= k <= 5.
    @type k: int
    @return: A list of all points of maximal value in the structure of tuples with the x position, the y position and
        the value.
    @returntype: list
    """
    # assert len(ixp.shape) == 2
    # assert isinstance(k, int) and 1 <= k <= 5

    import numpy as xp
    from scipy.interpolate import InterpolatedUnivariateSpline

    inp = inp[ignore_border:-ignore_border, ignore_border:-ignore_border]

    v = xp.amax(inp)  # the max value
    result = xp.where(inp == v)  # arrays of x and y positions of max values
    output = []

    for xpp, yp in zip(result[0], result[1]):
        # Find the highest point for x (first check if on sides otherwise interpolate)
        if xpp == 1 or xpp == inp.shape[0]:
            x = xpp
            xv = v
        else:
            f = InterpolatedUnivariateSpline(range(0, inp.shape[0]),
                                             inp[:, yp],
                                             k=k)  # spline interpolation
            cr_pts = f.derivative().roots()
            cr_vals = f(cr_pts)
            val = xp.argmax(cr_vals)
            x = cr_pts[val]
            xv = cr_vals[val]

        # Find the highest point for y (first check if on sides otherwise interpolate)
        if yp == 1 or yp == inp.shape[1]:
            y = yp
            yv = v
        else:
            f = InterpolatedUnivariateSpline(range(0, inp.shape[1]),
                                             inp[xpp, :],
                                             k=k)  # spline interpolation
            cr_pts = f.derivative().roots()
            cr_vals = f(cr_pts)
            val = xp.argmax(cr_vals)
            y = cr_pts[val]
            yv = cr_vals[val]

        # Calculate the average of the max value to return a single value which is maybe more close to the true value
        output.append([x + ignore_border, y + ignore_border, (xv + yv) / 2])

    return output[0]
Exemple #3
0
def test_aligned_spin_limit_ringdown(q):
    """ Test that the (2,2) mode frequency in the ringdown is within in 1Hz between v4HM and v4PHM.
    In particular, consider cases where the final spin is negative with respect to the initial
    orbital angular momentum. Of course considers only aligned-spin cases"""
    # Step 0: set parameters

    chi1_x, chi1_y, chi1_z = 0.0, 0.0, -0.95
    chi2_x, chi2_y, chi2_z = 0.0, 0.0, -0.95
    m_total = 150  # Feducial total mass in solar masses
    deltaT = 1.0 / 16384
    distance = 500 * 1e6 * lal.PC_SI  # 500 Mpc in m
    f_start22 = 20

    # Step 1: Get the SEOBNRv4PHM modes
    hlmP = get_SEOBNRv4PHM_modes(
        q,
        m_total,
        [chi1_x, chi2_y, chi1_z],
        [chi1_x, chi2_y, chi2_z],
        f_start22 * 0.5,
        distance,
        deltaT,
    )

    # Step 2: Get the SEOBNRv4HM modes
    hlmA = get_SEOBNRv4HM_modes(q, m_total, chi1_z, chi2_z, f_start22 * 0.5,
                                distance, deltaT)

    time = deltaT * np.arange(len(hlmA[(2, 2)]))
    time2 = deltaT * np.arange(len(hlmP[(2, 2)]))
    # Compute the (2,2) mode frequencies
    mode = (2, 2)

    phaseA = np.unwrap(np.angle(hlmA[mode]))
    phaseP = np.unwrap(np.angle(hlmP[mode]))

    intrpA = InterpolatedUnivariateSpline(time, phaseA)
    intrpP = InterpolatedUnivariateSpline(time2, phaseP)

    omega_A = intrpA.derivative()
    omega_P = intrpP.derivative()

    # Consider the frequency in the ringdown
    amp = np.abs(hlmA[mode].data)
    am = np.argmax(amp)

    omega_A_rd = omega_A(time[am:am + 350])
    omega_P_rd = omega_P(time[am:am + 350])

    # Ensure the difference is small. Note here atol=1 corresponds to 1 Hz difference on frequncies of hundreds of Hz. These small
    # diffrences are expected due to some minor code differences.
    # Before a bug was fixed the difference would be huge, i.e. ~100s Hz
    assert np.allclose(
        omega_A_rd, omega_P_rd, atol=1
    ), "The frequencies of the (2,2) mode don't agree between SEOBNRv4PHM and SEOBNRv4HM!"
def find_Tg(quenchTs, mean_vals,sap):
    print(sap)
    if True:#sap<=50.:
        use_first_deviation = False
        if use_first_deviation:
            model = piecewise(quenchTs, mean_vals)
            if len(model.segments) == 2:
                lines = []
                l1 = model.segments[0]
                m1 = l1.coeffs[1]
                b1 = l1.coeffs[0]
                l2 = model.segments[1]
                m2 = l2.coeffs[1]
                b2 = l2.coeffs[0]
            f = InterpolatedUnivariateSpline(quenchTs, mean_vals, k=2)
            dxdT = f.derivative(n=1)
            dx_dTs = dxdT(quenchTs)
            dev_index = np.where(np.abs(dx_dTs)>m1)[0][0]
            x=quenchTs[dev_index]
            y=mean_vals[dev_index]
        else:
            print('using derivatives')
            f = InterpolatedUnivariateSpline(quenchTs, mean_vals, k=2)
            dxdT = f.derivative(n=1)
            d2xdT = f.derivative(n=2)
            dx_dTs = dxdT(quenchTs)
            d2x_dT2s = d2xdT(quenchTs)
            max_dx2 = np.max(d2x_dT2s)
            min_dx2 = np.min(d2x_dT2s)
            max_i = np.where(d2x_dT2s==max_dx2)[0][0]
            min_i = np.where(d2x_dT2s==min_dx2)[0][0]
            x = (quenchTs[min_i]+quenchTs[max_i])/2
            y = (mean_vals[min_i]+mean_vals[max_i])/2
    else:
        print('using line iftting')
        #plot_data_with_regression(quenchTs, mean_vals)
        model = piecewise(quenchTs, mean_vals)
        #print(model) 
        if len(model.segments) == 2:
            lines = []
            l1 = model.segments[0]
            m1 = l1.coeffs[1]
            b1 = l1.coeffs[0]
            l2 = model.segments[1]
            m2 = l2.coeffs[1]
            b2 = l2.coeffs[0]
            x,y = line_intersect(m1,b1,m2,b2)
            
        else:
            print('WARNING: found more or less than 2 line segments in regression!')
    return x,y
Exemple #5
0
    def init_slope_and_curve(self):
        dim = 5
        delta_r = 0.01
        r_vals = np.array([
            self.R - 2 * delta_r, self.R - 1 * delta_r, self.R,
            self.R + 1 * delta_r, self.R + 2 * delta_r
        ])
        LP_E = np.zeros(dim)
        UP_E = np.zeros(dim)
        ### get a stencil of UP and LP energies
        for i in range(0, dim):
            self.R = r_vals[i]
            self.H_e()
            self.H_total = np.copy(self.H_electronic + self.H_photonic +
                                   self.H_interaction)
            vals, vecs = LA.eig(self.H_total)
            idx = vals.argsort()[::1]
            vals = vals[idx]
            LP_E[i] = np.real(vals[1])
            UP_E[i] = np.real(vals[2])

        ### fit spline to upper and lower polariton surface
        LP_spline = InterpolatedUnivariateSpline(r_vals, LP_E, k=3)
        UP_spline = InterpolatedUnivariateSpline(r_vals, UP_E, k=3)

        ### differentiate upper and lower polariton surfaces
        LP_slope = LP_spline.derivative()
        UP_slope = UP_spline.derivative()

        ### 2nd derivative of UP and LP surfaces
        LP_curve = LP_slope.derivative()
        UP_curve = UP_slope.derivative()

        ### store quantities
        self.en_up_old = UP_spline(self.R)
        self.en_up_new = UP_spline(self.R + delta_r)
        self.en_lp_old = LP_spline(self.R)
        self.en_lp_new = LP_spline(self.R + delta_r)
        self.slope_up_old = UP_slope(self.R)
        self.slope_up_new = UP_slope(self.R + delta_r)
        self.slope_lp_old = LP_slope(self.R)
        self.slope_lp_new = LP_slope(self.R + delta_r)
        self.curve_up_old = UP_curve(self.R)
        self.curve_up_new = UP_curve(self.R + delta_r)
        self.curve_lp_old = LP_slope(self.R)
        self.curve_lp_new = LP_slope(self.R + delta_r)

        return 1
Exemple #6
0
def get_data(filename):
    # Make dataframe
    df = pd.read_csv(filename,
                     names=["Wavelength", "Absorbance"],
                     delimiter=",")[::-1]

    # Remove rows where we get NaN as an absorbance
    df = df.apply(pd.to_numeric, errors='raise')
    df = df.dropna()

    # We only care about the wavelengths between 400 and 700 nm.
    df = df[(df["Wavelength"] < 700) & (400 < df["Wavelength"])]

    # Smooth the absorbance data
    df["Absorbance"] = ss.savgol_filter(df["Absorbance"],
                                        window_length=9,
                                        polyorder=4)

    # An object which makes splines
    spline_maker = IUS(df["Wavelength"], df["Absorbance"])

    # An object which calculates the derivative of those splines
    deriv_1 = spline_maker.derivative(n=1)
    deriv_2 = spline_maker.derivative(n=2)

    # Calculate the derivative at all of the splines
    df["First_derivative"] = deriv_1(df["Wavelength"])
    df["Second_derivative"] = deriv_2(df["Wavelength"])

    return df
    def interpolation_spline(x_vals, y_vals):
        """
        Use cubic spline interpolation to find the sub-pixel position of the peak of the CCF

        :param x_vals:
            If the CCF is y(x), this is the array of the x values of the data points supplied to interpolate.
        :param y_vals:
            If the CCF is y(x), this is the array of the y values of the data points supplied to interpolate.
        :return:
            Our best estimate of the position of the peak.
        """

        def quadratic_spline_roots(spl):
            roots = []
            knots = spl.get_knots()
            for a, b in zip(knots[:-1], knots[1:]):
                u, v, w = spl(a), spl((a + b) / 2), spl(b)
                t = np.roots([u + w - 2 * v, w - u, 2 * v])
                t = t[np.isreal(t) & (np.abs(t) <= 1)]
                roots.extend(t * (b - a) / 2 + (b + a) / 2)
            return np.array(roots)

        f = InterpolatedUnivariateSpline(x=x_vals, y=y_vals)
        cr_pts = quadratic_spline_roots(f.derivative())
        cr_vals = f(cr_pts)
        if len(cr_vals) == 0:
            return np.nan
        max_index = np.argmax(cr_vals)
        return cr_pts[max_index]
Exemple #8
0
 def convert_stress(self, mtype='qe'):
     raw = np.loadtxt("ishear.txt")
     data = np.zeros((len(raw), len(raw[0]) + 1))
     data[:, :-1] = raw
     if mtype in ['qe']:
         data[:, 1] /= unitconv.uengy['rytoeV']
     convunit = unitconv.ustress['evA3toGpa']
     vol = np.zeros(len(raw))
     vperf = 0.5 * self.pot['lattice']**3
     strmat = np.zeros([3, 3])
     for i in range(len(raw)):
         strmat[0, 0], strmat[1, 1], strmat[2, 2] = \
             raw[i, 2], raw[i, 3], raw[i, 4]
         strmat[1, 0], strmat[2, 0], strmat[2, 1] = \
             raw[i, 0], raw[i, 5], raw[i, 6]
         strmat = np.mat(strmat)
         vol[i] = vperf * np.linalg.det(strmat)
     tag = 'interp'
     if tag == 'interp':
         # interpolate
         spl = InterpolatedUnivariateSpline(raw[:, 0], raw[:, 1])
         # spl.set_smoothing_factor(0.5)
         splder1 = spl.derivative()
         for i in range(len(raw)):
             # append the stress to the last column
             print("coeff", convunit / vol[i])
             data[i, -1] = splder1(raw[i, 0]) * convunit / vol[i]
     print(data)
     np.savetxt("stress.txt", data)
Exemple #9
0
def FindCriticalPrice(prices_changes, revenue_curve):
    """
    Need to make sure that second derivative is negative (i.e., concave down)
    """
    from scipy.interpolate import InterpolatedUnivariateSpline
    f = InterpolatedUnivariateSpline(prices_changes, revenue_curve, k=4)
    cr_pts = f.derivative().roots()
    return cr_pts[0]  # assume there is only one local/global maximum
Exemple #10
0
def compute_freqInterp(time, hlm):

    philm = np.unwrap(np.angle(hlm))

    intrp = InterpolatedUnivariateSpline(time, philm)
    omegalm = intrp.derivative()(time)

    return omegalm
Exemple #11
0
def peak(x, y):
    """Calculate the FWHM and peak height of a vector y with corresponding coordinates x."""
    spline = InterpolatedUnivariateSpline(x, y, k=4, ext='raise')
    extrema = spline.derivative().roots()
    if len(extrema) < 1:
        return np.nan
    max_x = extrema[np.argmax(spline(extrema))]
    return max_x
Exemple #12
0
 def build_splines(self, scale_factor):
     lM_min, lM_max = self.lM_bounds
     M_space = np.logspace(lM_min - 1, lM_max + 1, 500, base=10)
     sigmaM = np.array([cc.sigmaMtophat_exact(M, scale_factor) for M in M_space])
     ln_sig_inv_spline = IUS(M_space, -np.log(sigmaM))
     deriv_spline = ln_sig_inv_spline.derivative()
     self.deriv_spline = deriv_spline
     self.splines_built = True
     return
 def cal_peierls_stress(self):
     if os.path.isfile('pengy.txt'):
         data = np.loadtxt('pengy.txt')
     else:
         data = self.read_peierls_barrier_neb()
     spl = InterpolatedUnivariateSpline(data[0], data[1], k=3)
     splder1 = spl.derivative()
     interpnts = np.linspace(0, self._burger, 51)
     stress = splder1(interpnts)
     plt.savefig("tmp.png")
     print(np.max(stress))
Exemple #14
0
def SWPI1(M1, rhof1, T1, rhop, dp, R, gamma, mu, cd, n):
    import numpy as np
    import scipy.integrate as intg
    import matplotlib.pyplot as plt
    from scipy.interpolate import interp1d
    from scipy.interpolate import InterpolatedUnivariateSpline
    Vp = (4*np.pi*(dp/2)**3)/3
    P1 = rhof1*R*T1
    P2 = P1*(2*gamma*M1**2/(gamma+1) - ((gamma-1)/(gamma+1)))
    T2 = T1*((1 + 0.5*(gamma-1)*M1**2)*(2*gamma*M1**2/(gamma-1) - 1)*2*(gamma-1)/((gamma+1)**2*M1**2))
    rhof2 = rhof1*(P2*T1)/(P1*T2)
    vf1 = M1*np.sqrt(gamma*R*T1)
    vf2 = vf1*rhof1/rhof2
    M2 = vf2/np.sqrt(gamma*R*T2)
    # return vf1, vf2
    "SW eqns"
    Pr = 0.75
    G = (gamma+1)/((4/3)+((gamma-1)/Pr))
    X_SW = (8/G)*(mu/(vf1-vf2)*rhof1)
    X_SW_array = np.linspace(-X_SW, X_SW, n)
    # return X_SW_array
    f = (8/3)*(rhof1*vf1/mu)*((gamma-1)/gamma)*X_SW_array
    vf_SW = (vf1 + vf2*np.e**f) / (1 + np.e**f)
    t_SW = X_SW/vf_SW[5]
    # return vf_SW
    t = np.linspace(0, t_SW, n)
    # vf_SW_inter = interp1d(t, vf_SW, kind='cubic', fill_value='extrapolate')
    vf_SW_inter = InterpolatedUnivariateSpline(t, vf_SW, k=3)
    vf_SW_diff = vf_SW_inter.derivative()
    # return vf_SW_diff(5)
    # return vf_SW_diff(t)
    # return vf_SW
    def Fd(vp,t):
        # dvpdt = -3*np.pi*mu*dp*(vp[0]-vf_SW_inter)/(Vp*rhop)
        # dvpdt = -3*np.pi*mu*dp*(vp[0]-vf_SW_inter(t))/(Vp*rhop)
        dvpdt = (0.5*rhof1*0.25*np.pi*(dp**2)*cd*(vp[0]-vf_SW_inter(t))**2)/(Vp*rhop)
        return dvpdt
    def Fp(vp, t):
        dvpdt = (rhof1/rhop)*(vf_SW_diff(t))
        return dvpdt
    def Fam(vp, t):
        dvpdt = (0.5*rhof1*vf_SW_diff(t))/(rhop+0.5*rhof1)
        return dvpdt

    vp0 = vf1
    vp_d = intg.odeint(Fd, vp0, t)
    vp_p = intg.odeint(Fp, vp0, t)
    vp_am = intg.odeint(Fam, vp0, t)
    plt.plot(X_SW_array, Fd(vp_d, t), '-r', lw=5.0)
    plt.plot(X_SW_array, Fp(vp_p, t), '-b', lw=5.0)
    plt.plot(X_SW_array, Fam(vp_am, t), '-g', lw=5.0)
    plt.show()
    plt.figure()
Exemple #15
0
def phaseOmegaOrbdiff(time_common, timeDyn_Lev1, phaseorb_Lev1, timeDyn_Lev2,
                      phaseorb_Lev2):

    intrp_Lev1 = InterpolatedUnivariateSpline(timeDyn_Lev1, phaseorb_Lev1)
    intrp_Lev2 = InterpolatedUnivariateSpline(timeDyn_Lev2, phaseorb_Lev2)

    phaseorbdiff = intrp_Lev2(time_common) - intrp_Lev1(time_common)
    intrp_phaseorbdiff = InterpolatedUnivariateSpline(time_common,
                                                      phaseorbdiff)
    omegaorbdiff = intrp_phaseorbdiff.derivative()(time_common)

    return phaseorbdiff, omegaorbdiff
Exemple #16
0
 def build_splines(self):
     """Build the splines needed for integrals over mass bins.
     """
     lM_min, lM_max = self.l10M_bounds
     M_domain = np.logspace(lM_min - 1, lM_max + 1, num=500)
     sigmaM = np.array(
         [cc.sigmaMtophat(M, self.scale_factor) for M in M_domain])
     self.sigmaM_spline = IUS(M_domain, sigmaM)
     ln_sig_inv_spline = IUS(M_domain, -np.log(sigmaM))
     deriv_spline = ln_sig_inv_spline.derivative()
     self.deriv_spline = deriv_spline
     return
 def build_splines(self):
     """Build the splines needed for integrals over mass bins.
     """
     lM_min,lM_max = self.l10M_bounds
     M_domain = np.logspace(lM_min-1, lM_max+1, num=1000)
     sigmaM = np.array([cc.sigmaMtophat(M, self.scale_factor) 
                        for M in M_domain])
     self.sigmaM_spline = IUS(M_domain, sigmaM)
     ln_sig_inv_spline = IUS(M_domain, -np.log(sigmaM))
     deriv_spline = ln_sig_inv_spline.derivative()
     self.deriv_spline = deriv_spline
     return
Exemple #18
0
def get_Vmixfn(tarr,th,Dt,getVmixdot=False,E51=1.,Vmax=None):
    sigEfn = get_sigEfn(tarr,th,E51=E51)
    Vmixarr = Vmix_base(tarr,Dt,sigEfn)
    if Vmax != None: Vmixarr[Vmixarr>Vmax]=Vmax
    Vmixfn = interp1d(tarr,Vmixarr)
    if getVmixdot:
        Vmixfnspline = InterpolatedUnivariateSpline(tarr,Vmixarr)
        Vmixdotspline = Vmixfnspline.derivative()
        Vmixdotarr = Vmixdotspline(tarr)
        Vmixdotfn = interp1d(tarr,Vmixdotarr)
        return Vmixfn,Vmixdotfn
    else:
        return Vmixfn
Exemple #19
0
def get_Vmixarr(tarr,th,Dt,getVmixdot=False,E51=1.,Vmax=None):
    sigEfn = get_sigEfn(tarr,th,E51=E51)
    Vmixarr = Vmix_base(tarr,Dt,sigEfn)
    if Vmax != None: Vmixarr[Vmixarr>Vmax]=Vmax
    if getVmixdot:
        Vmixfnspline = InterpolatedUnivariateSpline(tarr,Vmixarr)
        Vmixdotspline = Vmixfnspline.derivative()
        Vmixdotarr = Vmixdotspline(tarr)
        #dt = tarr[1]-tarr[0]
        #Vmixdotarr = (Vmixarr[1:]-Vmixarr[:-1])/dt
        #Vmixdotarr = np.concatenate((Vmixdotarr,[0]))
        return Vmixarr,Vmixdotarr
    else:
        return Vmixarr
    def deriv(self, degree: int) -> Tuple[np.array, np.array]:
        """Find the n-th derivative"""
        pH, volume = self.trim_values(self.ph, self.volume_titrant)

        # An object which makes splines
        spline_maker = IUS(volume, pH)

        # An object which calculates the derivative of those splines
        deriv_function = spline_maker.derivative(n=degree)

        # Calculate the derivative at all of the splines
        d = deriv_function(volume)

        return volume, d
Exemple #21
0
 def derivatives(self):
     """ 
     function to compute the first and second derivatives of the
     wavefunction by interpolating with a cubic spline and using
     the built-in derivative methods of the splines.  The first
     derivative will be stored in the attribute self.Psi_p
     and the second derivative will be stored in the attribute self.Psi_pp
     """
     ci = 0 + 1j
     ### fit the spline to real and imaginary part of wf
     fr = InterpolatedUnivariateSpline(self.x, np.real(self.Psi))
     fi = InterpolatedUnivariateSpline(self.x, np.imag(self.Psi))
     ### get the derivative of the spline
     fr_p = fr.derivative()
     fi_p = fi.derivative()
     ### get the second derivative of the spline
     fr_pp = fr_p.derivative()
     fi_pp = fi_p.derivative()
     ### store the derivative of the spline to self.Psi_p
     self.Psi_p = fr_p(self.x) + ci * fi_p(self.x)
     ### sore the second derivative of the spline to self.Psi_pp
     self.Psi_pp = fr_pp(self.x) + ci * fi_pp(self.x)
     return 1
Exemple #22
0
def get_maximum(x, y):
    """
    interpolate maximum
    """
    f = InterpolatedUnivariateSpline(x, y, k=4)
	# get Nullstellen
    cr_pts = f.derivative().roots()
    cr_pts = np.append(cr_pts, (x[0], x[-1]))  # also check the endpoints of the interval
    cr_vals = f(cr_pts)
    max_index = np.argmax(cr_vals)

    max_x = cr_pts[max_index]
    max_y = cr_vals[max_index]

    return max_x, max_y
def findMaximum(x_values, y_values):
    try:
        f = InterpolatedUnivariateSpline(x_values, y_values, k=4)
        cr_pts = f.derivative().roots()
        cr_pts = np.append(
            cr_pts, (x_values[0],
                     x_values[-1]))  # also check the endpoints of the interval
        cr_vals = f(cr_pts)
        min_index = np.argmin(cr_vals)
        max_index = np.argmax(cr_vals)
        #print("Maximum value {} at {}\nMinimum value {} at {}".format(cr_vals[max_index], cr_pts[max_index], cr_vals[min_index], cr_pts[min_index]))
        return cr_vals[max_index], cr_pts[max_index]
    except:
        print("findMaximum failes for x_values=" + str(x_values) +
              " y_values=" + str(y_values))
        return None, None
Exemple #24
0
    def findmaxima(template):
        '''Find the amplitude and peak frequency values of your template using spline interpolation'''
        x_axis = template[:, 0]
        y_axis = template[:, 1]
        f = InterpolatedUnivariateSpline(x_axis, y_axis, k=4)
        cr_pts = f.derivative().roots()
        cr_pts = np.append(
            cr_pts, (x_axis[0],
                     x_axis[-1]))  # also check the endpoints of the interval
        cr_vals = f(cr_pts)
        max_index = np.argmax(cr_vals)

        max_amplitude = cr_vals[max_index]
        peak_frequency = cr_pts[max_index]

        return max_amplitude, peak_frequency
Exemple #25
0
    def determine_spline_and_derivative(self):
        time, intensity = zip(*self.peak_data)
        low = bisect_left(time, self.peak_time - self.peak_window)
        high = bisect_right(time, self.peak_time + self.peak_window)

        # Failsafe
        if high == len(time):
            high = -1

        new_x = linspace(time[low], time[high],
                         int(2500 * (time[high] - time[low])))

        f = InterpolatedUnivariateSpline(time[low:high], intensity[low:high])
        f_prime = f.derivative()

        self.univariate_spline_data = list(zip(new_x, f(new_x)))
        self.first_derivative_data = list(zip(new_x, f_prime(new_x)))
class StrippedPowerLawMassFunction(GenericMassFunction):
    def __init__(self, m_a, gamma):

        #These parameters are specific to the model we use
        self.gamma = gamma
        self.m_a = m_a

        #Here 'us' denotes 'unstripped', i.e. the values before MW stripping has been accounted for
        self.mmin_us = calc_Mmin(m_a)
        self.mmax_us = calc_Mmax(m_a)

        #Here, we generally need the average mass *before* any disruption, so let's calculate this
        #before we do any correction for stripping due to the MW halo
        self.mavg = ((gamma) /
                     (gamma + 1)) * (self.mmax_us**(gamma + 1) - self.mmin_us**
                                     (gamma + 1)) / (self.mmax_us**gamma -
                                                     self.mmin_us**gamma)

        mi_list = np.geomspace(self.mmin_us, self.mmax_us, 10000)
        mf_list = mass_after_stripping(mi_list)

        self.mmin = np.min(mf_list)
        self.mmax = np.max(mf_list)
        print("M_max:", self.mmax)

        self.mi_of_mf = InterpolatedUnivariateSpline(mf_list,
                                                     mi_list,
                                                     k=1,
                                                     ext=1)
        self.dmi_by_dmf = self.mi_of_mf.derivative(n=1)

    def dPdlogM_nostripping(self, mass):
        return self.gamma * mass**self.gamma / (self.mmax_us**self.gamma -
                                                self.mmin_us**self.gamma)

    def dPdlogM_internal(self, mass):
        """
        Edit this halo mass function, dP/dlogM
        Strongly recommend making this vectorized
        """
        m_f = mass
        m_i = self.mi_of_mf(m_f)

        return self.dPdlogM_nostripping(m_i) * self.dmi_by_dmf(m_f) * m_f / m_i
Exemple #27
0
def execute(block, config):

    k_growth = config
    z_pk, k_pk, p_lin = block.get_grid(names.matter_power_lin, 'z', 'k_h',
                                       'p_k')
    a_pk = 1 / (1 + z_pk)
    growth_ind = np.where(k_pk > k_growth)[0][0]
    growth_array = np.sqrt(
        np.divide(p_lin[:, growth_ind],
                  p_lin[0, growth_ind],
                  out=np.zeros_like(p_lin[:, growth_ind]),
                  where=p_lin[:, growth_ind] != 0.))
    #compute f(a) = dlnD/dlna, need to reverse when splining as expects increasing x
    growth_spline = IUS(np.log(a_pk[::-1]), np.log(growth_array[::-1]))
    f_array = growth_spline.derivative()(np.log(a_pk[::-1]))[::-1]
    block[growth_section, 'd_z'] = growth_array
    block[growth_section, 'f_z'] = f_array
    block[growth_section, 'z'] = z_pk
    return 0
Exemple #28
0
    def __init__(self, cosmo):
        """
		Attributes
		----------
	    cosmo : Cosmo object (from universe.py)
	        Cosmology object
		"""
        self.cosmo = cosmo

        # self.fac = (3 * (self.cosmo.omegab+self.cosmo.omegac) * self.cosmo.H0**2.) / (const.c.to('km/s').value**3)
        self.fac = (3 * (self.cosmo.omegab + self.cosmo.omegac) *
                    self.cosmo.H0**2.) / (const.c.to('km/s').value**2)

        # Calculate growth factor derivative
        z = np.logspace(1e-5, np.log10(cosmo.zstar), 1000)
        s = InterpolatedUnivariateSpline(z, self.cosmo.D_z(z) * (1 + z))
        self.der = s.derivative()

        super(iSW, self).__init__(1e-5, self.cosmo.zstar)
Exemple #29
0
class Cubic_Spline_Table_Form(object):
    """Potential form that takes tabulated data and returns interpolated values.

  This potential uses cubic spline interpolation. It is simply a wrapper around
  the scipy.interpolate.InterpolatedUnivariateSpline class"""
    """Identifier used in config files through `interpolation` directive"""
    config_label = "cubic_spline"

    #Tag used during introspection of class so that it is automatically registered with Potential_Form_Registry
    is_potential = True

    def __init__(self, x_data, y_data):
        """Creates a potential form by linking x,y data points by cubic splines.

    :param x_data: List of x data values.
    :param y_data: List of y data values."""

        from scipy.interpolate import InterpolatedUnivariateSpline
        # ext =1 means that a value of zero is returned outside the data range.
        self._interpolant = InterpolatedUnivariateSpline(x_data, y_data, ext=1)
        self._deriv = self._interpolant.derivative()
        self._deriv2 = self._deriv.derivative()

    @property
    def interpolant(self):
        """This class is a wrapper around instances of scipy.interpolate.InterpolatedUnivariateSpline 
    This property returns the scipy object used internally"""
        return self._interpolant

    def __call__(self, x):
        """:return: interpolated value at x"""
        return float(self._interpolant(x))

    def deriv(self, x):
        """:return: derivative of potential form at x"""
        return float(self._deriv(x))

    def deriv2(self, x):
        """:return: second derivative of potential form at x"""
        return float(self._deriv2(x))
Exemple #30
0
def phaseOmegalmdiff(time_common, time_Lev1, phaselm_Lev1, time_Lev2,
                     phaselm_Lev2):

    phaselmdiff = {}
    omegalmdiff = {}

    assert (len(list(phaselm_Lev1.keys())) == len(list(
        phaselm_Lev2.keys()))), "Levs have different mode arrays!"

    for l, m in list(phaselm_Lev1.keys()):

        intrp_Lev1 = InterpolatedUnivariateSpline(time_Lev1, phaselm_Lev1[l,
                                                                          m])
        intrp_Lev2 = InterpolatedUnivariateSpline(time_Lev2, phaselm_Lev2[l,
                                                                          m])

        phaselmdiff[l, m] = intrp_Lev2(time_common) - intrp_Lev1(time_common)

        intrp_phaselmdiff = InterpolatedUnivariateSpline(
            time_common, phaselmdiff[l, m])
        omegalmdiff[l, m] = intrp_phaselmdiff.derivative()(time_common)

    return phaselmdiff, omegalmdiff
Exemple #31
0
def compute_OrbPhaseOmega(Lev3):

    timeDyn = Lev3['Horizons']['AhA']['CoordCenterInertial']['x'][:, 0]
    xA = Lev3['Horizons']['AhA']['CoordCenterInertial']['x'][:, 1]
    yA = Lev3['Horizons']['AhA']['CoordCenterInertial']['y'][:, 1]
    zA = Lev3['Horizons']['AhA']['CoordCenterInertial']['z'][:, 1]

    xB = Lev3['Horizons']['AhB']['CoordCenterInertial']['x'][:, 1]
    yB = Lev3['Horizons']['AhB']['CoordCenterInertial']['y'][:, 1]
    zB = Lev3['Horizons']['AhB']['CoordCenterInertial']['z'][:, 1]

    x = xA - xB
    y = yA - yB
    z = zA - zB
    #rvec = np.concatenate((x,y,z),axis=None)

    # Multiply by 2 the argument of unwrap and divide the outcome by two as suggested in https://stackoverflow.com/questions/52293831/unwrap-angle-to-have-continuous-phase
    phaseorb = np.unwrap(2 * np.arctan(y / x)) / 2

    intrp_phase = InterpolatedUnivariateSpline(timeDyn, phaseorb)
    omegaorb = intrp_phase.derivative()(timeDyn)

    return timeDyn, phaseorb, omegaorb
Exemple #32
0
def test_fermi_distribution_derivative(verbose=False):

    if is_numpy_newer_than('1.8.0'):
        beta = 3.3
        e = np.linspace(-5., 5., num=1000)
        f = fermi_distribution(beta, e)
        df = fermi_distribution_derivative(beta, e)

        from scipy.interpolate import InterpolatedUnivariateSpline
        sp = InterpolatedUnivariateSpline(e, f)
        dsp = sp.derivative(1)
        df_ref = dsp(e)

        np.testing.assert_almost_equal(df, df_ref)

        if verbose:
            import matplotlib.pyplot as plt
            plt.plot(e, f, label='f')
            plt.plot(e, df, label='df')
            plt.plot(e, df_ref, label='df_ref')
            plt.legend()
            plt.show()
            exit()
Exemple #33
0
    def minimize(self, data: Data, init_hypo: Parameters = None) -> float:
        """Minimization over POIs

      The method scans over the POI values in `scan_pois`, computes
      the NLL and profile NPs for each one, and returns the point
      that yields the minimal NLL.

      Args:
         data : dataset for which to compute the NLL
         init_hypo : initial value (of POIs and NPs) for the minimization
      Returns:
         best-fit parameters
    """
        self.nlls = np.zeros(self.scan_pois.size)
        for i in range(0, len(self.scan_pois)):
            scan_hypo = init_hypo.clone().set_poi(self.scan_pois[i])
            np_min = NPMinimizer(data)
            self.nlls[i] = np_min.profile_nll(scan_hypo)
            self.pars[i] = np_min.min_pars
            #print('@poi(', i, ') =', poi, self.nlls[i], ahat, bhat)
        smooth_nll = InterpolatedUnivariateSpline(self.scan_pois,
                                                  self.nlls,
                                                  k=4)
        minima = smooth_nll.derivative().roots()
        self.min_nll = np.amin(self.nlls)
        self.min_idx = np.argmin(self.nlls)
        self.min_pois = np.array([self.scan_pois[self.min_idx]])
        if len(minima) == 1:
            interp_min = smooth_nll(minima[0])
            if interp_min < self.min_nll:
                self.min_pois = minima
                self.min_nll = interp_min
        self.min_pars = Parameters(self.min_pois,
                                   self.pars[self.min_idx],
                                   model=data.model)
        return self.min_nll
# CAN PLOT THE SHAPE BELOW, SHOULD LOOK LIKE WHAT BRUNO HAD
#lets produce a lil smoothed analytic of the nEurtral
height = np.arange(0, 300, 0.1)
ray = np.zeros(len(height))
ray[:] = height
# lets model to 300 km
NeutralIndex = new_neutral(ray, len(height))
IonoIndex, ElectronDensity = iono(ray, len(height))
net_N = ((NeutralIndex) + IonoIndex) * 1e6
ElectronIndex, ElectronDesity = iono(ray, len(height))

# #we need a derivate of the iono density

smoothresults = InterpolatedUnivariateSpline(height, ElectronDesity)
prime = smoothresults.derivative(n=1)
doubleprime = smoothresults.derivative(n=2)
finerx = np.linspace(0, 300, 1000)
firstderivative = prime(finerx)
secondderivative = doubleprime(finerx)

# fig, ((ax1,ax2),(ax3,ax4)) = plt.subplots(2,2)

# ax1.plot(NeutralDesity[0,:],height, 'b')
# ax1.set_title('Neutral Density', loc='left')
# ax1.set_ylabel('Altitude (km)')
# ax1.set_xlabel('Density ($m^{-3}$)')
# ax1.set_ylim(0,300)

# ax2.plot(np.log10(NeutralDesity[0,:]),height,'b')
# ax2.set_title('Neutral Density', loc='left')
Exemple #35
0
#plot elevation and azimuth in simple plot
x = np.arange(0, len(sat_data[:,1]));
x = x/60.0; #convert to minutes
ax1.plot(x, sat_data[:,2], label="Elevation");
ax1.plot(x, sat_data[:,3], label="Azimuth");
ax1.plot(x, np.repeat(0, len(x)), label="Horizon", linestyle="dashed");
legendsize=10
ax1.legend(loc='best', fontsize=legendsize);
ax1.set_ylabel("Degrees");

#plot elevation rate
ax2.plot(x, sat_data[:,5], label="Elevation rate");

#plot numerical derivative estimated from an interpolating spline
f = InterpolatedUnivariateSpline(x, sat_data[:,2], k=1)
dfdx = f.derivative()
dydx = dfdx(x)
ax2.plot(x, sat_data[0,5]/dydx[0]*dydx, label="Scaled numerical derivative");
ax2.legend(loc='best', fontsize=legendsize);
ax2.set_ylabel("Degrees");
ax2.set_ylabel("Degrees");

#plot doppler shift
ax3.plot(x, np.repeat(1000, len(x)), label="Downlink frequency");
ax3.plot(x, sat_data[:,4], label="Doppler-shifted downlink frequency");
ax3.legend(loc='best', fontsize=legendsize);
ax3.set_ylabel("Frequency (MHz)");
tickrange=np.arange(999.98, 1000.025, 0.01);
ax3.set_yticks(tickrange)
ax3.set_yticklabels(map(str, tickrange));
plt.xlabel("Timestep (min)");
Exemple #36
0
class VTC(object):
    
    bracket_size = 1000
    stop_error = 0.001
    max_iters = 10
    
    def __init__(self, csv_file, vin='Vin', vout='Vout'):
        self.x_values = []
        self.y_values = []
        self.traces = {}
        self.annotations = []
        
        self.csvfile = csv_file
        try:
            f = open(csv_file, 'r')
            self.spamreader = csv.DictReader(f, delimiter=' ')
        except TypeError:
            print("THERE WAS AN ERROR!")
            raise
        for row in self.spamreader:
            self.x_values.append(float(row[vin]))
            self.y_values.append(float(row[vout]))
        f.close()
        
        # getting a spline's derivative is much more accurate for finding
        # the VTC's characteristic parameters
        self.spl = InterpolatedUnivariateSpline(self.x_values, self.y_values)
        self.spline_1drv = self.spl.derivative()
        self.get_characteristic_parameters()
        
        self.traces['VTC'] = {
                'x': self.x_values, 
                'y': self.y_values, 
                'label': 'Voltage Transfer Characteristic',
                'class': 'main',
        }
    
    def find_vm(self, start=None, stop=None, bracket_size=1000,
                stop_error=0.001, max_iters=10):
        if not start:
            start = self.min_x
        if not stop:
            stop = self.max_x
        
        iter_count = 0
        smallest = numpy.nan_to_num(numpy.inf)
        smallest_at = 0
        while smallest > stop_error and iter_count < max_iters:
            q = numpy.linspace(start, stop, bracket_size)
            for (x, y) in zip(q, self.spl.__call__(q)):
                if abs(y-x) < smallest:
                    smallest = abs(y-x)
                    smallest_at = x
            length = float(stop - start)
            if not float(smallest_at - (length/4)) < start:
                start = float(smallest_at - (length/4))
            if not float(smallest_at + (length/4)) > stop:
                stop = float(smallest_at + (length/4))
            iter_count += 1
        return smallest_at
        
    
    def find_inflection_point(self, **iter_params):
        if not hasattr(self, 'spline_1drv'):
            self.spline_1drv = self.spl.derivative()
        
        p = self.defaults
        p.update(iter_params)
        start, stop = p['start'], p['stop']
                
        iter_count = 0
        biggest_y = 0
        biggest_x = 0
        while iter_count < p['max_iters']:
            q = numpy.linspace(start, stop, p['bracket_size'])
            for (dx, dy) in zip(q, self.spline_1drv.__call__(q)):
                if abs(dy) > biggest_y:
                    biggest_y = abs(dy)
                    biggest_x = dx
            length = float(stop - start)
            if not float(biggest_x - (length/4)) < start:
                start = float(biggest_x - (length/4))
            if not float(biggest_x + (length/4)) > stop:
                stop = float(biggest_x + (length/4))            
            iter_count += 1
        self.inflection_point = biggest_x
        return biggest_x
            
    def find_where_derivative_is(self, value, start=None,
                                 stop=None, bracket_size=1000,
                                 stop_error=0.001, max_iters=10):
        if not hasattr(self, 'spline_1drv'):
            self.spline_1drv = self.spl.derivative()
        if not start:
            start = self.min_x
        if not stop:
            stop = self.max_x

        iter_count = 0
        closest_y = numpy.inf
        closest_x = numpy.inf
        while abs(value - closest_y) > stop_error and iter_count < max_iters:
            q = numpy.linspace(start, stop, bracket_size)
            for (dx, dy) in zip(q, self.spline_1drv.__call__(q)):
                if abs(value - dy) < abs(value - closest_y):
                    closest_y = dy
                    closest_x = dx
            length = float(stop - start)
            if not float(closest_x - (length/4)) < start:
                start = float(closest_x - (length/4))
            if not float(closest_x + (length/4)) > stop:
                stop = float(closest_x + (length/4))
            iter_count += 1
        return closest_x
    
    def get_tangent_line_at(self, x):
        y = self.spl.__call__(x)
        m = self.spl.__call__(x, 1)
        b = y - (m * x)
        return y, m, b
    
    def make_tangent_line_at(self, x):
        # make tangent line occupy 1/6 of plot
        x_extend = self.range_x / 9
        y_extend = self.range_y / 9
        y, m, b = self.get_tangent_line_at(x)
        x1 = x - x_extend
        x2 = x + x_extend
        y1 = m*x1+b
        y2 = m*x2+b
        return x1, x2, y1, y2
        
    def get_characteristic_parameters(self):
        
        self.min_x = float(min(self.x_values))
        self.max_x = float(max(self.x_values))
        self.min_y = float(min(self.y_values))
        self.max_y = float(max(self.y_values))
        self.range_x = float(self.max_x - self.min_x)
        self.range_y = float(self.max_y - self.min_y)
        
        self.defaults = {
            'bracket_size': self.bracket_size,
            'stop_error': self.stop_error,
            'max_iters': self.max_iters,
            'start': self.min_x,
            'stop': self.max_x,
        }
        
        if not hasattr(self, 'inflection_point'):
            self.find_inflection_point()
        self.voh = self.max_y
        self.vih = self.find_where_derivative_is(-1, start=self.inflection_point)
        self.vm = self.find_vm()
        self.vil = self.find_where_derivative_is(-1, stop=self.inflection_point)
        self.vol = self.min_y
        self.nml = self.vil - self.vol
        self.nmh = self.voh - self.vih
        
#         print(self.vol, self.vil, self.vm, self.vih, self.voh, self.nml, self.nmh)
    
    def plot_ly(self, filename):
        offset = (self.max_y/20)
        line_style = Line(
            color='rgb(44, 160, 44)',
            opacity=0.25,
            dash='dot',
        )
        helper_line_style = {
            'line': line_style,
            'showlegend': False,
            'mode': 'lines',
            'connectgaps': True,
        }
        
        traces = []
        traces.append(Scatter(
                x=self.x_values,
                y=self.y_values,
        ))
        
        for (point, name) in {self.vil: 'V_IL', self.vih: 'V_IH'}.items():
            x1, x2, y1, y2 = self.make_tangent_line_at(point)
            traces.append(
                Scatter(
                    x=[x1, x2], 
                    y=[y1, y2], 
                    mode='lines',
                    name='tangent at dy/dx=-1',
                    showlegend=False,
                    connectgaps=True,
                    opacity=0.5,
                    line=Line(
                        color='#AAAAAA',
                    )
                )
            )
            traces.append(
                Scatter(
                    x=[point, point],
                    y=[self.min_y, self.spl(point)],
                    **helper_line_style
                )
            )
        
        for (point, name) in dict({self.vol: 'V_{OL}', self.voh: 'V_{OH}'}).items():
            traces.append(Scatter(
                    x=[self.min_x, self.max_x], 
                    y=[point, point],
                    name=name,
                    **helper_line_style
            ))
        
        traces.append(Scatter(
                x=[0, self.vm],
                y=[0, self.vm],
                mode='lines',
                name=['V_M'],
                line=line_style,
        ))
        
        data = Data(traces)
        
        annotations = []
        annotations.append(Annotation(x=self.max_x, xanchor='left', align='left', yanchor='top', y=self.vol, text='$V_{OL}$', showarrow=False))
        annotations.append(Annotation(x=self.vil, y=self.min_y, yanchor='top', text='$V_{IL}$', showarrow=False))
        annotations.append(Annotation(x=self.vm, y=self.vm, xanchor='left', align='left', text='$V_{M}$', showarrow=False))
        annotations.append(Annotation(x=self.vih, y=self.min_y, yanchor='top', text='$V_{IH}$', showarrow=False))
        annotations.append(Annotation(x=self.max_x, xanchor='left', align='left', y=self.voh, text='$V_{OH}$', showarrow=False))
        
        layout = Layout(
            title='Voltage Transfer Characteristic',
            xaxis=XAxis(title='$V_{in} \\left(\\text{V}\\right)$', showgrid=False),
            yaxis=YAxis(title='$V_{out} \\left(\\text{V}\\right)$', showgrid=False),
            annotations=Annotations(annotations),
            showlegend=False,
            autosize=False,
            width=500,
            height=500,
            margin=Margin(
                l=50,
                r=50,
                b=50,
                t=50,
            ),
        )
        fig = Figure(data=data, layout=layout)
        plot_url = py.plot(fig, filename=filename)
        
    def matplotlib(self, filename):
        import seaborn as sns
        sns.set_style('white')

        offset = (self.voh - self.vol)/50
        self.figure = plt.figure(facecolor='white', figsize=(3.5, 3.6))
        ax = plt.gca()
        ax.spines['top'].set_visible(False)
        ax.spines['right'].set_visible(False)
        ax.clip_on=False
        plt.tick_params(top='off', right='off')
        plt.locator_params('both', tight=True, nbins=4)
        # set text and line formatting stuff
        # plt.rc('text', usetex=True)
        plt.rc('lines', linewidth=1)
        plt.rc('font', size=12)
        main_plot = dict(linewidth=3, zorder=20)
        tangent_lines = dict(color='grey', linewidth=1)
        marker_lines = dict(color='grey', linewidth=1, linestyle='--')
        # 
        plt.xlabel(r"$V_{in}$")
        plt.ylabel(r"$V_{out}$")
        # plot the main VTC
        plt.plot(self.x_values, self.y_values, label='VTC', **main_plot)
        plt.plot([0, 1, self.vm], [0, 1, self.vm], **marker_lines)
        ax.annotate('$V_{M}$', xy=(self.vm, self.vm), xytext=(0, -8), textcoords='offset points',
                     horizontalalignment='left', verticalalignment='middle')


        for label, point in {r'$V_{OL}$': self.vol, r'$V_{IL}$': self.vil, r'$V_{IH}$': self.vih,
                      r'$V_{OH}$': self.voh}.items():
            x1, x2, y1, y2 = self.make_tangent_line_at(point)
            ax.plot([x1, x2], [y1, y2], **tangent_lines)
            ax.axvline(x=point, **marker_lines)
            # ax.annotate(label, xy=(point, 0), xytext=(0, -8), textcoords='offset points',
            #              horizontalalignment='center', verticalalignment='top')

        # ax.axvline(x=self.vil, **marker_lines)
        # ax.axvline(x=self.vih, **marker_lines)
        ax.annotate('$V_{OL}$', xy=(self.vol, 0), xytext=(0, -8), textcoords='offset points',
                     horizontalalignment='left', verticalalignment='top')
        ax.annotate('$V_{IL}$', xy=(self.vil, 0), xytext=(0, -8), textcoords='offset points',
                     horizontalalignment='center', verticalalignment='top')
        ax.annotate('$V_{IH}$', xy=(self.vih, 0), xytext=(0, -8), textcoords='offset points',
                     horizontalalignment='center', verticalalignment='top')
        ax.annotate('$V_{OH}$', xy=(self.voh, 0), xytext=(0, -8), textcoords='offset points',
                     horizontalalignment='center', verticalalignment='top')
        ax.annotate('', xy=(0, self.voh/1.5), xycoords='data',
                    xytext=(self.vil, self.voh/1.5), textcoords='data',
                    arrowprops=dict(arrowstyle="<->", ec="k",))
        ax.annotate('$NM_L$', xy=(self.vil/2, self.voh/1.5), xytext=(0, -5), textcoords='offset points',
                    horizontalalignment='center', verticalalignment='top')
        ax.annotate('', xy=(self.vih, self.voh/1.5), xycoords='data',
                    xytext=(self.voh, self.voh/1.5), textcoords='data',
                    arrowprops=dict(arrowstyle="<->", ec="k",))
        ax.annotate('$NM_H$', xy=((self.voh-self.vih)/2+self.vih, self.voh/1.5), xytext=(0, -5), textcoords='offset points',
                    horizontalalignment='center', verticalalignment='top')


        plt.tight_layout()

        ax.locator_params(axis='both', tight=True)
        ax.set_ylim(0-0.02)
        ax.set_xlim(0)
        self.figure.savefig(filename)
        
    
    def matplotly(self, filename):
        plot_url = py.plot_mpl(self.figure)