Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Veto plugins #465

Merged
merged 43 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
e0ae5e1
Added veto plugin
WenzDaniel May 2, 2021
f2c7c49
Simplified merge_intervals
WenzDaniel May 3, 2021
e9ccdd5
Updated veto logic
WenzDaniel May 3, 2021
dfa78d5
Refactored code for more readability
WenzDaniel May 3, 2021
65c4174
Refactored nveto_recorder
WenzDaniel May 3, 2021
855d265
Added tests for merge intervals
WenzDaniel May 3, 2021
9d7e746
Added tests for coincidence
WenzDaniel May 3, 2021
4734fd4
updated settings
WenzDaniel May 3, 2021
6f9470c
Added mu-veto vetos
WenzDaniel May 3, 2021
e12296c
Adjusted settings of muveto veto
WenzDaniel May 3, 2021
7eccc84
Made veto save whennever
WenzDaniel May 3, 2021
61a6678
Updated settings
WenzDaniel May 3, 2021
8be0ebd
Renamed coincidence function
WenzDaniel May 3, 2021
5730531
Added last empty line
WenzDaniel May 3, 2021
b3e6174
Added parent option names
WenzDaniel May 3, 2021
5132c41
Added docs and generalized
WenzDaniel May 3, 2021
b97be79
removed second blank line
WenzDaniel May 3, 2021
de4bd31
Addressed some of the review dog comments
WenzDaniel May 3, 2021
d558029
Shut up reviewdog
WenzDaniel May 3, 2021
a7c8fa7
Merge branch 'master' into veto_plugins
WenzDaniel May 3, 2021
d4ae56e
Added preamble explicitly
WenzDaniel May 3, 2021
f40793e
Merge branch 'veto_plugins' of https://github.com/XENONnT/straxen int…
WenzDaniel May 3, 2021
aa3e009
Merge branch 'master' into veto_plugins
WenzDaniel May 4, 2021
6737308
Fix numba disabled test...
WenzDaniel May 4, 2021
5b3ce22
Merge branch 'veto_plugins' of https://github.com/XENONnT/straxen int…
WenzDaniel May 4, 2021
69a7f09
Updated veto and tests
WenzDaniel May 4, 2021
9f938a4
Merge branch 'master' into veto_plugins
WenzDaniel May 4, 2021
19c6a0a
Merge branch 'master' into veto_plugins
WenzDaniel May 4, 2021
c6d5541
Merge branch 'master' into veto_plugins
WenzDaniel May 4, 2021
ea23cf9
Merge branch 'master' into veto_plugins
JoranAngevaare May 4, 2021
f144bb8
updated settings
WenzDaniel May 6, 2021
d2713be
Merge branch 'master' into veto_plugins
WenzDaniel May 6, 2021
4c5be58
Merge branch 'master' into veto_plugins
JoranAngevaare May 6, 2021
735ef59
Update straxen/plugins/veto_vetos.py
WenzDaniel May 17, 2021
fe22d4b
Merge branch 'master' into veto_plugins
JoranAngevaare May 17, 2021
f5acc05
Merge branch 'veto_plugins' of https://github.com/XENONnT/straxen int…
WenzDaniel May 18, 2021
2732f94
Addressed comments
WenzDaniel May 18, 2021
44f3483
Fixed typo
WenzDaniel May 18, 2021
a6c94a0
Extended tests removed hardcoded tests
WenzDaniel May 18, 2021
9cb2bae
Fixed typo
WenzDaniel May 18, 2021
b678665
Fixed codefactor
WenzDaniel May 18, 2021
3e27ad8
Version bump nveto recorder
WenzDaniel May 18, 2021
25d70d9
Revert version bump
WenzDaniel May 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions straxen/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
from . import veto_events
from .veto_events import *

from . import veto_vetos
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
from .veto_vetos import *
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved

from . import acqmon_processing
from .acqmon_processing import *

Expand Down
111 changes: 67 additions & 44 deletions straxen/plugins/nveto_recorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,29 +105,37 @@ def compute(self, raw_records_nv, start, end):
min_amplitude=self.config['hit_min_amplitude_nv'])
del temp_records

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium: I think you need to also increment the version. The code is not entirely the same for the _merge_intervals

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resulting raw_records_coin_nv should be identical, but we can also increase the version number for bookkeeping. It will just mean a lot of reprocessing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you are sure that the results are the same, I stand corrected and no version bump would be needed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked with a 6 min run (42 million raw_record fragments and 1.6 million raw_records_coin_nv). Shape and all entries are identical.


