Esempio n. 1
0
def s12_time_profile(krdst,
                     Tnbins,
                     Trange,
                     timeStamps,
                     s2lim=(8e+3, 1e+4),
                     s1lim=(10, 11),
                     figsize=(8, 8)):

    xfmt = md.DateFormatter('%d-%m %H:%M')
    fig = plt.figure(figsize=figsize)

    x, y, yu = fitf.profileX(krdst.T, krdst.E, Tnbins, Trange)
    ax = fig.add_subplot(1, 2, 1)
    #plt.figure()
    #ax=plt.gca()
    #fig.add_subplot(1, 2, 1)
    ax.xaxis.set_major_formatter(xfmt)
    plt.errorbar(timeStamps, y, yu, fmt="kp", ms=7, lw=3)
    plt.xlabel('date')
    plt.ylabel('S2 (pes)')
    plt.ylim(s2lim)
    plt.xticks(rotation=25)

    x, y, yu = fitf.profileX(krdst.T, krdst.S1, Tnbins, Trange)
    ax = fig.add_subplot(1, 2, 2)
    #ax=plt.gca()

    #xfmt = md.DateFormatter('%d-%m %H:%M')
    ax.xaxis.set_major_formatter(xfmt)
    plt.errorbar(timeStamps, y, yu, fmt="kp", ms=7, lw=3)
    plt.xlabel('date')
    plt.ylabel('S1 (pes)')
    plt.ylim(s1lim)
    plt.xticks(rotation=25)
    plt.tight_layout()
Esempio n. 2
0
def lt(z, v, znbins, zrange, vnbins, vrange, plot=True):
    """ compute the lifetime of v-variable (S2e, Se1, E) vs Z
    """
    zbins = np.linspace(*zrange, znbins + 1)
    vbins = np.linspace(*vrange, vnbins + 1)
    x, y, yu = fitf.profileX(z, v, znbins, zrange)
    seed = expo_seed(x, y)
    f = fitf.fit(fitf.expo, x, y, seed, sigma=yu)

    if (not plot): return f

    #print('energy_0', f.values[0], ' +- ', f.errors[0] )
    #print('lifetime', f.values[1], ' +- ', f.errors[1] )

    frame_data = plt.gcf().add_axes((.1, .3, .8, .6))
    plt.hist2d(z, v, (zbins, vbins))
    x, y, yu = fitf.profileX(z, v, znbins, zrange)
    plt.errorbar(x, y, yu, np.diff(x)[0] / 2, fmt="kp", ms=7, lw=3)
    plt.plot(x, f.fn(x), "r-", lw=4)
    frame_data.set_xticklabels([])
    labels("", "Energy (pes)", "Lifetime fit")
    lims = plt.xlim()
    frame_res = plt.gcf().add_axes((.1, .1, .8, .2))
    plt.errorbar(x, (f.fn(x) - y) / yu, 1, np.diff(x)[0] / 2, fmt="p", c="k")
    plt.plot(lims, (0, 0), "g--")
    plt.xlim(*lims)
    plt.ylim(-5, +5)
    labels("Drift time (µs)", "Standarized residual")
    return f
Esempio n. 3
0
def test_lt_profile_yields_same_result_expo_fit():

    Nevt  = int(1e5)
    e0 = 1e+4 # pes
    std = 0.05 * e0
    lt = 2000 # lifetime in mus
    nbins_z = 12
    range_z = (1, 500)
    z, es = energy_lt_experiment(Nevt, e0, lt, std)

    x, y, yu     = fitf.profileX(z, es, nbins_z, range_z)
    valid_points = ~np.isnan(yu)

    x    = x [valid_points]
    y    = y [valid_points]
    yu   = yu[valid_points]
    seed = expo_seed(x, y)
    f    = fitf.fit(fitf.expo, x, y, seed, sigma=yu)

    par  = np.array(f.values)
    err  = np.array(f.errors)
    e0   = par[0]
    lt   = - par[1]
    e0_u = err[0]
    lt_u = err[1]

    _, _,  fr = fit_lifetime_profile(z, es, nbins_z, range_z)
    assert e0   == approx(fr.par[0],  rel=0.05)
    assert lt   == approx(fr.par[1],  rel=0.05)
    assert e0_u == approx(fr.err[0],  rel=0.05)
    assert lt_u == approx(fr.err[1],  rel=0.05)
