-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b18e8f3
commit c5e89bb
Showing
2 changed files
with
115 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
from . import veto_intervals | ||
from .veto_intervals import * | ||
|
||
from . import online_veto_intervals | ||
from .online_veto_intervals import * |
112 changes: 112 additions & 0 deletions
112
straxen/plugins/veto_intervals/online_veto_intervals.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import typing | ||
import numpy as np | ||
import strax | ||
import straxen | ||
|
||
from straxen.plugins.aqmon_hits.aqmon_hits import AqmonChannels | ||
|
||
export, __all__ = strax.exporter() | ||
|
||
|
||
# ### Veto hardware ###: | ||
# V1495 busy veto module: | ||
# Generates a 25 ns NIM pulse whenever a veto begins and a 25 ns NIM signal when it ends. | ||
# A new start signal can occur only after the previous busy instance ended. | ||
# 1ms (1e6 ns) - minimum busy veto length, or until the board clears its memory | ||
|
||
# DDC10 High Energy Veto: | ||
# 10ms (1e7 ns) - fixed HE veto length in XENON1T DDC10, | ||
# in XENONnT it will be calibrated based on the length of large S2 SE tails | ||
# The start/stop signals for the HEV are generated by the V1495 board | ||
|
||
|
||
@export | ||
class OnlineVetoIntervals(strax.OverlapWindowPlugin): | ||
"""Find pairs of veto start and veto stop signals and the veto. | ||
duration between them: | ||
- busy_* <= V1495 busy veto for tpc channels | ||
- busy_he_* <= V1495 busy veto for high energy tpc channels | ||
- hev_* <= DDC10 hardware high energy veto | ||
- straxen_deadtime <= special case of deadtime introduced by the | ||
DAQReader-plugin | ||
""" | ||
|
||
__version__ = "0.0.1" | ||
depends_on = "veto_intervals" | ||
provides = "online_veto_intervals" | ||
data_kind = "veto_intervals" | ||
|
||
# Save the data only when it is requested explicitly | ||
save_when = strax.SaveWhen.EXPLICIT | ||
|
||
# This option is just showing where the OverlapWindowPlugin fails. | ||
# We need to buffer the entire run in order not to run into chunking | ||
# issues. A better solution would be using | ||
# github.com/AxFoundation/strax/pull/654 | ||
max_veto_window = straxen.URLConfig( | ||
default=int(7.2e12), | ||
track=True, | ||
type=int, | ||
help=( | ||
"Maximum separation between veto stop and start pulses [ns]. " | ||
"Set to be >> than the max duration of the run to be able to " | ||
"fully store one run into buffer since aqmon-hits are not " | ||
"sorted by endtime" | ||
), | ||
) | ||
|
||
online_max_bytes = straxen.URLConfig( | ||
default=6e6, track=True, help="Maximum amount of bytes of data for MongoDB document" | ||
) | ||
|
||
def infer_dtype(self): | ||
dtype = [ | ||
(("veto interval [ns]", "veto_interval"), np.int64), | ||
(("veto signal type", "veto_type"), np.str_("U30")), | ||
(("cumulative time of the veto interval [ns]", "cumulative_deadtime"), np.float64), | ||
] | ||
dtype += strax.time_fields | ||
return dtype | ||
|
||
def compute(self, veto_intervals, start, end): | ||
|
||
# Calculate the cumulative deadtime for the entire chunk | ||
cumulative_deadtime = self._data_to_ms_cumsum(veto_intervals) | ||
|
||
if veto_intervals.nbytes > self.online_max_bytes: | ||
|
||
# Calculate fraction of the data that can be kept, | ||
# to reduce datasize. Randomly keep a fraction of the data | ||
new_len = int(len(veto_intervals) / veto_intervals.nbytes * self.online_max_bytes) | ||
idx = np.random.choice(np.arange(len(veto_intervals)), replace=False, size=new_len) | ||
veto_intervals = veto_intervals[np.sort(idx)] | ||
|
||
# Only keep the cumulative deadtime for the kept data indices | ||
cumulative_deadtime = cumulative_deadtime[np.sort(idx)] | ||
|
||
result = np.zeros(len(veto_intervals), dtype=self.dtype) | ||
result["veto_interval"] = veto_intervals["veto_interval"] | ||
result["veto_type"] = veto_intervals["veto_type"] | ||
result["cumulative_deadtime"] = cumulative_deadtime | ||
result["time"] = veto_intervals["time"] | ||
result["endtime"] = veto_intervals["endtime"] | ||
|
||
# If the final data array is still too large, we randomly sample again | ||
# up to 10MB | ||
if result.nbytes > self.online_max_bytes and result.nbytes < 10e6: | ||
new_len = int(len(result) / result.nbytes * self.online_max_bytes) | ||
idx = np.random.choice(np.arange(len(result)), replace=False, size=new_len) | ||
result = result[np.sort(idx)] | ||
|
||
return result | ||
|
||
def get_window_size(self): | ||
# Give a very wide window | ||
return self.max_veto_window | ||
|
||
@staticmethod | ||
def _data_to_ms_cumsum(data): | ||
return np.cumsum(data['veto_interval']) / 1e6 | ||
|