Example #1
0
def test_time_selection(d, second_time, second_dt):
    """
    Test that both 'touching' and 'fully_contained' give the same
        results as 'strax.fully_contained_in' and
        'strax.touching_windows' respectively
    :param d: test-data from get_dummy_data
    :param second_dt: the ofset w.r.t. the first
    :return: None
    """
    container = np.zeros(1, dtype=strax.time_fields)
    container['time'] = second_time
    container['endtime'] = second_time + second_dt
    time_range = (second_time, second_time + second_dt)

    # Fully contained in
    selected_data = strax.apply_selection(d,
                                          time_range=time_range,
                                          time_selection='fully_contained')
    contained = strax.fully_contained_in(d, container)
    selected_data_fc = d[contained != -1]
    assert np.all(selected_data == selected_data_fc)

    # TW
    selected_data = strax.apply_selection(d,
                                          time_range=time_range,
                                          time_selection='touching')
    windows = strax.touching_windows(d, container, window=0)
    assert np.diff(windows[0]) == len(selected_data)
    if len(windows) and len(selected_data):
        assert np.all(selected_data == d[windows[0][0]:windows[0][1]])
Example #2
0
def test_keep_drop_columns(d):
    """
    Test that the keep/drop_columns option of apply selection works. Also
        test that it does not affect the original array (e.g. if it were
        to use a view instead of a copy).

    :param d: test-data from get_dummy_data
    :return: None
    """
    columns = list(d.dtype.names)
    selected_data = strax.apply_selection(d, keep_columns=columns[1:])

    # Check we din't loose anything of the original array
    assert columns == list(d.dtype.names)

    for c in columns[1:]:
        assert np.all(selected_data[c] == d[c])
    for c in columns[:1]:
        assert c not in selected_data.dtype.names

    # Repeat test but for drop columns:
    selected_data = strax.apply_selection(d, drop_columns=columns[:1])
    for c in columns[1:]:
        assert np.all(selected_data[c] == d[c])
    for c in columns[:1]:
        assert c not in selected_data.dtype.names
Example #3
0
    def compute(self, events, start, end):
        # General setup
        res = np.zeros(1, dtype=self.dtype)
        res['time'] = start
        res['endtime'] = end

        # --- Drift time vs R^2 histogram ---
        res['drift_time_vs_R2_bounds'] = self.config['drift_time_vs_R2_bounds']

        dt_r2_events = strax.apply_selection(
            events, selection_str=self.config['drift_time_vs_R2_cut_string'])
        res['drift_time_vs_R2_hist'] = self.drift_time_r2_hist(dt_r2_events)

        # drift time vs. s2 width histogram
        res['drift_time_vs_s2width_bounds'] = self.config[
            'drift_time_vs_s2width_bounds']
        res['drift_time_vs_s2width_hist'] = self.drift_time_s2width_hist(
            events)

        # drift time vs. s1 aft histogram
        res['drift_time_vs_s1aft_bounds'] = self.config[
            'drift_time_vs_s1aft_bounds']
        res['drift_time_vs_s1aft_hist'] = self.drift_time_s1aft_hist(events)

        # s1 area vs. s2 area (log-log)
        res['s1area_vs_s2area_bounds'] = self.config['s1area_vs_s2area_bounds']
        res['s1area_vs_s2area_hist'] = self.s1area_s2area_hist(events)

        # Other event properties?
        return res
Example #4
0
    def compute(self, peaks, lone_hits, start, end):
        # General setup
        res = np.zeros(1, dtype=self.dtype)
        res['time'] = start
        res['endtime'] = end
        n_pmt = self.config['n_tpc_pmts']
        n_bins = self.config['online_peak_monitor_nbins']

        # Bounds for histograms
        res['area_vs_width_bounds'] = self.config['area_vs_width_bounds']
        res['lone_hits_area_bounds'] = self.config['lone_hits_area_bounds']

        # -- Peak vs area 2D histogram --
        # Always cut out unphysical peaks
        sel = (peaks['area'] > 0) & (peaks['range_50p_area'] > 0)
        res['area_vs_width_hist'] = self.area_width_hist(peaks[sel])
        del sel

        # -- Lone hit properties --
        # Make a mask with the cuts.
        # Now only take lone hits that are separated in time.
        if len(lone_hits):
            lh_timedelta = lone_hits[1:]['time'] - strax.endtime(lone_hits)[:-1]
            # Hits on the left are far away? (assume first is because of chunk bound)
            mask = np.hstack([True, lh_timedelta > self.config['lone_hits_min_gap']])
            # Hits on the right are far away? (assume last is because of chunk bound)
            mask &= np.hstack([lh_timedelta > self.config['lone_hits_min_gap'], True])
        else:
            mask = []
        masked_lh = strax.apply_selection(lone_hits[mask],
                                          selection_str=self.config['lone_hits_cut_string'])

        # Make histogram of ADC counts
        # NB: LONE HITS AREA ARE IN ADC!
        lone_hit_areas, _ = np.histogram(masked_lh['area'],
                                         bins=n_bins,
                                         range=self.config['lone_hits_area_bounds'])

        lone_hit_channel_count, _ = np.histogram(masked_lh['channel'],
                                                 bins=n_pmt,
                                                 range=[0, n_pmt])
        # Count number of lone-hits per PMT
        res['lone_hits_area_hist'] = lone_hit_areas
        res['lone_hits_per_channel'] = lone_hit_channel_count
        # Clear mask, don't re-use
        del mask

        # -- AFT histogram --
        aft_b = [0, 1]
        aft_hist, _ = np.histogram(peaks['area_fraction_top'], bins=n_bins, range=aft_b)
        res['aft_hist'] = aft_hist
        res['aft_bounds'] = aft_b

        # Estimate Single Electron (SE) gain
        se_hist, se_bins = np.histogram(peaks['area'], bins=n_bins,
                                        range=self.config['online_se_bounds'])
        bin_centers = (se_bins[1:] + se_bins[:-1]) / 2
        res['online_se_gain'] = bin_centers[np.argmax(se_hist)]
        return res