Esempio n. 4
0
def lifetimes_in_TRange(kre: KrEvent, krnb: KrNBins, krb: KrBins,
                        krr: KrRanges, TL) -> List[KrFit]:
    """ Plots lifetime fitted to a range of T values"""

    # Specify the range and number of bins in Z
    Znbins = krnb.Z
    Zrange = krr.Z

    kfs = []
    for tlim in TL:

        # select data
        kre_t = select_in_TRange(kre, *tlim)
        z, e = kre_t.Z, kre_t.E

        x, y, yu = fitf.profileX(z, e, Znbins, Zrange)
        # Fit profile to an exponential
        seed = expo_seed(x, y)
        f = fitf.fit(fitf.expo, x, y, seed, sigma=yu)

        kf = KrFit(par=np.array(f.values),
                   err=np.array(f.errors),
                   chi2=chi2(f, x, y, yu))

        #krf.print_fit(kf)
        kfs.append(kf)

    return kfs
Esempio n. 5
0
def plt_v_vs_u(V, U, Vnbins, Unbins, Vrange, Urange , Vname='', Uname=''):
    c = hst.Canvas(1, 2)
    hst.hist2d(U, V, (Unbins, Vnbins), (Urange, Vrange), canvas=c(1), xylabels=(Uname, Vname));
    xs, ys, eys = fitf.profileX(U, V, Unbins, xrange=Urange)
    hst.errorbar(xs, ys, yerr=eys, fmt='*', canvas=c(1), c='black')
    ymean = np.mean(ys)
    hst.hist(100.*ys/ymean, 20, canvas=c(2), xylabels=(' deviation ratio (%)', ''));
    return c
Esempio n. 6
0
def profile1d(z: np.array, e: np.array, nbins_z: int,
              range_z: np.array) -> Tuple[float, float, float]:
    """Adds an extra layer to profileX, returning only valid points"""
    x, y, yu = fitf.profileX(z, e, nbins_z, range_z)
    valid_points = ~np.isnan(yu)
    x = x[valid_points]
    y = y[valid_points]
    yu = yu[valid_points]
    return x, y, yu
def lifetime_calculation(z, zrange, energy, erange, elim, slope, axes):
    """
    Measure the lifetime for the given events and plots the raw energy distribution and the energy vs drift time in a separate axes instance.

    Parameters:
    z = Array of events' drift time
    zrange = Range in drift time for the fit.
    energy = Array of events' energy.
    erange = Range in energy for plotting.
    elim = Limits for the energy at z=0.
    slope = slope of the exponential, used in the selection of the events, should be the inverse of the expected lifetime (1/[expected lifetime])
    axes = Axes object from a subplot, should have length >= 2.
    """

    axes[0].hist(energy, 50, erange, rasterized=True)
    histFun.labels("S2 energy (pes)", "Entries",
                   "Fiducialized energy spectrum")

    low_cut = elim[0] * np.exp(-slope * z)
    high_cut = elim[1] * np.exp(-slope * z)
    sel = coref.in_range(energy, low_cut,
                         high_cut)  # remove low and high E background

    axes[1].hist2d(z,
                   energy, (100, 50),
                   range=(zrange, erange),
                   rasterized=True)
    x, y, u_y = fitf.profileX(z[sel],
                              energy[sel],
                              100,
                              xrange=zrange,
                              yrange=erange)

    axes[1].plot(x, y, "--k", rasterized=True)
    axes[1].plot(z[z < 500], low_cut[z < 500], "k.", rasterized=True)
    axes[1].plot(z[z < 500], high_cut[z < 500], "k.", rasterized=True)

    Zrange_LT = zrange

    seed = np.max(y), (x[15] - x[5]) / np.log(y[15] / y[5])
    f = fitf.fit(fitf.expo, x, y, seed, fit_range=Zrange_LT, sigma=u_y)

    axes[1].plot(x, f.fn(x), "r", lw=3, rasterized=True)
    print("Energy at z=0 = {:.1f} +- {:.1f}".format(f.values[0], f.errors[0]))
    print("Lifetime      = {:.1f} +- {:.1f}".format(-f.values[1], f.errors[1]))
    print("Chi2          = {:.2f}          \n".format(f.chi2))

    #    axes[1].text(zrange[0] + 0.05*(zrange[1]-zrange[0]), erange[0] + 1000, \
    #        "Lifetime = {:.1f} $\pm$ {:.1f}".format(-f.values[1], f.errors[1]), color = "white")#, fontsize = 14)

    histFun.labels("Drift time ($\mu$s)", "S2 energy (pes)", "")

    return np.array([-f.values[1], f.errors[1]
                     ]), corrf.LifetimeCorrection(-f.values[1], f.errors[1])
