Esempio n. 1
0
def hist2d(*args, **kwargs):
    """
    Create a figure and then the histogram
    """
    create_new_figure(kwargs)

    z, x, y, p = plt.hist2d(*args, **kwargs)
    return z, shift_to_bin_centers(x), shift_to_bin_centers(y), p
Esempio n. 2
0
def compute_and_save_hist_as_pd(values     : np.array           ,
                                out_file   : pd.HDFStore        ,
                                hist_name  : str                ,
                                n_bins     : int                ,
                                range_hist : Tuple[float, float],
                                norm       : bool = False       )->None:
    """
    Computes 1d-histogram and saves it in a file.
    The name of the table inside the file must be provided.
    Parameters
    ----------
    values : np.array
        Array with values to be plotted.
    out_file: pd.HDFStore
        File where histogram will be saved.
    hist_name: string
        Name of the pd.Dataframe to contain the histogram.
    n_bins: int
        Number of bins to make the histogram.
    range_hist: length-2 tuple (optional)
        Range of the histogram.
    norm: bool
        If True, histogram will be normalized.
    """
    n, b = np.histogram(values, bins = n_bins,
                        range = range_hist,
                        density = norm)
    table = pd.DataFrame({'entries': n,
                          'magnitude': shift_to_bin_centers(b)})
    out_file.put(hist_name, table, format='table', data_columns=True)

    return
Esempio n. 3
0
def fit_energy(e : np.array,
               nbins   : int,
               range   : Tuple[float],
               n_sigma : float = 3.0)->FitCollection:
    """
    Takes an "energy vector" (e.g, 1d array), with number of bins enbins and range erange, then:
        1. Computes the histogram of e with enbins in erange. This returns an array of bin
        edges (b), and bin contents (y). The array (b) is shifted to bin centers (x)
        2. The arrays x and y are fitted to a gaussian, in a range given by an interval
        arround the estimation of the maximum of the gaussian. The interval size is estimated
        by multiplying n_sigma by the estimation of the gaussian std.

    The result of the fit is a fit collection, that includes a FitPar and a HistoPar objects
    needed for printing and plotting the fit result.
       """

    y, b = np.histogram(e, bins= nbins, range=range)
    x = shift_to_bin_centers(b)
    bin_size = (range[1] - range[0]) / nbins
    seed = gaussian_parameters(e, range, bin_size)

    fp, fr = gaussian_fit(x, y, seed, n_sigma)

    hp = HistoPar(var      = e,
                  nbins    = nbins,
                  range    = range)

    return FitCollection(fp = fp, hp = hp, fr = fr)
Esempio n. 4
0
def profileX(xdata, ydata, nbins=100,
             xrange=None, yrange=None,
             std=False, drop_nan=True):
    """
    Compute the x-axis binned average of a dataset.

    Parameters
    ----------
    xdata, ydata : 1-dim np.ndarray
        x and y coordinates from a dataset.
    nbins : int, optional
        Number of divisions in the x axis. Defaults to 100.
    xrange : tuple of ints/floats or None, optional
        Range over the x axis. Defaults to dataset extremes.
    yrange : tuple of ints/floats or None, optional
        Range over the y axis. Defaults to dataset extremes.
    drop_nan : bool, optional
        Exclude empty bins. Defaults to True.

    Returns
    -------
    x_out : 1-dim np.ndarray.
        Bin centers.
    y_out : 1-dim np.ndarray
        Data average for each bin.
    y_err : 1-dim np.ndarray
        Average error for each bin.
    """
    if xrange is None: xrange = np.min(xdata), np.max(xdata)

    selection = coref.in_range(xdata, *xrange)
    xdata     = xdata[selection]
    ydata     = ydata[selection]

    if yrange is not None:
        selection = coref.in_range(ydata, *yrange)
        xdata     = xdata[selection]
        ydata     = ydata[selection]

    bin_edges   = np.linspace(*xrange, nbins + 1)
    bin_centers = coref.shift_to_bin_centers(bin_edges)
    bin_numbers = np.digitize(xdata, bin_edges, right=False)
    df          = pd.DataFrame(dict(bin=bin_numbers, y=ydata))
    gb          = df.groupby("bin").y

    mean      = gb.mean().values
    deviation = gb.std () if std else gb.std() / gb.size()**0.5
    indices   = deviation.index.values - 1

    if drop_nan:
        return bin_centers[indices], mean, deviation.values

    mean_               = np.full_like(bin_centers, np.nan)
    deviation_          = np.full_like(bin_centers, np.nan)
    mean_     [indices] = mean
    deviation_[indices] = deviation

    return bin_centers, mean_, deviation_
