From 37fcd0e48f4201e1955cd360ce5705a505eeb074 Mon Sep 17 00:00:00 2001 From: Simon Brugman Date: Mon, 4 Jul 2022 20:17:35 +0200 Subject: [PATCH] feat: configurable title and colors The report title, primary color and traffic light colors are now configurable. Co-authored-by: pradyot-09 --- examples/flight_delays.py | 1 + examples/synthetic_data.py | 10 ++- popmon/config.py | 14 +++- .../visualization/alert_section_generator.py | 2 + popmon/visualization/histogram_section.py | 6 +- popmon/visualization/report_generator.py | 4 ++ popmon/visualization/section_generator.py | 16 +++-- .../templates/aggregated-overview.html | 16 ++--- .../templates/assets/css/custom-style.css | 11 +++- .../templates/assets/js/custom-script.js | 3 +- popmon/visualization/templates/core.html | 2 +- popmon/visualization/templates/header.html | 9 ++- .../visualization/templates/modal-popup.html | 5 +- popmon/visualization/templates/section.html | 56 ++++++++-------- popmon/visualization/templates/table.html | 64 +++++++++---------- .../traffic_light_section_generator.py | 8 ++- 16 files changed, 130 insertions(+), 97 deletions(-) diff --git a/examples/flight_delays.py b/examples/flight_delays.py index 59cc79b2..521f9b26 100644 --- a/examples/flight_delays.py +++ b/examples/flight_delays.py @@ -12,6 +12,7 @@ # Configuration of the monitoring rules and report settings = Settings(time_axis="DATE", reference_type="self") settings.report.extended_report = False +settings.report.title += " | Flight Delays Dataset" settings.monitoring.pull_rules = {"*_pull": [10, 7, -7, -10]} # generate stability report using automatic binning of all encountered features diff --git a/examples/synthetic_data.py b/examples/synthetic_data.py index 9e006701..5a6977d0 100644 --- a/examples/synthetic_data.py +++ b/examples/synthetic_data.py @@ -1,17 +1,23 @@ import pandas as pd import popmon # noqa -from popmon import resources +from popmon import Settings, resources # open synthetic data df = pd.read_csv(resources.data("test.csv.gz"), parse_dates=["date"]) +# report configuration +settings = Settings( + features=["date:age", "date:gender", "date:isActive", "date:eyeColor"] +) +settings.report.title += " | Synthetic Dataset" + # generate stability report using automatic binning of all encountered features # (importing popmon automatically adds this functionality to a dataframe) report = df.pm_stability_report( time_axis="date", time_width="2w", - features=["date:age", "date:gender", "date:isActive", "date:eyeColor"], + settings=settings, ) # or save the report to file diff --git a/popmon/config.py b/popmon/config.py index d40ee232..12023325 100644 --- a/popmon/config.py +++ b/popmon/config.py @@ -149,6 +149,9 @@ class Section(BaseModel): class Report(BaseModel): """Report-specific configuration""" + title = "POPMON Report" + """Report title in browser and navbar. May contain HTML.""" + skip_empty_plots: bool = True """if false, also show empty plots in report with only nans or zeroes (optional)""" @@ -194,8 +197,15 @@ class Report(BaseModel): ] """list of statistic name patterns to show in the report. If None, show all (optional)""" - zline_color: List[str] = ["#FF0000", "#FFC800"] - """"Configure line colors in barplots of Comparisons and Profiles section. First and second elements as hex color code in list will replace the default red and yellow respectively""" + primary_color = "#000080" + """Primary color used throughout the report""" + + tl_colors: Dict[str, str] = { + "green": "#008000", + "yellow": "#FFC800", + "red": "#FF0000", + } + """"Configure line colors in barplots of Comparisons and Profiles section. Need to be hex format (full length)""" section: Section = Section() """Configuration for the individual sections""" diff --git a/popmon/visualization/alert_section_generator.py b/popmon/visualization/alert_section_generator.py index ff8a5b85..7b5e17a5 100644 --- a/popmon/visualization/alert_section_generator.py +++ b/popmon/visualization/alert_section_generator.py @@ -84,6 +84,7 @@ def __init__( self.section_name = settings.section.alerts.name self.description = settings.section.alerts.description self.descriptions = settings.section.alerts.descriptions + self.tl_colors = settings.tl_colors def get_description(self): return self.section_name @@ -141,6 +142,7 @@ def transform( 0, 0, 0, + self.tl_colors, style="alerts", ) ] diff --git a/popmon/visualization/histogram_section.py b/popmon/visualization/histogram_section.py index 7457d6b4..624a4863 100644 --- a/popmon/visualization/histogram_section.py +++ b/popmon/visualization/histogram_section.py @@ -33,7 +33,7 @@ from ..base import Module from ..config import HistogramSectionModel from ..utils import parallel, short_date -from ..visualization.utils import plot_heatmap_b64, plot_overlay_1d_histogram_b64 +from ..visualization.utils import plot_heatmap, plot_histogram_overlay class HistogramSection(Module): @@ -242,7 +242,7 @@ def _plot_histograms(feature, date, hc_list, hist_names, top_n, max_nbins=1000): entries_list = np.reshape(entries_list.ravel(), (-1, len(bins))) hists = [(el, bins) for el in entries_list] - plot = plot_overlay_1d_histogram_b64( + plot = plot_histogram_overlay( hists, feature, hist_names, y_label, is_num, is_ts ) elif hc_list[0].n_dim == 2: @@ -338,7 +338,7 @@ def _plot_heatmap( (hist, bins, date, feature, hist_name, y_label, is_num, is_ts, cmap) for hist, hist_name in zip(hists, hist_names) ] - heatmaps = parallel(plot_heatmap_b64, args) + heatmaps = parallel(plot_heatmap, args) if isinstance(heatmaps, list): plot = [hist_lookup(heatmaps, hist_name) for hist_name in hist_names] diff --git a/popmon/visualization/report_generator.py b/popmon/visualization/report_generator.py index 2d571e38..a31a0e7e 100644 --- a/popmon/visualization/report_generator.py +++ b/popmon/visualization/report_generator.py @@ -44,7 +44,9 @@ def __init__(self, read_key, store_key, settings: Report): super().__init__() self.read_key = read_key self.store_key = store_key + self.title = settings.title self.online_report = settings.online_report + self.tl_colors = settings.tl_colors def get_description(self): return "HTML Report" @@ -64,5 +66,7 @@ def transform(self, sections: list) -> str: generator=f"popmon {version}", sections=sections_html, online_report=self.online_report, + title=self.title, + **self.tl_colors, ) ) diff --git a/popmon/visualization/section_generator.py b/popmon/visualization/section_generator.py index 38eb4010..485d65a4 100644 --- a/popmon/visualization/section_generator.py +++ b/popmon/visualization/section_generator.py @@ -30,7 +30,7 @@ from ..base import Module from ..config import Report from ..utils import filter_metrics, parallel, short_date -from ..visualization.utils import _prune, plot_bars_b64 +from ..visualization.utils import _prune, plot_bars profiles = Profiles.get_descriptions() @@ -117,7 +117,6 @@ def __init__( self.last_n = settings.last_n self.skip_first_n = settings.skip_first_n self.skip_last_n = settings.skip_last_n - self.zline_color = settings.zline_color self.prefix = prefix self.suffices = suffices self.ignore_stat_endswith = ignore_stat_endswith or [] @@ -125,6 +124,9 @@ def __init__( self.description = description self.show_stats = settings.show_stats if not settings.extended_report else None + self.primary_color = settings.primary_color + self.tl_colors = settings.tl_colors + def get_description(self): return self.section_name @@ -181,7 +183,8 @@ def transform( self.skip_first_n, self.skip_last_n, self.skip_empty_plots, - self.zline_color, + self.primary_color, + self.tl_colors, ) for metric in metrics ] @@ -230,6 +233,7 @@ def _plot_metric( skip_first_n, skip_last_n, skip_empty, + primary_color, zline_color, ): """Split off plot histogram generation to allow for parallel processing""" @@ -251,13 +255,15 @@ def _plot_metric( values = _prune(values, last_n, skip_first_n, skip_last_n) # make plot. note: slow! - plot = plot_bars_b64( + plot = plot_bars( data=values, labels=dates, ylim=True, bounds=bounds, skip_empty=skip_empty, - zline_color=zline_color, + primary_color=primary_color, + tl_colors=zline_color, + metric=metric, ) if not isinstance(plot, dict): diff --git a/popmon/visualization/templates/aggregated-overview.html b/popmon/visualization/templates/aggregated-overview.html index 9ffc73f6..aa690379 100644 --- a/popmon/visualization/templates/aggregated-overview.html +++ b/popmon/visualization/templates/aggregated-overview.html @@ -1,20 +1,20 @@ - {% for feature, vals in values.items() %} + {%- for feature, vals in values.items() -%} - {% endfor %} + {%- endfor -%}
{{ feature }}
- {% for i in [2, 1, 0] %} - {% if vals[i] > 0 %} -
+ {%- for i in [2, 1, 0] -%} + {%- if vals[i] > 0 -%} +
{{ vals[i] }} ({{ "%d" % (vals[i] / (vals["total"] * 0.01))}}%)
- {% else %} + {%- else -%}
 
