Skip to content

Commit

Permalink
Add online_veto_intervals plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
JoranAngevaare committed Feb 13, 2024
1 parent b18e8f3 commit c5e89bb
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
3 changes: 3 additions & 0 deletions straxen/plugins/veto_intervals/__init__.py
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 straxen/plugins/veto_intervals/online_veto_intervals.py
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

0 comments on commit c5e89bb

Please sign in to comment.