Esempio n. 5
0
def hist(*args, **kwargs):
    """
    Return output of histogram with shift bins
    """
    y, x, p = plt.hist(*args, **kwargs)
    #"get current axes"
    ax = plt.gca()
    ax.xaxis.set_minor_locator(AutoMinorLocator())
    return y, shift_to_bin_centers(x), p
Esempio n. 6
0
def quick_gauss_fit(data, bins):
    """
    Histogram input data and fit it to a gaussian with the parameters
    automatically estimated.
    """
    y, x = np.histogram(data, bins)
    x = shift_to_bin_centers(x)
    seed = gauss_seed(x, y)
    f = fitf.fit(fitf.gauss, x, y, seed)
    assert np.all(f.values != seed)
    return f
Esempio n. 7
0
def plot_and_fit(data: List,
                 title: str = '',
                 xlabel: str = 'Charge (pes)',
                 ylabel: str = 'Entries / bin',
                 num_bins: int = 100) -> Tuple[float, float, float]:

    # Fitting function
    def gauss(x, amplitude, mu, sigma):
        return amplitude / (2 * np.pi)**.5 / sigma * np.exp(
            -0.5 * (x - mu)**2. / sigma**2.)

    # Plotting the data
    fig = plt.figure(figsize=(8, 5))
    mean = np.mean(data)
    max_range = 0.1
    plt_range = ((1. - max_range) * mean, (1. + max_range) * mean)

    y, x, _ = plt.hist(data, bins=num_bins, range=plt_range)
    x = shift_to_bin_centers(x)

    # Fitting data
    seed = 1000, mean, mean * 0.01
    sigma = poisson_sigma(y)
    max_range = 0.05
    fit_range = ((1. - max_range) * mean, (1. + max_range) * mean)
    f = fitf.fit(gauss, x, y, seed, fit_range=fit_range, sigma=sigma)

    amplitude, mu, sigma = f.values[0], f.values[1], f.values[2]
    mu_err, sigma_err = f.errors[1], f.errors[2]
    fwhm = 2.35 * sigma / mu

    # Plotting the gauss fit
    mx = np.linspace(fit_range[0], fit_range[1], 1000)

    legend = f"$\mu$ = {mu:.3f}\n"
    legend += f"$\sigma$ = {sigma:.3f}\n"
    legend += f"fwhm = {fwhm/units.perCent:.2f} %"

    plt.plot(mx, f.fn(mx), 'r-')
    plt.plot(mx, gauss(mx, amplitude, mu, sigma), 'r-', label=legend)
    plt.title(title, size=14)
    plt.xlabel(xlabel, size=14)
    plt.ylabel(ylabel, size=14)
    plt.legend(loc=1)
    plt.show()

    # Verbosing
    print(f"DATA from {title} ...\n" + \
          f"mu    = {mu:10.3f} +- {mu_err:.3f}\n" +\
          f"sigma = {sigma:10.3f} +- {sigma_err:.3f}  ->  " + \
          f"fwhm  = {fwhm/units.perCent:.3f} %\n"
          f"Chi2  = {f.chi2:10.3f}\n")

    return mu, sigma, fwhm
Esempio n. 8
0
def compute_drift_v(zdata: np.array,
                    nbins: int = 35,
                    zrange: Tuple[float, float] = (500, 640),
                    seed: Tuple[float, float, float, float] = None,
                    detector: str = 'new') -> Tuple[float, float]:
    """
    Computes the drift velocity for a given distribution
    using the sigmoid function to get the cathode edge.

    Parameters
    ----------
    zdata: array_like
        Values of Z coordinate.
    nbins: int (optional)
        The number of bins in the z coordinate for the binned fit.
    zrange: length-2 tuple (optional)
        Fix the range in z.
    seed: length-4 tuple (optional)
        Seed for the fit.
    detector: string (optional)
        Used to get the cathode position from DB.
    plot_fit: boolean (optional)
        Flag for plotting the results.

    Returns
    -------
    dv: float
        Drift velocity.
    dvu: float
        Drift velocity uncertainty.
    """

    y, x = np.histogram(zdata, nbins, zrange)
    x = shift_to_bin_centers(x)

    if seed is None: seed = np.max(y), np.mean(zrange), 0.5, np.min(y)

    z_cathode = DB.DetectorGeo(detector).ZMAX[0]
    try:
        f = fitf.fit(sigmoid,
                     x,
                     y,
                     seed,
                     sigma=poisson_sigma(y),
                     fit_range=zrange)
        dv = z_cathode / f.values[1]
        dvu = dv / f.values[1] * f.errors[1]
    except RuntimeError:
        print(
            "WARNING: Sigmoid fit for dv computation fails. NaN value will be set in its place."
        )
        dv, dvu = np.nan, np.nan

    return dv, dvu
