Skip to content
Snippets Groups Projects
Commit 180faedd authored by Tamas Gal's avatar Tamas Gal :speech_balloon:
Browse files

Merge branch 'master' of git.km3net.de:km3py/km3mon

parents 5f1d5f57 08714e71
No related branches found
No related tags found
No related merge requests found
...@@ -83,10 +83,25 @@ start: ...@@ -83,10 +83,25 @@ start:
"echo narf" "echo narf"
@tmux select-layout even-vertical @tmux select-layout even-vertical
@# AHRS
@#
@tmux new-window -n ahrs -t ${SESSION_NAME}
@tmux split-window -v -t ${SESSION_NAME}:ahrs
@tmux send-keys -t ${SESSION_NAME}:ahrs.1 \
"python scripts/ahrs_calibration.py -d ${DETECTOR_ID} -p ${MONITORING_LIGIER_PORT}" Enter
@tmux select-layout even-vertical
@# Log.io
@#
@tmux new-window -n logio -t ${SESSION_NAME}
@tmux split-window -v -t ${SESSION_NAME}:logio
@tmux send-keys -t ${SESSION_NAME}:logio.1 \
"python scripts/logio.py -p ${MONITORING_LIGIER_PORT} -x ${LOGIO_IP} -q ${LOGIO_PORT}" Enter
@tmux select-layout even-vertical
stop: stop:
killall gunicorn
tmux kill-session -t ${SESSION_NAME} tmux kill-session -t ${SESSION_NAME}
killall gunicorn
clean: clean:
rm Makefile rm Makefile
......
...@@ -60,3 +60,21 @@ If you want to stop it: ...@@ -60,3 +60,21 @@ If you want to stop it:
make stop make stop
easy. easy.
## Configuration file
A file called `pipeline.toml` can be placed into the root folder of the
monitoring software (usually `~/monitoring`) which can be used to set
different kind of parameters, like plot attributes or ranges.
Here is an example `pipeline.toml`:
[DOMRates]
lowest_rate = 200
highest_rate = 400
[PMTRates]
lowest_rate = 1000
highest_rate = 10000
After a `make stop` and `make start`, the file is parsed and the default
values are overwritten by those defined in the configuration file.
...@@ -8,6 +8,9 @@ app.config['FREEZER_DESTINATION'] = '../km3web' ...@@ -8,6 +8,9 @@ app.config['FREEZER_DESTINATION'] = '../km3web'
PLOTS = [['dom_activity', 'dom_rates'], ['pmt_rates', 'pmt_hrv'], PLOTS = [['dom_activity', 'dom_rates'], ['pmt_rates', 'pmt_hrv'],
['trigger_rates'], ['ztplot', 'triggermap']] ['trigger_rates'], ['ztplot', 'triggermap']]
AHRS_PLOTS = [['yaw_calib'], ['pitch_calib'], ['roll_calib']]
TRIGGER_PLOTS = [['trigger_rates'], ['trigger_rates_lin']]
@app.after_request @app.after_request
def add_header(r): def add_header(r):
...@@ -27,6 +30,16 @@ def index(): ...@@ -27,6 +30,16 @@ def index():
return render_template('plots.html', plots=PLOTS) return render_template('plots.html', plots=PLOTS)
@app.route('/ahrs.html')
def ahrs():
return render_template('plots.html', plots=AHRS_PLOTS)
@app.route('/trigger.html')
def trigger():
return render_template('plots.html', plots=TRIGGER_PLOTS)
@app.route('/plots/<path:filename>') @app.route('/plots/<path:filename>')
def custom_static(filename): def custom_static(filename):
print(filename) print(filename)
......
...@@ -29,11 +29,17 @@ ...@@ -29,11 +29,17 @@
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="active"><a href="index.html">Overview</a></li> <li class="active"><a href="index.html">Overview</a></li>
</ul> </ul>
<!-- <ul class="nav navbar&#45;nav"> -->
<!-- <li class="active"><a href="#">Intra DOM Calibration</a></li> -->
<!-- </ul> -->
<!-- <ul class="nav navbar&#45;nav"> -->
<!-- <li class="active"><a href="#">K40 Rate Dist</a></li> -->
<!-- </ul> -->
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="active"><a href="#">Intra DOM Calibration</a></li> <li class="active"><a href="trigger.html">Trigger</a></li>
</ul> </ul>
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="active"><a href="#">K40 Rate Dist</a></li> <li class="active"><a href="ahrs.html">AHRS</a></li>
</ul> </ul>
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="active"><a href="https://git.km3net.de/km3py/km3mon/issues">Issues</a></li> <li class="active"><a href="https://git.km3net.de/km3py/km3mon/issues">Issues</a></li>
......
...@@ -5,6 +5,8 @@ daq_ligier_ip="192.168.0.110" ...@@ -5,6 +5,8 @@ daq_ligier_ip="192.168.0.110"
daq_ligier_port=5553 daq_ligier_port=5553
monitoring_ligier_ip="127.0.0.1" monitoring_ligier_ip="127.0.0.1"
monitoring_ligier_port=5553 monitoring_ligier_port=5553
logio_ip="127.0.0.1"
logio_port=28777
webserver_port=8080 webserver_port=8080
tmux_session_name="km3mon" tmux_session_name="km3mon"
...@@ -37,6 +39,14 @@ for arg in "$@"; do ...@@ -37,6 +39,14 @@ for arg in "$@"; do
monitoring_ligier_port=`echo $arg | sed 's/--monitoring-ligier-port=//'` monitoring_ligier_port=`echo $arg | sed 's/--monitoring-ligier-port=//'`
;; ;;
--logio-ip=*)
logio_ip=`echo $arg | sed 's/--logio-ip=//'`
;;
--logio-port=*)
logio_port=`echo $arg | sed 's/--logio-port=//'`
;;
--tmux-session-name=*) --tmux-session-name=*)
tmux_session_name=`echo $arg | sed 's/--tmux-session-name=//'` tmux_session_name=`echo $arg | sed 's/--tmux-session-name=//'`
;; ;;
...@@ -54,6 +64,8 @@ for arg in "$@"; do ...@@ -54,6 +64,8 @@ for arg in "$@"; do
echo " --daq-ligier-ip DAQ Ligier ${daq_ligier_ip}" echo " --daq-ligier-ip DAQ Ligier ${daq_ligier_ip}"
echo " --daq-ligier-port Port of the DAQ Ligier ${daq_ligier_port}" echo " --daq-ligier-port Port of the DAQ Ligier ${daq_ligier_port}"
echo " --monitoring-ligier-port Port of the monitoring Ligier ${monitoring_ligier_port}" echo " --monitoring-ligier-port Port of the monitoring Ligier ${monitoring_ligier_port}"
echo " --logio-ip Log.io IP ${logio_ip}"
echo " --logio-port Port of the Log.io server ${logio_port}"
echo " --tmux-session-name TMUX session name ${tmux_session_name}" echo " --tmux-session-name TMUX session name ${tmux_session_name}"
echo " --webserver-port Port of the web server ${webserver_port}" echo " --webserver-port Port of the web server ${webserver_port}"
echo echo
...@@ -67,6 +79,8 @@ echo "DETECTOR_ID = ${detector_id}" > Makefile ...@@ -67,6 +79,8 @@ echo "DETECTOR_ID = ${detector_id}" > Makefile
echo "DAQ_LIGIER_IP = ${daq_ligier_ip}" >> Makefile echo "DAQ_LIGIER_IP = ${daq_ligier_ip}" >> Makefile
echo "DAQ_LIGIER_PORT = ${daq_ligier_port}" >> Makefile echo "DAQ_LIGIER_PORT = ${daq_ligier_port}" >> Makefile
echo "MONITORING_LIGIER_PORT = ${monitoring_ligier_port}" >> Makefile echo "MONITORING_LIGIER_PORT = ${monitoring_ligier_port}" >> Makefile
echo "LOGIO_IP = ${logio_ip}" >> Makefile
echo "LOGIO_PORT = ${logio_port}" >> Makefile
echo "WEBSERVER_PORT = ${webserver_port}" >> Makefile echo "WEBSERVER_PORT = ${webserver_port}" >> Makefile
echo "SESSION_NAME = ${tmux_session_name}" >> Makefile echo "SESSION_NAME = ${tmux_session_name}" >> Makefile
...@@ -76,6 +90,7 @@ show_km3mon_banner ...@@ -76,6 +90,7 @@ show_km3mon_banner
echo "Detector ID: ${detector_id}" echo "Detector ID: ${detector_id}"
echo "DAQ Ligier: ${daq_ligier_ip}:${daq_ligier_port}" echo "DAQ Ligier: ${daq_ligier_ip}:${daq_ligier_port}"
echo "Monitoring Ligier: ${monitoring_ligier_ip}:${monitoring_ligier_port}" echo "Monitoring Ligier: ${monitoring_ligier_ip}:${monitoring_ligier_port}"
echo "Log.io Server: ${logio_ip}:${logio_port}"
echo "Webserver: 0.0.0.0:${webserver_port}" echo "Webserver: 0.0.0.0:${webserver_port}"
echo "TMUX session: ${tmux_session_name}" echo "TMUX session: ${tmux_session_name}"
echo echo
......
{
"words": {
"ERROR": "color: #CC0C28;",
"STATUS": "color: #2F76CC;",
"DataFilter": "background-color: #138799; color: #ffffff",
"DataWriter": "background-color: #FFBE05; color: #000000",
"DataQueue": "background-color: #674591; color=: #ffffff"
},
"lines": {
"ERROR": "font-weight: bold;"
}
}
#!/usr/bin/env python
# coding=utf-8
# vim: ts=4 sw=4 et
"""
Runs the AHRS calibration online.
Usage:
ahrs_calibration.py [options]
ahrs_calibration.py (-h | --help)
Options:
-l LIGIER_IP The IP of the ligier [default: 127.0.0.1].
-p LIGIER_PORT The port of the ligier [default: 5553].
-d DET_ID Detector ID [default: 29].
-o PLOT_DIR The directory to save the plot [default: plots].
-h --help Show this screen.
"""
from __future__ import division
from datetime import datetime
from collections import deque, defaultdict
from functools import partial
import io
import os
import threading
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as md
import seaborn as sns
import km3pipe as kp
from km3pipe.io.daq import TMCHData
from km3modules.ahrs import fit_ahrs, get_latest_ahrs_calibration
import km3pipe.style
km3pipe.style.use('km3pipe')
class CalibrateAHRS(kp.Module):
def configure(self):
self.plots_path = self.require('plots_path')
det_id = self.require('det_id')
self.detector = kp.hardware.Detector(det_id=det_id)
self.du = self.get('du', default=1)
self.clbmap = kp.db.CLBMap(det_oid=det_id)
self.cuckoo = kp.time.Cuckoo(60, self.create_plot)
self.cuckoo_log = kp.time.Cuckoo(10, print)
self.data = {}
queue_size = 50000
for ahrs_param in ('yaw', 'pitch', 'roll'):
self.data[ahrs_param] = defaultdict(
partial(deque, maxlen=queue_size))
self.times = defaultdict(partial(deque, maxlen=queue_size))
self.lock = threading.Lock()
self.index = 0
def process(self, blob):
self.index += 1
if self.index % 29 != 0:
return blob
now = datetime.utcnow()
tmch_data = TMCHData(io.BytesIO(blob['CHData']))
dom_id = tmch_data.dom_id
clb = self.clbmap.dom_id[dom_id]
if clb.floor == 0:
self.log.info("Skipping base CLB")
return blob
if clb.du != self.du:
return blob
yaw = tmch_data.yaw
calib = get_latest_ahrs_calibration(clb.upi, max_version=4)
if calib is None:
return blob
cyaw, cpitch, croll = fit_ahrs(tmch_data.A, tmch_data.H, *calib)
self.cuckoo_log("DU{}-DOM{} (random pick): calibrated yaw={}".format(
clb.du, clb.floor, cyaw))
with self.lock:
self.data['yaw'][clb.floor].append(cyaw)
self.data['pitch'][clb.floor].append(cpitch)
self.data['roll'][clb.floor].append(croll)
self.times[clb.floor].append(now)
self.cuckoo.msg()
return blob
def create_plot(self):
print(self.__class__.__name__ + ": updating plot.")
# xfmt = md.DateFormatter('%Y-%m-%d %H:%M')
xfmt = md.DateFormatter('%H:%M')
for ahrs_param in self.data.keys():
fig, ax = plt.subplots(figsize=(16, 6))
sns.set_palette("husl", 18)
ax.set_title("AHRS {} Calibration on DU{}\n{}".format(
ahrs_param, self.du, datetime.utcnow()))
ax.set_xlabel("UTC time")
ax.xaxis.set_major_formatter(xfmt)
ax.set_ylabel(ahrs_param)
with self.lock:
for floor in sorted(self.data[ahrs_param].keys()):
ax.plot(
self.times[floor],
self.data[ahrs_param][floor],
marker='.',
linestyle='none',
label="Floor {}".format(floor))
lgd = plt.legend(
bbox_to_anchor=(1.005, 1), loc=2, borderaxespad=0.)
fig.tight_layout()
plt.savefig(
os.path.join(self.plots_path, ahrs_param + '_calib.png'),
bbox_extra_artists=(lgd, ),
bbox_inches='tight')
plt.close('all')
def main():
from docopt import docopt
args = docopt(__doc__)
det_id = int(args['-d'])
plots_path = args['-o']
ligier_ip = args['-l']
ligier_port = int(args['-p'])
pipe = kp.Pipeline()
pipe.attach(
kp.io.ch.CHPump,
host=ligier_ip,
port=ligier_port,
tags='IO_MONIT',
timeout=60 * 60 * 24 * 7,
max_queue=2000)
pipe.attach(kp.io.daq.DAQProcessor)
pipe.attach(CalibrateAHRS, det_id=det_id, plots_path=plots_path)
pipe.drain()
if __name__ == '__main__':
main()
...@@ -91,7 +91,8 @@ class DOMActivityPlotter(kp.Module): ...@@ -91,7 +91,8 @@ class DOMActivityPlotter(kp.Module):
self.detector, self.detector,
filename, filename,
'last activity [s]', 'last activity [s]',
"DOM Activity - via Summary Slices", "DOM Activity for DetID-{} - via Summary Slices".format(
self.detector.det_id),
vmin=0.0, vmin=0.0,
vmax=15 * 60) vmax=15 * 60)
......
...@@ -80,7 +80,7 @@ class DOMRates(kp.Module): ...@@ -80,7 +80,7 @@ class DOMRates(kp.Module):
self.detector, self.detector,
filename, filename,
'rate [kHz]', 'rate [kHz]',
"DOM Rates", "DOM Rates for DetID-{}".format(self.detector.det_id),
vmin=self.lowest_rate, vmin=self.lowest_rate,
vmax=self.highest_rate, vmax=self.highest_rate,
cmap='coolwarm', cmap='coolwarm',
......
...@@ -125,9 +125,10 @@ class DOMHits(Module): ...@@ -125,9 +125,10 @@ class DOMHits(Module):
ax.tick_params(labelbottom=False) ax.tick_params(labelbottom=False)
ax.tick_params(labeltop=False) ax.tick_params(labeltop=False)
ax.set_xlabel("event (latest on the right)") ax.set_xlabel("event (latest on the right)")
ax.set_title("{0} - via the last {1} Events\n{2} UTC".format( ax.set_title(
title, self.max_events, "{0} for DetID-{1} - via the last {2} Events\n{3} UTC".format(
datetime.utcnow().strftime("%c"))) title, self.det.det_id, self.max_events,
datetime.utcnow().strftime("%c")))
cb = fig.colorbar(im, pad=0.05) cb = fig.colorbar(im, pad=0.05)
cb.set_label("number of hits") cb.set_label("number of hits")
...@@ -180,7 +181,7 @@ def main(): ...@@ -180,7 +181,7 @@ def main():
kp.io.ch.CHPump, kp.io.ch.CHPump,
host=ligier_ip, host=ligier_ip,
port=ligier_port, port=ligier_port,
tags='IO_EVT, IO_SUM', tags='IO_EVT',
timeout=60 * 60 * 24 * 7, timeout=60 * 60 * 24 * 7,
max_queue=2000) max_queue=2000)
pipe.attach(kp.io.daq.DAQProcessor) pipe.attach(kp.io.daq.DAQProcessor)
......
#!/usr/bin/env python
# coding=utf-8
# Filename: logio.py
# Author: Tamas Gal <tgal@km3net.de>
# vim: ts=4 sw=4 et
"""
Sends MSG data from Ligier to a log.io server to be displayed in real-time.
Usage:
logio.py [options]
logio.py (-h | --help)
Options:
-l LIGIER_IP The IP of the ligier [default: 127.0.0.1].
-p LIGIER_PORT The port of the ligier [default: 5553].
-x LOGIO_IP The IP of the ligier [default: 127.0.0.1].
-q LOGIO_PORT The port of the ligier [default: 28777].
-h --help Show this screen.
"""
import socket
import time
from km3pipe import Pipeline, Module
from km3pipe.io import CHPump
class LogIO(Module):
def configure(self):
url = self.get('logio_ip', default='127.0.0.1')
port = self.get('logio_port', default=28777)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect((url, port))
def process(self, blob):
data = blob['CHData']
log_level = 'info'
if "ERROR" in data:
log_level = 'error'
if "WARNING" in data:
log_level = 'warning'
source = "Other"
if " F0" in data:
source = "DataFilter"
if " Q0" in data:
source = "DataQueue"
if " W0" in data:
source = "DataWriter"
self.sock.send("+log|{0}|Portopalo DAQ|{1}|{2}\r\n".format(
source, log_level, data))
return blob
def finish(self):
self.sock.close()
def main():
from docopt import docopt
args = docopt(__doc__)
ligier_ip = args['-l']
ligier_port = int(args['-p'])
logio_ip = args['-x']
logio_port = int(args['-q'])
pipe = Pipeline()
pipe.attach(
CHPump,
host=ligier_ip,
port=ligier_port,
tags='MSG',
timeout=7 * 60 * 60 * 24,
max_queue=500)
pipe.attach(LogIO, logio_ip=logio_ip, logio_port=logio_port)
pipe.drain()
if __name__ == '__main__':
main()
#!/usr/bin/env python
# coding=utf-8
# Filename: msg_dumper.py
# Author: Tamas Gal <tgal@km3net.de>
# vim: ts=4 sw=4 et
"""
Dumps MSG data from Ligier to a file.
Usage:
msg_dumper.py [options]
msg_dumper.py (-h | --help)
Options:
-l LIGIER_IP The IP of the ligier [default: 127.0.0.1].
-p LIGIER_PORT The port of the ligier [default: 5553].
-f LOG_FILE Log file to dump the messages [default: MSG.log].
-h --help Show this screen.
"""
import os
import time
from km3pipe import Pipeline, Module
from km3pipe.io import CHPump
class MSGDumper(Module):
def configure(self):
self.filename = self.get('filename', default='MSG.log')
self.fobj = open(os.path.abspath(self.filename), 'a')
def process(self, blob):
data = blob['CHData'].decode()
source = "Other"
if " F0" in data:
source = "DataFilter"
if " Q0" in data:
source = "DataQueue"
if " W0" in data:
source = "DataWriter"
entry = "{} [{}]: {}\n".format(
os.path.basename(self.filename), source, data)
self.fobj.write(entry)
return blob
def finish(self):
self.fobj.close()
def main():
from docopt import docopt
args = docopt(__doc__)
ligier_ip = args['-l']
ligier_port = int(args['-p'])
filename = args['-f']
pipe = Pipeline()
pipe.attach(
CHPump,
host=ligier_ip,
port=ligier_port,
tags='MSG',
timeout=7 * 60 * 60 * 24,
max_queue=500)
pipe.attach(MSGDumper, filename=filename)
pipe.drain()
if __name__ == '__main__':
main()
...@@ -21,6 +21,7 @@ from __future__ import division, print_function ...@@ -21,6 +21,7 @@ from __future__ import division, print_function
from datetime import datetime from datetime import datetime
from collections import defaultdict, deque, OrderedDict from collections import defaultdict, deque, OrderedDict
from itertools import chain
import sys import sys
from io import BytesIO from io import BytesIO
from os.path import join from os.path import join
...@@ -35,11 +36,10 @@ import matplotlib.dates as md ...@@ -35,11 +36,10 @@ import matplotlib.dates as md
import km3pipe as kp import km3pipe as kp
from km3pipe.config import Config from km3pipe.config import Config
from km3pipe.io.daq import (DAQPreamble, DAQEvent, from km3pipe.io.daq import (DAQPreamble, DAQEvent, is_3dshower, is_3dmuon,
is_3dshower, is_3dmuon, is_mxshower) is_mxshower)
import km3pipe.style import km3pipe.style
VERSION = "1.0" VERSION = "1.0"
km3pipe.style.use('km3pipe') km3pipe.style.use('km3pipe')
...@@ -47,8 +47,8 @@ km3pipe.style.use('km3pipe') ...@@ -47,8 +47,8 @@ km3pipe.style.use('km3pipe')
class TriggerRate(kp.Module): class TriggerRate(kp.Module):
def configure(self): def configure(self):
self.plots_path = self.require('plots_path') self.plots_path = self.require('plots_path')
self.interval = self.get("interval", self.interval = self.get(
default=self.trigger_rate_sampling_period()) "interval", default=self.trigger_rate_sampling_period())
self.filename = self.get("filename", default="trigger_rates") self.filename = self.get("filename", default="trigger_rates")
self.with_minor_ticks = self.get("with_minor_ticks", default=False) self.with_minor_ticks = self.get("with_minor_ticks", default=False)
print("Update interval: {}s".format(self.interval)) print("Update interval: {}s".format(self.interval))
...@@ -56,18 +56,25 @@ class TriggerRate(kp.Module): ...@@ -56,18 +56,25 @@ class TriggerRate(kp.Module):
self.trigger_rates = OrderedDict() self.trigger_rates = OrderedDict()
self.styles = { self.styles = {
"xfmt": md.DateFormatter('%Y-%m-%d %H:%M'), "xfmt":
"general": dict(markersize=6, linestyle='None'), md.DateFormatter('%Y-%m-%d %H:%M'),
"Overall": dict(marker='D', "general":
markerfacecolor='None', dict(markersize=6, linestyle='None'),
markeredgecolor='tomato', "Overall":
markeredgewidth=1), dict(
"3DMuon": dict(marker='X', markerfacecolor='dodgerblue'), marker='D',
"MXShower": dict(marker='v', markerfacecolor='orange'), markerfacecolor='None',
"3DShower": dict(marker='^', markerfacecolor='olivedrab'), markeredgecolor='tomato',
markeredgewidth=1),
"3DMuon":
dict(marker='X', markerfacecolor='dodgerblue'),
"MXShower":
dict(marker='v', markerfacecolor='orange'),
"3DShower":
dict(marker='^', markerfacecolor='olivedrab'),
} }
queue_len = int(60*24/(self.interval/60)) queue_len = int(60 * 24 / (self.interval / 60))
for trigger in ["Overall", "3DMuon", "MXShower", "3DShower"]: for trigger in ["Overall", "3DMuon", "MXShower", "3DShower"]:
self.trigger_rates[trigger] = deque(maxlen=queue_len) self.trigger_rates[trigger] = deque(maxlen=queue_len)
...@@ -75,6 +82,10 @@ class TriggerRate(kp.Module): ...@@ -75,6 +82,10 @@ class TriggerRate(kp.Module):
self.thread = threading.Thread(target=self.plot).start() self.thread = threading.Thread(target=self.plot).start()
self.lock = threading.Lock() self.lock = threading.Lock()
self.run_changes = []
self.current_run_id = 0
self.det_id = 0
def process(self, blob): def process(self, blob):
if not str(blob['CHPrefix'].tag) == 'IO_EVT': if not str(blob['CHPrefix'].tag) == 'IO_EVT':
return blob return blob
...@@ -85,6 +96,10 @@ class TriggerRate(kp.Module): ...@@ -85,6 +96,10 @@ class TriggerRate(kp.Module):
data_io = BytesIO(data) data_io = BytesIO(data)
preamble = DAQPreamble(file_obj=data_io) # noqa preamble = DAQPreamble(file_obj=data_io) # noqa
event = DAQEvent(file_obj=data_io) event = DAQEvent(file_obj=data_io)
self.det_id = event.header.det_id
if event.header.run > self.current_run_id:
self.current_run_id = event.header.run
self._log_run_change()
tm = event.trigger_mask tm = event.trigger_mask
with self.lock: with self.lock:
self.trigger_counts["Overall"] += 1 self.trigger_counts["Overall"] += 1
...@@ -96,6 +111,27 @@ class TriggerRate(kp.Module): ...@@ -96,6 +111,27 @@ class TriggerRate(kp.Module):
return blob return blob
def _log_run_change(self):
self.print("New run: %s" % self.current_run_id)
now = datetime.utcnow()
self.run_changes.append((now, self.current_run_id))
def _get_run_changes_to_plot(self):
self.print("Checking run changes out of range")
overall_rates = self.trigger_rates['Overall']
if not overall_rates:
self.print("No trigger rates logged yet, nothing to remove.")
return
self.print(" all: {}".format(self.run_changes))
run_changes_to_plot = []
min_timestamp = min(overall_rates)[0]
self.print(" earliest timestamp to plot: {}".format(min_timestamp))
for timestamp, run in self.run_changes:
if timestamp > min_timestamp:
run_changes_to_plot.append((timestamp, run))
self.print(" to plot: {}".format(run_changes_to_plot))
return run_changes_to_plot
def plot(self): def plot(self):
while self.run: while self.run:
time.sleep(self.interval) time.sleep(self.interval)
...@@ -119,12 +155,35 @@ class TriggerRate(kp.Module): ...@@ -119,12 +155,35 @@ class TriggerRate(kp.Module):
self.log.warning("Empty rates, skipping...") self.log.warning("Empty rates, skipping...")
continue continue
timestamps, trigger_rates = zip(*rates) timestamps, trigger_rates = zip(*rates)
ax.plot(timestamps, trigger_rates, ax.plot(
**self.styles[trigger], timestamps,
**self.styles['general'], trigger_rates,
label=trigger) **self.styles[trigger],
ax.set_title("Trigger Rates\n{0} UTC" **self.styles['general'],
.format(datetime.utcnow().strftime("%c"))) label=trigger)
run_changes_to_plot = self._get_run_changes_to_plot()
self.print("Recorded run changes: {}".format(run_changes_to_plot))
all_rates = [r for d, r in chain(*self.trigger_rates.values())]
if not all_rates:
self.log.warning("Empty rates, skipping...")
return
min_trigger_rate = min(all_rates)
max_trigger_rate = max(all_rates)
for run_start, run in run_changes_to_plot:
plt.text(
run_start, (min_trigger_rate + max_trigger_rate) / 2,
"\nRUN %s " % run,
rotation=60,
verticalalignment='top',
fontsize=8,
color='gray')
ax.axvline(
run_start, color='#ff0f5b', linestyle='--', alpha=0.8) # added
ax.set_title("Trigger Rates for DetID-{0}\n{1} UTC".format(
self.det_id,
datetime.utcnow().strftime("%c")))
ax.set_xlabel("time") ax.set_xlabel("time")
ax.set_ylabel("trigger rate [Hz]") ax.set_ylabel("trigger rate [Hz]")
ax.xaxis.set_major_formatter(self.styles["xfmt"]) ax.xaxis.set_major_formatter(self.styles["xfmt"])
...@@ -175,11 +234,13 @@ def main(): ...@@ -175,11 +234,13 @@ def main():
ligier_port = int(args['-p']) ligier_port = int(args['-p'])
pipe = kp.Pipeline() pipe = kp.Pipeline()
pipe.attach(kp.io.ch.CHPump, host=ligier_ip, pipe.attach(
port=ligier_port, kp.io.ch.CHPump,
tags='IO_EVT', host=ligier_ip,
timeout=60*60*24*7, port=ligier_port,
max_queue=200000) tags='IO_EVT',
timeout=60 * 60 * 24 * 7,
max_queue=200000)
pipe.attach(TriggerRate, interval=300, plots_path=plots_path) pipe.attach(TriggerRate, interval=300, plots_path=plots_path)
pipe.drain() pipe.drain()
......
...@@ -135,13 +135,17 @@ class ZTPlot(Module): ...@@ -135,13 +135,17 @@ class ZTPlot(Module):
label.set_rotation(45) label.set_rotation(45)
if idx % n_cols == 0: if idx % n_cols == 0:
ax.set_ylabel('time [ns]', fontsize=fontsize) ax.set_ylabel('z [m]', fontsize=fontsize)
if idx >= len(axes) - n_cols: if idx >= len(axes) - n_cols:
ax.set_xlabel('z [m]', fontsize=fontsize) ax.set_xlabel('time [ns]', fontsize=fontsize)
print
plt.suptitle( plt.suptitle(
"FrameIndex {0}, TriggerCounter {1}\n{2} UTC".format( "z-t-Plot for DetID-{0}, Run {1}, FrameIndex {2}, "
event_info.frame_index, event_info.trigger_counter, "TriggerCounter {3}, Overlays {4}\n{5} UTC".format(
event_info.det_id[0], event_info.run_id[0],
event_info.frame_index[0], event_info.trigger_counter[0],
event_info.overlays[0],
datetime.utcfromtimestamp(event_info.utc_seconds)), datetime.utcfromtimestamp(event_info.utc_seconds)),
fontsize=fontsize, fontsize=fontsize,
y=1.05) y=1.05)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment