def kr_bins(xxrange: Range = (-220, 220), yrange: Range = (-220, 220), zrange: Range = (100, 550), s2erange: Range = (3e3, 13e3), s1erange: Range = (1, 25), s2qrange: Range = (200, 800), xnbins: Int = 60, ynbins: Int = 60, znbins: Int = 12, s2enbins: Int = 50, s1enbins: Int = 10, s2qnbins: Int = 25) -> KrBins: Xbins = np.linspace(*xxrange, xnbins + 1) Ybins = np.linspace(*yrange, ynbins + 1) Xcenters = shift_to_bin_centers(Xbins) Ycenters = shift_to_bin_centers(Ybins) Xpitch = np.diff(Xbins)[0] Ypitch = np.diff(Ybins)[0] return KrBins(S2e=np.linspace(*s2erange, s2enbins + 1), S1e=np.linspace(*s1erange, s1enbins + 1), S2q=np.linspace(*s2qrange, s2qnbins + 1), X=Xbins, Y=Ybins, Z=np.linspace(*zrange, znbins + 1), Xc=Xcenters, Yc=Ycenters, Xp=Xpitch, Yp=Ypitch, T=None)
def kr_bins(Zrange=(100, 550), XYrange=(-220, 220), Erange=(2e3, 15e3), S1range=(0, 50), Qrange=(100, 1500), Znbins=10, XYnbins=30, Enbins=50, S1nbins=10, Qnbins=25): Zbins = np.linspace(*Zrange, Znbins + 1) Ebins = np.linspace(*Erange, Enbins + 1) S1bins = np.linspace(*S1range, S1nbins + 1) Qbins = np.linspace(*Qrange, Qnbins + 1) XYbins = np.linspace(*XYrange, XYnbins + 1) XYcenters = shift_to_bin_centers(XYbins) XYpitch = np.diff(XYbins)[0] exyzBins = ExyzBins(E=Ebins, S1=S1bins, Q=Qbins, Z=Zbins, XY=XYbins, cXY=XYcenters, pXY=XYpitch) return exyzBins
def h1d(x, bins=None, range=None, xlabel='Variable', ylabel='Number of events', title=None, legend='upper right', weights=None, ax=None): if ax is None: fig = plt.figure(figsize=figsize) ax = fig.add_subplot(1, 1, 1) if weights is None: weights = [1.] * len(x) ax.set_xlabel(xlabel) #,fontsize = 11) ax.set_ylabel(ylabel) #, fontsize = 11) yhist, xhist, _ = ax.hist(x, bins=bins, range=range, histtype='step', edgecolor='black', linewidth=1.5, weights=weights, rasterized=True) plt.grid(True) if title: plt.title(title) return yhist, shift_to_bin_centers(xhist)
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)
def get_time_series_df(time_bins : Number, time_range : Tuple[float, float], dst : DataFrame, time_column : str = 'DT')->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. """ nt = time_bins ip = np.linspace(time_range[0], time_range[-1], 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
def fit_s2_energy_in_z_bins_within_XY_limits( kre: KrEvent, kL: KrRanges, kNB: KrNBins, kB: KrBins, eR: Ranges, figsize=(12, 12)) -> KrFit: fig = plt.figure(figsize=figsize) # Creates a new figure EMU = [] ES = [] CHI2 = [] for j, i in enumerate(range(kNB.Z)): ax = fig.add_subplot(5, 2, i + 1) ax.set_xlabel('S2 energy (pes)', fontsize=11) #xlabel ax.set_ylabel('Number of events', fontsize=11) #ylabel zlim = kB.Z[i], kB.Z[i + 1] sel = in_range(kre.X, *kL.XY) & in_range(kre.Y, *kL.XY) & in_range( kre.Z, *zlim) e = kre.E[sel] print( f'bin : {j}, energy range for fit: lower = {eR.lower[j]}, upper = {eR.upper[j]}' ) sel = in_range(e, eR.lower[j], eR.upper[j]) er = e[sel] y, b, _ = ax.hist(er, bins=kB.E, histtype='step', edgecolor='black', linewidth=1.5) x = shift_to_bin_centers(b) df = pd.DataFrame(dict(y=y, x=x)) df = df[df.y > 0] fit_range = (df.x.values[0], df.x.values[-1]) x = df.x.values y = df.y.values yu = np.sqrt(y) seed = gauss_seed(x, y) f = fitf.fit(fitf.gauss, x, y, seed, fit_range=fit_range, sigma=yu) plt.plot(x, f.fn(x), "r-", lw=4) EMU.append(f.values[1]) ES.append(f.errors[1]) CHI2.append(chi2(f, x, y, yu)) plt.grid(True) plt.tight_layout() return KrFit(par=np.array(EMU), err=np.array(ES), chi2=np.array(CHI2), valid=np.ones(len(EMU)))
def kr_times_ranges_and_bins(dst, Zrange=(100, 550), XYrange=(-220, 220), Erange=(2e3, 15e3), S1range=(0, 50), Qrange=(100, 1500), Znbins=10, XYnbins=30, Enbins=50, S1nbins=10, Qnbins=25, nStimeprofile=3600): Zbins = np.linspace(*Zrange, Znbins + 1) Ebins = np.linspace(*Erange, Enbins + 1) S1bins = np.linspace(*S1range, S1nbins + 1) Qbins = np.linspace(*Qrange, Qnbins + 1) XYbins = np.linspace(*XYrange, XYnbins + 1) XYcenters = shift_to_bin_centers(XYbins) XYpitch = np.diff(XYbins)[0] dst_time = dst.sort_values('event') T = dst_time.time.values tstart = T[0] tfinal = T[-1] Trange = (datetime.datetime.fromtimestamp(tstart), datetime.datetime.fromtimestamp(tfinal)) ntimebins = int(np.floor((tfinal - tstart) / nStimeprofile)) Tnbins = np.max([ntimebins, 1]) Tbins = np.linspace(tstart, tfinal, ntimebins + 1) krNBins = KrNBins(E=Enbins, S1=S1nbins, Q=Qnbins, Z=Znbins, XY=XYnbins, T=Tnbins) krRanges = KrRanges(E=Erange, S1=S1range, Q=Qrange, Z=Zrange, XY=XYrange, T=Trange) krBins = KrBins(E=Ebins, S1=S1bins, Q=Qbins, Z=Zbins, XY=XYbins, cXY=XYcenters, T=Tbins) times = [np.mean([Tbins[t], Tbins[t + 1]]) for t in range(Tnbins)] TL = [(Tbins[t], Tbins[t + 1]) for t in range(Tnbins)] timeStamps = list(map(datetime.datetime.fromtimestamp, times)) krTimes = KrTimes(times=times, timeStamps=timeStamps, TL=TL) return krTimes, krRanges, krNBins, krBins
def fit_lifetime(kB, kf, title="Lifetime Fit"): x = shift_to_bin_centers(kB.Z) y = kf.par yu = kf.err 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) print_fit(f) print('chi2 = {}'.format(chi2(f, x, y, yu)))
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
def main(): """ Basic plot of event rate """ # bin width in seconds bin_width = int(sys.argv[2]) max_evt = np.inf if len(sys.argv) > 3: max_evt = int(sys.argv[3]) hist_end = int(datetime.now().timestamp()) bins_def = False bins = None stamp_hist = None nevt = 0 true_last = 0 for fileName in iglob(sys.argv[1]+'*_waveforms.h5'): if nevt < max_evt: with tb.open_file(fileName, 'r') as dataF: timestamps = np.fromiter((evt[1]/1000 for evt in dataF.root.Run.events), np.int) nevt += len(timestamps) if not bins_def: #start time in seconds start_time = int(timestamps[0]) bins = np.arange(start_time, hist_end, bin_width) stamp_hist = np.zeros(len(bins)-1, dtype=np.int) bins_def = True # Ignore last bin as probably not equal width true_last = max(true_last, np.argwhere(bins>timestamps[-1])[0][0])-1 stamp_hist += np.histogram(timestamps, bins)[0] print('check: ', datetime.fromtimestamp(shift_to_bin_centers(bins)[0])) ## Convert to human readable bins = shift_to_bin_centers(bins)[:true_last] dates = [ datetime.fromtimestamp(t) for t in bins ] plt.plot(dates, stamp_hist[:true_last]/bin_width) plt.title('Trigger rate in bins of '+str(bin_width/60)+' minutes') plt.xlabel('Timestamp (s)') plt.ylabel('events per second') plt.show()
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', plot_fit: bool = False) -> 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) f = fitf.fit(sigmoid, x, y, seed, sigma=poisson_sigma(y), fit_range=zrange) z_cathode = DB.DetectorGeo(detector).ZMAX[0] dv = z_cathode / f.values[1] dvu = dv / f.values[1] * f.errors[1] if plot_fit: plt.figure() plt.hist(zdata, nbins, zrange) xx = np.linspace(zrange[0], zrange[1], nbins) plt.plot(xx, sigmoid(xx, *f[1]), color='red') return dv, dvu
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)) # return data 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
def energy_in_XYRange(kre: KrEvent, xr: Tuple[float], yr: Tuple[float], ernb: ExyzNBins) -> KrFit: sel = in_range(kre.X, *xr) & in_range(kre.Y, *yr) e = kre.E[sel] bins = ernb.E frame_data = plt.gcf().add_axes((.1, .3, .8, .6)) y, b, _ = plt.hist(e, bins=bins, histtype='step', edgecolor='black', linewidth=1.5) x = shift_to_bin_centers(b) seed = gauss_seed(x, y) fit_range = seed[1] - 2.0 * seed[2], seed[1] + 2.0 * seed[2] x, y = x[in_range(x, *fit_range)], y[in_range(x, *fit_range)] f = fitf.fit(fitf.gauss, x, y, seed, sigma=poisson_sigma(y)) yu = poisson_sigma(y) plt.plot(x, f.fn(x), "r-", lw=4) frame_data.set_xticklabels([]) labels("", "Entries", "Energy fit example") 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) kf = KrFit(par=np.array(f.values), err=np.array(f.errors), chi2=chi2(f, x, y, yu)) return kf
def selection_in_band(E, Z, Erange, Zrange, Zfitrange, nsigma=3.5, Znbins=50, Enbins=100, plot=True): """ This returns a selection of the events that are inside the Kr E vz Z returns: np.array(bool) If plot=True, it draws E vs Z and the band """ Zfit = Zfitrange Zbins = np.linspace(*Zrange, Znbins + 1) Ebins = np.linspace(*Erange, Enbins + 1) Zcenters = shift_to_bin_centers(Zbins) Zerror = np.diff(Zbins) * 0.5 sel_e = in_range(E, *Erange) mean, sigma, chi2, ok = fit_slices_1d_gauss(Z[sel_e], E[sel_e], Zbins, Ebins, min_entries=5e2) ok = ok & in_range(Zcenters, *Zfit) def _line_cut(sign): x = Zcenters[ok] y = mean.value[ok] + sign * nsigma * sigma.value[ok] yu = mean.uncertainty[ok] seed = expo_seed(x, y) efit = fitf.fit(fitf.expo, x, y, seed, sigma=yu) assert np.all(efit.values != seed) return efit.fn lowE_cut = _line_cut(-1.) highE_cut = _line_cut(+1.) sel_inband = in_range(E, lowE_cut(Z), highE_cut(Z)) if (plot == False): return sel_inband plt.hist2d(Z, E, (Zbins, Ebins), cmap=default_cmap) plt.errorbar(Zcenters[ok], mean.value[ok], sigma.value[ok], Zerror[ok], "kp", label="Kr peak energy $\pm 1 \sigma$") f = fitf.fit(fitf.expo, Zcenters[ok], mean.value[ok], (1e4, -1e3)) plt.plot(Zcenters, f.fn(Zcenters), "r-") print(f.values) plt.plot(Zbins, lowE_cut(Zbins), "m", lw=2, label="$\pm " + str(nsigma) + " \sigma$ region") plt.plot(Zbins, highE_cut(Zbins), "m", lw=2) plt.legend() labels("Drift time (µs)", "S2 energy (pes)", "Energy vs drift") return sel_inband
def relative_pmt_response(): """ Script which uses pmaps (will be generalised in future to check XY dependence) to look at the relative response of the PMTs in Kr events and compares to the results on Poisson mu from calibrations """ pmap_file_base = sys.argv[1] dst_file_base = sys.argv[2] run_number = pmap_file_base.split('/')[2][1:] pmt_dats = DB.DataPMT(int(run_number)) s1hists = {x: [] for x in range(12)} s2hists = {x: [] for x in range(12)} s1sumh = [] s2sumh = [] hitPMTdist = {x: [] for x in range(12)} hitPMTZpos = {x: [] for x in range(12)} pmap_sorter = sorter_func(pmap_file_base) pmap_file_list = sorted(glob(pmap_file_base + '*.h5'), key=pmap_sorter) dst_sorter = sorter_func(dst_file_base) dst_file_list = sorted(glob(dst_file_base + '*.h5'), key=dst_sorter) ## dst_frame = load_dsts(dst_file_list, 'DST', 'Events') dst_frame = load_dsts(dst_file_list, 'RECO', 'Events') dst_evt_list = dst_frame['event'].unique() #for fn in iglob(pmap_file_base + '*.h5'): for fn in pmap_file_list: ## This version just using pmt databases s1df, s2df, _, s1pmtdf, s2pmtdf = load_pmaps_as_df(fn) common_evts = np.intersect1d(s1pmtdf['event'].unique(), dst_evt_list) for evt in common_evts: #for evt in s1pmtdf['event'].unique(): #evt = dst_evt_iter[0] s1evt = s1pmtdf[s1pmtdf['event'] == evt] s2evt = s2pmtdf[s2pmtdf['event'] == evt] s1sevt = s1df[s1df['event'] == evt] s2sevt = s2df[s2df['event'] == evt] hit_evt = dst_frame[dst_frame['event'] == evt] ## if hit_evt['nS2'].iloc[0] == 1 and len(s2evt['peak'].unique()) == 1 and len(s1evt['peak'].unique()) == 1: if hit_evt['npeak'].nunique() == 1 and len( s2evt['peak'].unique()) == 1 and len( s1evt['peak'].unique()) == 1: ## Not well defined for multi-S2 events hit_x = hit_evt['X'].iloc[0] hit_y = hit_evt['Y'].iloc[0] hit_z = hit_evt['Z'].iloc[0] for peak in s1evt['peak'].unique(): s1peak = s1evt[s1evt['peak'] == peak] s1sumh.append(s1sevt[s1sevt['peak'] == peak]['ene'].sum()) pmt1Q = s1peak[s1peak['npmt'] == 1]['ene'].sum() for pmt in s1peak['npmt'].unique(): hitPMTdist[pmt].append( np.sqrt( np.power( hit_x - pmt_dats[pmt_dats['SensorID'] == pmt].X.values, 2) + np.power( hit_y - pmt_dats[pmt_dats['SensorID'] == pmt].Y.values, 2))) hitPMTZpos[pmt].append(hit_z) if pmt != 1: s1hists[pmt].append( s1peak[s1peak['npmt'] == pmt]['ene'].sum() / pmt1Q) else: s1hists[pmt].append(pmt1Q) for peak in s2evt['peak'].unique(): s2peak = s2evt[s2evt['peak'] == peak] s2sumh.append(s2sevt[s2sevt['peak'] == peak]['ene'].sum()) if s2sumh[-1] > 4000: # and s2sumh[-1] < 12000: ## pmt1Q = s2peak[s2peak['npmt'] == 1]['ene'].values[5:-5] pmt1Q = s2peak[s2peak['npmt'] == 1]['ene'].sum() for pmt in s2peak['npmt'].unique(): if pmt != 1: ## s2hists[pmt].append(s2peak[s2peak['npmt'] == pmt]['ene'].values[5:-5]/pmt1Q) s2hists[pmt].append( s2peak[s2peak['npmt'] == pmt]['ene'].sum() / pmt1Q) else: s2hists[pmt].append(pmt1Q) #dst_evt_iter.iternext() ## Make the plots s1sumh = np.array(s1sumh) s2sumh = np.array(s2sumh) figs0, axes0 = plt.subplots(nrows=1, ncols=2) axes0[0].hist(s1sumh) axes0[0].set_title('PMT sum S1 distribution') axes0[1].hist(s2sumh) axes0[1].set_title('PMT sum S2 distribution') plt.tight_layout() figs0.show() figs0.savefig('SumChargescharge_R' + run_number + '.png') figs1, axess1 = plt.subplots(nrows=3, ncols=4, figsize=(20, 6)) s1pmt1 = np.array(s1hists[1]) s1bins = np.arange(-2, 4, 0.1) s2bins = np.arange(0.4, 1.1, 0.005) s1select = (s1sumh > 2) & (s1sumh < 150) for (key, val), ax in zip(s1hists.items(), axess1.flatten()): if key == 1: ax.hist(np.array(val)[s1select], bins=100) #ax.scatter(s1sumh[s1select], np.array(val)[s1select]) ## ax.scatter(np.array(hitPMTdist[key])[s1select], np.array(val)[s1select]) #ax.scatter(np.array(hitPMTZpos[key])[s1select], np.array(val)[s1select]) ax.set_title('PMT 1 S1 charge') #ax.set_xlabel('integrated charge in PMT sum (pe)') #ax.set_xlabel('z pos.') #ax.set_ylabel('integrated charge in PMT1 (pe)') ax.set_ylabel('AU)') ax.set_xlabel('integrated charge in PMT1 (pe)') sh_hits = np.array(hitPMTZpos[key])[s1select].shape sh_val = np.array(val)[s1select].shape covar = np.cov( np.array(hitPMTZpos[key])[s1select].reshape(1, sh_hits[0]), np.array(val)[s1select].reshape(1, sh_val[0]))[0, 1] corr_coef = covar / ( np.std(np.array(val)[s1select], ddof=1) * np.std(np.array(hitPMTZpos[key])[s1select], ddof=1)) print('Sensor ', key, ' correlation coefficient = ', corr_coef) else: vals, bins, _ = ax.hist(np.array(val)[s1select], bins=s1bins) ## ax.scatter(s1pmt1[np.abs(val) < 10], np.array(val)[np.abs(val) < 10]) #ax.scatter(s1sumh[s1select], np.array(val)[s1select]) ## ax.scatter(np.array(hitPMTdist[key])[s1select & (np.abs(val) < 10)], np.array(val)[s1select & (np.abs(val) < 10)]) #ax.scatter(np.array(hitPMTZpos[key])[s1select & (np.abs(val) < 10)], np.array(val)[s1select & (np.abs(val) < 10)]) ax.set_title('PMT ' + str(key) + ' S1 relative charge') #ax.set_xlabel('integrated charge in PMT sum (pe)') ## ax.set_xlabel('PMT-hit dist. (mm)') #ax.set_xlabel('hit Z pos') #ax.set_ylabel('pmt q / pmt1 q') ax.set_ylabel('AU') ax.set_xlabel('pmt q / pmt1 q') ## sh_hits = np.array(hitPMTZpos[key])[s1select].shape ## sh_val = np.array(val)[s1select].shape ## covar = np.cov(np.array(hitPMTZpos[key])[s1select].reshape(1, sh_hits[0]), np.array(val)[s1select].reshape(1, sh_val[0]))[0, 1] ## corr_coef = covar / (np.std(np.array(val)[s1select], ddof=1)*np.std(np.array(hitPMTZpos[key])[s1select], ddof=1)) s1select2 = s1select & (np.array(val) > 0) & (np.array(val) <= 2) print('Sensor ', key, ' mean = ', np.mean(np.array(val)[s1select2])) useful_bins = np.argwhere(vals >= 100) b1 = useful_bins[0][0] b2 = useful_bins[-1][0] errs = np.sqrt(vals[b1:b2]) fvals = fitf.fit(fitf.gauss, shift_to_bin_centers(bins)[b1:b2], vals[b1:b2], seed=(vals.sum(), bins[vals.argmax()], 0.1), sigma=errs) ax.plot( shift_to_bin_centers(bins)[b1:b2], fvals.fn(shift_to_bin_centers(bins)[b1:b2])) print('Fit S1 ' + str(key), fvals.values, fvals.errors, fvals.chi2) plt.tight_layout() figs1.show() figs1.savefig('s1relativechargeThzoom_R' + run_number + '.png') fitVals = {} figs2, axess2 = plt.subplots(nrows=3, ncols=4, figsize=(20, 6)) s2pmt1 = np.array(s2hists[1]) for (key, val), ax in zip(s2hists.items(), axess2.flatten()): if key == 1: ## ax.set_title('PMT 1 S2 charge') ax.set_title('PMT 1 S2 charge vs s2 sum charge') ax.set_xlabel('S2pmt sum charge (pe)') #ax.set_xlabel('integrated charge in PMT sum (pe)') #ax.set_xlabel('z pos') ax.set_ylabel('integrated charge in PMT1 (pe)') #ax.set_ylabel('AU') ax.set_xlabel('integrated charge in PMT1 (pe)') ## ax.hist(np.array(val)[(s2sumh>4000) & (s2sumh<12000)], bins=100) ##ax.hist(np.concatenate(val), bins=100) ## ax.hist(np.array(val)[s2sumh>4000], bins=100) ax.scatter(s2sumh[s2sumh > 4000], np.array(val)[s2sumh > 4000]) #ax.scatter(s2sumh[(s2sumh>4000) & (s2sumh<12000)], np.array(val)[(s2sumh>4000) & (s2sumh<12000)]) ## ax.scatter(np.array(hitPMTdist[key])[(s2sumh>4000) & (s2sumh<12000)], np.array(val)[(s2sumh>4000) & (s2sumh<12000)]) #ax.scatter(np.array(hitPMTZpos[key])[(s2sumh>4000) & (s2sumh<12000)], np.array(val)[(s2sumh>4000) & (s2sumh<12000)]) ## sh_hits = np.array(hitPMTdist[key])[(s2sumh>4000) & (s2sumh<12000)].shape ## sh_val = np.array(val)[(s2sumh>4000) & (s2sumh<12000)].shape ## covar = np.cov(np.array(hitPMTdist[key])[(s2sumh>4000) & (s2sumh<12000)].reshape(1, sh_hits[0]), np.array(val)[(s2sumh>4000) & (s2sumh<12000)].reshape(1, sh_val[0]))[0, 1] ## corr_coef = covar / (np.std(np.array(val)[(s2sumh>4000) & (s2sumh<12000)], ddof=1)*np.std(np.array(hitPMTdist[key])[(s2sumh>4000) & (s2sumh<12000)], ddof=1)) ## print('Sensor ', key, ' correlation coefficient = ', corr_coef) else: ## ax.set_title('PMT '+str(key)+' S2 relative charge') ax.set_title('PMT ' + str(key) + ' S2 relative charge vs pmt sum') ax.set_ylabel('pmt q / pmt1 q') #ax.set_xlabel('zpos') ax.set_xlabel('integrated charge in PMT sum (pe)') #ax.set_xlabel('pmt q / pmt1 q') #ax.set_ylabel('AU') #ax.scatter(s2pmt1[np.abs(val) < 10], np.array(val)[np.abs(val) < 10]) #ax.scatter(s2sumh[(s2sumh>4000) & (s2sumh<12000)], np.array(val)[(s2sumh>4000) & (s2sumh<12000)]) ## vals, bins, _ = ax.hist(np.array(val)[(s2sumh>4000) & (s2sumh<12000)], bins=s2bins) ## vals, bins, _ = ax.hist(np.concatenate(val), bins=s2bins) ## vals, bins, _ = ax.hist(np.array(val)[s2sumh>4000], bins=s2bins) ax.scatter(s2sumh[s2sumh > 4000], np.array(val)[s2sumh > 4000]) ## ax.scatter(np.array(hitPMTdist[key])[(s2sumh>4000) & (s2sumh<12000)], np.array(val)[(s2sumh>4000) & (s2sumh<12000)]) #ax.scatter(np.array(hitPMTZpos[key])[(s2sumh>4000) & (s2sumh<12000)], np.array(val)[(s2sumh>4000) & (s2sumh<12000)]) sh_sum = s2sumh[s2sumh > 4000].shape sh_vals = np.array(val)[s2sumh > 4000].shape covar = np.cov(s2sumh[s2sumh > 4000].reshape(1, sh_sum[0]), np.array(val)[s2sumh > 4000].reshape(1, sh_vals[0]))[0, 1] corr_coef = covar / (np.std(np.array(val)[s2sumh > 4000], ddof=1) * np.std(s2sumh[s2sumh > 4000], ddof=1)) ## sh_hits = np.array(hitPMTdist[key])[(s2sumh>4000) & (s2sumh<12000)].shape ## sh_val = np.array(val)[(s2sumh>4000) & (s2sumh<12000)].shape ## covar = np.cov(np.array(hitPMTdist[key])[(s2sumh>4000) & (s2sumh<12000)].reshape(1, sh_hits[0]), np.array(val)[(s2sumh>4000) & (s2sumh<12000)].reshape(1, sh_val[0]))[0, 1] ## corr_coef = covar / (np.std(np.array(val)[(s2sumh>4000) & (s2sumh<12000)], ddof=1)*np.std(np.array(hitPMTdist[key])[(s2sumh>4000) & (s2sumh<12000)], ddof=1)) print('Sensor ', key, ' correlation coefficient = ', corr_coef) ## limit fit to region with stat error <= 10% Poisson ## useful_bins = np.argwhere(vals>=200) ## b1 = useful_bins[0][0] ## b2 = useful_bins[-1][0] ## errs = np.sqrt(vals[b1:b2]) ## print('Seed check: ', (vals.sum(), bins[vals.argmax()], 0.02)) ## fvals = fitf.fit(fitf.gauss, shift_to_bin_centers(bins)[b1:b2], vals[b1:b2], ## seed=(vals.sum(), bins[vals.argmax()], 0.02), ## sigma=errs, bounds=[(0, 0, 0.00001), (1e10, 2, 3)]) ## ax.plot(shift_to_bin_centers(bins), ## fitf.gauss(shift_to_bin_centers(bins), *fvals.values)) ## fitVals[key] = (fvals.values[1], fvals.values[2]) ## print('Fit PMT '+str(key), fvals.values, fvals.errors, fvals.chi2) plt.tight_layout() figs2.show() figs2.savefig('s2relativechargeThvsSum_R' + run_number + '.png') ## figcal, axcal = plt.subplots() ## axcal.errorbar(list(fitVals.keys()), ## np.fromiter((x[0] for x in fitVals.values()), np.float), ## yerr=np.fromiter((x[1] for x in fitVals.values()), np.float), ## label='Average response of PMTs to Kr relative to PMT 1') ## ## Get the calibration info for comparison. ## cal_files = [ fname for fname in sys.argv[3:] ] ## read_params = partial(spr, table_name='FIT_pmt_scaled_dark_pedestal', ## param_names=['poisson_mu']) ## ## Assumes ordering, ok? ## for i, fn in enumerate(cal_files): ## cal_run = fn.split('_')[1] ## with tb.open_file(fn) as cal_in: ## pmt1Val = 0 ## pmt1Err = 0 ## cVals = [] ## cErrs = [] ## for sens, (pars, errs) in read_params(cal_in): ## if sens != 1: ## cVals.append(pars['poisson_mu']) ## cErrs.append(errs['poisson_mu']) ## else: ## pmt1Val = pars['poisson_mu'] ## pmt1Err = errs['poisson_mu'] ## normVals = np.array(cVals) / pmt1Val ## normErrs = normVals * np.sqrt(np.power(np.array(cErrs)/np.array(cVals), 2) + ## np.power(pmt1Err/pmt1Val, 2)) ## axcal.errorbar(list(fitVals.keys()), normVals, ## yerr=normErrs, label='Calibration '+cal_run) ## axcal.legend() ## axcal.set_xlabel('PMT sensor ID') ## axcal.set_ylabel('Response relative to that of PMT 1') ## figcal.show() ## figcal.savefig('calPoisKrRelCompStatsFILT.png') input('plots good?')
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)") plt.savefig('/Users/neus/current-work/diffusion/energy_resolution/'+name_fig+'.png')