Esempio n. 9
0
def apply_skeleton(df):

    x = df.X.values
    y = df.Y.values
    z = df.Z.values

    xx = np.linspace(x.min() - 0.5, x.max() + 0.5, int(x.max() - x.min() + 2))
    yy = np.linspace(y.min() - 0.5, y.max() + 0.5, int(y.max() - y.min() + 2))
    zz = shift_to_bin_centers(df.Z.unique())

    zz = np.append(zz, zz[-1] + 1)
    zz = np.append(zz[0] - 1, zz)
    values = np.histogramdd((x, y, z), bins=[xx, yy, zz])
    val = values[0].transpose(2, 0, 1).flatten()
    digitize = np.where(values[0] > 0, 1, 0)
    skeleton = skeletonize_3d(digitize)
    #if skeleton.sum() > 0:
    skeleton_mask = np.where(skeleton == 1)
    x_skel = shift_to_bin_centers(xx)[skeleton_mask[0]]
    y_skel = shift_to_bin_centers(yy)[skeleton_mask[1]]
    z_skel = shift_to_bin_centers(zz)[skeleton_mask[2]]
    e_skel = values[0][skeleton_mask]

    return pd.DataFrame({'X': x_skel, 'Y': y_skel, 'Z': z_skel, 'E': e_skel})
Esempio n. 10
0
def selection_in_band(
    z: np.array,
    e: np.array,
    range_z: Range,
    range_e: Range,
    nbins_z: int = 50,
    nbins_e: int = 100,
    nsigma: float = 3.5
) -> Tuple[np.array, FitPar, FitPar, HistoPar2, ProfilePar]:
    """ This returns a selection of the events that are inside the Kr E vz Z
    returns: np.array(bool)
    """

    zbins = np.linspace(*range_z, nbins_z + 1)
    zerror = np.diff(zbins) * 0.5
    ebins = np.linspace(*range_e, nbins_e + 1)
    zc = shift_to_bin_centers(zbins)

    sel_e = in_range(e, *range_e)
    mean, sigma, chi2, ok = fit_slices_1d_gauss(z[sel_e],
                                                e[sel_e],
                                                zbins,
                                                ebins,
                                                min_entries=5e2)
    e_mean = mean.value
    e_sigma = sigma.value
    # 1. Profile of mean values of e in bins of z
    #zc, e_mean, e_sigma = fitf.profileX(z, e, nbins_z, range_z, range_e)
    #2. Fit two exponentials to e_mmean +- ns_igma * e_sigma defining a band
    y = e_mean + nsigma * e_sigma
    fph, _, _ = fit_lifetime_unbined(zc, y, nbins_z, range_z)
    y = e_mean - nsigma * e_sigma
    fpl, _, _ = fit_lifetime_unbined(zc, y, nbins_z, range_z)
    # 3. Select events in the range defined by the band
    sel_inband = in_range(e, fpl.f(z), fph.f(z))

    hp = HistoPar2(var=z,
                   nbins=nbins_z,
                   range=range_z,
                   var2=e,
                   nbins2=nbins_e,
                   range2=range_e)

    pp = ProfilePar(x=zc, xu=zerror, y=e_mean, yu=e_sigma)

    return sel_inband, fpl, fph, hp, pp
Esempio n. 11
0
def get_time_series_df(
        time_bins: Number,
        time_range: Tuple[float, float],
        dst: DataFrame,
        time_column: str = 'time') -> Tuple[np.array, List[np.array]]:
    """

    Given a dst (DataFrame) with a time column specified by the name time,
    this function returns a time series (ts) and a list of masks which are used to divide
    the event in time tranches.

    More generically, one can produce a "time series" using any column of the dst
    simply specifying time_column = ColumName

        Parameters
        ----------
            time_bins
                Number of time bines.
            time_range
                Time range.
            dst
                A Data Frame
            time_column
            A string specifyng the dst column to be divided in time slices.

        Returns
        -------
            A Tuple with:
            np.array       : This is the ts vector
            List[np.array] : This are the list of masks defining the events in the time series.

    """
    #Add small number to right edge to be included with in_range function
    modified_right_limit = np.nextafter(time_range[-1], np.inf)
    ip = np.linspace(time_range[0], modified_right_limit, time_bins + 1)
    masks = np.array([
        in_range(dst[time_column].values, ip[i], ip[i + 1])
        for i in range(len(ip) - 1)
    ])
    return shift_to_bin_centers(ip), masks