- {% endif %} - {% endfor %} + {%- endif -%} + {%- endfor -%}
\ No newline at end of file diff --git a/popmon/visualization/templates/assets/css/custom-style.css b/popmon/visualization/templates/assets/css/custom-style.css index 4fd58e89..2dab39c0 100644 --- a/popmon/visualization/templates/assets/css/custom-style.css +++ b/popmon/visualization/templates/assets/css/custom-style.css @@ -94,13 +94,13 @@ table.overview tbody td:not(.metric){ text-align: center; } .g{ - background: green; + background: {{ green }}; } .y{ - background: rgba(255, 200, 0, 1.0); + background: {{ yellow }}; } .r{ - background: rgba(255, 0, 0, 1.0); + background: {{ red }}; } table.overview tfoot td { padding-top: 5px; @@ -131,3 +131,8 @@ table.overview tfoot td span{ display: flex; width: 100%; } + +#settings-btn{ + background-color: transparent; + border-color: #666; +} \ No newline at end of file diff --git a/popmon/visualization/templates/assets/js/custom-script.js b/popmon/visualization/templates/assets/js/custom-script.js index a91108c7..28afc936 100644 --- a/popmon/visualization/templates/assets/js/custom-script.js +++ b/popmon/visualization/templates/assets/js/custom-script.js @@ -16,7 +16,7 @@ $(document).on("click", "button.dropdown-item", function() { var type = window.location.hash.substr(1); if (type.length > 0){ // Find link to that section - var o = $("a.nav-link.js-scroll-trigger[href='#" + type +"'"); + var o = $("a.nav-link.js-scroll-trigger[href='#" + type +"'" ); // If exists if (o.length == 1){ @@ -34,7 +34,6 @@ $(document).on("click", "a.table-item", function(){ // making navigation work: after clicking a nav link scrolling to the corresponding section's position $(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 diff --git a/popmon/visualization/templates/core.html b/popmon/visualization/templates/core.html index 802b53f4..6843aecc 100644 --- a/popmon/visualization/templates/core.html +++ b/popmon/visualization/templates/core.html @@ -8,7 +8,7 @@ - POPMON Report + {{ title | striptags }} {%- if online_report %} diff --git a/popmon/visualization/templates/header.html b/popmon/visualization/templates/header.html index 50d85a31..defc502f 100644 --- a/popmon/visualization/templates/header.html +++ b/popmon/visualization/templates/header.html @@ -1,15 +1,14 @@ - - diff --git a/popmon/visualization/templates/modal-popup.html b/popmon/visualization/templates/modal-popup.html index 7e46bef3..d9845d9a 100644 --- a/popmon/visualization/templates/modal-popup.html +++ b/popmon/visualization/templates/modal-popup.html @@ -1,9 +1,8 @@ - -