def generate_timing(self, n_sigma=3): t_correction, fit = self.calc_timing_range() if fit is None: return TCut('') corrected_time = '{peak} - {t_corr}'.format(peak=self.Ana.Timing.get_peak_var(corr=True), t_corr=t_correction) string = 'TMath::Abs({cor_t} - {mp}) / {sigma} < {n_sigma}'.format(cor_t=corrected_time, mp=fit.GetParameter(1), sigma=fit.GetParameter(2), n_sigma=n_sigma) description = '{:1.1f}ns < peak timing < {:.1f}ns'.format(fit.GetParameter(1) - fit.GetParameter(2), fit.GetParameter(1) + fit.GetParameter(2)) return CutString('timing', string, description)
def generate_rhit(self, value=None): ((mx, sx), (my, sy)), n = self.calc_res_sigmas(), choose( value, self.get_config('rhit sigma', dtype=float, required=True)) cut = f'((sres_x[{self.N}] - {mx}) / {sx}) ** 2 + ((sres_y[{self.N}] - {my}) / {sy}) ** 2 <= {n ** 2}' return CutString( 'rhit', f'({cut} || sres[{self.N}] == -999)', f'(rx/{sx * 1e4:.0f})² + (ry/{sy * 1e4:.0f})² < {n}² [um] ({n} sigma)' )
def generate_masks(self, col=None, row=None, pixels=None, exclude=True): cut_string = TCut('') cut_string += self.get_line_mask('col', col, exclude) cut_string += self.get_line_mask('row', row, exclude) cut_string += self.get_pixel_mask(pixels, exclude) return CutString( 'masks', cut_string, 'masking {} columns, {} rows and {} pixels'.format( *self.find_n_masked(col, row, pixels)) if exclude else '')
def generate_pulser(self): return CutString('pulser', '!pulser', 'exclude {:.1f}% pulser events'.format(100. * self.find_n_pulser('pulser') / self.Run.NEvents))
def generate_saturated(self): cut_string = '!is_saturated[{ch}]'.format(ch=self.Channel) description = 'exclude {:.2f}% saturated events'.format(100. * self.find_n_saturated(Cut.invert(cut_string)) / self.Run.NEvents) return CutString('saturated', cut_string, description)
def get_timing(self): return CutString('timing', self.generate_custom(exclude='timing', prnt=False), 'All cuts expect timing.')
def get_pulser(self, beam_on=True): cut = self.generate_custom(include=['ped sigma', 'event range'], prnt=False) + Cut.invert(self.get('pulser')) cut += self.get('beam stops', warn=False) if beam_on else Cut.invert(self.generate_jump_cut()) return CutString('PulserBeam{}'.format('On' if beam_on else 'Off'), cut)
def generate_cft(self, n_sigma=3): fit = self.calc_cft() m, s = fit.Parameter(1), fit.Parameter(2) description = '{:1.1f}ns < constant fraction time < {:.1f}ns'.format(m - n_sigma * s, m + n_sigma * s) var = self.Ana.Timing.get_cft_var() return CutString('cft', '{} < {v} && {v} < {}'.format(m - n_sigma * s, m + n_sigma * s, v=var), description)
def generate_trigger_phase(self): tps = self.get_trigger_phases() return CutString('trigger phase', ' && '.join(f'trigger_phase != {i}' for i in tps), f'trigger phase != {tps}')
def generate_b2(self, n_sigma): fit, b1, b2, noise = self.get_b2_fit(), self.Ana.get_raw_signal_var(), self.Ana.get_b2_var(), self.calc_pedestal_()[1] * n_sigma string = f'{b2} < {fit[0].n} + {fit[1].n} * {b1} + {fit[2].n} * pow({b1}, 2) + {noise}' descr = f'signals above 3 sigma in bucket 2 with pedestal shape {fit[0].n:.2f} + {fit[1].n:.2f} * x + {fit[2].n:.4f} * x²' return CutString('bucket2', string, descr)
def generate_bucket(self): """exclude events with a peak in bucket 2 and no peak in the signal region""" return CutString('bucket', f'!bucket[{self.DUT.Number - 1}]', 'bucket events')
def generate_pedestal_bucket(self): """exclude events with a peak in bucket -1 (the pre-pedstal bucket)""" wide_range = diff(self.Ana.get_region())[0] * self.Run.DigitiserBinWidth > 1.5 * self.BunchSpacing return CutString() if wide_range else CutString('ped bucket', f'!ped_bucket[{self.DUT.Number - 1}]', 'pedestal bucket events')
def generate_threshold(self): thresh = self.calc_threshold(show=False) return CutString('threshold', '{} > {}'.format(self.Ana.get_raw_signal_var(), thresh), thresh)
def generate_pedestal_sigma(self, sigma=None): sigma = self.get_ped_sigma(sigma) ped_range = self.calc_pedestal(sigma) description = 'sigma <= {} -> [{:1.1f}mV, {:1.1f}mV]'.format(sigma, *ped_range) return CutString('ped sigma', '{ped} > {} && {ped} < {}'.format(ped=self.Ana.get_pedestal_name(), *ped_range), description)
def generate_ncluster(self, max_n=1): return CutString('ncluster', f'n_clusters[{self.N}] <= {max_n}', f'number of clusters <= {max_n}')
def generate_trigger_phase(self): v = self.load_dut_config('trigger phase') return CutString() if v is None else CutString( 'trigger_phase', f'trigger_phase[1] >= {v[0]} && trigger_phase[1]<={v[1]}', f'{v[0]} <= trigger phase <= {v[1]}')