Esempio n. 12
0
def plot_residuals_E_reso_gauss(energy, e_nbins, e_range, mu, mu_u, sigma,
                                sigma_u, N, N_u, name_fig):

    import seaborn as sns
    sns.set()
    sns.set_style("white")
    sns.set_style("ticks")

    fig = plt.figure(figsize=(9, 7))
    global_linewidth = 2
    global_linecolor = "r"

    # compute y values from histogram
    e_bins = np.linspace(*e_range, e_nbins + 1)
    entries, e = np.histogram(energy, e_bins)
    e = shift_to_bin_centers(e)
    e_u = np.diff(e)[0] * 0.5
    #entries_u    =  poisson_sigma(entries)
    entries_u = entries**0.5

    # compute residuals
    scale = (e_range[1] - e_range[0]) / e_nbins
    #    print(scale)
    y_from_fit = mypdf_gauss(e, mu, sigma, N * scale)
    residuals = (y_from_fit - entries) / entries_u

    # Plot
    frame_data = plt.gcf().add_axes((.1, .3, .8, .6))

    plt.errorbar(e, entries, entries_u, 0, "p", c="k")
    plt.plot(e, y_from_fit, lw=global_linewidth, color=global_linecolor)

    leg1 = plt.gca().legend(('fit', 'data'), loc='upper right')

    # compute resolution
    resolution = 235 * sigma / mu

    textstr = '\n'.join(
        ('$\mu={:.2f}      \pm {:.2f} $'.format(mu, mu_u),
         '$\sigma 1={:.2f} \pm {:.2f}$'.format(sigma, sigma_u),
         '$N ={:.2f}      \pm {:.2f}$'.format(N, N_u),
         '$\sigma_E/E =        {:.2f} \%  $'.format(resolution, )))

    props = dict(boxstyle='square', facecolor='white', alpha=0.5)
    plt.gca().text(0.05,
                   0.95,
                   textstr,
                   transform=plt.gca().transAxes,
                   fontsize=14,
                   verticalalignment='top',
                   bbox=props)

    frame_data.set_xticklabels([])
    plt.ylabel("Entries")
    plt.ylim(0)
    lims = plt.xlim()
    print(lims)

    type(lims)
    frame_res = plt.gcf().add_axes((.1, .1, .8, .2))
    plt.plot(lims, [0, 0], "-g", lw=0.7)  # linia en 00 verde
    plt.errorbar(e, residuals, 1, 0, linestyle='None', fmt='|', c="k")
    plt.ylim(-3.9, 3.9)
    plt.xlabel("E (pes)")
Esempio n. 13
0
def profileXY(xdata, ydata, zdata, nbinsx, nbinsy,
              xrange=None, yrange=None, zrange=None,
              std=False, drop_nan=True):
    """
    Compute the xy-axis binned average of a dataset.

    Parameters
    ----------
    xdata, ydata, zdata : 1-dim np.ndarray
        x, y, z coordinates from a dataset.
    nbinsx, nbinsy : int
        Number of divisions in each axis.
    xrange : tuple of ints/floats or None, optional
        Range over the x axis. Defaults to dataset extremes.
    yrange : tuple of ints/floats or None, optional
        Range over the y axis. Defaults to dataset extremes.
    zrange : tuple of ints/floats or None, optional
        Range over the z axis. Defaults to dataset extremes.
    drop_nan : bool, optional
        Exclude empty bins. Defaults to True.

    Returns
    -------
    x_out : 1-dim np.ndarray.
        Bin centers in the x axis.
    y_out : 1-dim np.ndarray.
        Bin centers in the y axis.
    z_out : 1-dim np.ndarray
        Data average for each bin.
    z_err : 1-dim np.ndarray
        Average error for each bin.
    """
    if xrange is None: xrange = np.min(xdata), np.max(xdata)
    if yrange is None: yrange = np.min(ydata), np.max(ydata)

    selection  = coref.in_range(xdata, *xrange)
    selection &= coref.in_range(ydata, *yrange)
    xdata      = xdata[selection]
    ydata      = ydata[selection]
    zdata      = zdata[selection]

    if zrange is not None:
        selection = coref.in_range(zdata, *zrange)
        xdata     = xdata[selection]
        ydata     = ydata[selection]
        zdata     = zdata[selection]

    bin_edges_x   = np.linspace(*xrange, nbinsx + 1)
    bin_edges_y   = np.linspace(*yrange, nbinsy + 1)
    bin_centers_x = coref.shift_to_bin_centers(bin_edges_x)
    bin_centers_y = coref.shift_to_bin_centers(bin_edges_y)
    bin_numbers_x = np.digitize(xdata, bin_edges_x, right=False)
    bin_numbers_y = np.digitize(ydata, bin_edges_y, right=False)
    df            = pd.DataFrame(dict(binx=bin_numbers_x, biny=bin_numbers_y, z=zdata))
    gb            = df.groupby(["binx", "biny"]).z

    shape     = nbinsx, nbinsy
    mean      = np.zeros(shape)
    deviation = np.zeros(shape)

    mean_       = gb.mean().values
    deviation_  = gb.std () if std else gb.std() / gb.size()**0.5
    (indices_x,
     indices_y) = map(np.array, zip(*deviation_.index.values))

    notnan = ~np.isnan(deviation_.values)
    mean     [indices_x - 1, indices_y - 1] = mean_
    deviation[indices_x - 1, indices_y - 1] = np.where(notnan, deviation_.values, 0)

    return bin_centers_x, bin_centers_y, mean, deviation
