Пример #1
0
    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']
Пример #2
0
    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']
Пример #3
0
    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']
Пример #4
0
    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']
Пример #5
0
    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']
Пример #6
0
    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']
Пример #7
0
    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']
Пример #8
0
    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)
Пример #9
0
    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)
Пример #10
0
 def test_get_hit_amplitude():
     straxen.hit_min_amplitude('pmt_commissioning_initial')
     straxen.hit_min_amplitude('pmt_commissioning_initial_he')
Пример #11
0
 def test_non_existing(self):
     with self.assertRaises(ValueError):
         straxen.hit_min_amplitude('non existing key')
Пример #12
0
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