def compute(self, raw_records): # Remove records from channels for which the gain is unknown r = raw_records[raw_records['channel'] < len(to_pe)] hits = strax.find_hits(r) strax.cut_outside_hits(r, hits) return r
def compute(self, raw_records): # Remove records from channels for which the gain is unknown r = raw_records[raw_records['channel'] < len(to_pe)] # Experimental data reduction: disabled # Seems to remove many S2s since it triggers on S1s! # (perhaps due to larger amount of afterpuless #r = strax.exclude_tails(r, to_pe) hits = strax.find_hits(r) strax.cut_outside_hits(r, hits) return r
def compute(self, raw_records_coin_nv): # Do not trust in DAQ + strax.baseline to leave the # out-of-bounds samples to zero. r = strax.raw_to_records(raw_records_coin_nv) del raw_records_coin_nv r = strax.sort_by_time(r) strax.zero_out_of_bounds(r) strax.baseline(r, baseline_samples=self.baseline_samples, flip=True) if self.config['min_samples_alt_baseline_nv']: m = r['pulse_length'] > self.config['min_samples_alt_baseline_nv'] if np.any(m): # Correcting baseline after PMT saturated signals r[m] = median_baseline(r[m]) strax.integrate(r) strax.zero_out_of_bounds(r) hits = strax.find_hits(r, min_amplitude=self.hit_thresholds) le, re = self.config['save_outside_hits_nv'] r = strax.cut_outside_hits(r, hits, left_extension=le, right_extension=re) strax.zero_out_of_bounds(r) return r
def compute(self, raw_records_coin_nv): # Do not trust in DAQ + strax.baseline to leave the # out-of-bounds samples to zero. r = strax.raw_to_records(raw_records_coin_nv) del raw_records_coin_nv r = strax.sort_by_time(r) strax.zero_out_of_bounds(r) strax.baseline(r, baseline_samples=self.config['baseline_samples_nv'], flip=True) strax.integrate(r) strax.zero_out_of_bounds(r) hits = strax.find_hits( r, min_amplitude=self.config['hit_min_amplitude_nv']) le, re = self.config['save_outside_hits_nv'] r = strax.cut_outside_hits(r, hits, left_extension=le, right_extension=re) strax.zero_out_of_bounds(r) rlinks = strax.record_links(r) r = clean_up_empty_records(r, rlinks, only_last=True) return r
def compute(self, raw_records): # Remove records from funny channels (if present) r = raw_records[raw_records['channel'] < len(to_pe)] # Do not trust in DAQ + strax.baseline to leave the # out-of-bounds samples to zero. strax.zero_out_of_bounds(r) if self.config['s2_tail_veto']: # Experimental data reduction r = strax.exclude_tails(r, to_pe) # Find hits before filtering hits = strax.find_hits(r) if self.config['filter']: # Filter to concentrate the PMT pulses strax.filter_records( r, np.array(self.config['filter'])) le, re = self.config['save_outside_hits'] r = strax.cut_outside_hits(r, hits, left_extension=le, right_extension=re) # Probably overkill, but just to be sure... strax.zero_out_of_bounds(r) return r
def compute(self, raw_records): # Remove records from channels for which the gain is unknown # or low channels_to_cut = np.argwhere( self.config['to_pe'] > (adc_to_e / self.config['min_gain'])) r = raw_records for ch in channels_to_cut.reshape(-1): r = r[r['channel'] != ch] strax.zero_out_of_bounds(r) hits = strax.find_hits(r, threshold=self.config['hit_threshold']) strax.cut_outside_hits( r, hits, left_extension=self.config['left_cut_extension'], right_extension=self.config['right_cut_extension']) return r
def compute(self, raw_records): # Do not trust in DAQ + strax.baseline to leave the # out-of-bounds samples to zero. strax.zero_out_of_bounds(raw_records) ## # Split off non-TPC records and count TPC pulses # (perhaps we should migrate this to DAQRreader in the future) ## r, other = channel_split(raw_records, n_tpc) pulse_counts = count_pulses(r, n_tpc) diagnostic_records, aqmon_records = channel_split(other, 254) ## # Process the TPC records ## if self.config['tail_veto_threshold'] and len(r): r, r_vetoed, veto_regions = software_he_veto( r, self.to_pe, area_threshold=self.config['tail_veto_threshold'], veto_length=self.config['tail_veto_duration'], veto_res=self.config['tail_veto_resolution'], pass_veto_fraction=self.config['tail_veto_pass_fraction'], pass_veto_extend=self.config['tail_veto_pass_extend']) # In the future, we'll probably want to sum the waveforms # inside the vetoed regions, so we can still save the "peaks". del r_vetoed else: veto_regions = np.zeros(0, dtype=strax.hit_dtype) if len(r): # Find hits # -- before filtering,since this messes with the with the S/N hits = strax.find_hits(r, threshold=self.config['hit_threshold']) if self.config['pmt_pulse_filter']: # Filter to concentrate the PMT pulses strax.filter_records(r, np.array(self.config['pmt_pulse_filter'])) le, re = self.config['save_outside_hits'] r = strax.cut_outside_hits(r, hits, left_extension=le, right_extension=re) # Probably overkill, but just to be sure... strax.zero_out_of_bounds(r) return dict(records=r, diagnostic_records=diagnostic_records, aqmon_records=aqmon_records, pulse_counts=pulse_counts, veto_regions=veto_regions)
def compute(self, raw_records_coin_nv): # Do not trust in DAQ + strax.baseline to leave the # out-of-bounds samples to zero. r = strax.raw_to_records(raw_records_coin_nv) del raw_records_coin_nv r = strax.sort_by_time(r) strax.zero_out_of_bounds(r) strax.baseline(r, baseline_samples=self.baseline_samples, flip=True) strax.integrate(r) strax.zero_out_of_bounds(r) hits = strax.find_hits(r, min_amplitude=self.hit_thresholds) le, re = self.config['save_outside_hits_nv'] r = strax.cut_outside_hits(r, hits, left_extension=le, right_extension=re) strax.zero_out_of_bounds(r) return r
def software_he_veto(records, to_pe, chunk_end, area_threshold=int(1e5), veto_length=int(3e6), veto_res=int(1e3), pass_veto_fraction=0.01, pass_veto_extend=3, max_veto_value=None): """Veto veto_length (time in ns) after peaks larger than area_threshold (in PE). Further large peaks inside the veto regions are still passed: We sum the waveform inside the veto region (with time resolution veto_res in ns) and pass regions within pass_veto_extend samples of samples with amplitude above pass_veto_fraction times the maximum. :returns: (preserved records, vetoed records, veto intervals). :param records: PMT records :param to_pe: ADC to PE conversion factors for the channels in records. :param chunk_end: Endtime of chunk to set as maximum ceiling for the veto period :param area_threshold: Minimum peak area to trigger the veto. Note we use a much rougher clustering than in later processing. :param veto_length: Time in ns to veto after the peak :param veto_res: Resolution of the sum waveform inside the veto region. Do not make too large without increasing integer type in some strax dtypes... :param pass_veto_fraction: fraction of maximum sum waveform amplitude to trigger veto passing of further peaks :param pass_veto_extend: samples to extend (left and right) the pass veto regions. :param max_veto_value: if not None, pass peaks that exceed this area no matter what. """ veto_res = int(veto_res) if veto_res > np.iinfo(np.int16).max: raise ValueError("Veto resolution does not fit 16-bit int") veto_length = np.ceil(veto_length / veto_res).astype(np.int) * veto_res veto_n = int(veto_length / veto_res) + 1 # 1. Find large peaks in the data. # This will actually return big agglomerations of peaks and their tails peaks = strax.find_peaks(records, to_pe, gap_threshold=1, left_extension=0, right_extension=0, min_channels=100, min_area=area_threshold, result_dtype=strax.peak_dtype( n_channels=len(to_pe), n_sum_wv_samples=veto_n)) # 2a. Set 'candidate regions' at these peaks. These should: # - Have a fixed maximum length (else we can't use the strax hitfinder on them) # - Never extend beyond the current chunk # - Do not overlap veto_start = peaks['time'] veto_end = np.clip(peaks['time'] + veto_length, None, chunk_end) veto_end[:-1] = np.clip(veto_end[:-1], None, veto_start[1:]) # 2b. Convert these into strax record-like objects # Note the waveform is float32 though (it's a summed waveform) regions = np.zeros(len(veto_start), dtype=strax.interval_dtype + [ ("data", (np.float32, veto_n)), ("baseline", np.float32), ("baseline_rms", np.float32), ("reduction_level", np.int64), ("record_i", np.int64), ("pulse_length", np.int64), ]) regions['time'] = veto_start regions['length'] = (veto_end - veto_start) // veto_n regions['pulse_length'] = veto_n regions['dt'] = veto_res if not len(regions): # No veto anywhere in this data return records, records[:0], np.zeros(0, strax.hit_dtype) # 3. Find pass_veto regios with big peaks inside the veto regions. # For this we compute a rough sum waveform (at low resolution, # without looping over the pulse data) rough_sum(regions, records, to_pe, veto_n, veto_res) if max_veto_value is not None: pass_veto = strax.find_hits(regions, min_amplitude=max_veto_value) else: regions['data'] /= np.max(regions['data'], axis=1)[:, np.newaxis] pass_veto = strax.find_hits(regions, min_amplitude=pass_veto_fraction) # 4. Extend these by a few samples and inverse to find veto regions regions['data'] = 1 regions = strax.cut_outside_hits(regions, pass_veto, left_extension=pass_veto_extend, right_extension=pass_veto_extend) regions['data'] = 1 - regions['data'] veto = strax.find_hits(regions, min_amplitude=1) # Do not remove very tiny regions veto = veto[veto['length'] > 2 * pass_veto_extend] # 5. Apply the veto and return results veto_mask = strax.fully_contained_in(records, veto) == -1 return tuple(list(mask_and_not(records, veto_mask)) + [veto])
def compute(self, raw_records, start, end): if self.config['check_raw_record_overlaps']: check_overlaps(raw_records, n_channels=3000) # Throw away any non-TPC records; this should only happen for XENON1T # converted data raw_records = raw_records[ raw_records['channel'] < self.config['n_tpc_pmts']] # Convert everything to the records data type -- adds extra fields. r = strax.raw_to_records(raw_records) del raw_records # Do not trust in DAQ + strax.baseline to leave the # out-of-bounds samples to zero. # TODO: better to throw an error if something is nonzero strax.zero_out_of_bounds(r) strax.baseline( r, baseline_samples=self.config['baseline_samples'], allow_sloppy_chunking=self.config['allow_sloppy_chunking'], flip=True) strax.integrate(r) pulse_counts = count_pulses(r, self.config['n_tpc_pmts']) pulse_counts['time'] = start pulse_counts['endtime'] = end if len(r) and self.hev_enabled: r, r_vetoed, veto_regions = software_he_veto( r, self.to_pe, end, area_threshold=self.config['tail_veto_threshold'], veto_length=self.config['tail_veto_duration'], veto_res=self.config['tail_veto_resolution'], pass_veto_extend=self.config['tail_veto_pass_extend'], pass_veto_fraction=self.config['tail_veto_pass_fraction'], max_veto_value=self.config['max_veto_value']) # In the future, we'll probably want to sum the waveforms # inside the vetoed regions, so we can still save the "peaks". del r_vetoed else: veto_regions = np.zeros(0, dtype=strax.hit_dtype) if len(r): # Find hits # -- before filtering,since this messes with the with the S/N hits = strax.find_hits(r, min_amplitude=straxen.hit_min_amplitude( self.config['hit_min_amplitude'])) if self.config['pmt_pulse_filter']: # Filter to concentrate the PMT pulses strax.filter_records(r, np.array(self.config['pmt_pulse_filter'])) le, re = self.config['save_outside_hits'] r = strax.cut_outside_hits(r, hits, left_extension=le, right_extension=re) # Probably overkill, but just to be sure... strax.zero_out_of_bounds(r) return dict(records=r, pulse_counts=pulse_counts, veto_regions=veto_regions)
def software_he_veto(records, to_pe, area_threshold=int(1e5), veto_length=int(3e6), veto_res=int(1e3), pass_veto_fraction=0.01, pass_veto_extend=3): """Veto veto_length (time in ns) after peaks larger than area_threshold (in PE). Further large peaks inside the veto regions are still passed: We sum the waveform inside the veto region (with time resolution veto_res in ns) and pass regions within pass_veto_extend samples of samples with amplitude above pass_veto_fraction times the maximum. :returns: (preserved records, vetoed records, veto intervals). :param records: PMT records :param to_pe: ADC to PE conversion factors for the channels in records. :param area_threshold: Minimum peak area to trigger the veto. Note we use a much rougher clustering than in later processing. :param veto_length: Time in ns to veto after the peak :param veto_res: Resolution of the sum waveform inside the veto region. Do not make too large without increasing integer type in some strax dtypes... :param pass_veto_fraction: fraction of maximum sum waveform amplitude to trigger veto passing of further peaks :param pass_veto_extend: samples to extend (left and right) the pass veto regions. """ veto_res = int(veto_res) if veto_res > np.iinfo(np.int16).max: raise ValueError("Veto resolution does not fit 16-bit int") veto_length = np.ceil(veto_length / veto_res).astype(np.int) * veto_res veto_n = int(veto_length / veto_res) + 1 # 1. Find large peaks in the data. # This will actually return big agglomerations of peaks and their tails peaks = strax.find_peaks( records, to_pe, gap_threshold=1, left_extension=0, right_extension=0, min_channels=100, min_area=area_threshold, result_dtype=strax.peak_dtype(n_channels=len(to_pe), n_sum_wv_samples=veto_n)) # 2. Find initial veto regions around these peaks # (with a generous right extension) veto_start, veto_end = strax.find_peak_groups( peaks, gap_threshold=veto_length + 2 * veto_res, right_extension=veto_length, left_extension=veto_res) veto_end = veto_end.clip(0, strax.endtime(records[-1])) veto_length = veto_end - veto_start # dtype is like record (since we want to use hitfiding etc) # but with float32 waveform regions = np.zeros( len(veto_start), dtype=strax.interval_dtype + [ ("data", (np.float32, veto_n)), ("baseline", np.float32), ("reduction_level", np.int64), ("record_i", np.int64), ("pulse_length", np.int64), ]) regions['time'] = veto_start regions['length'] = veto_length regions['pulse_length'] = veto_length regions['dt'] = veto_res if not len(regions): # No veto anywhere in this data return records, records[:0], np.zeros(0, strax.hit_dtype) # 3. Find pass_veto regios with big peaks inside the veto regions. # For this we compute a rough sum waveform (at low resolution, # without looping over the pulse data) rough_sum(regions, records, to_pe, veto_n, veto_res) regions['data'] /= np.max(regions['data'], axis=1)[:, np.newaxis] pass_veto = strax.find_hits(regions, threshold=pass_veto_fraction) # 4. Extend these by a few samples and inverse to find veto regions regions['data'] = 1 regions = strax.cut_outside_hits( regions, pass_veto, left_extension=pass_veto_extend, right_extension=pass_veto_extend) regions['data'] = 1 - regions['data'] veto = strax.find_hits(regions, threshold=0.5) # Do not remove very tiny regions veto = veto[veto['length'] > 2 * pass_veto_extend] # 5. Apply the veto and return results veto_mask = strax.fully_contained_in(records, veto) == -1 return tuple(list(_mask_and_not(records, veto_mask)) + [veto])
def compute(self, raw_records): r = strax.exclude_tails(raw_records, to_pe) hits = strax.find_hits(r) strax.cut_outside_hits(r, hits) return r