Esempio n. 14
0
def plot_histogram(histogram,
                   ax=None,
                   plot_errors=False,
                   draw_color='black',
                   stats=True,
                   normed=True):
    """Plot a Histogram.

    Parameters
    ----------
    ax          : axes object, optional
    If None, a new axes will be created.
    plot_errors : bool, optional
    If True, plot the associated errors instead of data.
    draw_color  : string, optional
    Sets the linecolor.
    stats       : bool, optional
    If True, histogram statistics info is added to the plotself.
    normed      : bool, optional
    If True, histogram is normalized.
    """
    if ax is None:
        fig, ax = plt.subplots(1, 1, figsize=(8, 6))

    bins = histogram.bins
    out_range = histogram.out_range
    labels = histogram.labels
    title = histogram.title
    scale = histogram.scale
    if plot_errors:
        entries = histogram.errors
    else:
        entries = histogram.data

    if len(bins) == 1:
        ax.hist(shift_to_bin_centers(bins[0]),
                bins[0],
                weights=entries,
                histtype='step',
                edgecolor=draw_color,
                linewidth=1.5,
                density=normed)
        ax.grid(True)
        ax.set_axisbelow(True)
        ax.set_ylabel("Entries", weight='bold', fontsize=20)
        ax.set_yscale(scale[0])

        if stats:
            entries_string = f'Entries = {np.sum(entries):.0f}\n'
            out_range_string = 'Out range (%) = [{0:.2f}, {1:.2f}]'.format(
                get_percentage(out_range[0, 0], np.sum(entries)),
                get_percentage(out_range[1, 0], np.sum(entries)))

            if np.sum(entries) > 0:
                mean, std = weighted_mean_and_std(shift_to_bin_centers(
                    bins[0]),
                                                  entries,
                                                  frequentist=True,
                                                  unbiased=True)
            else:
                mean, std = 0, 0

            ax.annotate(entries_string + 'Mean = {0:.2f}\n'.format(mean) +
                        'RMS = {0:.2f}\n'.format(std) + out_range_string,
                        xy=(0.99, 0.99),
                        xycoords='axes fraction',
                        fontsize=11,
                        weight='bold',
                        color='black',
                        horizontalalignment='right',
                        verticalalignment='top')

    elif len(bins) == 2:
        ax.pcolormesh(bins[0], bins[1], entries.T)
        ax.set_ylabel(labels[1], weight='bold', fontsize=20)

        if stats:
            entries_string = f'Entries = {np.sum(entries):.0f}\n'
            out_range_stringX = 'Out range X (%) = [{0:.2f}, {1:.2f}]'.format(
                get_percentage(out_range[0, 0], np.sum(entries)),
                get_percentage(out_range[1, 0], np.sum(entries)))
            out_range_stringY = 'Out range Y (%) = [{0:.2f}, {1:.2f}]'.format(
                get_percentage(out_range[0, 1], np.sum(entries)),
                get_percentage(out_range[1, 1], np.sum(entries)))

            if np.sum(entries) > 0:
                meanX, stdX = weighted_mean_and_std(shift_to_bin_centers(
                    bins[0]),
                                                    np.sum(entries, axis=1),
                                                    frequentist=True,
                                                    unbiased=True)
                meanY, stdY = weighted_mean_and_std(shift_to_bin_centers(
                    bins[1]),
                                                    np.sum(entries, axis=0),
                                                    frequentist=True,
                                                    unbiased=True)
            else:
                meanX, stdX = 0, 0
                meanY, stdY = 0, 0

            ax.annotate(entries_string + 'Mean X = {0:.2f}\n'.format(meanX) +
                        'Mean Y = {0:.2f}\n'.format(meanY) +
                        'RMS X = {0:.2f}\n'.format(stdX) +
                        'RMS Y = {0:.2f}\n'.format(stdY) + out_range_stringX +
                        '\n' + out_range_stringY,
                        xy=(0.99, 0.99),
                        xycoords='axes fraction',
                        fontsize=11,
                        weight='bold',
                        color='white',
                        horizontalalignment='right',
                        verticalalignment='top')

    elif len(bins) == 3:
        ave = np.apply_along_axis(average_empty, 2, entries,
                                  shift_to_bin_centers(bins[2]))
        ave = np.ma.masked_array(ave, ave < 0.00001)

        img = ax.pcolormesh(bins[0], bins[1], ave.T)
        cb = plt.colorbar(img, ax=ax)
        cb.set_label(labels[2], weight='bold', fontsize=20)

        for label in cb.ax.yaxis.get_ticklabels():
            label.set_weight('bold')
            label.set_fontsize(16)

        ax.set_ylabel(labels[1], weight='bold', fontsize=20)
    ax.set_xlabel(labels[0], weight='bold', fontsize=20)
    ax.ticklabel_format(axis='x', style='sci', scilimits=(-3, 3))

    for label in (ax.get_xticklabels() + ax.get_yticklabels()):
        label.set_fontweight('bold')
        label.set_fontsize(16)
    ax.xaxis.offsetText.set_fontsize(14)
    ax.xaxis.offsetText.set_fontweight('bold')