Esempio n. 8
0
def lifetimes_in_XYRange(kre: KrEvent,
                         krnb: KrNBins,
                         krb: KrBins,
                         krr: KrRanges,
                         xyr: XYRanges,
                         XL=[(-125, -75), (-125, -75), (75, 125), (75, 125)],
                         YL=[(-125, -75), (75, 125), (75, 125), (-125, -75)],
                         nx=2,
                         ny=2,
                         figsize=(8, 8)) -> KrFit:
    """ Plots lifetime fitted to a range of XY values"""

    # Specify the range and number of bins in Z
    Znbins = krnb.Z
    Zrange = krr.Z

    fig = plt.figure(figsize=figsize)

    # XL = [(-125, -75), (-125, -75), (75, 125),(75, 125)]
    # YL = [(-125, -75), (75, 125), (75, 125),(-125, -75)]
    KF = []
    for i, pair in enumerate(zip(XL, YL)):
        xlim = pair[0]
        ylim = pair[1]
        print(f'xlim = {xlim}, ylim ={ylim}')

        # select data in region defined by xyr
        xyr = XYRanges(X=xlim, Y=ylim)
        kre_xy = select_in_XYRange(kre, xyr)
        z, e = kre_xy.Z, kre_xy.E

        ax = fig.add_subplot(nx, ny, i + 1)
        x, y, yu = fitf.profileX(z, e, Znbins, Zrange)
        plt.errorbar(x, y, yu, np.diff(x)[0] / 2, fmt="kp", ms=7, lw=3)

        # Fit profile to an exponential
        seed = expo_seed(x, y)
        f = fitf.fit(fitf.expo, x, y, seed, sigma=yu)

        # plot fitted value
        plt.plot(x, f.fn(x), "r-", lw=4)

        labels("", "Energy (pes)", "Lifetime fit")

        kf = KrFit(par=np.array(f.values),
                   err=np.array(f.errors),
                   chi2=chi2(f, x, y, yu))
        KF.append(kf)
    return KF
Esempio n. 9
0
def fit_profile_1d_expo(xdata, ydata, nbins, *args, **kwargs):
    """
    Make a profile of the input data and fit it to an exponential
    function with the parameters automatically estimated.
    """
    x, y, yu     = fitf.profileX(xdata, ydata, nbins, *args, **kwargs)
    valid_points = yu > 0

    x    = x [valid_points]
    y    = y [valid_points]
    yu   = yu[valid_points]
    seed = expo_seed(x, y)
    f    = fitf.fit(fitf.expo, x, y, seed, sigma=yu)
    assert np.all(f.values != seed)
    return f
Esempio n. 10
0
def _hprofile(u, v, bins, std=False, **kwargs):
    #hst.hist2d(u, v, bins, **kwargs)
    n = len(bins[0]) - 1
    urange = u.min(), u.max()
    if (not isinstance(bins[0], int)):
        n = len(bins[0]) - 1
        urange = bins[0].min(), bins[0].max()
    if (not isinstance(bins[1], int)):
        vrange = bins[1].min(), bins[1].max()
    if 'range' in kwargs:
        urange = kwargs['range'][0]
        vrange = kwargs['range'][1]
    # print('hprofile ', n, urange, vrange)
    xs, ys, eys = fitf.profileX(u, v, n, urange, vrange, std=std)
    cc = hst.errorbar(xs, ys, yerr=eys, **kwargs)
    return cc
Esempio n. 11
0
def energy_X_profile(X: np.array,
                     E: np.array,
                     xnbins: int,
                     xrange: Tuple[float, float],
                     xlabel: str = 'R',
                     erange: Tuple[float, float] = (9e+3, 14e+3),
                     figsize: Tuple[float, float] = (10, 8)):

    fig = plt.figure(figsize=figsize)

    x, y, yu = fitf.profileX(X, E, xnbins, xrange)
    ax = fig.add_subplot(1, 1, 1)

    plt.errorbar(x, y, yu, fmt="kp", ms=7, lw=3)
    plt.xlabel(xlabel)
    plt.ylabel('E (pes)')
    plt.ylim(erange)
