Beispiel #1
0
    def compute(self, events, peaks):
        split_peaks = strax.split_by_containment(peaks, events)
        result = np.zeros(len(events), self.dtype)

        self.set_nan_defaults(result)

        # 1. Assign peaks features to main S1 and main S2 in the event
        for event_i, (event, sp) in enumerate(zip(events, split_peaks)):
            res_i = result[event_i]
            # Fetch the features of main S1 and main S2
            for idx, main_peak in zip([event['s1_index'], event['s2_index']],
                                      ['s1_', 's2_']):
                if idx >= 0:
                    for key in [
                            's1_time_shadow', 's2_time_shadow',
                            's2_position_shadow'
                    ]:
                        type_str = key.split('_')[0]
                        res_i[f'{main_peak}shadow_{key}'] = sp[
                            f'shadow_{key}'][idx]
                        res_i[f'{main_peak}dt_{key}'] = sp[f'dt_{key}'][idx]
                        if 'time' in key:
                            res_i[f'{main_peak}nearest_dt_{type_str}'] = sp[
                                f'nearest_dt_{type_str}'][idx]
                        if 's2' in key:
                            res_i[f'{main_peak}x_{key}'] = sp[f'x_{key}'][idx]
                            res_i[f'{main_peak}y_{key}'] = sp[f'y_{key}'][idx]
                    # Record the PDF of HalfCauchy
                    res_i[f'{main_peak}pdf_s2_position_shadow'] = sp[
                        'pdf_s2_position_shadow'][idx]

        # 2. Set time and endtime for events
        result['time'] = events['time']
        result['endtime'] = strax.endtime(events)
        return result
Beispiel #2
0
    def compute(self, events, peaks):
        split_peaks = strax.split_by_containment(peaks, events)
        res = np.zeros(len(events), self.dtype)

        res['shadow_index'] = -1
        res['pre_s2_x'] = np.nan
        res['pre_s2_y'] = np.nan

        for event_i, (event, sp) in enumerate(zip(events, split_peaks)):
            if event['s1_index'] >= 0:
                res['s1_shadow'][event_i] = sp['shadow'][event['s1_index']]
            if event['s2_index'] >= 0:
                res['s2_shadow'][event_i] = sp['shadow'][event['s2_index']]
            if (sp['type'] == 2).sum() > 0:
                # Define event shadow as the first S2 peak shadow
                first_s2_index = np.argwhere(sp['type'] == 2)[0]
                res['shadow_index'][event_i] = first_s2_index
                res['shadow'][event_i] = sp['shadow'][first_s2_index]
                res['pre_s2_area'][event_i] = sp['pre_s2_area'][first_s2_index]
                res['shadow_dt'][event_i] = sp['shadow_dt'][first_s2_index]
                res['pre_s2_x'][event_i] = sp['pre_s2_x'][first_s2_index]
                res['pre_s2_y'][event_i] = sp['pre_s2_y'][first_s2_index]
        res['shadow_distance'] = ((res['pre_s2_x'] - events['s2_x'])**2 +
                                  (res['pre_s2_y'] - events['s2_y'])**2)**0.5
        res['time'] = events['time']
        res['endtime'] = strax.endtime(events)
        return res
Beispiel #3
0
    def compute(self, events, peaks):
        split_tags = strax.split_by_containment(peaks, events)
        result = np.zeros(len(events), self.dtype)
        result['time'] = events['time']
        result['endtime'] = events['endtime']
        get_veto_tags(events, split_tags, result)

        return result
Beispiel #4
0
    def compute(self, events, peaks):
        result = np.zeros(len(events), dtype=self.dtype)
        self.set_nan_defaults(result)

        split_peaks = strax.split_by_containment(peaks, events)

        result['time'] = events['time']
        result['endtime'] = events['endtime']
        result['event_number'] = events['event_number']

        self.fill_events(result, events, split_peaks)
        return result
