9 Commits

8 changed files with 96 additions and 34 deletions

View File

@@ -1,6 +1,6 @@
# survBot
version: 0.1
version: 0.2
survBot is a small program used to track station quality channels of DSEBRA stations via PowBox output over SOH channels
by analysing contents of a Seiscomp3 datapath.
@@ -40,8 +40,16 @@ The GUI can be loaded via
python survBotGui.py
```
## Version Changes
- surveillance of mass, clock and gaps
- individual mailing lists for different stations
- html mail with recent status information
- updated web page design
- restructured parameter file
- recognize if PBox is disconnected
## Staff
Original author: M.Paffrath (marcel.paffrath@rub.de)
November 2022
June 2023

View File

@@ -0,0 +1,3 @@
# survBot is a small program used to track station quality channels of DSEBRA stations via PowBox output
# over SOH channels by analysing contents of a Seiscomp3 datapath.
__version__ = "0.2"

View File

@@ -128,7 +128,7 @@ add_global_links:
- {"text": "show recent events on map",
"URL": "https://fdsnws.geophysik.ruhr-uni-bochum.de/map/?lat=39.5&lon=21&zoom=7&baselayer=mapnik"}
# html logo at page bottom
# html logo at page bottom (path relative to html directory)
html_logo: "figures/Logo_RUB_BLAU_rgb.png"
# E-mail notifications

View File

@@ -3,27 +3,35 @@ body {
place-items: center;
text-align: center;
padding-bottom: 30px;
font-family: "Helvetica", "sans-serif";
}
table {
position: relative
}
td {
border-radius: 4px;
border-radius: 2px;
padding: 0px;
white-space: nowrap;
}
th {
background-color: #999;
border-radius: 4px;
color: #fff;
border-radius: 2px;
padding: 3px 1px;
position: sticky;
top: 0;
}
a:link, a:visited {
background-color: #ccc;
background-color: #e8e8e8;
color: #000;
text-decoration: none;
display: block;
border-radius: 4px;
border: 1px solid #bbb;
border: 1px solid #ccc;
}
a:hover {

View File

@@ -3,27 +3,35 @@ body {
place-items: center;
text-align: center;
padding-bottom: 30px;
font-family: "Helvetica", "sans-serif";
}
table {
position: relative
}
td {
border-radius: 4px;
border-radius: 3px;
padding: 10px 2px;
white-space: nowrap;
}
th {
background-color: #999;
border-radius: 4px;
color: #fff;
border-radius: 3px;
padding: 10px, 2px;
position: sticky;
top: 0;
}
a:link {
background-color: #ccc;
a:link, a:visited {
background-color: #e8e8e8;
color: #000;
text-decoration: none;
display: block;
border-radius: 4px;
border: 1px solid #bbb;
border-radius: 6px;
border: 1px solid #ccc;
}
a:hover {
@@ -39,9 +47,9 @@ a:hover {
animation: blinkingBackground 2s infinite;
}
@keyframes blinkingBackground{
0% { background-color: #ffee00;}
0% { background-color: #ffcc00;}
50% { background-color: #ff3200;}
100% { background-color: #ffee00;}
100% { background-color: #ffcc00;}
}
.footer {

View File

@@ -22,7 +22,7 @@ from obspy.clients.filesystem.sds import Client
from write_utils import get_html_text, get_html_link, get_html_row, html_footer, get_html_header, get_print_title_str, \
init_html_table, finish_html_table, get_mail_html_header, add_html_image
from utils import get_bg_color, modify_stream_for_plot, set_axis_yticks, set_axis_color, plot_axis_thresholds
from utils import get_bg_color, get_font_color, modify_stream_for_plot, set_axis_yticks, set_axis_color, plot_axis_thresholds
try:
import smtplib
@@ -441,7 +441,7 @@ class SurveillanceBot(object):
fig_name = self.get_fig_path_rel(nwst_id)
nwst_id_str = nwst_id.rstrip('.')
col_items = [dict(text=nwst_id_str, color=default_color, hyperlink=fig_name if hyperlinks else None,
bold=True, tooltip=f'Show plot of {nwst_id_str}')]
bold=True, tooltip=f'Show plot of {nwst_id_str}', font_color='#000000')]
for check_key in header:
if check_key in self.keys:
@@ -453,6 +453,7 @@ class SurveillanceBot(object):
bg_color = get_bg_color(check_key, status, dt_thresh, hex=True)
if not bg_color:
bg_color = default_color
font_color = get_font_color(bg_color, hex=True)
# add degree sign for temp
if check_key == 'temp':
@@ -461,7 +462,7 @@ class SurveillanceBot(object):
html_class = self.get_html_class(hide_keys_mobile, status=status, check_key=check_key)
item = dict(text=str(message), tooltip=str(detailed_message), color=bg_color,
html_class=html_class)
html_class=html_class, font_color=font_color)
elif check_key in self.add_links:
value = self.add_links.get(check_key).get('URL')
link_text = self.add_links.get(check_key).get('text')
@@ -503,12 +504,21 @@ class SurveillanceBot(object):
outfile.write(finish_html_table())
# add optional links below html table
for dct in self.add_global_links:
link_str = get_html_link(dct.get('text'), dct.get('URL'))
outfile.write(get_html_text(link_str))
# add status message
outfile.write(get_html_text(self.status_message))
outfile.write(html_footer(footer_logo=self.parameters.get('html_logo')))
# write footer with optional logo
logo_file = self.parameters.get('html_logo')
if not os.path.isfile(pjoin(self.outpath_html, logo_file)):
print(f'Specified file {logo_file} not found.')
logo_file = None
outfile.write(html_footer(footer_logo=logo_file))
except Exception as e:
print(f'Could not write HTML table to {fnout}:')

View File

@@ -34,13 +34,19 @@ def get_bg_color(check_key, status, dt_thresh=None, hex=False):
def get_color(key):
# some GUI default colors
colors_dict = {'FAIL': (255, 50, 0, 255),
# some old GUI default colors
# colors_dict = {'FAIL': (255, 85, 50, 255),
# 'NO DATA': (255, 255, 125, 255),
# 'WARN': (255, 255, 80, 255),
# 'OK': (173, 255, 133, 255),
# 'undefined': (230, 230, 230, 255),
# 'disc': (255, 160, 40, 255),}
colors_dict = {'FAIL': (195, 29, 14, 255),
'NO DATA': (255, 255, 125, 255),
'WARN': (255, 255, 80, 255),
'OK': (125, 255, 125, 255),
'undefined': (230, 230, 230, 255),
'disc': (255, 160, 40, 255),}
'WARN': (250, 192, 63, 255),
'OK': (185, 245, 145, 255),
'undefined': (240, 240, 240, 255),
'disc': (126, 127, 131, 255), }
return colors_dict.get(key)
@@ -59,9 +65,11 @@ def get_time_delay_color(dt, dt_thresh):
return get_color('FAIL')
def get_warn_color(count):
color = (min([255, 200 + count ** 2]), 255, 80, 255)
return color
def get_warn_color(count, n_colors=20):
if count >= n_colors:
count = -1
gradient = np.linspace((240, 245, 110, 255), (250, 192, 63, 255), n_colors, dtype=int)
return tuple(gradient[count])
def get_mass_color(message):
@@ -81,6 +89,24 @@ def get_temp_color(temp, vmin=-10, vmax=60, cmap='coolwarm'):
return rgba
def get_font_color(bg_color, hex=False):
if hex:
bg_color = matplotlib.colors.to_rgb(bg_color)
bg_color_hsv = matplotlib.colors.rgb_to_hsv(bg_color)
bg_color_hsl = hsv_to_hsl(bg_color_hsv)
font_color = (255, 255, 255, 255) if bg_color_hsl[2] < 0.6 else (0, 0, 0, 255)
if hex:
font_color = '#{:02x}{:02x}{:02x}'.format(*font_color[:3])
return font_color
def hsv_to_hsl(hsv):
hue, saturation, value = hsv
lightness = value * (1 - saturation / 2)
saturation = 0 if lightness in (0, 1) else (value - lightness) / min(lightness, 1 - lightness)
return hue, saturation, lightness
def modify_stream_for_plot(input_stream, parameters):
""" copy (if necessary) and modify stream for plotting """
@@ -219,4 +245,4 @@ def plot_threshold_lines(fig, channel_threshold_list, parameters, **kwargs):
if isinstance(warn_thresh, str):
warn_thresh = parameters.get('THRESHOLDS').get(warn_thresh)
if type(warn_thresh in (float, int)):
ax.axhline(warn_thresh, **kwargs)
ax.axhline(warn_thresh, **kwargs)

View File

@@ -79,15 +79,14 @@ def get_html_row(items, html_key='td'):
if item.get('italic'):
text = '<i>' + text + '</i>'
tooltip = item.get('tooltip')
color = item.get('color')
# check for black background of headers (shouldnt happen anymore)
color = '#e6e6e6' if color == '#000000' else color
font_color = item.get('font_color')
hyperlink = item.get('hyperlink')
color = 'transparent' if hyperlink else item.get('color')
text_str = get_html_link(text, hyperlink) if hyperlink else text
html_class = item.get('html_class')
class_str = f' class="{html_class}"' if html_class else ''
row_string += 2 * default_space + f'<{html_key}{class_str} bgcolor="{color}" title="{tooltip}"> {text_str}'\
+ f'</{html_key}>\n'
row_string += 2 * default_space + f'<{html_key}{class_str} bgcolor="{color}" title="{tooltip}"' \
+ f'style="color:{font_color}"> {text_str}</{html_key}>\n'
row_string += default_space + '</tr>\n'
return row_string