Esempio n. 12
0
def profile_and_fit(X, Y, xrange, yrange, nbins, fitpar, label):
    fitOpt = "r"
    xe = (xrange[1] - xrange[0]) / nbins

    x, y, sy = fitf.profileX(X,
                             Y,
                             nbins=nbins,
                             xrange=xrange,
                             yrange=yrange,
                             drop_nan=True)
    sel = in_range(x, xrange[0], xrange[1])
    x, y, sy = x[sel], y[sel], sy[sel]
    f = fitf.fit(fitf.expo, x, y, fitpar, sigma=sy)

    plt.errorbar(x=x, xerr=xe, y=y, yerr=sy, linestyle='none', marker='.')
    plt.plot(x, f.fn(x), fitOpt)
    #set_plot_labels(xlabel=label[0], ylabel=label[1], grid=True)
    return f, x, y, sy
Esempio n. 13
0
def build_correction_map_rad(kr_df    : pd.DataFrame,
                             num_bins : int
                            )        -> pd.DataFrame:
    rad, pes, pes_error = profileX(kr_df.rad_rec, kr_df.s2_pes, num_bins)
    corr = pes / pes.min()

    # Plotting corrections if running interactively
    if is_interactive():
        fig, (ax1, ax2) = plt.subplots(1,2, figsize=(16,7))
        ax1.errorbar(rad, pes, pes_error, fmt="kp", ms=7, lw=3)
        ax1.set_title ("S2 pes (with errors)"   , size=16);
        ax1.set_xlabel("Radius (mm)", size=16);
        ax1.set_ylabel("pes"        , size=16);
        ax2.plot(rad, corr)
        ax2.set_title ("Correction factor"   , size=16);
        ax2.set_xlabel("Radius (mm)", size=16);

    return pd.DataFrame({'rad': rad, 'correction': corr})
Esempio n. 14
0
def lifetime_in_XYRange(kre: KrEvent, krnb: KrNBins, krb: KrBins,
                        krr: KrRanges, xyr: XYRanges) -> KrFit:
    """ Fits lifetime to a range of XY values"""

    # select data in region defined by xyr
    kre_xy = select_in_XYRange(kre, xyr)
    z, e = kre_xy.Z, kre_xy.E

    # Specify the range and number of bins in Z
    Znbins = krnb.Z
    Zrange = krr.Z

    # create a figure and plot 2D histogram and profile
    frame_data = plt.gcf().add_axes((.1, .3, .8, .6))
    plt.hist2d(z, e, (krb.Z, krb.E))
    x, y, yu = fitf.profileX(z, e, Znbins, Zrange)
    plt.errorbar(x, y, yu, np.diff(x)[0] / 2, fmt="kp", ms=7, lw=3)

    # Fit profile to an exponential
    seed = expo_seed(x, y)
    f = fitf.fit(fitf.expo, x, y, seed, sigma=yu)

    # plot fitted value
    plt.plot(x, f.fn(x), "r-", lw=4)

    # labels and ticks
    frame_data.set_xticklabels([])
    labels("", "Energy (pes)", "Lifetime fit")

    # add a second frame

    lims = plt.xlim()
    frame_res = plt.gcf().add_axes((.1, .1, .8, .2))
    # Plot (y - f(x)) / sigma(y) as a function of x
    plt.errorbar(x, (f.fn(x) - y) / yu, 1, np.diff(x)[0] / 2, fmt="p", c="k")
    plt.plot(lims, (0, 0), "g--")
    plt.xlim(*lims)
    plt.ylim(-5, +5)
    labels("Drift time (µs)", "Standarized residual")

    return KrFit(par=np.array(f.values),
                 err=np.array(f.errors),
                 chi2=chi2(f, x, y, yu))
Esempio n. 15
0
def energy_time_profile(T: np.array,
                        E: np.array,
                        Tnbins: int,
                        Trange: Tuple[float, float],
                        timeStamps: List[datetime.datetime],
                        erange: Tuple[float, float] = (9e+3, 14e+3),
                        figsize: Tuple[float, float] = (10, 8)):

    xfmt = md.DateFormatter('%d-%m %H:%M')
    fig = plt.figure(figsize=figsize)

    x, y, yu = fitf.profileX(T, E, Tnbins, Trange, erange)
    ax = fig.add_subplot(1, 1, 1)

    ax.xaxis.set_major_formatter(xfmt)
    plt.errorbar(timeStamps, y, yu, fmt="kp", ms=7, lw=3)
    plt.xlabel('date')
    plt.ylabel('E (pes)')
    plt.ylim(erange)
    plt.xticks(rotation=25)