def test_split_by_containment(things, containers):
    result = strax.split_by_containment(things, containers)

    assert len(result) == len(containers)

    for container_i, things_in in enumerate(result):
        for t in things:
            assert ((t in things_in) == _is_contained(t,
                                                      containers[container_i]))

    if len(result) and len(np.concatenate(result)) > 1:
        assert np.diff(np.concatenate(result)['time']) >= 0, "Sorting broken"
Beispiel #6
0
    def compute(self, **kwargs):
        # If not otherwise specified, data kind to loop over
        # is that of the first dependency (e.g. events)
        # Can't be in __init__: deps not initialized then
        if hasattr(self, 'loop_over'):
            loop_over = self.loop_over
        else:
            loop_over = self.deps[self.depends_on[0]].data_kind
        if not isinstance(loop_over, str):
            raise TypeError("Please add \"loop_over = <base>\""
                            " to your plugin definition")

        # Group into lists of things (e.g. peaks)
        # contained in the base things (e.g. events)
        base = kwargs[loop_over]
        if len(base) > 1:
            assert np.all(base[1:]['time'] >= strax.endtime(base[:-1])), \
                f'{base}s overlap'

        for k, things in kwargs.items():
            # Check for sorting
            difs = np.diff(things['time'])
            if difs.min(initial=0) < 0:
                i_bad = np.argmin(difs)
                examples = things[i_bad - 1:i_bad + 3]
                t0 = examples['time'].min()
                raise ValueError(f'Expected {k} to be sorted, but found ' +
                                 str([(x['time'] - t0, strax.endtime(x) - t0)
                                      for x in examples]))

            if k != loop_over:
                r = strax.split_by_containment(things, base)
                if len(r) != len(base):
                    raise RuntimeError(f"Split {k} into {len(r)}, "
                                       f"should be {len(base)}!")
                kwargs[k] = r

        results = np.zeros(len(base), dtype=self.dtype)
        deps_by_kind = self.dependencies_by_kind()

        for i in range(len(base)):
            r = self.compute_loop(
                base[i],
                **{k: kwargs[k][i]
                   for k in deps_by_kind if k != loop_over})

            # Convert from dict to array row:
            for k, v in r.items():
                results[i][k] = v

        return results
Beispiel #7
0
    def __init__(self,
                 events=None,
                 hitlets=None,
                 run_id=0,
                 channel_range=(2000, 2119),
                 pmt_map='nveto_pmt_position.csv',
                 plot_extension='bokeh'):
        """
        Class to plot an interactive nveto display.

        :param events: Events which should be plot. Can also be none
            in case the hitlet matrix and/or pattern map should be
            plotted separately.
        :param hitlets: Same as events, but hitlets_nv.
        :param run_id: Run_id which should be displayed in the title.
        :param channel_range: Channel range of the detector.
        :param pmt_map: PMT map which is loaded via straxen.get_resource.
            The map has to contain the channel number, and xyz
            coordinates.
        :param plot_extension: Extension which should be used for
            rendering can be either bokeh or matpltolib. Default is
            bokeh to support dynamic plots.
        """
        self.import_holoviews()
        self.hv.extension(plot_extension)
        self.df_event_time = None
        self.df_event_properties = None
        self.hitlets = hitlets
        self.channel_range = channel_range
        self.run_id = run_id

        # Load PMT data:
        if isinstance(pmt_map, str):
            self.pmt_positions = straxen.get_resource(pmt_map, fmt='csv')
        elif isinstance(pmt_map, np.ndarray):
            self.pmt_positions = pmt_map
        else:
            raise ValueError('pmt_map not understood, has either to be '
                             f'a string or a numpy array, got "{pmt_map}".')

        if events is not None:
            self.event_df = straxen.convert_array_to_df(events)
        else:
            self.event_df = None

        if events is not None and hitlets is not None:
            self.hitlets_per_event = strax.split_by_containment(
                hitlets, events)
