Ejemplo n.º 1
0
    def whatevers_bar_chart(self, whatever: str="total") -> Figure:
        """ Stacked bar chart of total active, deaths and recovered values """

        columns = ["active", "deaths", "recovered"]
        dates   = self.main_df.reset_index()["Date"]
        color   = {
            "active":    "#ffb347",  # Pastel Orange
            "deaths":    "#ff6961",  # Pastel Red
            "recovered": "#77dd78",  # Pastel Green
        }

        engine = inflect.engine()

        fig = Figure()

        for column in columns:
            name = "{} {}".format(whatever.capitalize(), column.capitalize())

            ys = self.main_df[name].sum(level=1)
            if whatever == "daily":
                ys = ys[1:]

            fig.add_trace(Bar(name=name, x=dates, y=ys, marker={"color": color[column]}))

        fig.update_layout(barmode="stack", title_text=engine.plural(whatever).capitalize())

        fig.update_traces(marker_line_width=0)

        return fig
Ejemplo n.º 2
0
def format_well_overview_figure(figure: go.Figure, charttype: str,
                                settings: List[str], sumvec: str) -> go.Figure:
    """This function formate the well overview figure. The reason for keeping this
    function outside the figure class is that we can update the figure formatting
    without generating a new WellOverviewFigure object and reloading the data. It can
    be applied directly to the current state of the figure dict if only formatting
    settings are changed. See in the well_overview_callbacks how it is used.
    """

    if charttype == "pie":
        figure.update_traces(
            texttemplate=("%{label}<br>%{value:.2s}" if "show_prod_text" in
                          settings else "%{label}"))

    elif charttype == "bar":
        figure.update_layout(
            barmode=("overlay" if "overlay_bars" in settings else "group"))
        figure.update_traces(
            textposition=("auto" if "show_prod_text" in settings else "none"))

    # These are valid for all chart types
    figure.update_layout(template=(
        "plotly_white" if "white_background" in settings else "plotly"))

    phase = {"WOPT": "Oil", "WGPT": "Gas", "WWPT": "Water"}[sumvec]

    figure.update(
        layout_title_text=f"Cumulative Well {phase} Production (Sm3)",
        layout_showlegend=("legend" in settings),
    )
    return figure
def add_custom_hovercard(fig: go.Figure) -> None:
    """Add a custom hovercard to the figure based on the first element of
    customdata, without the title to the right.

    :param fig: Plotly figure.
    :type fig: go.Figure
    """
    # Per https://stackoverflow.com/a/69430974/1840471.
    fig.update_traces(hovertemplate="%{customdata[0]}<extra></extra>")
Ejemplo n.º 4
0
    def add_to_plot(
            fig: go.Figure, y: List[float], y_labels: Optional[List[str]] = None, y_err: Optional[List[float]] = None,
            practical_maximum: Optional[float] = None, label: Optional[str] = None, index: int = 0):
        color = QUALITATIVE_COLORS[index % len(QUALITATIVE_COLORS)]
        rgb_ints = [str(int(x.strip(" "))) for x in color[4:][:-1].split(",")]
        new_color = f"rgba({','.join(rgb_ints + ['0.2'])})"

        custom_data: Optional[List[Any]] = None
        hover_template = None
        if y_labels:
            if y_err:
                custom_data: List[Any] = list(zip(y_labels, y_err))
                hover_template = '<b>%{y:.3f} +- %{customdata[1]:.3f}</b><br>%{customdata[0]}'
            else:
                custom_data = y_labels
                hover_template = '<b>%{y:.3f}</b><br>%{customdata}'

        # Error range
        x = list(range(1, len(y) + 1))
        if y_err:
            y_upper = [m + e for m, e in zip(y, y_err)]
            y_lower = [m - e for m, e in zip(y, y_err)]
            fig.add_trace(go.Scatter(
                x=x + x[::-1],
                y=y_upper + y_lower[::-1],
                fill='toself',
                fillcolor=new_color,
                line_color='rgba(255,255,255,0)',
                showlegend=False,
                name=label,
                hoverinfo='skip',
                legendgroup=label,
            ))

        # Mean line
        fig.add_trace(go.Scatter(
            x=x, y=y,
            customdata=custom_data,
            hovertemplate=hover_template,
            line_color=color,
            showlegend=True,
            name=label,
            legendgroup=label,
        ))
        fig.update_traces(mode='lines')

        # Make serif
        fig.update_layout(font=dict(
            family="serif",
        ))

        return fig