Esempio n. 16
0
def fit_lifetime_from_profile(kre: KrEvent,
                              kR: KrRanges,
                              kNB: KrNBins,
                              kB: KrBins,
                              kL: KrRanges,
                              title="Lifetime Fit") -> KrFit:

    sel = in_range(kre.X, *kL.XY) & in_range(kre.Y, *kL.XY)
    z, e = kre.Z[sel], kre.E[sel]

    frame_data = plt.gcf().add_axes((.1, .35, .8, .6))
    plt.hist2d(z, e, (kB.Z, kB.E))

    x, y, yu = fitf.profileX(z, e, kNB.Z, kR.Z, kR.E)
    plt.errorbar(x, y, yu, np.diff(x)[0] / 2, fmt="kp", ms=7, lw=3)

    seed = expo_seed(x, y)
    f = fitf.fit(fitf.expo, x, y, seed, sigma=yu)

    plt.plot(x, f.fn(x), "r-", lw=4)

    frame_data.set_xticklabels([])
    labels("", "Energy (pes)", title)
    lims = plt.xlim()

    frame_res = plt.gcf().add_axes((.1, .1, .8, .2))
    plt.errorbar(x, (f.fn(x) - y) / yu, 1, np.diff(x)[0] / 2, fmt="p", c="k")
    plt.plot(lims, (0, 0), "g--")
    plt.xlim(*lims)
    plt.ylim(-5, +5)
    labels("Drift time (µs)", "Standarized residual")
    print_fit(f)
    print('chi2 = {}'.format(chi2(f, x, y, yu)))

    return KrFit(par=np.array(f.values[1]),
                 err=np.array(f.errors[1]),
                 chi2=np.array(chi2(f, x, y, yu)),
                 valid=np.ones(1))
Esempio n. 17
0
def lt_lsqfit(Z, E, chi2=True, nbins=12):
    """ unbinned fit to the lifetime, return e0, lt best estimate, chi2, and valid (bool) flag
    if chi2 is False, return 0 for chi2,
    nbins is the number of bins to compute the chi2 (default 12)
    """
    ok = True
    e0, lt, e0u, ltu, xchi2 = 0, 0, 0, 0, 0
    DE = -np.log(E)
    try:
        cc, cov = np.polyfit(Z, DE, 1, full=False, cov=True)
        #print(cov)
        a, b = cc[0], cc[1]
        lt = 1 / a
        ltu = lt * lt * np.sqrt(cov[0, 0])
        e0 = np.exp(-b)
        e0u = e0 * np.sqrt(cov[1, 1])
    except:
        ok = False
        pass
    # print('lifetime :', lt, '+-', ult)
    # print('e0       :', e0, '+-', ue0)
    me0, mlt = Measurement(e0, e0u), Measurement(lt, ltu)

    if (not chi2 or not ok):
        return me0, mlt, xchi2, ok

    xs, ys, uys = fitf.profileX(Z, DE, nbins)
    c*k = ~np.isnan(uys)
    try:
        res = (a * xs[c*k] + b - ys[c*k]) / uys[c*k]
        # print(res, uys)
        xchi2 = np.sum(res * res) / (1. * len(xs) - 1)
    except:
        ok = False
        pass
    #print(me0, mlt, chi2)
    return me0, mlt, xchi2, ok