Beispiel #8
0
    def compute(self, events, peaks):
        split_peaks = strax.split_by_containment(peaks, events)

        # 1. Initialization, ambience is set to be the lowest possible value
        result = np.zeros(len(events), self.dtype)
        # 2. Assign peaks features to main S1, main S2 in the event
        for event_i, (event, sp) in enumerate(zip(events, split_peaks)):
            for idx, main_peak in zip([event['s1_index'], event['s2_index']],
                                      ['s1_', 's2_']):
                if idx >= 0:
                    for ambience in self.origin_dtype:
                        result[f'{main_peak}n_{ambience}'][event_i] = sp[
                            f'n_{ambience}'][idx]

        # 3. Set time and endtime for events
        result['time'] = events['time']
        result['endtime'] = strax.endtime(events)
        return result
Beispiel #9
0
    def compute(self, events_nv, hitlets_nv):
        event_angles = np.zeros(len(events_nv), dtype=self.dtype)

        # Split hitlets by containment, works since we updated event start/end in
        # compute_event_properties.
        hits_in_events = strax.split_by_containment(hitlets_nv, events_nv)

        # Compute hitlets within the first x ns of event:
        hits_in_events, n_prompt = first_hitlets(
            hits_in_events, self.config['position_max_time_nv'])
        event_angles['n_prompt_hitlets'] = n_prompt

        # Compute azimuthal angle and xyz positions:
        angle = get_average_angle(hits_in_events, self.pmt_properties)
        event_angles['angle'] = angle
        compute_positions(event_angles, hits_in_events, self.pmt_properties)
        strax.copy_to_buffer(events_nv, event_angles, f'_copy_events_nv')

        return event_angles
Beispiel #10
0
    def compute(self, **kwargs):
        # If not otherwise specified, data kind to loop over
        # is that of the first dependency (e.g. events)
        # Can't be in __init__: deps not initialized then
        if hasattr(self, 'loop_over'):
            loop_over = self.loop_over
        else:
            loop_over = self.deps[self.depends_on[0]].data_kind

        # Group into lists of things (e.g. peaks)
        # contained in the base things (e.g. events)
        base = kwargs[loop_over]
        if len(base) > 1:
            assert np.all(base[1:]['time'] >= strax.endtime(base[:-1])), \
                f'{base}s overlap'

        for k, things in kwargs.items():
            if len(things) > 1:
                assert np.diff(things['time']).min() > 0, f'{k} not sorted'
            if k != loop_over:
                r = strax.split_by_containment(things, base)
                if len(r) != len(base):
                    raise RuntimeError(f"Split {k} into {len(r)}, "
                                       f"should be {len(base)}!")
                kwargs[k] = r

        results = np.zeros(len(base), dtype=self.dtype)
        for i in range(len(base)):
            r = self.compute_loop(
                base[i], **{
                    k: kwargs[k][i]
                    for k in self.dependencies_by_kind() if k != loop_over
                })

            # Convert from dict to array row:
            for k, v in r.items():
                results[i][k] = v

        return results
 def peak_plot(self, index):
     print(index)
     if not index:
         index = [0]
     events = self.event_table.iloc[index].data
     all_peaks = np.load("181028_0045_peaks.npy")
     peaks = strax.split_by_containment(all_peaks, events.to_records())
     # print(peaks[0])
     plots = []
     for i, peak in enumerate(peaks):
         if len(peak["data"]) and len(peak["data"]) < 30:
             ymax = np.max(peak["data"])
             overlay = hv.NdOverlay({
                 j: hv.Curve(peak["data"][k],
                             kdims='digtizer index',
                             vdims="counts").opts(width=500,
                                                  interpolation="steps-mid",
                                                  xlim=(0, 200),
                                                  ylim=(0, ymax))
                 for j, k in enumerate(reversed(np.argsort(peak["area"])))
             })
             plots.append(overlay)
     return hv.Layout(plots)
