def test_ofamp(): """ Testing function for `qetpy.ofamp`. """ signal, template, psd = create_example_data() fs = 625e3 res1 = qp.ofamp(signal, template, psd, fs, lgcsigma=True, nconstrain=100, withdelay=True) OF = qp.OptimumFilter(signal, template, psd, fs) res2 = OF.ofamp_withdelay(nconstrain=100) res_compare1 = res2 + (OF.energy_resolution(), ) res3 = qp.ofamp(signal, template, psd, fs, withdelay=False) OF = qp.OptimumFilter(signal, template, psd, fs) res4 = OF.ofamp_nodelay() res_compare2 = (res4[0], 0.0, res4[1]) assert isclose(res1, res_compare1) assert isclose(res3, res_compare2)
def chi2cut(self, template=None, psd=None, outlieralgo="iterstat", verbose=False, **kwargs): """ Function to automatically cut out outliers of the optimum filter chi-squares of the inputted traces. Parameters ---------- template : ndarray, NoneType, optional The pulse template to use for the optimum filter. If not passed, then a 10 us rise time and 100 us fall time pulse is used. psd : ndarray, NoneType, optional The two-sided PSD (units of A^2/Hz) to use for the optimum filter. If not passed, then all frequencies are weighted equally. outlieralgo : str, optional Which outlier algorithm to use: iterstat, removeoutliers, or astropy's sigma_clip. Default is "iterstat". verbose : bool, optional If True, the events that pass or fail each cut will be plotted at each step. Default is False. If `plotall` is True when initializing this class, then this will be ignored in favor of `plotall`. **kwargs Keyword arguments to pass to the outlier algorithm function call. Returns ------- cchi2 : ndarray Boolean array giving which indices to keep or throw out based on the outlier algorithm. """ if template is None: time = np.arange(self._nbin) / self.fs template = make_template(time, 10e-6, 100e-6) if psd is None: psd = np.ones(self._nbin) temp_traces = self.traces[self._cutinds] ntemptraces = len(temp_traces) chi2s = np.zeros(ntemptraces) #do optimum filter on all traces for itrace in range(ntemptraces): chi2s[itrace] = ofamp( temp_traces[itrace], template, psd, self.fs, )[-1] self._run_algo(chi2s, outlieralgo, verbose, **kwargs) return self.cmask
def chi2cut(traces, fs=625e3, outlieralgo="iterstat", nsig=2): """ Function to automatically cut out outliers of the baselines of the inputted traces. Parameters ---------- traces : ndarray 2-dimensional array of traces to do cuts on fs : float, optional Digitization rate that the data was taken at outlieralgo : string, optional Which outlier algorithm to use. If set to "removeoutliers", uses the removeoutliers algorithm that removes data based on the skewness of the dataset. If set to "iterstat", uses the iterstat algorithm to remove data based on being outside a certain number of standard deviations from the mean nsig : float, optional If outlieralgo is "iterstat", this can be used to tune the number of standard deviations from the mean to cut outliers from the data when using iterstat on the Chi2s. Default is 2. Returns ------- cchi2 : ndarray Boolean array giving which indices to keep or throw out based on the outlier algorithm """ nbin = len(traces[0]) ind_trigger = round(nbin/2) time = 1.0/fs*(np.arange(1, nbin+1)-ind_trigger) lgc_b0 = time < 0.0 # pulse shape tau_risepulse = 10.0e-6 tau_fallpulse = 100.0e-6 dummytemplate = (1.0-np.exp(-time/tau_risepulse))*np.exp(-time/tau_fallpulse) dummytemplate[lgc_b0]=0.0 dummytemplate = dummytemplate/max(dummytemplate) # assume we just have white noise dummypsd = np.ones(nbin) chi2 = np.zeros(len(traces)) # First do optimum filter on all traces without mean subtracted for itrace in range(0,len(traces)): chi2[itrace] = ofamp(traces[itrace], dummytemplate, dummypsd, fs)[2] if outlieralgo=="removeoutliers": cchi2 = removeoutliers(chi2) elif outlieralgo=="iterstat": cchi2 = iterstat(chi2, cut=nsig, precision=10000.0)[2] else: raise ValueErrror("Unknown outlier algorithm inputted.") return cchi2
def test_chi2lowfreq(): """ Testing function for `qetpy.chi2lowfreq`. """ signal, template, psd = create_example_data() fs = 625e3 res1 = qp.ofamp(signal, template, psd, fs) chi2low = qp.chi2lowfreq(signal, template, res1[0], res1[1], psd, fs, fcutoff=10000) OF = qp.OptimumFilter(signal, template, psd, fs) res2 = OF.ofamp_withdelay() chi2low_compare = OF.chi2_lowfreq(amp=res2[0], t0=res2[1], fcutoff=10000) assert isclose(chi2low, chi2low_compare)
def pileupcut(traces, fs=625e3, outlieralgo="removeoutliers", nsig=2, removemeans=False): """ Function to automatically cut out outliers of the optimum filter amplitudes of the inputted traces. Parameters ---------- traces : ndarray 2-dimensional array of traces to do cuts on fs : float, optional Digitization rate that the data was taken at outlieralgo : string, optional Which outlier algorithm to use. If set to "removeoutliers", uses the removeoutliers algorithm that removes data based on the skewness of the dataset. If set to "iterstat", uses the iterstat algorithm to remove data based on being outside a certain number of standard deviations from the mean nsig : float, optional If outlieralgo is "iterstat", this can be used to tune the number of standard deviations from the mean to cut outliers from the data when using iterstat on the optimum filter amplitudes. Default is 2. removemeans : boolean, optional Boolean flag on if the mean of each trace should be removed before doing the optimal filter (True) or if the means should not be removed (False). This is useful for dIdV traces, when we want to cut out pulses that have smaller amplitude than the dIdV overshoot. Default is False. Returns ------- cpileup : ndarray Boolean array giving which indices to keep or throw out based on the outlier algorithm """ nbin = len(traces[0]) ind_trigger = round(nbin/2) time = 1.0/fs*(np.arange(1, nbin+1)-ind_trigger) lgc_b0 = time < 0.0 # pulse shape tau_risepulse = 10.0e-6 tau_fallpulse = 100.0e-6 dummytemplate = (1.0-np.exp(-time/tau_risepulse))*np.exp(-time/tau_fallpulse) dummytemplate[lgc_b0]=0.0 dummytemplate = dummytemplate/max(dummytemplate) # assume we just have white noise dummypsd = np.ones(nbin) if removemeans: mean = np.mean(traces, axis=1) traces -= mean[:, np.newaxis] amps = np.zeros(len(traces)) #do optimum filter on all traces for itrace in range(0,len(traces)): amps[itrace] = ofamp(traces[itrace], dummytemplate, dummypsd, fs)[0] if outlieralgo=="removeoutliers": cpileup = removeoutliers(abs(amps)) elif outlieralgo=="iterstat": cpileup = iterstat(abs(amps), cut=nsig, precision=10000.0)[2] else: raise ValueErrror("Unknown outlier algorithm inputted.") return cpileup
def pileupcut(self, template=None, psd=None, removemeans=False, outlieralgo="iterstat", verbose=False, **kwargs): """ Function to automatically cut out outliers of the optimum filter amplitudes of the inputted traces. Parameters ---------- template : ndarray, NoneType, optional The pulse template to use for the optimum filter. If not passed, then a 10 us rise time and 100 us fall time pulse is used. psd : ndarray, NoneType, optional The two-sided PSD (units of A^2/Hz) to use for the optimum filter. If not passed, then all frequencies are weighted equally. removemeans : bool, optional Boolean flag for if the mean of each trace should be removed before doing the optimum filter (True) or if the means should not be removed (False). This is useful for dIdV traces, when we want to cut out pulses that have smaller amplitude than the dIdV overshoot. Default is False. outlieralgo : str, optional Which outlier algorithm to use: iterstat, removeoutliers, or astropy's sigma_clip. Default is "iterstat". verbose : bool, optional If True, the events that pass or fail each cut will be plotted at each step. Default is False. If `plotall` is True when initializing this class, then this will be ignored in favor of `plotall`. **kwargs Keyword arguments to pass to the outlier algorithm function call. Returns ------- cpileup : ndarray Boolean array giving which indices to keep or throw out based on the outlier algorithm. """ if template is None: time = np.arange(self._nbin) / self.fs template = make_template(time, 10e-6, 100e-6) if psd is None: psd = np.ones(self._nbin) temp_traces = self.traces[self._cutinds] if removemeans: mean = np.mean(temp_traces, axis=-1, keepdims=True) temp_traces -= mean ntemptraces = len(temp_traces) amps = np.zeros(ntemptraces) #do optimum filter on all traces for itrace in range(ntemptraces): amps[itrace] = ofamp( temp_traces[itrace], template, psd, self.fs, )[0] self._run_algo(np.abs(amps), outlieralgo, verbose, **kwargs) return self.cmask
def _calc_cuts(self, data_array, sample_rate): """ Calculate cut values for pile-up rejection """ # initialize cuts_val = dict() nb_channels = data_array.shape[0] nb_samples = data_array.shape[1] # -------- # min max # -------- if 'minmax' in self._analysis_config['pileup_cuts']: data_max = np.amax(data_array, axis=1) data_min = np.amin(data_array, axis=1) cut_val = data_max - data_min cut_val.shape += (1, ) cuts_val['minmax'] = cut_val # ----------- # OF amp/chi2 # ----------- if ('ofamp' in self._analysis_config['pileup_cuts'] or 'ofchi2' in self._analysis_config['pileup_cuts']): # Build template tau_risepulse = 10.0e-6 tau_fallpulse = 100.0e-6 ind_trigger = round(nb_samples / 2) time = 1.0 / sample_rate * (np.arange(1, nb_samples + 1) - ind_trigger) lgc_b0 = time < 0.0 dummytemplate = (1.0 - np.exp(-time / tau_risepulse)) * np.exp( -time / tau_fallpulse) dummytemplate[lgc_b0] = 0.0 dummytemplate = dummytemplate / max(dummytemplate) # assume we just have white noise dummypsd = np.ones(nb_samples) # OF amp = list() chi2 = list() for ichan in range(0, nb_channels): trace = data_array[ichan, :] trace_amp, trace_t0, trace_chi2 = qp.ofamp( trace, dummytemplate, dummypsd, sample_rate) amp.append(trace_amp) chi2.append(trace_chi2) # store if 'ofamp' in self._analysis_config['pileup_cuts']: cut_val = np.asarray(amp) cut_val.shape += (1, ) cuts_val['ofamp'] = cut_val if 'ofchi2' in self._analysis_config['pileup_cuts']: cut_val = np.asarray(chi2) cut_val.shape += (1, ) cuts_val['ofchi2'] = cut_val # ----------- # slope # ----------- if 'slope' in self._analysis_config['pileup_cuts']: # interval definition slope_rangebegin = range(0, int(nb_samples / 10)) slope_rangeend = range(int(9 * nb_samples / 10), nb_samples) # calculate meam traces_begin = np.mean(data_array[:, slope_rangebegin], axis=1) traces_end = np.mean(data_array[:, slope_rangeend], axis=1) # slope cut_val = traces_end - traces_begin cut_val.shape += (1, ) # store cuts_val['slope'] = cut_val # ----------- # baseline # ----------- if 'baseline' in self._analysis_config['pileup_cuts']: cut_val = np.mean(data_array, axis=1) cut_val.shape += (1, ) cuts_val['baseline'] = cut_val return cuts_val