Esempio n. 18
0
def psf_fit(mapDST, DX, DY, groupZ, groupQ, z_int, Ec_conv, sigma_range,
            sipm_lim, cut, min_count, run_number):
    """
    Calculates (through a data-driven fit) and returns the transverse spread for a given dataset.

    Parameters:
    mapDST = Full raw DST.
    DX = Difference in position between event and sensor in x-dimension.
    DY = Difference in position between event and sensor in y-dimension.
    groupQ = Charge of the SiPMs.
    groupZ = Mean drift time of the event.
    z_int = Drift time interval to do the fit.
    Ec_conv = Collection (for several sigmas) of PSF+gaussian convolutions (for the fit).
    sigma_range = Collection of sigmas considered in the convolution.
    sipm_lim = Limit in the distance point-sensor for the fit.
    cut = Minimum charge in a bin to be used for the fit.
    min_count = Minimum number of events in a bin to be used for the fit.
    """
    fig, axes = plt.subplots(1, 3, figsize=(24, 6))

    chimin = 1e20
    sipm_xyrange = (-sipm_lim, sipm_lim)
    binfactor = 2.
    sigmamin = 0.
    bin_lim_min = -50.
    sipm_lim_min = -50.
    nbins = int(binfactor * sipm_lim)

    # Plot the distribution to be fitted.
    base_selection = ((np.sqrt(DX**2 + DY**2) < 50.) & (mapDST.Q > 0.) &
                      (mapDST.Q.values / groupQ < 1.))
    z_interval_selection = base_selection & coref.in_range(
        groupZ, z_int[0], z_int[1])

    xc, Ec, Ece = fitf.profileX(DX[z_interval_selection], mapDST[z_interval_selection].Q/groupQ[z_interval_selection],\
                                  nbins, sipm_xyrange)

    try:
        x_min = xc[(Ec < cut) & (xc < 0)].max()
        x_max = xc[(Ec < cut) & (xc > 0)].min()
    except:
        x_min = xc.min()
        x_max = xc.max()

    fig1 = plt.figure()
    ax1 = fig.add_subplot(1, 1, 1)
    (xc, yc, Ec_m, Ece_m), _, cb = \
    histFun.hist2d_profile(DX[z_interval_selection], DY[z_interval_selection], mapDST[z_interval_selection].Q.values / groupQ[z_interval_selection],\
                           nbins, nbins, sipm_xyrange, sipm_xyrange,  new_figure = False, rasterized=True)
    cb.set_label("Charge fraction")
    histFun.labels("X (mm)", "Y (mm)", "")
    ax1.set_xticks(np.linspace(-20., 20., 5))
    ax1.set_yticks(np.linspace(-20., 20., 5))
    fig1.tight_layout()
    fig1.savefig("TransPSF_Z{0}-{1}_R{2}.pdf".format(z_int[0], z_int[1],
                                                     run_number))

    fig, axes = plt.subplots(1, 3, figsize=(24, 6))
    plt.axes(axes[0])
    (xc, yc, Ec_m, Ece_m), _, cb = \
    histFun.hist2d_profile(DX[z_interval_selection], DY[z_interval_selection], mapDST[z_interval_selection].Q.values / groupQ[z_interval_selection],\
                           nbins, nbins, sipm_xyrange, sipm_xyrange,  new_figure = False, rasterized=True)
    cb.set_label("E (pes)")
    histFun.labels("X (mm)", "Y (mm)", "")

    # Fit.
    Ec_fit = 0

    Ec = Ec_m
    Ece = Ece_m

    counts, *_ = np.histogram2d(DX[z_interval_selection], DY[z_interval_selection],\
                                [np.linspace(-sipm_lim, sipm_lim, nbins+1), np.linspace(-sipm_lim, sipm_lim, nbins+1)])

    for lim in np.arange(sipm_lim, sipm_lim + 1, 1.):
        bin_lim = [len(xc[xc < x_min]), len(xc[xc < x_max]) + 1]
        Ec = Ec_m[bin_lim[0]:bin_lim[1], bin_lim[0]:bin_lim[1]]
        Ece = Ece_m[bin_lim[0]:bin_lim[1], bin_lim[0]:bin_lim[1]]
        counts_sel = counts[bin_lim[0]:bin_lim[1], bin_lim[0]:bin_lim[1]]
        for i, sigma in enumerate(sigma_range):
            Ec_c = Ec_conv[i]
            Ec_c = Ec_c[bin_lim[0]:bin_lim[1], bin_lim[0]:bin_lim[1]]
            Ec_c = Ec_c * Ec.sum() / Ec_c.sum()
            sel = counts_sel > min_count
            chi = ((Ec[sel] - Ec_c[sel])**2 /
                   (Ece[sel]**2)).sum() / (len(Ec[sel]) - 1)
            if chi < chimin:
                chimin = chi
                sigmamin = sigma
                Ec_fit = Ec_c

    # Plot the projection at x = 0 / y = 0
    xproj = Ec_m[np.argmax(Ec_m.sum(axis=0))]
    yproj = Ec_m[:, np.argmax(Ec_m.sum(axis=0))]

    xprojf = Ec_fit[np.argmax(Ec_fit.sum(axis=0))]
    yprojf = Ec_fit[:, np.argmax(Ec_fit.sum(axis=1))]

    h1d(xc, len(xc), [np.min(xc), np.max(xc)], weights=xproj, ax=axes[1])
    axes[1].plot(xc[bin_lim[0]:bin_lim[1]],
                 xprojf,
                 "r",
                 lw=1.25,
                 rasterized=True)
    axes[1].set_xlabel("X (mm)")
    axes[1].set_ylabel("Charge fraction")
    axes[1].grid(True)

    h1d(yc, len(yc), [np.min(yc), np.max(yc)], weights=yproj, ax=axes[2])
    axes[2].plot(yc[bin_lim[0]:bin_lim[1]],
                 yprojf,
                 "r",
                 lw=1.25,
                 rasterized=True)
    axes[2].set_xlabel("Y (mm)")
    axes[2].set_ylabel("Charge fraction")
    axes[2].grid(True)

    fig.tight_layout()

    extent = axes[0].get_tightbbox(fig.canvas.get_renderer()).transformed(
        fig.dpi_scale_trans.inverted())
    axes[0].set_xticks(np.linspace(-20., 20., 5))
    axes[0].set_yticks(np.linspace(-20., 20., 5))
    #    fig.savefig("TransPSF_Z{0}-{1}_R{2}.pdf".format(z_int[0], z_int[1], run_number), bbox_inches=extent)
    extent = axes[1].get_tightbbox(fig.canvas.get_renderer()).transformed(
        fig.dpi_scale_trans.inverted())
    fig.savefig("TransPSF_X_Z{0}-{1}_R{2}.pdf".format(z_int[0], z_int[1],
                                                      run_number),
                bbox_inches=extent)
    extent = axes[2].get_tightbbox(fig.canvas.get_renderer()).transformed(
        fig.dpi_scale_trans.inverted())
    fig.savefig("TransPSF_Y_Z{0}-{1}_R{2}.pdf".format(z_int[0], z_int[1],
                                                      run_number),
                bbox_inches=extent)

    axes[0].set_title("Energy vs XY for Z = [{0},{1}]".format(
        z_int[0], z_int[1]))
    axes[1].set_title("Charge profile X projection at Y = 0")
    axes[2].set_title("Charge profile Y projection at X = 0")
    fig.tight_layout()
    plt.close(fig)

    return sigmamin, chimin
