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 monitor #707

Merged
merged 11 commits into from
Oct 29, 2021
4 changes: 3 additions & 1 deletion straxen/contexts.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,9 @@ def xenonnt_online(output_folder='./strax_data',
take_only=('veto_intervals',
'online_peak_monitor',
'event_basics',
'online_monitor_nv'))]
'online_monitor_nv',
'online_monitor_mv',
))]

# Remap the data if it is before channel swap (because of wrongly cabled
# signal cable connectors) These are runs older than run 8797. Runs
Expand Down
122 changes: 86 additions & 36 deletions straxen/plugins/online_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,69 +184,119 @@ def area_width_hist(self, data):
'channel_map',
track=False,
type=immutabledict,
help="immutabledict mapping subdetector to (min, max) \
channel number."),
help='immutabledict mapping subdetector to (min, max) '
'channel number.'),
strax.Option(
'events_nv_area_bounds',
'events_area_bounds',
type=tuple, default=(-0.5, 130.5),
help='Boundaries area histogram of events_nv_area_per_chunk [PE]')
help='Boundaries area histogram of events_nv_area_per_chunk [PE]'),
strax.Option(
'events_area_nbins',
type=int, default=131,
help='Number of bins of histogram of events_nv_area_per_chunk, '
'defined value 1 PE/bin')
)
class OnlineMonitorNV(strax.Plugin):
"""
Plugin to write data of nVeto detector to the online-monitor.
Data that is written by this plugin should be small (~MB/chunk)
to not overload the runs-database.

This plugin takes 'hitlets_nv' and 'events_nv'. Although they are
not strictly related, they are aggregated into a single data_type
in order to minimize the number of documents in the online monitor.

Produces 'online_monitor_nv' with info on the hitlets_nv and events_nv
"""

depends_on = ('hitlets_nv', 'events_nv')
provides = 'online_monitor_nv'
data_kind = 'online_monitor_nv'
__version__ = '0.0.3'
rechunk_on_save = False

# Needed in case we make again an muVETO child.
ends_with = '_nv'

__version__ = '0.0.4'

def infer_dtype(self):
min_pmt, max_pmt = self.config['channel_map']['nveto']
n_pmt = (max_pmt - min_pmt) + 1
dtype = [
(('Start time of the chunk', 'time'),
np.int64),
(('End time of the chunk', 'endtime'),
np.int64),
(('hitlets_nv per channel', 'hitlets_nv_per_channel'),
(np.int64, n_pmt)),
(('events_nv per chunk', 'events_nv_per_chunk'),
np.int64),
(('events_nv_area per chunk', 'events_nv_area_per_chunk'),
np.int64, 130)
]
return dtype
self.channel_range = self.config['channel_map']['nveto']
self.n_channel = (self.channel_range[1] - self.channel_range[0]) + 1
return veto_monitor_dtype(self.ends_with, self.n_channel, self.config['events_area_nbins'])

def compute(self, hitlets_nv, events_nv, start, end):
# General setup
res = np.zeros(1, dtype=self.dtype)
res['time'] = start
res['endtime'] = end
min_pmt, max_pmt = self.config['channel_map']['nveto']
n_pmt = (max_pmt - min_pmt) + 1

# Count number of hitlets_nv per PMT
hitlets_channel_count, _ = np.histogram(hitlets_nv['channel'],
bins=n_pmt,
range=[min_pmt, max_pmt + 1])
res['hitlets_nv_per_channel'] = hitlets_channel_count

# Count number of events_nv per chunk
res['events_nv_per_chunk'] = len(events_nv)

bins=self.n_channel,
range=[self.channel_range[0],
self.channel_range[1] + 1])
res[f'hitlets{self.ends_with}_per_channel'] = hitlets_channel_count

# Count number of events_nv with coincidence cut
res[f'events{self.ends_with}_per_chunk'] = len(events_nv)
sel = events_nv['n_contributing_pmt'] >= 4
res[f'events{self.ends_with}_4coinc_per_chunk'] = np.sum(sel)
sel = events_nv['n_contributing_pmt'] >= 5
res[f'events{self.ends_with}_5coinc_per_chunk'] = np.sum(sel)
sel = events_nv['n_contributing_pmt'] >= 8
res[f'events{self.ends_with}_8coinc_per_chunk'] = np.sum(sel)
sel = events_nv['n_contributing_pmt'] >= 10
res[f'events{self.ends_with}_10coinc_per_chunk'] = np.sum(sel)

# Get histogram of events_nv_area per chunk
min_bin, max_bin = self.config['events_nv_area_bounds']
res['events_nv_area_per_chunk'], _ = np.histogram(events_nv['area'],
bins=np.arange(min_bin, max_bin, 1),
weights=np.ones(len(events_nv)))
events_area, bins_ = np.histogram(events_nv['area'],
bins=self.config['events_area_nbins'],
range=self.config['events_area_bounds'])
res[f'events{self.ends_with}_area_per_chunk'] = events_area
return res


def veto_monitor_dtype(veto_name: str = '_nv',
n_pmts: int = 120,
n_bins: int = 131) -> list:
dtype = []
dtype += strax.time_fields # because mutable
dtype += [((f'hitlets{veto_name} per channel', f'hitlets{veto_name}_per_channel'), (np.int64, n_pmts)),
((f'events{veto_name}_area per chunk', f'events{veto_name}_area_per_chunk'), np.int64, n_bins),
((f'events{veto_name} per chunk', f'events{veto_name}_per_chunk'), np.int64),
((f'events{veto_name} 4-coincidence per chunk', f'events{veto_name}_4coinc_per_chunk'), np.int64),
((f'events{veto_name} 5-coincidence per chunk', f'events{veto_name}_5coinc_per_chunk'), np.int64),
((f'events{veto_name} 8-coincidence per chunk', f'events{veto_name}_8coinc_per_chunk'), np.int64),
((f'events{veto_name} 10-coincidence per chunk', f'events{veto_name}_10coinc_per_chunk'), np.int64)
]
return dtype


@export
@strax.takes_config(
strax.Option(
'adc_to_pe_mv',
type=int, default=170.0,
help='conversion factor from ADC to PE for muon Veto')
)
class OnlineMonitorMV(OnlineMonitorNV):
__doc__ = OnlineMonitorNV.__doc__.replace('_nv', '_mv').replace('nVeto', 'muVeto')
depends_on = ('hitlets_mv', 'events_mv')
provides = 'online_monitor_mv'
data_kind = 'online_monitor_mv'
rechunk_on_save = False

# Needed in case we make again an muVETO child.
ends_with = '_mv'
child_plugin = True

__version__ = '0.0.1'

def infer_dtype(self):

Choose a reason for hiding this comment

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

[pep8] reported by reviewdog 🐶
D102 Missing docstring in public method

self.channel_range = self.config['channel_map']['mv']
self.n_channel = (self.channel_range[1] - self.channel_range[0]) + 1
return veto_monitor_dtype(self.ends_with, self.n_channel, self.config['events_area_nbins'])

def compute(self, hitlets_mv, events_mv, start, end):

Choose a reason for hiding this comment

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

[pep8] reported by reviewdog 🐶
D102 Missing docstring in public method

events_mv = np.copy(events_mv)
events_mv['area'] *= 1./self.config['adc_to_pe_mv']
return super().compute(hitlets_mv, events_mv, start, end)