Example #5
0
def test_selection_str(d):
    """
    Test selection string. We are going for this example check that
        selecting the data based on the data field is the same as if we
        were to use a mask NB: data must have some length!

    :param d: test-data from get_dummy_data
    :return: None
    """
    mean_data = np.mean(d['data'])
    max_data = np.max(d['data'])
    mask = (d['data'] > mean_data) & (d['data'] < max_data)
    selections_str = [f'data > {mean_data}', f'data < {max_data}']
    selected_data = strax.apply_selection(d, selection_str=selections_str)
    assert np.all(selected_data == d[mask])
Example #6
0
        def wrapped_f(context: strax.Context, run_id: str, **kwargs):
            # Validate arguments
            known_kwargs = (
                'time_range seconds_range time_within time_selection '
                'ignore_time_warning '
                'selection_str t_reference to_pe config').split()
            for k in kwargs:
                if k not in known_kwargs and k not in parameters:
                    # Python itself also raises TypeError for invalid kwargs
                    raise TypeError(f"Unknown argument {k} for {f.__name__}")

            if 'config' in kwargs:
                context = context.new_context(config=kwargs['config'])
            if 'config' in parameters:
                kwargs['config'] = context.config

            # Say magic words to enable holoviews
            if hv_bokeh:
                # Generally using globals is not great, but it would be
                # the same as doing a slow import on the top of this file
                # pylint: disable=global-statement
                global _hv_bokeh_initialized
                if not _hv_bokeh_initialized:
                    import holoviews
                    holoviews.extension('bokeh')
                    _hv_bokeh_initialized = True

            if 'to_pe' in parameters and 'to_pe' not in kwargs:
                kwargs['to_pe'] = straxen.get_correction_from_cmt(
                    run_id, context.config['gain_model'])

            # Prepare selection arguments
            kwargs['time_range'] = context.to_absolute_time_range(
                run_id,
                targets=requires,
                **{
                    k: kwargs.get(k)
                    for k in ('time_range seconds_range time_within'.split())
                })
            kwargs.setdefault('time_selection', default_time_selection)
            kwargs.setdefault('selection_str', None)

            kwargs['t_reference'], _ = context.estimate_run_start_and_end(
                run_id, requires)

            if warn_beyond_sec is not None and not kwargs.get(
                    'ignore_time_warning'):
                tr = kwargs['time_range']
                if tr is None:
                    sec_requested = float('inf')
                else:
                    sec_requested = (tr[1] - tr[0]) / int(1e9)
                if sec_requested > warn_beyond_sec:
                    tr_str = "the entire run" if tr is None else f"{sec_requested} seconds"
                    raise ValueError(
                        f"The author of this mini analysis recommends "
                        f"not requesting more than {warn_beyond_sec} seconds. "
                        f"You are requesting {tr_str}. If you wish to proceed, "
                        "pass ignore_time_warning = True.")

            # Load required data, if any
            if len(requires):
                deps_by_kind = strax.group_by_kind(requires, context=context)
                for dkind, dtypes in deps_by_kind.items():
                    if dkind in kwargs:
                        # Already have data, just apply cuts
                        kwargs[dkind] = strax.apply_selection(
                            kwargs[dkind],
                            selection_str=kwargs['selection_str'],
                            time_range=kwargs['time_range'],
                            time_selection=kwargs['time_selection'])
                    else:
                        kwargs[dkind] = context.get_array(
                            run_id,
                            dtypes,
                            selection_str=kwargs['selection_str'],
                            time_range=kwargs['time_range'],
                            time_selection=kwargs['time_selection'],
                            # Arguments for new context, if needed
                            config=kwargs.get('config'),
                            register=kwargs.get('register'),
                            storage=kwargs.get('storage', tuple()),
                            progress_bar=False,
                        )

                # If user did not give time kwargs, but the function expects
                # a time_range, try to add one based on the time range of the data
                base_dkind = list(deps_by_kind.keys())[0]
                x = kwargs[base_dkind]
                if len(x) and kwargs.get('time_range') is None:
                    x0 = x.iloc[0] if isinstance(x, pd.DataFrame) else x[0]
                    try:
                        kwargs.setdefault('time_range',
                                          (x0['time'], strax.endtime(x).max()))

                    except AttributeError:
                        # If x is a holoviews dataset, this will fail.
                        pass

            if 'seconds_range' in parameters:
                if kwargs.get('time_range') is None:
                    scr = None
                else:
                    scr = tuple([(t - kwargs['t_reference']) / int(1e9)
                                 for t in kwargs['time_range']])
                kwargs.setdefault('seconds_range', scr)

            kwargs.setdefault('run_id', run_id)
            kwargs.setdefault('context', context)

            if 'kwargs' in parameters:
                # Likely this will be passed to another mini-analysis
                to_pass = kwargs
                # Do not pass time_range and seconds_range both (unless explicitly requested)
                # strax does not like that
                if 'seconds_range' in to_pass and not 'seconds_range' in parameters:
                    del to_pass['seconds_range']
                if 'time_within' in to_pass and not 'time_within' in parameters:
                    del to_pass['time_within']
            else:
                # Pass only arguments the function wants
                to_pass = {k: v for k, v in kwargs.items() if k in parameters}
            return f(**to_pass)