Esempio n. 15
0
def plot_residuals_E_reso_gaussC(plots_dir, label, energy, e_nbins, e_range,
                                 mu, mu_u, sigma, sigma_u, N, N_u, N2, N2_u,
                                 chi2_val):

    resolution = 235 * sigma / mu

    sns.set()
    sns.set_style("white")
    sns.set_style("ticks")

    fig = plt.figure(figsize=(9, 7))

    global_linewidth = 2
    global_linecolor = "r"

    # compute y values from histogram
    e_bins = np.linspace(*e_range, e_nbins + 1)
    entries, e = np.histogram(energy, e_bins)
    e = shift_to_bin_centers(e)
    #e_u          =  np.diff(e)[0] * 0.5
    entries_u = poisson_sigma(entries)
    #entries_u    =  entries**0.5

    # compute bin width
    w = (e_range[1] - e_range[0]) / e_nbins

    # compute residuals
    y_from_fit = gaussC(e, mu, sigma, N * w, N2 * w)
    residuals = (y_from_fit - entries) / entries_u
    y_from_fit_1 = gauss(e, mu, sigma, N * w)
    y_from_fit_2 = N2 * w

    # Plot
    frame_data = plt.gcf().add_axes((.1, .3, .8, .6))

    plt.errorbar(e, entries, entries_u, 0, "p", c="k", label='data')
    plt.plot(e,
             y_from_fit,
             lw=global_linewidth,
             color=global_linecolor,
             label='fit')
    plt.fill_between(e, y_from_fit_1, 0, alpha=0.3, color='')
    plt.fill_between(e, y_from_fit_2, 0, alpha=0.5, color='pink')
    plt.legend(loc='upper right', numpoints=1)

    textstr = '\n'.join(
        ('$\mu={:.2f}      \pm {:.2f} $'.format(mu, mu_u),
         '$\sigma 1={:.2f} \pm {:.2f}$'.format(sigma, sigma_u),
         '$N 1={:.2f}      \pm {:.2f}$'.format(N, N_u),
         '$N 2={:.2f}      \pm {:.2f}$'.format(N2, N2_u),
         '$\sigma_E/E =        {:.2f} \%  $'.format(resolution, ),
         f'$\chi^2 = {chi2_val:.2f}$'))

    props = dict(boxstyle='square', facecolor='white', alpha=0.5)
    plt.gca().text(0.05,
                   0.95,
                   textstr,
                   transform=plt.gca().transAxes,
                   fontsize=14,
                   verticalalignment='top',
                   bbox=props)
    frame_data.set_xticklabels([])

    plt.ylabel("Entries")
    plt.ylim(-10)

    # set my own xlimits
    #lims = plt.xlim()
    lims = plt.xlim(e_range[0], e_range[1])
    frame_res = plt.gcf().add_axes((.1, .1, .8, .2))
    plt.plot(lims, [0, 0], "-g", lw=0.7)  # linia en 00 verde
    plt.errorbar(e, residuals, 1, 0, linestyle='None', fmt='|', c="k")
    plt.ylim(-3.9, 3.9)
    plt.xlim(e_range[0], e_range[1])
    plt.xlabel("E (pes)")
    #plt.show()

    #fix: add save as option
    #plt.savefig(f'{plots_dir}/fit_energy_reso_{label}.png')
    #print('plots saved in '+ plots_dir)

    return resolution, fig
