Source code for covid19_data_analyzer.dashboard.utils.plot

from typing import Callable, Dict, List, Iterable

import pandas as pd
from plotly.colors import DEFAULT_PLOTLY_COLORS

from covid19_data_analyzer.dashboard.utils.data_loader import (
    DASHBOARD_DATA,
    DASHBOARD_FIT_PLOT_DATA,
)


[docs]def plotly_color_cycler(plot_index: int) -> str: """ Colorcycler on base of the plotly default colors, to ensure that raw data and fits have the same color Parameters ---------- plot_index : int index of the current plot Returns ------- str Color to be used for a plot """ mod_index = plot_index % len(DEFAULT_PLOTLY_COLORS) return DEFAULT_PLOTLY_COLORS[mod_index]
[docs]def generate_figure( data_source: str, parent_regions: Iterable[str], regions: Iterable[str], title: str, y_title: str, data_transform_fuction: Callable = None, subsets: Iterable[str] = ["confirmed"], plot_settings: Iterable[str] = [], fit_model: str = None, ) -> Dict: """ Creates the Figure data for a plot Parameters ---------- data_source : str name of the data source parent_regions : Iterable[str] names of the parent_regions which should be plotted regions : Iterable[str] names of the regions which should be plotted title : str Title of the plot y_title : str caption of the y-axis data_transform_fuction : Callable, optional function which should be applied on the data, by default None subsets : Iterable[str], optional subsets of the data which should be ploted, by default ["confirmed"] plot_settings : Iterable[str], optional settings which should be used for the plot, by default [] fit_model : str, optional name of the fit model which should be used, by default None Returns ------- Dict figure data of the plot """ if data_source and regions: plot_data = [] plot_index = 0 data = DASHBOARD_DATA[data_source] data = data[data.parent_region.isin(parent_regions)] if data_transform_fuction is not None: data = data_transform_fuction(data) if fit_model is not None: fit_plot_data = DASHBOARD_FIT_PLOT_DATA[data_source][fit_model] if data_transform_fuction is not None: fit_plot_data = data_transform_fuction(fit_plot_data) else: fit_plot_data = None for subset in subsets: for region in regions: color = plotly_color_cycler(plot_index) plot_sub_data = generate_plot_sub_data( raw_data=data, region=region, subset=subset, hide_raw_data="hide_raw_data" in plot_settings, color=color, fit_data=fit_plot_data, ) for plot_sub_data_entry in plot_sub_data: plot_data.append(plot_sub_data_entry) plot_index += 1 return { "data": plot_data, "layout": { "title": title, "clickmode": "event+select", "yaxis": { "type": "log" if "log_plot" in plot_settings else "linear", "title": y_title, }, "xaxis": {"title": "Date"}, }, } else: return {"data": [], "layout": {"title": title}}
[docs]def generate_plot_sub_data( raw_data: pd.DataFrame, region: str, subset: str, color: str, hide_raw_data: bool = False, fit_data: pd.DataFrame = None, ) -> List[Dict]: """ Function to generate the data used to plot raw data and/or its fit Parameters ---------- raw_data : pd.DataFrame Actual case data region : str region name of the data, needed to generate the legend subset : str subset name of the data, needed to generate the legend color : str color of the trace, needed so raw data and fits have the same color hide_raw_data : bool, optional Whether or not to hide the raw data, by default False fit_data : pd.DataFrame, optional Data used to plot a fit, by default None Returns ------- List[Dict] List of traces which should be ploted """ plot_sub_data = [] if not hide_raw_data: raw_region_data = raw_data[raw_data.region == region] raw_data_trace = create_trace(raw_region_data, region, subset, color) plot_sub_data.append(raw_data_trace,) if fit_data is not None: fit_region_data = fit_data[fit_data.region == region] if len(fit_region_data) and not fit_region_data[subset].isna().any(): fit_data_trace = create_trace( fit_region_data, region, subset, color, is_fit=True ) plot_sub_data.append(fit_data_trace,) return plot_sub_data
[docs]def create_trace( data: pd.DataFrame, region: str, subset: str, color: str, is_fit: bool = False ) -> Dict: """ Function to generate the Plot trace of a single dataset, with the appropriate style (raw data -> marker, fit -> line) Parameters ---------- data : pd.DataFrame Data which should be plotted region : str region name of the data, needed to generate the legend subset : str subset name of the data, needed to generate the legend color : str color of the trace, needed so raw data and fits have the same color is_fit : bool, optional Whether or not the data are from a fit, by default False Returns ------- Dict Trace data to generate a plot with dash """ name = f"{region} {subset}" if is_fit: mode = "line" name = f"fit {name}" else: mode = "markers" return { "x": data.date, "y": data[subset], "name": name, "mode": mode, "marker": {"size": 8, "color": color}, "line": {"color": color}, "hoverlabel": {"namelength": -1}, }