# First we have to split rr into records and lone records:
# Please note that we consider everything as a lone record which
# does not satisfy the coincidence requirement
intervals = coincidence(hits,
self.config['coincidence_level_recorder_nv'],
self.config['resolving_time_recorder_nv'],
self.config['pre_trigger_time_nv'])
intervals = find_coincidence(hits,
self.config['coincidence_level_recorder_nv'],
self.config['resolving_time_recorder_nv'],
self.config['pre_trigger_time_nv'])
del hits

# Always save the first and last resolving_time nanoseconds (e.g. 600 ns) since we cannot guarantee the gap
# size to be larger. (We cannot use an OverlapingWindow plugin either since it requires disjoint objects.)
if len(intervals):
intervals_with_bounds = np.zeros((len(intervals) + 2, 2), dtype=np.int64)
intervals_with_bounds[1:-1, :] = intervals
intervals_with_bounds[0, :] = start, min(start + self.config['resolving_time_recorder_nv'], intervals[0, 0])
intervals_with_bounds[-1, :] = max(end - self.config['resolving_time_recorder_nv'], intervals[-1, 1]), end
intervals_with_bounds = np.zeros(len(intervals) + 2, dtype=strax.time_fields)
intervals_with_bounds['time'][1:-1] = intervals['time']
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
intervals_with_bounds['endtime'][1:-1] = intervals['endtime']
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
intervals_with_bounds['time'][0] = start
intervals_with_bounds['endtime'][0] = min(start + self.config['resolving_time_recorder_nv'],
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
intervals['time'][0])
intervals_with_bounds['time'][-1] = max(end - self.config['resolving_time_recorder_nv'],
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
intervals['endtime'][-1])
intervals_with_bounds['endtime'][-1] = end
del intervals
else:
intervals_with_bounds = np.zeros((0, 2), dtype=np.int64)
intervals_with_bounds = np.zeros((0, 2), dtype=strax.time_fields)

neighbors = strax.record_links(raw_records_nv)
mask = pulse_in_interval(raw_records_nv, neighbors, *np.transpose(intervals_with_bounds))
mask = pulse_in_interval(raw_records_nv,
neighbors,
intervals_with_bounds['time'],
intervals_with_bounds['endtime'],)

rr, lone_records = straxen.mask_and_not(raw_records_nv, mask)

# Compute some properties of the lone_records:
Expand Down Expand Up @@ -326,7 +334,7 @@ def pulse_in_interval(raw_records, record_links, start_times, end_times):


@export
def coincidence(records, nfold=4, resolving_time=300, pre_trigger=0):
def find_coincidence(records, nfold=4, resolving_time=300, pre_trigger=0):
"""
Checks if n-neighboring events are less apart from each other then
the specified resolving time.
Expand All @@ -351,10 +359,12 @@ def coincidence(records, nfold=4, resolving_time=300, pre_trigger=0):
# In case of a "single-fold" coincidence every thing gives
# the start of a new interval:
start_times = records['time']
intervals = _merge_intervals(start_times-pre_trigger,
resolving_time+pre_trigger)
intervals = np.zeros(len(start_times), dtype=strax.time_fields)
intervals['time'] = start_times - pre_trigger
intervals['endtime'] = start_times + resolving_time
intervals = merge_intervals(intervals)
else:
intervals = np.zeros((0, 2), np.int64)
intervals = np.zeros(0, dtype=strax.time_fields)
return intervals


Expand All @@ -377,7 +387,7 @@ def _coincidence(rr, nfold=4, resolving_time=300):
t_diff = np.diff(start_times, prepend=start_times[0])

# 2. Now we have to check if n-events are within resolving time:
# -> use moving average with size n to accumulate time between n-pulses
# -> use moving sum with size n to accumulate time between n-pulses
# -> check if accumulated time is below resolving time

# generate kernel:
Expand All @@ -393,34 +403,47 @@ def _coincidence(rr, nfold=4, resolving_time=300):
return start_times[mask]


@numba.njit(nogil=True, cache=True)
def _merge_intervals(start_time, resolving_time):
@export
def merge_intervals(intervals):
"""
Function which merges overlapping time intervals into a single one.
Function which merges overlapping intervals into a single one.
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved

