Source code for visualization_toolkit.helpers.plotly.theme

from copy import deepcopy
from collections.abc import Mapping

from plotly import graph_objects as go


def merge_themes(theme_1: dict, theme_2: dict) -> dict:
    """
    Recursively merges theme_2 into theme_1.
    """
    merged = deepcopy(
        theme_1
    )  # Start with a copy of theme_1 to avoid modifying original

    for key, value in theme_2.items():
        if (
            key in merged
            and isinstance(merged[key], Mapping)
            and isinstance(value, Mapping)
        ):
            # Recursively merge dictionaries
            merged[key] = merge_themes(merged[key], value)
        else:
            # Overwrite or add new key-value pairs
            merged[key] = value

    return merged


# Creating color object based on Material Specs for each of our company colors
# https://m2.material.io/design/color/the-color-system.html#tools-for-picking-colors
[docs] COLORS = { # Dark Blue in Ernie "brand-blue": { "default": "#0d4753", 900: "#00323c", 800: "#0d4753", 700: "#1c5b67", 600: "#2b6f7d", 500: "#377e8d", 400: "#5591a0", 300: "#70a6b3", 200: "#93c1cc", 100: "#b4dce4", 50: "#d4f3fe", }, "light-blue": { "default": "#abd0d9", 900: "#002c58", 800: "#004775", 700: "#005786", 600: "#006796", 500: "#0072a1", 400: "#0084aa", 300: "#2896b2", 200: "#70b2c4", 100: "#abd0d9", 50: "#ddecf0", }, # Orange in Ernie "accent": { "default": "#f48d5c", 900: "#b23d00", 800: "#ca4a00", 700: "#d85200", 600: "#e55904", 500: "#f05f09", 400: "#f27437", 300: "#f48d5c", 200: "#f7ac8b", 100: "#faccb8", 50: "#fae9e6", }, "green": { "default": "#288b6f", 900: "#144f38", 800: "#1d6b52", 700: "#237b60", 600: "#288b6f", 500: "#2c987b", 400: "#3ea88d", 300: "#5bb8a0", 200: "#87ccba", 100: "#b6e0d5", 50: "#e1f2ef", }, "yellow": { "default": "#f4bb01", 900: "#f46c00", 800: "#f48b00", 700: "#f49b00", 600: "#f4ae00", 500: "#f4bb01", 400: "#f5c525", 300: "#f7d14d", 200: "#f9dd80", 100: "#fbeab2", 50: "#fdf7e1", }, "red": { "default": "#e9514e", 900: "#b11a1b", 800: "#c02626", 700: "#cd2d2d", 600: "#de3633", 500: "#ed4034", 400: "#e9514e", 300: "#e07171", 200: "#eb9898", 100: "#fdccd1", 50: "#feebed", }, "medium-blue": { "default": "#19889F", 900: "#0a6672", 800: "#19889F", 700: "#209db8", 600: "#209db8", 500: "#2fc2e7", 400: "#3bcbed", 300: "#59d4f3", 200: "#87e1f8", 100: "#b6edfb", 50: "#e2f8fe", }, "light-orange": { "default": "#f8bca0", 900: "#8f0400", 800: "#a61800", 700: "#b32100", 600: "#bf2800", 500: "#c82e00", 400: "#d24d00", 300: "#dc6a2f", 200: "#eb9267", 100: "#f8bca0", 50: "#fbe2dc", }, "light-green": { "default": "#61d1b1", 900: "#005129", 800: "#006d44", 700: "#007e51", 600: "#008e60", 500: "#009b6c", 400: "#00ac7f", 300: "#00bc93", 200: "#61d1b1", 100: "#a4e3d0", 50: "#daf4ed", }, "light-yellow": { "default": "#fedd71", 900: "#ff6500", 800: "#ff8700", 700: "#fe9900", 600: "#fdad00", 500: "#fbbb00", 400: "#fcc500", 300: "#fdd132", 200: "#fedd71", 100: "#ffeaaa", 50: "#fff7dd", }, "light-red": { "default": "#ef8280", 900: "#c5362b", 800: "#d44037", 700: "#e1473e", 600: "#f45145", 500: "#ff5845", 400: "#fb665f", 300: "#ef8280", 200: "#f6a4a4", 100: "#ffd3d8", 50: "#ffeef0", }, "ultra-light-blue": { "default": "#daeff2", 900: "#003136", 800: "#00515d", 700: "#006374", 600: "#00768b", 500: "#00839b", 400: "#0093a8", 300: "#00a3b6", 200: "#62bdca", 100: "#a2d7df", 50: "#daeff2", }, "black": { "default": "#000000", 900: "#000000", 800: "#262626", 700: "#434343", 600: "#555555", 500: "#7b7b7b", 400: "#9d9d9d", 300: "#c4c4c4", 200: "#d9d9d9", 100: "#e9e9e9", 50: "#f5f5f5", }, # Gray in Ernie "light-grey": { "default": "#999999", 900: "#1d1d1d", 800: "#3e3e3e", 700: "#5d5d5d", 600: "#707070", 500: "#999999", 400: "#b8b8b8", 300: "#dcdcdc", 200: "#ebebeb", 100: "#f3f3f3", 50: "#f9f9f9", }, # Not in Ernie but in our company colors "blue": { "default": "#1788b0", 900: "#0a577c", 800: "#16769d", 700: "#1788b0", 600: "#239ac2", 500: "#2ca7cf", 400: "#43b4d4", 300: "#5ec1d8", 200: "#86d2e3", 100: "#b4e4ed", 50: "#e1f5f8", }, "dark-grey": { "default": "#444444", 900: "#232323", 800: "#444444", 700: "#636363", 600: "#777777", 500: "#a0a0a0", 400: "#bfbfbf", 300: "#e2e2e2", 200: "#efefef", 100: "#f5f5f5", 50: "#fafafa", }, }
""" Standard colors used in Plotly chart components. """ COLORS["gray"] = deepcopy(COLORS["light-grey"]) COLORS["orange"] = deepcopy(COLORS["accent"]) COLORS["dark-blue"] = deepcopy(COLORS["brand-blue"]) POSITIVE_COLORSCALE = [ [0.0, "#ffffff"], [0.1, "#dcf5f9"], [0.2, "#b8eaf4"], [0.3, "#95e0ee"], [0.4, "#72d5e9"], [0.5, "#2bc0de"], [0.6, "#1ea7c2"], [0.7, "#19889f"], [0.8, "#19889f"], [0.9, "#136a7c"], [1.0, "#0d4753"], ] NEGATIVE_COLORSCALE = [ [1.0, "#ffffff"], [0.9, "#FBE4E4"], [0.8, "#f8c9c9"], [0.7, "#f4a6a4"], [0.6, "#ef8280"], [0.5, "#e9514e"], [0.4, "#e63a37"], [0.3, "#da1e1b"], [0.2, "#b61916"], [0.1, "#911412"], [0.0, "#6d0f0d"], ] POSITIVE_AND_NEGATIVE_COLORSCALE = [ [1.0, "#0d4753"], [0.9, "#19889f"], [0.8, "#2bc0de"], [0.7, "#95e0ee"], [0.6, "#dcf5f9"], [0.5, "#ffffff"], [0.4, "#f8c9c9"], [0.3, "#ef8280"], [0.2, "#e63a37"], [0.1, "#b61916"], [0.0, "#6d0f0d"], ] DEFAULT_COLORS = [ COLORS[scale]["default"] for scale in [ "dark-blue", "light-blue", "orange", "green", "yellow", "red", "medium-blue", "light-orange", "light-green", "light-yellow", "light-red", "ultra-light-blue", "black", "gray", ] ] TRANSPARENT = "rgba(255,255,255,0)" WHITE = "rgba(255,255,255,1)" BACKGROUND_SECONDARY = "#F5F5F5" TITLE_TO_AXIS_MARGIN = 24 MARGIN_TOP = 64 MARGIN_BOTTOM = 80 MARGIN_RIGHT = 64 MARGIN_LEFT = 64 FONT_URLS = [ "https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" ] FONT_FAMILY = "Roboto,system-ui,sans-serif" TICK_FORMAT_WHOLE_NUMBER = "," TICK_FORMAT_DECIMAL_NUMBER = ",.2f" FONT_COLOR = COLORS["dark-grey"]["default"] LEGEND_FONT_COLOR = COLORS["dark-grey"]["default"] ANNOTATION_FONT_COLOR = COLORS["dark-grey"]["default"] AXIS_FONT_COLOR = COLORS["dark-grey"][500] FONT_SIZE = 16 TITLE_FONT_SIZE = 18 LEGEND_FONT_SIZE = 16 ANNOTATION_FONT_SIZE = 16 SERIES_LINE_WIDTH = 3 BACKGROUND_COLOR = TRANSPARENT LEGEND_BORDER_COLOR = TRANSPARENT AXIS_COLOR = COLORS["light-grey"]["default"] AXIS_GRID_COLOR = COLORS["light-grey"][100] AXIS_LINE_COLOR = COLORS["light-grey"][200] AXIS_ZERO_LINE_COLOR = COLORS["dark-grey"][400] ANNOTATION_LINE_COLOR = COLORS["dark-grey"]["default"] HOVER_LABEL_BACKGROUND_COLOR = "rgba(255, 255, 255, 0.9)" ANNOTATION_LINE_WIDTH = 1 SHADE_DEFAULT_COLOR = COLORS["light-grey"]["default"] SHADE_OPACITY = 0.15 SHADE_LINE_WIDTH = 0 LEGEND_ORIENTATION = "h" LEGEND_X_POSITION = 0.5 LEGEND_X_ANCHOR = "center" LEGEND_Y_POSITION = 0 LEGEND_MEDIUM_Y_POSITION = 0 # Use if legend has multiple series LEGEND_LARGE_Y_POSITION = 0 # Use if legend + x-axis title is visible LEGEND_Y_ANCHOR = "bottom" CHART_LOGO_X_POSITION = 1.07875 CHART_LOGO_MEDIUM_X_POSITION = 1.1125 CHART_LOGO_X_SIZE = 0.15 CHART_LOGO_Y_SIZE = 0.15 # Properties here: https://plotly.com/python/reference/layout/
[docs] YD_CLASSIC_THEME_CONFIG = dict( height=610, title={ "font": { "size": TITLE_FONT_SIZE, } }, font={ "family": FONT_FAMILY, "color": FONT_COLOR, "size": FONT_SIZE, }, separators=".,", paper_bgcolor=BACKGROUND_COLOR, plot_bgcolor=BACKGROUND_COLOR, colorway=DEFAULT_COLORS, legend={ "bordercolor": LEGEND_BORDER_COLOR, "font": { "family": FONT_FAMILY, "color": LEGEND_FONT_COLOR, "size": LEGEND_FONT_SIZE, }, "orientation": LEGEND_ORIENTATION, "x": LEGEND_X_POSITION, "y": LEGEND_Y_POSITION, "xref": "container", "yref": "container", "xanchor": LEGEND_X_ANCHOR, "yanchor": LEGEND_Y_ANCHOR, "title": { "font": { "family": FONT_FAMILY, "color": LEGEND_FONT_COLOR, "size": LEGEND_FONT_SIZE, }, "side": "top", "text": "", }, "grouptitlefont": { "family": FONT_FAMILY, "color": LEGEND_FONT_COLOR, "size": LEGEND_FONT_SIZE, }, }, xaxis={ "color": AXIS_COLOR, "gridcolor": AXIS_GRID_COLOR, "tickfont": { "family": FONT_FAMILY, "size": LEGEND_FONT_SIZE, "color": LEGEND_FONT_COLOR, }, "title": { "font": { "family": FONT_FAMILY, "size": LEGEND_FONT_SIZE, "color": LEGEND_FONT_COLOR, }, "standoff": TITLE_TO_AXIS_MARGIN, }, "automargin": True, "showline": True, "linecolor": AXIS_LINE_COLOR, }, yaxis={ "color": AXIS_COLOR, "gridcolor": AXIS_GRID_COLOR, "tickfont": { "family": FONT_FAMILY, "size": LEGEND_FONT_SIZE, "color": LEGEND_FONT_COLOR, }, "title": { "font": { "family": FONT_FAMILY, "size": LEGEND_FONT_SIZE, "color": LEGEND_FONT_COLOR, }, "standoff": TITLE_TO_AXIS_MARGIN, }, "automargin": True, "showline": True, "linecolor": AXIS_LINE_COLOR, "zerolinecolor": AXIS_ZERO_LINE_COLOR, }, yaxis2={ "color": AXIS_COLOR, "gridcolor": TRANSPARENT, "tickfont": { "family": FONT_FAMILY, "size": LEGEND_FONT_SIZE, "color": LEGEND_FONT_COLOR, }, "title": { "font": { "family": FONT_FAMILY, "size": LEGEND_FONT_SIZE, "color": LEGEND_FONT_COLOR, }, "standoff": TITLE_TO_AXIS_MARGIN, }, "automargin": True, "showline": True, "linecolor": AXIS_LINE_COLOR, "zerolinecolor": AXIS_ZERO_LINE_COLOR, "overlaying": "y", }, margin={ "t": MARGIN_TOP, "b": MARGIN_BOTTOM, "r": MARGIN_LEFT, "l": MARGIN_RIGHT, }, annotations=[ { "align": "left", "arrowcolor": ANNOTATION_LINE_COLOR, "arrowhead": 0, "arrowsize": 0.5, "arrowwidth": ANNOTATION_LINE_WIDTH, "bgcolor": TRANSPARENT, "bordercolor": TRANSPARENT, "borderwidth": 0, "font": { "family": FONT_FAMILY, "size": ANNOTATION_FONT_SIZE, "color": ANNOTATION_FONT_COLOR, }, "showarrow": False, "valign": "middle", } ], hoverlabel={ "bgcolor": WHITE, "bordercolor": BACKGROUND_SECONDARY, "font": { "family": FONT_FAMILY, "color": FONT_COLOR, "size": FONT_SIZE, }, "align": "left", }, # TODO: not being respected shapes=[ { "type": "line", "line": { "color": ANNOTATION_LINE_COLOR, "dash": "dot", "width": ANNOTATION_LINE_WIDTH, }, }, ], )
YD_CLASSIC_THEME = { "layout": go.Layout(**YD_CLASSIC_THEME_CONFIG), } """ Standard template used when creating Plotly figure objects that are returned from the toolkit. Styling is indended for emailed reports. """ ATLAS_FONT_SIZE = 14 ATLAS_AXIS_TITLE_COLOR = "rgba(0, 0, 0, 0.87)" ATLAS_TICK_COLOR = "rgb(158, 158, 158)" ATLAS_THEME_CONFIG = merge_themes( YD_CLASSIC_THEME_CONFIG, { "margin": {"t": 16}, "font": { "color": ATLAS_AXIS_TITLE_COLOR, "size": ATLAS_FONT_SIZE, }, "legend": { "font": { "color": ATLAS_AXIS_TITLE_COLOR, "size": ATLAS_FONT_SIZE, } }, "yaxis": { "title": { "font": { "color": ATLAS_TICK_COLOR, "size": ATLAS_FONT_SIZE, } }, "tickfont": { "color": ATLAS_TICK_COLOR, "size": ATLAS_FONT_SIZE, }, }, "yaxis2": { "title": { "font": { "color": ATLAS_TICK_COLOR, "size": ATLAS_FONT_SIZE, } }, "tickfont": { "color": ATLAS_TICK_COLOR, "size": ATLAS_FONT_SIZE, }, }, "xaxis": { "title": { "font": { "color": ATLAS_TICK_COLOR, "size": ATLAS_FONT_SIZE, } }, "tickfont": { "color": ATLAS_TICK_COLOR, "size": ATLAS_FONT_SIZE, }, }, "hoverlabel": { "font": { "size": ATLAS_FONT_SIZE, }, }, }, ) ATLAS_THEME = { "layout": go.Layout(**ATLAS_THEME_CONFIG), } """ New template to be used when creating Plotly figure objects that are embedded in interactive experiences """