Esempio n. 19
0
def fit_and_plot_slices_2d_expo(
    kre: KrEvent,
    krnb: KrNBins,
    krb: KrBins,
    krr: KrRanges,
    fit_var="E",
    min_entries=1e2,
    figsize=(12, 12)) -> KrLTSlices:
    """
    Slice the data in x and y, make the profile in z of E,
    fit it to a exponential and return the relevant values.

    """

    xybins = krb.XY
    nbins_xy = np.size(xybins) - 1
    nbins_z = krnb.Z
    nbins = nbins_xy, nbins_xy
    const = np.zeros(nbins)
    slope = np.zeros(nbins)
    constu = np.zeros(nbins)
    slopeu = np.zeros(nbins)
    chi2 = np.zeros(nbins)
    valid = np.zeros(nbins, dtype=bool)
    zrange = krr.Z

    fig = plt.figure(figsize=figsize)  # Creates a new figure
    k = 0
    index = 0
    for i in range(nbins_xy):
        sel_x = in_range(kre.X, *xybins[i:i + 2])
        for j in range(nbins_xy):
            index += 1
            #print(f' bin =({i},{j});  index = {index}')
            if k % 25 == 0:
                k = 0
                fig = plt.figure(figsize=figsize)
            ax = fig.add_subplot(5, 5, k + 1)
            k += 1
            sel_y = in_range(kre.Y, *xybins[j:j + 2])
            sel = sel_x & sel_y
            entries = np.count_nonzero(sel)
            if entries < min_entries:
                print(
                    f'entries ={entries} not enough  to fit bin (i,j) =({i},{j})'
                )
                valid[i, j] = False
                continue

            try:
                z = kre.Z[sel]
                t = kre.E[sel]
                if fit_var == "Q":
                    t = kre.Q[sel]

                x, y, yu = fitf.profileX(z, t, nbins_z, zrange)
                ax.errorbar(x, y, yu, np.diff(x)[0] / 2, fmt="kp", ms=7, lw=3)
                seed = expo_seed(x, y)
                f = fitf.fit(fitf.expo, x, y, seed, sigma=yu)
                plt.plot(x, f.fn(x), "r-", lw=4)
                plt.grid(True)
                re = np.abs(f.errors[1] / f.values[1])
                #print(f' E +- Eu = {f.values[0]} +- {f.errors[0]}')
                #print(f' LT +- LTu = {-f.values[1]} +- {f.errors[1]}')
                #print(f' LTu/LT = {re} chi2 = {f.chi2}')

                if re > 0.5:
                    print(
                        f'Relative error to large, re ={re} for bin (i,j) =({i},{j})'
                    )
                    print(f' LT +- LTu = {-f.values[1]} +- {f.errors[1]}')
                    print(f' LTu/LT = {re} chi2 = {f.chi2}')
                    valid[i, j] = False

                const[i, j] = f.values[0]
                constu[i, j] = f.errors[0]
                slope[i, j] = -f.values[1]
                slopeu[i, j] = f.errors[1]
                chi2[i, j] = f.chi2
                valid[i, j] = True
            except:
                print(f'fit failed for bin (i,j) =({i},{j})')
                pass
    plt.tight_layout()

    return KrLTSlices(Ez0=Measurement(const, constu),
                      LT=Measurement(slope, slopeu),
                      chi2=chi2,
                      valid=valid)