Note:
If start times of two intervals are exactly resolving_time apart
from each other they will be merged into a single interval.
:param intervals: Any numpy array with strax time fields.
:returns: New intervals with time and endtime according to the
overlapping intervals.
"""
if not len(start_time):
# If the input is empty return empty array:
return np.zeros((0, 2), dtype=np.int64)

# check for gaps larger than resolving_time:
# The gaps will indicate the starts of new intervals
gaps = np.diff(start_time) > resolving_time

last_element = np.argwhere(gaps).flatten()
first_element = 0
# Creating output
# There is one more interval than gaps
intervals = np.zeros((np.sum(gaps) + 1, 2), dtype=np.int64)

# Looping over all intervals, except for the last one:
for ind, le in enumerate(last_element):
intervals[ind] = (start_time[first_element], start_time[le]+resolving_time)
first_element = le + 1

# Now we have to deal with the last gap:
intervals[-1] = (start_time[first_element], start_time[first_element:][-1] + resolving_time)
return intervals
res = np.zeros(len(intervals), dtype=strax.time_fields)
res = _merge_intervals(intervals['time'],
strax.endtime(intervals),
res)
return res
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved


@numba.njit(cache=True, nogil=True)
def _merge_intervals(start, end, res):
offset = 0

interval_start = start[0]
interval_end = end[0]
for next_interval_start, next_interval_end in zip(start[1:], end[1:]):
if interval_end >= next_interval_start:
# Interval overlaps, updated only end:
interval_end = next_interval_end
continue

# Intervals do not overlap, save interval:
res[offset]['time'] = interval_start
res[offset]['endtime'] = interval_end
offset += 1

# New interval:
interval_start = next_interval_start
interval_end = next_interval_end

# Save last interval:
res[offset]['time'] = interval_start
res[offset]['endtime'] = interval_end
offset += 1

return res[:offset]

WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
10 changes: 5 additions & 5 deletions straxen/plugins/veto_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,12 @@ def find_veto_events(hitlets: np.ndarray,
:returns: events, hitelt_ids_per_event
"""
# Find intervals which satisfy requirement:
intervals = straxen.plugins.nveto_recorder.coincidence(hitlets,
coincidence_level,
resolving_time,
left_extension,
intervals = straxen.plugins.nveto_recorder.find_coincidence(hitlets,
coincidence_level,
resolving_time,
left_extension,

)
)
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved

# Create some preliminary events:
event_intervals = np.zeros(len(intervals),
Expand Down
166 changes: 166 additions & 0 deletions straxen/plugins/veto_vetos.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import strax
import straxen
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved

WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
import numpy as np
import numba

export, __all__ = strax.exporter()


@export
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pep8] reported by reviewdog 🐶
E302 expected 2 blank lines, found 1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WenzDaniel , I actually like this convention for readability, you disagree?

@strax.takes_config(
strax.Option(
'min_veto_area_nv', default=5, type=float, track=True,
help='Minimal area required in pe to trigger veto.'),
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
strax.Option(
'min_veto_hits_nv', default=10, type=int, track=True,
help='Minimal number of hitlets in event to trigger veto.'),
strax.Option(
'min_veto_channel_nv', default=0, type=int, track=True,
help='Minimal number PMT channel contributing to the event.'),
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
strax.Option(
'veto_left_nv', default=500_000, type=int, track=True,
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
help='Veto time in ns left t the start of a vetoing event.'),
strax.Option(
'veto_right_nv', default=0, type=int, track=True,
help='Veto time in ns right to the end of a vetoing event.'),
)
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
class nVETOveto(strax.OverlapWindowPlugin):
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
"""
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
This is a default plugin, like used by many plugins in straxen. It
takes hitlets and multipliers their area with a user defined
multiplier.
"""
__version__ = '0.0.1'

depends_on = 'events_nv'
provides = 'veto_nv'
data_kind = 'veto_nv'
save_when = strax.SaveWhen.NEVER

dtype = strax.time_fields
ends_with = '_nv'

def get_window_size(self):
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
# Take a large window for safety, events can be ~500 ns large
return 10 * (self.config['veto_left_nv']
+ self.config['veto_right_nv'])
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved

def compute(self, events_nv, start, end):
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
vetos = create_veto_intervals(events_nv,
self.config['min_veto_area_nv'],
self.config['min_veto_hits_nv'],
self.config['min_veto_channel_nv'],
self.config['veto_left_nv'],
self.config['veto_right_nv'])

# Now we have to do clip all times and end endtimes in case
# they go beyond a chunk boundary:
vetos['time'] = np.clip(vetos['time'], start, end)
vetos['endtime'] = np.clip(vetos['endtime'], start, end)

return vetos


def create_veto_intervals(events,
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
min_area,
min_hits,
min_contributing_channels,
left_extension,
right_extension, ):
"""
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
Function which creates veto regions.

:param events: nveto events
:param min_area: min area in pe required to create a veto region.
:param min_hits: same but with hitlets
:param min_contributing_channels: Minimal number of contributing
channels.
:param left_extension: Left extension of the event to define veto
region in ns.
:param right_extension: Same but right hand side after.

:returns: numpy.structured.array containing the veto regions.
"""
res = np.zeros(len(events),
dtype=strax.time_fields)

res = _create_veto_intervals(events,
min_area,
min_hits,
min_contributing_channels,
left_extension,
right_extension,
res, )
res = straxen.merge_intervals(res)

return res


@numba.njit(cache=True)
def _create_veto_intervals(events,
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
min_area,
min_hits,
min_contributing_channels,
left_extension,
right_extension,
res, ):
offset = 0

for ev in events:
satisfies_veto_trigger = (ev['area'] >= min_area
and ev['n_hits'] >= min_hits
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
and ev['n_contributing_pmt'] >= min_contributing_channels)
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
if not satisfies_veto_trigger:
continue

res[offset]['time'] = ev['time'] - left_extension
res[offset]['endtime'] = ev['endtime'] + right_extension
offset += 1
return res[:offset]

@strax.takes_config(
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
strax.Option(
'min_veto_area_mv', default=10, type=float, track=True,
child_option=True, parent_option_name='min_veto_area_nv',
help='Minimal area required in pe to trigger veto.'),
strax.Option(
'min_veto_hits_mv', default=0, type=int, track=True,
child_option=True, parent_option_name='min_veto_hits_nv',
help='Minimal number of hitlets in event to trigger veto.'),
strax.Option(
'min_veto_channel_mv', default=5, type=int, track=True,
child_option=True, parent_option_name='min_veto_channel_nv',
help='Minimal number PMT channel contributing to the event.'),
strax.Option(
'veto_left_mv', default=0, type=int, track=True,
child_option=True, parent_option_name='veto_left_nv',
help='Veto time in ns left t the start of a vetoing event.'),
strax.Option(
'veto_right_mv', default=1_000, type=int, track=True,
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
child_option=True, parent_option_name='veto_right_nv',
help='Veto time in ns right to the end of a vetoing event.'),
)
class muVETOveto(nVETOveto):
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
"""
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pep8] reported by reviewdog 🐶
D204 1 blank line required after class docstring

This is a default plugin, like used by many plugins in straxen. It
takes hitlets and multipliers their area with a user defined
multiplier.
"""
__version__ = '0.0.1'

depends_on = 'events_mv'
provides = 'veto_mv'
data_kind = 'veto_mv'
save_when = strax.SaveWhen.NEVER

dtype = strax.time_fields
ends_with = '_mv'

def get_window_size(self):
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
# Take a large window for safety, events can be ~500 ns large
return 10 * (self.config['veto_left_mv']
+ self.config['veto_right_mv'])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[pep8] reported by reviewdog 🐶
W503 line break before binary operator


def compute(self, events_mv, start, end):
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
return super().compue(events_mv, start, end)
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
WenzDaniel marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 3 additions & 3 deletions tests/test_nveto_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ def test_nveto_event_building(hitlets,
"""
hitlets = strax.sort_by_time(hitlets)

intervals = straxen.plugins.nveto_recorder.coincidence(hitlets,
coincidence,
300)
intervals = straxen.plugins.nveto_recorder.find_coincidence(hitlets,
coincidence,
300)

# Create event_intervals:
event_intervals = np.zeros(len(intervals),
Expand Down
Loading