Beispiel #12
0
def test_event_info_double_w_double_peaks(self: PluginTestCase,
                                          trigger_min_area=10):
    """
    Try building event-info double with very long events
    """
    st = self.st.new_context()
    ev = st.get_array(self.run_id, 'events')
    if not len(ev):
        return
    ev_time_diff = np.median(np.diff(ev['time']))
    # increase the event_extension such that we start merging several events
    st.set_config(dict(event_right_extension=ev_time_diff))
    st.get_array(self.run_id, 'event_info_double')

    distinct_channels = st.get_single_plugin(self.run_id, 'distinct_channels')
    events = st.get_array(self.run_id, 'event_basics')
    # Make alt == main just to test that we are able to compute that
    # all have no distinct channels
    events['alt_s1_index'] = events['s1_index']
    peaks = st.get_array(self.run_id, 'peaks')
    split_peaks = strax.split_by_containment(peaks, events)
    for event, split_peak in zip(events, split_peaks):
        res = distinct_channels.compute_loop(event, split_peak)
        assert res['alt_s1_distinct_channels'] == 0
Beispiel #13
0
def test_nveto_event_plugin(hitlets, area):
    hitlets['area'] = area
    hitlets = strax.sort_by_time(hitlets)
    events, hitlets_ids_in_event = straxen.find_veto_events(hitlets, 3, 300, 0)

    straxen.plugins.veto_events.compute_nveto_event_properties(
        events, hitlets, hitlets_ids_in_event, start_channel=2000)
    # Test some of the parameters:
    for e, hit_ids in zip(events, hitlets_ids_in_event):
        hits = hitlets[hit_ids[0]:hit_ids[1]]

        assert e['time'] == np.min(
            hits['time']), f'Event start is wrong (hit_ids: hit_ids)'
        assert e['endtime'] == np.max(
            strax.endtime(hits)), f'Event end is wrong (hit_ids: hit_ids)'
        assert np.isclose(
            e['area'], np.sum(hits['area'])
        ), f'Event area is wrong for {e["area"]}, {hits["area"]}'
        mes = f'Event n_contributing_pmt is wrong for {e["n_contributing_pmt"]}, {hits["channel"]}'
        assert e['n_contributing_pmt'] == len(np.unique(hits['channel'])), mes
        assert e['n_hits'] == len(
            hits), f'Event n_hits is wrong for {e["n_hits"]}, {hits}'

    # -----------------------
    # Check if updated events
    # have the correct boundaries:
    # -----------------------
    if len(events) > 1:
        mes = f'Updated event boundaries overlap! {events}'
        assert (events['endtime'][:-1] - events['time'][1:]) > 0, mes

    split_hitlets = strax.split_by_containment(hitlets, events)

    for sbc_hitlets, tw_hitlet_id in zip(split_hitlets, hitlets_ids_in_event):
        h = hitlets[tw_hitlet_id[0]:tw_hitlet_id[1]]
        mes = (
            'Touching windows and split_by_containment yield different hitlets'
            ' after updating the event boundaries. This should not have happened.'
        )
        assert np.all(sbc_hitlets == h), mes

    # Test event positions:
    try:
        npmt_pos = straxen.get_resource('nveto_pmt_position.csv', fmt='csv')
        npmt_pos = npmt_pos.to_records(index=False)
    except FileNotFoundError:
        npmt_pos = np.ones(120,
                           dtype=[('x', np.float64), ('y', np.float64),
                                  ('z', np.float64)])

    events_angle = np.zeros(
        len(events),
        dtype=straxen.plugins.veto_events.veto_event_positions_dtype())

    straxen.plugins.veto_events.compute_positions(events_angle,
                                                  events,
                                                  split_hitlets,
                                                  npmt_pos,
                                                  start_channel=2000)

    angle = straxen.plugins.veto_events.compute_average_angle(
        split_hitlets, npmt_pos, start_channel=2000)
    # Compute truth angles:
    truth_angle = np.angle(events_angle['pos_x'] + events_angle['pos_y'] * 1j)
    # Replace not defined angles, into zeros to match np.angles return
    # and to simplify comparison
    m = (events_angle['pos_x'] == 0) & (events_angle['pos_y'] == 0)
    angle[m] = 0

    # Fixing +2pi issue and np.angle [-180, 180] and [0, 360) convention
    # issue.
    angle = angle % (2 * np.pi)
    truth_angle = truth_angle % (2 * np.pi)

    # Compare angle, also indirectly tests average x/y/z
    mes = f'Event angle did not match expected {truth_angle}, got {angle}.'
    assert np.isclose(angle, truth_angle), mes
