Newer
Older
from os.path import basename, join, exists, splitext, getsize
import toml
from flask import render_template, send_from_directory, request, Response
PLOTS = [['dom_activity', 'dom_rates'], 'pmt_rates_du*', ['trigger_rates'],
['ztplot', 'triggermap']]
AHRS_PLOTS = ['yaw_calib_du*', 'pitch_calib_du*', 'roll_calib_du*']
RECO_PLOTS = [['track_reco', 'ztplot_roy'], ['time_residuals']]
COMPACT_PLOTS = [['dom_activity', 'dom_rates', 'pmt_rates'],
SN_PLOTS = [['sn_bg_histogram', 'sn_pk_history']]
RASP_PLOTS = [['dom_rates', 'ztplot', 'triggermap'],
[
'pmt_rates_du2', 'pmt_rates_du3', 'pmt_rates_du4',
'pmt_rates_du5'
], ['trigger_rates', 'trigger_rates_lin']]
if exists(CONFIG_PATH):
config = toml.load(CONFIG_PATH)
if "WebServer" in config:
print("Reading authentication information from '%s'" % CONFIG_PATH)
USERNAME = config["WebServer"]["username"]
PASSWORD = config["WebServer"]["password"]
def expand_wildcards(plot_layout):
"""Replace wildcard entries with list of files"""
plots = []
if not isinstance(row, list) and '*' in row:
plots.append(
sorted([
splitext(basename(p))[0]
for p in glob(join(app.root_path, PLOTS_PATH, row))
]))
else:
plots.append(row)
return plots
def check_auth(username, password):
"""This function is called to check if a username /
password combination is valid.
"""
if USERNAME is not None and PASSWORD is not None:
return username == USERNAME and password == PASSWORD
else:
return True
def authenticate():
"""Sends a 401 response that enables basic auth"""
return Response(
'Could not verify your access level for that URL.\n'
'You have to login with proper credentials', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'})
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated
@app.after_request
def add_header(r):
"""
Disable caches.
"""
r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
r.headers["Pragma"] = "no-cache"
r.headers["Expires"] = "0"
r.headers["Cache-Control"] = "public, max-age=0"
return r
return render_template('plots.html', plots=expand_wildcards(PLOTS))
@app.route('/plot_<plot>.html')
@requires_auth
def single_plot(plot):
return render_template('plot.html', plot=plot)
return render_template('plots.html', plots=expand_wildcards(AHRS_PLOTS))
return render_template('plots.html', plots=expand_wildcards(RECO_PLOTS))
return render_template('plots.html', plots=expand_wildcards(SN_PLOTS))
@app.route('/compact.html')
@requires_auth
def compact():
return render_template('plots.html', plots=expand_wildcards(COMPACT_PLOTS))
plots=expand_wildcards(RTTC_PLOTS),
info=
"Cable Round Trip Time calculated from realtime data provided by the "
"Detector Manager. The red lines shows the median and the STD "
"RTTC = Cable_RTT - (TX_Slave + RX_Slave + TX_Master + RX_Master)")
# @app.route('/k40.html')
# @requires_auth
# def k40():
# return render_template(
# 'plots.html',
# plots=expand_wildcards(K40_PLOTS),
# info="The first plot shows the intra-DOM calibration. "
# "y-axis: delta_t [ns], x-axis: cosine of angles. "
# "The second plot the angular distribution of K40 rates. "
# "y-axis: rate [Hz], x-axis: cosine of angles. "
# "blue=before, red=after")
return render_template('plots.html', plots=expand_wildcards(TRIGGER_PLOTS))
@app.route('/top10.html')
@requires_auth
def top10():
category_names = {
'n_hits': 'Number of hits',
'overlays': 'Number of overlays'
}
dbs = LocalDBService(filename="data/monitoring.sqlite3")
for category in ["overlays", "n_hits"]:
"SELECT plot_filename, n_hits, n_triggered_hits, overlays, "
"det_id, run_id, frame_index, trigger_counter, utc_timestamp "
"FROM event_selection ORDER BY {cat} DESC LIMIT 10".format(
cat=category))
top10[category_names[category]] = [{
"plot_filename": r[0],
"Number of hits (triggered)": "{} ({})".format(r[1], r[2]),
"Overlays": r[3],
"Detector ID": r[4],
"Run": r[5],
"Frame index": r[6],
"Trigger counter": r[7],
return render_template('top10.html', top10=top10)
@app.route('/logs.html')
@requires_auth
def logs():
filenames = sorted(glob(join(app.root_path, LOGS_PATH, "MSG*.log")),
reverse=True)
main_log = filenames.pop(-1)
for filename in [main_log] + filenames:
files[basename(filename)] = getsize(filename)
return render_template('logs.html', files=files)
@app.route('/logs/<path:filename>')
@requires_auth
def custom_static_logfile(filename):
filepath = join(app.root_path, LOGS_PATH)
print("Serving: {}/{}".format(filepath, filename))
return send_from_directory(join(app.root_path, LOGS_PATH), filename)
# filepath = join(app.root_path, PLOTS_PATH)
# print("Serving: {}/{}".format(filepath, filename))
return send_from_directory(join(app.root_path, PLOTS_PATH), filename)