def setup(self): self.baseline_samples = self.config['baseline_samples_mv'] # Check config of `hit_min_amplitude_mv` and define hit thresholds # if cmt config if is_cmt_option(self.config['hit_min_amplitude_mv']): self.hit_thresholds = straxen.get_correction_from_cmt(self.run_id, self.config['hit_min_amplitude_mv']) # if hitfinder_thresholds config elif isinstance(self.config['hit_min_amplitude_mv'], str): self.hit_thresholds = straxen.hit_min_amplitude( self.config['hit_min_amplitude_mv']) else: # int or array self.hit_thresholds = self.config['hit_min_amplitude_mv']
def setup(self): self.hev_enabled = False self.config['n_tpc_pmts'] = self.config['n_he_pmts'] # Check config of `hit_min_amplitude` and define hit thresholds # if cmt config if is_cmt_option(self.config['hit_min_amplitude_he']): self.hit_thresholds = straxen.get_correction_from_cmt( self.run_id, self.config['hit_min_amplitude_he']) # if hitfinder_thresholds config elif isinstance(self.config['hit_min_amplitude_he'], str): self.hit_thresholds = straxen.hit_min_amplitude( self.config['hit_min_amplitude_he']) else: # int or array self.hit_thresholds = self.config['hit_min_amplitude_he']
def setup(self): self.to_pe = straxen.get_correction_from_cmt(self.run_id, self.config['gain_model']) self.hit_left_extension, self.hit_right_extension = self.config[ 'save_outside_hits'] # Check config of `hit_min_amplitude` and define hit thresholds # if cmt config if is_cmt_option(self.config['hit_min_amplitude']): self.hit_thresholds = straxen.get_correction_from_cmt( self.run_id, self.config['hit_min_amplitude']) # if hitfinder_thresholds config elif isinstance(self.config['hit_min_amplitude'], str): self.hit_thresholds = straxen.hit_min_amplitude( self.config['hit_min_amplitude']) else: # int or array self.hit_thresholds = self.config['hit_min_amplitude']
def setup(self): self.hev_enabled = ((self.config['hev_gain_model'][0] != 'disabled') and self.config['tail_veto_threshold']) if self.hev_enabled: self.to_pe = straxen.get_correction_from_cmt( self.run_id, self.config['hev_gain_model']) # Check config of `hit_min_amplitude` and define hit thresholds # if cmt config if is_cmt_option(self.config['hit_min_amplitude']): self.hit_thresholds = straxen.get_correction_from_cmt( self.run_id, self.config['hit_min_amplitude']) # if hitfinder_thresholds config elif isinstance(self.config['hit_min_amplitude'], str): self.hit_thresholds = straxen.hit_min_amplitude( self.config['hit_min_amplitude']) else: # int or array self.hit_thresholds = self.config['hit_min_amplitude']
def setup(self): self.to_pe = straxen.get_correction_from_cmt(self.run_id, self.config['gain_model']) buffer_pmts = np.zeros(self.config['he_channel_offset']) self.to_pe = np.concatenate((buffer_pmts, self.to_pe)) self.to_pe *= self.config['le_to_he_amplification'] # Check config of `hit_min_amplitude_he` and define hit thresholds # if cmt config if is_cmt_option(self.config['hit_min_amplitude_he']): self.hit_thresholds = straxen.get_correction_from_cmt( self.run_id, self.config['hit_min_amplitude_he']) # if hitfinder_thresholds config elif isinstance(self.config['hit_min_amplitude_he'], str): self.hit_thresholds = straxen.hit_min_amplitude( self.config['hit_min_amplitude_he']) else: # int or array self.hit_thresholds = self.config['hit_min_amplitude_he'] self.channel_range = self.config['channel_map']['he']
def setup(self): self.channel_range = self.config['channel_map']['nveto'] self.n_channel = (self.channel_range[1] - self.channel_range[0]) + 1 to_pe = straxen.get_correction_from_cmt(self.run_id, self.config['gain_model_nv']) # Create to_pe array of size max channel: self.to_pe = np.zeros(self.channel_range[1] + 1, dtype=np.float32) self.to_pe[self.channel_range[0]:] = to_pe[:] # Check config of `hit_min_amplitude_nv` and define hit thresholds # if cmt config if is_cmt_option(self.config['hit_min_amplitude_nv']): self.hit_thresholds = straxen.get_correction_from_cmt( self.run_id, self.config['hit_min_amplitude_nv']) # if hitfinder_thresholds config elif isinstance(self.config['hit_min_amplitude_nv'], str): self.hit_thresholds = straxen.hit_min_amplitude( self.config['hit_min_amplitude_nv']) else: # int or array self.hit_thresholds = self.config['hit_min_amplitude_nv']
def setup(self): if self.config['peak_min_pmts'] > 2: # Can fix by re-splitting, raise NotImplementedError( f"Raising the peak_min_pmts to {self.config['peak_min_pmts']} " f"interferes with lone_hit definition. " f"See github.com/XENONnT/straxen/issues/295") self.to_pe = straxen.get_correction_from_cmt(self.run_id, self.config['gain_model']) # Check config of `hit_min_amplitude` and define hit thresholds # if cmt config if is_cmt_option(self.config['hit_min_amplitude']): self.hit_thresholds = straxen.get_correction_from_cmt( self.run_id, self.config['hit_min_amplitude']) # if hitfinder_thresholds config elif isinstance(self.config['hit_min_amplitude'], str): self.hit_thresholds = straxen.hit_min_amplitude( self.config['hit_min_amplitude']) else: # int or array self.hit_thresholds = self.config['hit_min_amplitude'] self.channel_range = self.config['channel_map']['tpc']
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 compute(self, records, start, end): r = records hits = strax.find_hits(r, min_amplitude=straxen.hit_min_amplitude( self.config['hit_min_amplitude'])) # Remove hits in zero-gain channels # they should not affect the clustering! hits = hits[self.to_pe[hits['channel']] != 0] hits = strax.sort_by_time(hits) # Use peaklet gap threshold for initial clustering # based on gaps between hits peaklets = strax.find_peaks( hits, self.to_pe, gap_threshold=self.config['peaklet_gap_threshold'], left_extension=self.config['peak_left_extension'], right_extension=self.config['peak_right_extension'], min_channels=self.config['peak_min_pmts'], result_dtype=self.dtype_for('peaklets')) # Make sure peaklets don't extend out of the chunk boundary # This should be very rare in normal data due to the ADC pretrigger # window. self.clip_peaklet_times(peaklets, start, end) # Get hits outside peaklets, and store them separately. # fully_contained is OK provided gap_threshold > extension, # which is asserted inside strax.find_peaks. lone_hits = hits[strax.fully_contained_in(hits, peaklets) == -1] strax.integrate_lone_hits( lone_hits, records, peaklets, save_outside_hits=(self.config['peak_left_extension'], self.config['peak_right_extension']), n_channels=len(self.to_pe)) # Compute basic peak properties -- needed before natural breaks strax.sum_waveform(peaklets, r, self.to_pe) strax.compute_widths(peaklets) # Split peaks using low-split natural breaks; # see https://github.com/XENONnT/straxen/pull/45 # and https://github.com/AxFoundation/strax/pull/225 peaklets = strax.split_peaks( peaklets, r, self.to_pe, algorithm='natural_breaks', threshold=self.natural_breaks_threshold, split_low=True, filter_wing_width=self.config['peak_split_filter_wing_width'], min_area=self.config['peak_split_min_area'], do_iterations=self.config['peak_split_iterations']) # Saturation correction using non-saturated channels # similar method used in pax # see https://github.com/XENON1T/pax/pull/712 if self.config['saturation_correction_on']: peak_saturation_correction( r, peaklets, self.to_pe, reference_length=self.config['saturation_reference_length'], min_reference_length=self. config['saturation_min_reference_length']) # Compute tight coincidence level. # Making this a separate plugin would # (a) doing hitfinding yet again (or storing hits) # (b) increase strax memory usage / max_messages, # possibly due to its currently primitive scheduling. hit_max_times = np.sort(hits['time'] + hits['dt'] * hit_max_sample(records, hits)) peaklet_max_times = ( peaklets['time'] + np.argmax(peaklets['data'], axis=1) * peaklets['dt']) peaklets['tight_coincidence'] = get_tight_coin( hit_max_times, peaklet_max_times, self.config['tight_coincidence_window_left'], self.config['tight_coincidence_window_right']) if self.config['diagnose_sorting'] and len(r): assert np.diff(r['time']).min(initial=1) >= 0, "Records not sorted" assert np.diff(hits['time']).min(initial=1) >= 0, "Hits not sorted" assert np.all(peaklets['time'][1:] >= strax.endtime(peaklets)[:-1] ), "Peaks not disjoint" # Update nhits of peaklets: counts = strax.touching_windows(hits, peaklets) counts = np.diff(counts, axis=1).flatten() counts += 1 peaklets['n_hits'] = counts return dict(peaklets=peaklets, lone_hits=lone_hits)
def test_get_hit_amplitude(): straxen.hit_min_amplitude('pmt_commissioning_initial') straxen.hit_min_amplitude('pmt_commissioning_initial_he')
def test_non_existing(self): with self.assertRaises(ValueError): straxen.hit_min_amplitude('non existing key')
def plot_pulses(context, raw_records, run_id, time_range, plot_hits=False, plot_median=False, max_plots=20, store_pdf=False, path='', detector_ending=''): """ Plots nveto pulses for a list of records. :param context: Context to be used. :param plot_hits: If True plot hit boundaries including the left and right extension as orange shaded regions. :param plot_median: If true plots pulses sample median as dotted line. :param max_plots: Limits the number of figures. If you would like to plot more pulses you should put the plots in a PDF. :param store_pdf: If true figures are put to a PDF instead of plotting them to your notebook. The file name is automatically generated including the time range and run_id. :param path: Relative path where the PDF should be stored. By default it is the directory of the notebook. :param detector_ending: Ending of the corresponding detector. Empty string for TPC '_nv' for neutron-veto and '_mv' muon-veto. """ # Register records plugin to get settings p = context.get_single_plugin(run_id, 'records' + detector_ending) # Compute strax baseline and baseline_rms: records = strax.raw_to_records(raw_records) records = strax.sort_by_time(records) strax.zero_out_of_bounds(records) baseline_key = 'baseline_samples' + detector_ending if isinstance(p.config[baseline_key], int): baseline_samples = p.config[baseline_key] else: baseline_samples = straxen.get_correction_from_cmt( run_id, p.config[baseline_key]) strax.baseline(records, baseline_samples=baseline_samples, flip=True) nfigs = 1 if store_pdf: fname = f'pulses_{run_id}_{time_range[0]}_{time_range[1]}.pdf' fname = os.path.join(path, fname) pdf = PdfPages(fname) for inds in _yield_pulse_indices(raw_records): # Grouped our pulse so now plot: rr_pulse = raw_records[inds] r_pulse = records[inds] fig, axes = straxen.plot_single_pulse(rr_pulse, run_id) if detector_ending == '_nv': # We only store for the nv digitizer baseline values: axes.axhline(rr_pulse[0]['baseline'], ls='dashed', color='k', label=f'D. Bas.: {rr_pulse[0]["baseline"]} ADC') baseline = r_pulse[0]['baseline'] baseline_rms = r_pulse[0]['baseline_rms'] axes.axhline( baseline, ls='solid', color='k', label= f'Strax Bas. +/-RMS:\n ({baseline:.2f}+/-{baseline_rms:.2f}) ADC') xlim = axes.get_xlim() axes.fill_between(xlim, [baseline + baseline_rms] * 2, [baseline - baseline_rms] * 2, color='gray', alpha=0.4) if plot_median: # Plot median if asked. # Have to make pulse again: pulse = straxen.matplotlib_utils._make_pulse(rr_pulse) median = np.median(pulse) axes.axhline(median, ls='dotted', color='k', label=f'Median Bas.: {median:.0f} ADC') axes.axhline(median - p.config['hit_min_amplitude_nv'], ls='dotted', color='orange') hits = None # needed for delet if false if plot_hits: if detector_ending: min_amplitude = p.config['hit_min_amplitude' + detector_ending] else: min_amplitude = straxen.hit_min_amplitude( p.config['hit_min_amplitude']) min_amplitude = min_amplitude[rr_pulse[0]['channel']] axes.axhline(baseline - min_amplitude, color='orange', label='Hitfinder threshold') hits = strax.find_hits(r_pulse, min_amplitude=min_amplitude) le, re = p.config['save_outside_hits' + detector_ending] start = (hits['time'] - r_pulse[0]['time']) / r_pulse[0]['dt'] - le end = (strax.endtime(hits) - r_pulse[0]['time']) / r_pulse[0]['dt'] + re ylim = axes.get_ylim() for s, e in zip(start, end): plt.fill_between((s, e), *ylim, alpha=0.2, color='orange') axes.set_ylim(*ylim) plt.legend() axes.set_xlim(*xlim) if store_pdf: plt.close() pdf.savefig(fig) nfigs += 1 if max_plots is not None and nfigs > max_plots: break if store_pdf: pdf.close() del records, hits