Beispiel #14
0
    def compute(self, **kwargs):
        # If not otherwise specified, data kind to loop over
        # is that of the first dependency (e.g. events)
        # Can't be in __init__: deps not initialized then
        if hasattr(self, 'loop_over'):
            loop_over = self.loop_over
        else:
            loop_over = self.deps[self.depends_on[0]].data_kind
        if not isinstance(loop_over, str):
            raise TypeError("Please add \"loop_over = <base>\""
                            " to your plugin definition")

        # Group into lists of things (e.g. peaks)
        # contained in the base things (e.g. events)
        base = kwargs[loop_over]
        if len(base) > 1:
            assert np.all(base[1:]['time'] >= strax.endtime(base[:-1])), \
                f'{base}s overlap'

        for k, things in kwargs.items():
            # Check for sorting
            difs = np.diff(things['time'])
            if difs.min(initial=0) < 0:
                i_bad = np.argmin(difs)
                examples = things[i_bad - 1:i_bad + 3]
                t0 = examples['time'].min()
                raise ValueError(f'Expected {k} to be sorted, but found ' +
                                 str([(x['time'] - t0, strax.endtime(x) - t0)
                                      for x in examples]))

            if k != loop_over:
                if self.time_selection == 'fully_contained':
                    r = strax.split_by_containment(things, base)
                elif self.time_selection == 'touching':
                    # Experimental feature that should be handled with care:
                    # github.com/AxFoundation/strax/pull/424
                    warn(
                        f'{self.__class__.__name__} has a touching time '
                        f'selection. This may lead to ambiguous results as two '
                        f'{loop_over}\'s may contain the same {k}, thereby a '
                        f'given {k} can be included multiple times.')
                    window = 0
                    if hasattr(self, 'touching_window'):
                        window = self.touching_window
                    r = strax.split_touching_windows(things,
                                                     base,
                                                     window=window)
                else:
                    raise RuntimeError('Unknown time_selection')
                if len(r) != len(base):
                    raise RuntimeError(f"Split {k} into {len(r)}, "
                                       f"should be {len(base)}!")
                kwargs[k] = r

        if self.multi_output:
            # This is the a-typical case. Most of the time you just have
            # one output. Just doing the same as below but this time we
            # need to create a dict for the outputs.
            # NB: both outputs will need to have the same length as the
            # base!
            results = {
                k: np.zeros(len(base), dtype=self.dtype[k])
                for k in self.provides
            }
            deps_by_kind = self.dependencies_by_kind()

            for i, base_chunk in enumerate(base):
                res = self.compute_loop(
                    base_chunk, **{
                        k: kwargs[k][i]
                        for k in deps_by_kind if k != loop_over
                    })
                if not isinstance(res, (dict, immutabledict)):
                    raise AttributeError('Please provide result in '
                                         'compute loop as dict')
                # Convert from dict to array row:
                for provides, r in res.items():
                    for k, v in r.items():
                        if np.shape(v) != np.shape(results[provides][i][k]):
                            # Make sure that the buffer length as
                            # defined by the base matches the output of
                            # the compute argument.
                            raise ValueError(
                                f'{provides} returned an improper length array '
                                f'that is not equal to the {loop_over} '
                                'data-kind! Are you sure a LoopPlugin is the '
                                'right Plugin for your application?')
                        results[provides][i][k] = v
        else:
            # Normally you end up here were we are going to loop over
            # base and add the results to the right format.
            results = np.zeros(len(base), dtype=self.dtype)
            deps_by_kind = self.dependencies_by_kind()

            for i, base_chunk in enumerate(base):
                r = self.compute_loop(
                    base_chunk, **{
                        k: kwargs[k][i]
                        for k in deps_by_kind if k != loop_over
                    })
                if not isinstance(r, (dict, immutabledict)):
                    raise AttributeError('Please provide result in '
                                         'compute loop as dict')
                # Convert from dict to array row:
                for k, v in r.items():
                    results[i][k] = v
        return results