Esempio n. 20
0
def fit_lifetime_slices(kre: KrEvent,
                        krnb: KrNBins,
                        krb: KrBins,
                        krr: KrRanges,
                        fit_var="E",
                        min_entries=1e2) -> KrLTSlices:
    """
    Slice the data in x and y, make the profile in z of E,
    fit it to a exponential and return the relevant values.

    """

    xybins = krb.XY
    nbins_xy = np.size(xybins) - 1
    nbins_z = krnb.Z
    nbins = nbins_xy, nbins_xy
    const = np.zeros(nbins)
    slope = np.zeros(nbins)
    constu = np.zeros(nbins)
    slopeu = np.zeros(nbins)
    chi2 = np.zeros(nbins)
    valid = np.zeros(nbins, dtype=bool)
    zrange = krr.Z

    for i in range(nbins_xy):
        sel_x = in_range(kre.X, *xybins[i:i + 2])
        for j in range(nbins_xy):
            #print(f' bin =({i},{j});  index = {index}')
            sel_y = in_range(kre.Y, *xybins[j:j + 2])
            sel = sel_x & sel_y
            entries = np.count_nonzero(sel)
            if entries < min_entries:
                #print(f'entries ={entries} not enough  to fit bin (i,j) =({i},{j})')
                valid[i, j] = False
                continue

            try:
                z = kre.Z[sel]
                t = kre.E[sel]
                if fit_var == "Q":
                    t = kre.Q[sel]

                x, y, yu = fitf.profileX(z, t, nbins_z, zrange)

                seed = expo_seed(x, y)
                f = fitf.fit(fitf.expo, x, y, seed, sigma=yu)
                re = np.abs(f.errors[1] / f.values[1])
                #print(f' E +- Eu = {f.values[0]} +- {f.errors[0]}')
                #print(f' LT +- LTu = {-f.values[1]} +- {f.errors[1]}')
                #print(f' LTu/LT = {re} chi2 = {f.chi2}')

                const[i, j] = f.values[0]
                constu[i, j] = f.errors[0]
                slope[i, j] = -f.values[1]
                slopeu[i, j] = f.errors[1]
                chi2[i, j] = f.chi2
                valid[i, j] = True

                if re > 0.5:
                    # print(f'Relative error to large, re ={re} for bin (i,j) =({i},{j})')
                    # print(f' LT +- LTu = {-f.values[1]} +- {f.errors[1]}')
                    # print(f' LTu/LT = {re} chi2 = {f.chi2}')
                    valid[i, j] = False

            except:
                print(f'fit failed for bin (i,j) =({i},{j})')
                pass

    return KrLTSlices(Es=Measurement(const, constu),
                      LT=Measurement(slope, slopeu),
                      chi2=chi2,
                      valid=valid)