Esempio n. 16
0
def generate_pdfs():
    """
    Generate SiPM PDFs using Kr RAW data.
    Multiple types of PDF are generated:
    Full spectrum PDFs : using full buffer
    Z vetoed PDFs      : Vetoing all sipms for regions in z where there is an identified s1 or s2
    1 ring vetoed PDFs : Vetoing sipms within 1 ring distance of a hit.
    2 ring vetoed PDFs : As above for 2 rings
    ...
    """

    pmap_file_base = sys.argv[1]
    hit_file_base = sys.argv[2]
    raw_file_base = sys.argv[3]

    pmap_sorter = sorter_func(pmap_file_base)
    pmap_files = sorted(glob(pmap_file_base + '*.h5'), key=pmap_sorter)
    hit_sorter = sorter_func(hit_file_base)
    hit_files = sorted(glob(hit_file_base + '*.h5'), key=hit_sorter)
    raw_sorter = sorter_func(raw_file_base)
    raw_files = sorted(glob(raw_file_base + '*.h5'), key=raw_sorter)

    ## Details of raw waveforms to aid vetoing (assumes all same in run)
    with tb.open_file(raw_files[0]) as rwf_in:
        sipmrwf = rwf_in.root.RD.sipmrwf[0][0]
        wf_range = np.arange(len(sipmrwf))

    run_no = int(sys.argv[4])
    ## Gains and sensor positions
    sipm_gains = DB.DataSiPM(run_no).adc_to_pes.values
    sipm_xy = DB.DataSiPM(run_no)[['X', 'Y']].values

    ## output
    histbins = np.arange(-10, 300, 0.1)
    bin_centres = shift_to_bin_centers(histbins)
    with tb.open_file('vetoedPDFs_R' + str(run_no) + '.h5', 'w') as pdf_out:
        HIST = partial(hist_writer,
                       pdf_out,
                       group_name='HIST',
                       n_sensors=1792,
                       n_bins=len(bin_centres),
                       bin_centres=bin_centres)
        full_spec = HIST(table_name='full_spec')
        z_vetoed = HIST(table_name='z_vetoed')
        one_ring = HIST(table_name='one_ring_vetoed')
        two_ring = HIST(table_name='two_ring_vetoed')
        thr_ring = HIST(table_name='thr_ring_vetoed')
        inv_thre = HIST(table_name='thr_ring_avetoed')

        ## Hit info
        hit_positions = load_dsts(hit_files, 'DST',
                                  'Events')[['event', 'X', 'Y']].values
        ## Start assuming KR data and Kdst
        ## For each event [evt_no, list tuples start and end veto areas]
        reduced_pulse_info = []
        for pmf in pmap_files:
            #print(pmf)
            sys.stdout.write(pmf + '\n')
            sys.stdout.flush()
            try:
                ## pmap_dict = load_pmaps(pmf)
                s1s, s2s, _, _, _ = load_pmaps_as_df(pmf)
            except (ValueError, tb.exceptions.NoSuchNodeError):
                print("Empty file. Skipping.")
                continue

            ## for key, pmap in pmap_dict.items():
            for evtNo in s1s['event'].unique():
                evtS1 = s1s[s1s['event'] == evtNo]
                evtS2 = s2s[s2s['event'] == evtNo]
                mask_list = []
                ## for s1 in pmap.s1s:
                for is1 in evtS1['peak'].unique():
                    s1 = evtS1[evtS1['peak'] == is1]
                    mask_list.append(
                        (wf_range < s1['time'].iloc[0] / units.mus - 1)
                        | (wf_range > s1['time'].iloc[-1] / units.mus + 1))
                for is2 in evtS2['peak'].unique():
                    s2 = evtS2[evtS2['peak'] == is2]
                    mask_list.append(
                        (wf_range < s2['time'].iloc[0] / units.mus - 2)
                        | (wf_range > s2['time'].iloc[-1] / units.mus + 2))
                reduced_pulse_info.append(
                    [evtNo, np.logical_and.reduce(mask_list)])
        print('masking info stored')
        mask_counter = 0
        pmap_evts = np.fromiter((x[0] for x in reduced_pulse_info), np.int)
        for rawf in raw_files:
            #print(rawf)
            sys.stdout.write(rawf + '\n')
            sys.stdout.flush()
            if mask_counter >= len(reduced_pulse_info):
                continue
            try:
                ## empty arrays for histograms
                shape = 1792, len(bin_centres)
                hist_full_spec = np.zeros(shape, dtype=np.int)
                hist_z_vetoed = np.zeros(shape, dtype=np.int)
                hist_1_vetoed = np.zeros(shape, dtype=np.int)
                hist_2_vetoed = np.zeros(shape, dtype=np.int)
                hist_3_vetoed = np.zeros(shape, dtype=np.int)
                hist_3_aveto = np.zeros(shape, dtype=np.int)
                with tb.open_file(rawf) as raw_in:
                    revent_nos = np.fromiter(
                        (x[0] for x in raw_in.root.Run.events), np.int)

                    #evt_no = reduced_pulse_info[mask_counter][0]
                    #indx = np.argwhere(revent_nos==evt_no)
                    #print(reduced_pulse_info)
                    #pmap_evts = np.array(reduced_pulse_info)[:, 0]
                    pmap_overlap_indx = np.arange(revent_nos.shape[0])[np.in1d(
                        revent_nos, pmap_evts)]
                    hit_overlap_indx = np.arange(revent_nos.shape[0])[np.in1d(
                        revent_nos, hit_positions[:, 0])]
                    hit_indcs = np.arange(hit_positions[:,
                                                        0].shape[0])[np.in1d(
                                                            hit_positions[:,
                                                                          0],
                                                            revent_nos)]
                    hindx = 0
                    #print(indx, indx[0][0])
                    #while indx.shape[0] != 0:
                    for indx in pmap_overlap_indx:
                        #print(indx[0][0])
                        #rwf = raw_in.root.RD.sipmrwf[indx[0][0]]
                        ## cwf = csf.sipm_processing["subtract_mode_calibrate"](raw_in.root.RD.sipmrwf[indx[0][0]], sipm_gains)
                        cwf = csf.sipm_processing["subtract_mode_calibrate"](
                            raw_in.root.RD.sipmrwf[indx], sipm_gains)

                        hist_full_spec += cf.bin_waveforms(cwf, histbins)
                        z_veto = reduced_pulse_info[mask_counter][1]
                        hist_z_vetoed += cf.bin_waveforms(
                            cwf[:, z_veto], histbins)

                        #dst_indx = np.argwhere(hit_positions[:, 0]==evt_no)
                        #if dst_indx.shape[0] != 0:
                        if indx in hit_overlap_indx:
                            ## hit_p = hit_positions[dst_indx[0][0], 1:]
                            hit_p = hit_positions[hit_indcs[hindx], 1:]
                            hindx += 1
                            hist_1_vetoed += cf.bin_waveforms(
                                ring_veto(cwf, 1, z_veto, hit_p, sipm_xy),
                                histbins)
                            hist_2_vetoed += cf.bin_waveforms(
                                ring_veto(cwf, 2, z_veto, hit_p, sipm_xy),
                                histbins)
                            thrVeto = ring_veto(cwf, 3, z_veto, hit_p, sipm_xy)
                            hist_3_vetoed += cf.bin_waveforms(
                                thrVeto, histbins)
                            hist_3_aveto += cf.bin_waveforms(
                                thrVeto[:, np.invert(z_veto)], histbins)

                        mask_counter += 1
                        #if mask_counter < len(reduced_pulse_info):
                        #    evt_no = reduced_pulse_info[mask_counter][0]
                        #    indx = np.argwhere(revent_nos==evt_no)
                        #else:
                        ## dummy evt_no to definitely give no info
                        #    indx = np.argwhere(revent_nos==-100)
                        #print(indx, indx[0][0])
                    full_spec(hist_full_spec)
                    z_vetoed(hist_z_vetoed)
                    one_ring(hist_1_vetoed)
                    two_ring(hist_2_vetoed)
                    thr_ring(hist_3_vetoed)
                    inv_thre(hist_3_aveto)
            except tb.HDF5ExtError:
                print('corrupt file')
                continue