Ejemplo n.º 5
0
def get_cmp_indicator(cmps: List[float]) -> Figure:
    # get last and first values
    last_cmp = 0.0
    first_cmp = 0.0
    if len(cmps) > 0:
        last_cmp = cmps[-1]
        first_cmp = cmps[0]
    # create indicator
    fig = Figure(
        Indicator(mode="number+delta",
                  value=last_cmp,
                  delta={
                      'reference': first_cmp,
                      'relative': True,
                      'valueformat': '.2%'
                  }))
    fig.update_traces(delta_font={'size': 14},
                      number_font_size=18,
                      number_valueformat=',.2f')
    fig.update_layout(height=80, width=150)
    return fig
Ejemplo n.º 6
0
def timeseries_comparison_plot(
    series_1: pd.Series,
    series_2: pd.Series,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 200,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """

    fig = Figure()
    # Only thing I figured is - I could do this

    s1 = series_1.sort_index()

    fig.add_scatter(
        x=s1.index, y=s1, mode="lines", name=s1.name if s1.name else "series_1"
    )  # Not what is desired - need a line

    s2 = series_2.sort_index()

    fig.add_scatter(
        x=s2.index, y=s2, mode="lines", name=s2.name if s2.name else "series_2"
    )  # Not what is desired - need a line

    fig.update_layout(**layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    fig.update_layout(margin=dict(l=0, r=0, b=0, t=5, pad=0))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)
    return fig
def multi_plotly_timeseries_plot(
    dataframe: pd.DataFrame,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 200,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """

    fig = Figure()
    columns = list(dataframe.keys())

    to_plot_df = dataframe.sort_index()

    # Only thing I figured is - I could do this
    for key in columns:
        fig.add_scatter(x=to_plot_df.index,
                        y=to_plot_df[key],
                        mode="lines",
                        name=key)  # Not what is desired - need a line

    fig.update_layout(
        **layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    fig.update_layout(margin=dict(l=0, r=0, b=0, t=5, pad=0))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)
    return fig
Ejemplo n.º 8
0
def update_traces(figure: go.Figure, **kwargs: Any) -> go.Figure:
    data_frame = kwargs["data_frame"]
    facet_col = kwargs.get("facet_col")
    return (figure.update_traces(
        marker_size=max((20 - (1.5 * data_frame[facet_col].nunique())), 5)
        if facet_col is not None else 20,
        selector=lambda t: t["type"] in ["scatter", "scattergl"],
    ).update_traces(textposition="inside",
                    selector=dict(type="pie")).for_each_trace(
                        lambda t: set_marker_color(t)).for_each_trace(
                            lambda t: t.update(xbins_size=(t["x"].max() - t[
                                "x"].min()) / kwargs.get("nbins", 15))
                            if is_numeric_dtype(t["x"]) else None,
                            selector=dict(type="histogram"),
                        ))
Ejemplo n.º 9
0
def substituted_data_plot(
    raw_values: pd.Series,
    substitutions: pd.Series,
    message_series: pd.Series = None,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 200,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """

    fig = Figure()

    s1 = raw_values.sort_index()
    s1 = s1.loc[~s1.index.duplicated(keep="first")]

    s2 = substitutions.sort_index()
    s2 = s2.loc[~s2.index.duplicated(keep="first")]

    completely_handled_series, replaced_originals, replacements, new_values, deleted = handle_substitutions(
        s1, s2)

    fig.add_scatter(
        x=completely_handled_series.index,
        y=completely_handled_series,
        mode="markers+lines",
        name=raw_values.name +
        "_substituted" if raw_values.name else "raw_values_substituted",
        line_color="blue",
        opacity=0.6,
    )  # Not what is desired - need a line

    fig.add_scatter(
        x=replaced_originals.index,
        y=replaced_originals,
        mode="markers",
        name="replaced raw values",
        line_color="orange",
        marker=dict(size=10, opacity=0.6),
    )  # Not what is desired - need a line

    fig.add_scatter(
        x=deleted.index,
        y=deleted,
        mode="markers",
        name="ignored raw values",
        line_color="red",
        marker=dict(symbol="x", size=10, opacity=0.6),
    )  # Not what is desired - need a line

    fig.add_scatter(
        x=new_values.index,
        y=new_values,
        mode="markers",
        name="added values",
        line_color="green",
        marker=dict(symbol="cross", size=10, opacity=0.6),
    )  # Not what is desired - need a line

    fig.update_layout(
        **layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    fig.update_layout(margin=dict(l=0, r=0, b=0, t=5, pad=0))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)
    return fig
Ejemplo n.º 10
0
def timeseries_comparison_plot(
    series_1: pd.Series,
    series_2: pd.Series,
    limit_violation_timestamp: str,
    limit: float,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 200,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """

    fig = Figure()
    # Only thing I figured is - I could do this

    s1 = series_1.sort_index()

    fig.add_scatter(
        x=s1.index, y=s1, mode="lines", name=s1.name if s1.name else "series_1"
    )  # Not what is desired - need a line

    s2 = series_2.sort_index()

    fig.add_scatter(
        x=s2.index, y=s2, mode="lines", name=s2.name if s2.name else "series_2"
    )  # Not what is desired - need a line

    fig.update_layout(**layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    vline_y_min = np.min([series_1.min(), series_2.min(), limit])
    vline_y_max = np.max([series_1.max(), series_2.max(), limit])

    hline_x_min = np.min([series_1.index.min(), series_2.index.min()])
    hline_x_max = np.max([series_1.index.max(), series_2.index.max()])

    fig.update_layout(
        shapes=(
            [
                dict(
                    type="line",
                    yref="y",
                    y0=vline_y_min,
                    y1=vline_y_max,
                    xref="x",
                    x0=limit_violation_timestamp,
                    x1=limit_violation_timestamp,
                )
            ]
            if limit_violation_timestamp is not None
            else []
        )
        + [
            dict(
                type="line",
                yref="y",
                y0=limit,
                y1=limit,
                xref="x",
                x0=hline_x_min,
                x1=hline_x_max,
                line={"color": "red", "width": 1},
            )
        ]
    )

    fig.update_layout(margin=dict(l=0, r=0, b=0, t=5, pad=0))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)
    return fig
Ejemplo n.º 11
0
    def plot(self, Xt, sample=0, homology_dimensions=None, plotly_params=None):
        """Plot a sample from a collection of Betti curves arranged as in the
        output of :meth:`transform`. Include homology in multiple dimensions.

        Parameters
        ----------
        Xt : ndarray of shape (n_samples, n_homology_dimensions, n_bins)
            Collection of Betti curves, such as returned by :meth:`transform`.

        sample : int, optional, default: ``0``
            Index of the sample in `Xt` to be plotted.

        homology_dimensions : list, tuple or None, optional, default: ``None``
            Which homology dimensions to include in the plot. ``None`` means
            plotting all dimensions present in :attr:`homology_dimensions_`.

        plotly_params : dict or None, optional, default: ``None``
            Custom parameters to configure the plotly figure. Allowed keys are
            ``"traces"`` and ``"layout"``, and the corresponding values should
            be dictionaries containing keyword arguments as would be fed to the
            :meth:`update_traces` and :meth:`update_layout` methods of
            :class:`plotly.graph_objects.Figure`.

        Returns
        -------
        fig : :class:`plotly.graph_objects.Figure` object
            Plotly figure.

        """
        check_is_fitted(self)

        homology_dimensions_mapping = _make_homology_dimensions_mapping(
            homology_dimensions, self.homology_dimensions_)

        layout_axes_common = {
            "type": "linear",
            "ticks": "outside",
            "showline": True,
            "zeroline": True,
            "linewidth": 1,
            "linecolor": "black",
            "mirror": False,
            "showexponent": "all",
            "exponentformat": "e"
        }
        layout = {
            "xaxis1": {
                "title": "Filtration parameter",
                "side": "bottom",
                "anchor": "y1",
                **layout_axes_common
            },
            "yaxis1": {
                "title": "Betti number",
                "side": "left",
                "anchor": "x1",
                **layout_axes_common
            },
            "plot_bgcolor": "white",
            "title": f"Betti curves from diagram {sample}"
        }

        fig = Figure(layout=layout)

        for ix, dim in homology_dimensions_mapping:
            fig.add_trace(
                Scatter(x=self.samplings_[dim],
                        y=Xt[sample][ix],
                        mode="lines",
                        showlegend=True,
                        name=f"H{dim}"))

        # Update traces and layout according to user input
        if plotly_params:
            fig.update_traces(plotly_params.get("traces", None))
            fig.update_layout(plotly_params.get("layout", None))

        return fig
def timeseries_comparison_plot(
    series_1: pd.Series,
    series_2: pd.Series,
    freq,
    freq_factor,
    max_shifts_past,
    max_shifts_future,
    traces_opts: dict = {},
    layout_opts: dict = {
        "xaxis_title": "Time",
        "yaxis_title": "Values",
        "autosize": True,
        "height": 480,
    },
    line_opts: dict = {},
) -> Figure:
    """Create a single time series line plot Plotly figure
    
    Returns the plotly figure object.
    """
    if max_shifts_past < 0 or max_shifts_future < 0:
        raise ValueError("Shift maxima values must be greater equal zero.")

    fig = Figure()

    s1 = series_1.sort_index()

    fig.add_scatter(
        x=s1.index,
        y=s1,
        mode="lines",
        name=s1.name if (s1.name and s1.name != "measurement") else "series",
    )

    s2 = series_2.sort_index()

    for step in np.arange(-max_shifts_past, max_shifts_future, 1):
        shifted = s2.copy()
        shifted.index = shifted.index.shift(periods=step * freq_factor,
                                            freq=freq)
        fig.add_scatter(
            x=shifted.index,
            y=shifted,
            mode="lines",
            name=shifted.name if
            (shifted.name
             and shifted.name != "measurement") else "series_shiftable",
            visible=False,
        )

    fig.data[max_shifts_past + 1].visible = True  # start somewhere

    steps = []
    for i in range(len(fig.data)):
        step = dict(
            method="update",
            args=[
                {
                    "visible": [False] * (len(fig.data))
                },
                {
                    "title":
                    f"Shifted by x times frequency {freq_factor}{freq}: " +
                    str(i - max_shifts_past - 1)
                },
            ],  # layout attribute
        )
        step["args"][0]["visible"][i] = True  # Toggle i'th trace to "visible"
        step["args"][0]["visible"][0] = True
        step["label"] = str(i - max_shifts_past - 1)
        steps.append(step)

    sliders = [
        dict(
            active=max_shifts_past,
            currentvalue={
                "prefix": f"Shifted by x times frequency {freq_factor}{freq}: "
            },
            pad={
                "t": 80,
                "b": 10
            },
            steps=steps[1:],
        )
    ]

    fig.update_layout(
        **layout_opts)  # see https://plotly.com/python/figure-labels/
    fig.update_traces(traces_opts)  # set line color?

    fig.update_layout(margin=dict(l=0, r=0, b=40, t=30, pad=10))

    fig.update_yaxes(automargin=True)
    fig.update_xaxes(automargin=True)

    fig.update_layout(sliders=sliders)

    return fig
Ejemplo n.º 13
0
    def plot_dimensions_graph(
            fig: go.Figure, y: List[float], y_labels: Optional[List[str]] = None, y_err: Optional[List[float]] = None,
            practical_maximum: Optional[float] = None, label: Optional[str] = None):
        color = QUALITATIVE_COLORS[0]
        rgb_ints = [str(int(x.strip(" "))) for x in color[4:][:-1].split(",")]
        new_color = f"rgba({','.join(rgb_ints + ['0.2'])})"

        # Error range
        x = list(range(1, len(y) + 1))
        if y_err:
            y_upper = [m + e for m, e in zip(y, y_err)]
            y_lower = [m - e for m, e in zip(y, y_err)]
            fig.add_trace(go.Scatter(
                x=x + x[::-1],
                y=y_upper + y_lower[::-1],
                fill='toself',
                fillcolor=new_color,
                line_color='rgba(255,255,255,0)',
                showlegend=False,
                name=label,
                hoverinfo='skip',
                legendgroup=label,
            ))

        custom_data: Optional[List[Any]] = None
        hover_template = None
        if y_labels:
            if y_err:
                custom_data = list(zip(y_labels, y_err))
                hover_template = '<b>%{y:.3f} +- %{customdata[1]:.3f}</b><br>%{customdata[0]}'
            else:
                custom_data = y_labels
                hover_template = '<b>%{y:.3f}</b><br>%{customdata}'

        # Mean line
        fig.add_trace(go.Scatter(
            x=x, y=y,
            customdata=custom_data,
            hovertemplate=hover_template,
            line_color=color,
            showlegend=True,
            name=label,
            legendgroup=label,
        ))
        fig.update_traces(mode='lines')

        # Max MI
        if practical_maximum:
            fig.add_shape(
                # Line Horizontal
                type="line",
                x0=min(x),
                y0=practical_maximum,
                x1=max(x),
                y1=practical_maximum,
                line=dict(
                    color="LightSeaGreen",
                    dash="dash",
                ),
            )

        fig.update_layout(margin=dict(l=20, r=20, t=20, b=20))  # noqa
        fig.update_xaxes(title_text="Dimensions Selected", tickvals=x)

        # Make serif
        fig.update_layout(font=dict(
            family="serif",
        ))

        return fig