Skip to content

Commit

Permalink
Traffic light overview (#62)
Browse files Browse the repository at this point in the history
* Traffic light overview plot

Other changes:
- suppress "matplotlib backend" verbose warning
- click on "popmon report" also scrolls to top
- fix example comment
  • Loading branch information
sbrugman committed Oct 28, 2020
1 parent 0aa004a commit 1f6c45e
Show file tree
Hide file tree
Showing 12 changed files with 337 additions and 56 deletions.
2 changes: 1 addition & 1 deletion README.rst
Expand Up @@ -94,7 +94,7 @@ As a quick example, you can do:
# to show the output of the report in a Jupyter notebook you can simply run:
report
# or save the report to file and open in a browser
# or save the report to file
report.to_file("monitoring_report.html")
To specify your own binning specifications and features you want to report on, you do:
Expand Down
13 changes: 8 additions & 5 deletions popmon/pipeline/report_pipelines.py
Expand Up @@ -29,7 +29,12 @@
metrics_rolling_reference,
metrics_self_reference,
)
from ..visualization import HistogramSection, ReportGenerator, SectionGenerator
from ..visualization import (
HistogramSection,
ReportGenerator,
SectionGenerator,
TrafficLightSectionGenerator,
)


def self_reference(
Expand Down Expand Up @@ -338,10 +343,8 @@ def sg_kws(read_key):
ignore_stat_endswith=["_mean", "_std", "_pull"],
**sg_kws("comparisons"),
),
SectionGenerator(
section_name=traffic_lights_section,
tl_section=True,
**sg_kws("traffic_lights"),
TrafficLightSectionGenerator(
section_name=traffic_lights_section, **sg_kws("traffic_lights")
),
SectionGenerator(section_name=alerts_section, **sg_kws("alerts")),
HistogramSection(
Expand Down
4 changes: 2 additions & 2 deletions popmon/version.py
@@ -1,6 +1,6 @@
"""THIS FILE IS AUTO-GENERATED BY SETUP.PY."""

name = "popmon"
version = "0.3.8"
full_version = "0.3.8"
version = "0.3.9"
full_version = "0.3.9"
release = True
10 changes: 9 additions & 1 deletion popmon/visualization/__init__.py
Expand Up @@ -23,6 +23,9 @@
from popmon.visualization.histogram_section import HistogramSection
from popmon.visualization.report_generator import ReportGenerator
from popmon.visualization.section_generator import SectionGenerator
from popmon.visualization.traffic_light_section_generator import (
TrafficLightSectionGenerator,
)

# set matplotlib backend to batchmode when running in shell
# need to do this *before* matplotlib.pyplot gets imported
Expand All @@ -31,4 +34,9 @@
set_matplotlib_backend()


__all__ = ["SectionGenerator", "HistogramSection", "ReportGenerator"]
__all__ = [
"SectionGenerator",
"HistogramSection",
"ReportGenerator",
"TrafficLightSectionGenerator",
]
9 changes: 5 additions & 4 deletions popmon/visualization/backend.py
Expand Up @@ -107,10 +107,11 @@ def set_matplotlib_backend(backend=None, batch=None, silent=True):
raise RuntimeError(
"Cannot set Matplotlib backend: pyplot module already loaded."
)
else:
logger.warning(
"Cannot set Matplotlib backend: pyplot module already loaded."
)
# Warning is too verbose
# else:
# logger.warning(
# "Cannot set Matplotlib backend: pyplot module already loaded."
# )
return

# set matplotlib backend
Expand Down
47 changes: 10 additions & 37 deletions popmon/visualization/section_generator.py
Expand Up @@ -28,11 +28,11 @@

from ..base import Module
from ..config import get_stat_description
from ..visualization.utils import plot_bars_b64, plot_traffic_lights_b64
from ..visualization.utils import _prune, plot_bars_b64


class SectionGenerator(Module):
"""This module takes the time-series data of already computed statistcs, plots the data and
"""This module takes the time-series data of already computed statistics, plots the data and
combines all the plots into a list which is stored together with the section name in a dictionary
which later will be used for the report generation.
"""
Expand All @@ -55,7 +55,6 @@ def __init__(
skip_empty_plots=True,
description="",
show_stats=None,
tl_section=False,
):
"""Initialize an instance of SectionGenerator.
Expand All @@ -75,7 +74,6 @@ def __init__(
:param bool skip_empty_plots: if false, also show empty plots in report with only nans or zeroes (optional)
:param str description: description of the section. default is empty (optional)
:param list show_stats: list of statistic name patterns to show in the report. If None, show all (optional)
:param bool tl_section: whether to use traffic light plotting or not
"""
super().__init__()
self.read_key = read_key
Expand All @@ -94,7 +92,6 @@ def __init__(
self.skip_empty_plots = skip_empty_plots
self.description = description
self.show_stats = show_stats
self.tl_section = tl_section

def transform(self, datastore):
data_obj = self.get_datastore_object(datastore, self.read_key, dtype=dict)
Expand Down Expand Up @@ -158,7 +155,6 @@ def short_date(date):
self.skip_first_n,
self.skip_last_n,
self.skip_empty_plots,
self.tl_section,
)
for metric in metrics
)
Expand Down Expand Up @@ -196,7 +192,6 @@ def _plot_metric(
skip_first_n,
skip_last_n,
skip_empty,
tl_section,
):
"""Split off plot histogram generation to allow for parallel processing"""
# pick up static traffic light boundaries
Expand All @@ -218,34 +213,12 @@ def _plot_metric(
values = _prune(values, last_n, skip_first_n, skip_last_n)

# make plot. note: slow!
if tl_section:
plot = plot_traffic_lights_b64(
data=np.array(values), labels=dates, skip_empty=skip_empty
)
else:
plot = plot_bars_b64(
data=np.array(values),
labels=dates,
ylim=True,
bounds=bounds,
skip_empty=skip_empty,
)
return dict(name=metric, description=get_stat_description(metric), plot=plot)


def _prune(values, last_n=0, skip_first_n=0, skip_last_n=0):
"""inline function to select first or last items of input list
plot = plot_bars_b64(
data=np.array(values),
labels=dates,
ylim=True,
bounds=bounds,
skip_empty=skip_empty,
)

:param values: input list to select from
:param int last_n: select last 'n' items of values. default is 0.
:param int skip_first_n: skip first n items of values. default is 0. last_n takes precedence.
:param int skip_last_n: in plot skip last 'n' periods. last_n takes precedence (optional)
:return: list of selected values
"""
if last_n > 0:
return values[-last_n:]
if skip_first_n > 0:
values = values[skip_first_n:]
if skip_last_n > 0:
values = values[:-skip_last_n]
return values
return dict(name=metric, description=get_stat_description(metric), plot=plot)
4 changes: 4 additions & 0 deletions popmon/visualization/templates/assets/css/custom-style.css
Expand Up @@ -49,4 +49,8 @@ section h2 {

.feature-select button {
font-weight: 300
}

.card-image-top {
padding-bottom: 7px;
}
7 changes: 5 additions & 2 deletions popmon/visualization/templates/assets/js/custom-script.js
Expand Up @@ -10,18 +10,21 @@ $(document).on("click", "button.dropdown-item", function() {
obj.parent().siblings("button").text("Feature: " + obj.text())
});
// making navigation work: after clicking a nav link scrolling to the corresponding section's position
$(document).on("click", "a.nav-link", function(e) {
$(document).on("click", "a.nav-link,a.navbar-brand", function(e) {
e.preventDefault();
obj = $(this)
$([document.documentElement, document.body]).animate({
scrollTop: $("section[data-section-title='" + obj.attr("data-scroll-to-section") + "']").offset().top
}, 1000);
});
// automatic insertion of navigation links based on section titles
$('section').each(function(){
$('section').each(function(i, el){
title = $(this).attr("data-section-title");
code = '<li class="nav-item"><a class="nav-link js-scroll-trigger" data-scroll-to-section="' + title + '">' + title + '</a></li>'
$("ul#navigation-sections").append(code);
if ( i === 0) {
$("a.navbar-brand").attr('data-scroll-to-section', title);
}
});

$('#myModal').on('shown.bs.modal', function () {
Expand Down
2 changes: 1 addition & 1 deletion popmon/visualization/templates/card.html
@@ -1,4 +1,4 @@
<div class="col-md-6 mb-5">
<div class="col-md-{% if 'full_width' in metric %}12{% else %}6{% endif %} mb-5">
<div class="card shadow-sm">
<div class="card-body" style="text-align: center">
<h4 class="card-title">{{metric.name}}</h4>
Expand Down
2 changes: 1 addition & 1 deletion popmon/visualization/templates/header.html
@@ -1,7 +1,7 @@
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand js-scroll-trigger">POPMON REPORTING</a>
<a class="navbar-brand js-scroll-trigger">POPMON REPORT</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
Expand Down

0 comments on commit 1f6c45e

Please sign in to comment.