Exemplo n.º 1
0
 def add_to_plot(self, fig: go.Figure, bars: List[Bar], time):
     super().add_to_plot(fig, bars, time)
     lines = self.channel.get_number_of_lines()
     styles = self.channel.get_line_styles()
     names = self.channel.get_line_names()
     offset = 1  # we take it with offset 1
     self.logger.info("adding channel")
     for idx in range(0, lines):
         sub_data = list(map(lambda b: self.channel.get_data_for_plot(b)[idx], bars))
         fig.add_scatter(x=time, y=sub_data[offset:], mode='lines', line=styles[idx],
                         name=self.channel.id + "_" + names[idx])
Exemplo n.º 2
0
    def add_to_plot(self, fig: go.Figure, bars: List[Bar], time):
        super().add_to_plot(fig, bars, time)
        styles = self.mean.get_line_styles()

        names = self.mean.get_line_names()
        offset = 0  # we take it with offset 1

        sub_data = list(map(lambda b: self.mean.get_data_for_plot(b)[0], bars))
        fig.add_scatter(x=time,
                        y=sub_data[offset:],
                        mode='lines',
                        line=styles[0],
                        name=self.mean.id + "_" + names[0])
        sub_data = list(map(lambda b: self.mean.get_data_for_plot(b)[1], bars))
        fig.add_scatter(x=time,
                        y=sub_data[offset:],
                        mode='lines',
                        line=styles[1],
                        name=self.mean.id + "_" + names[1])
        sub_data = list(map(lambda b: self.mean.get_data_for_plot(b)[2], bars))
        fig.add_scatter(x=time,
                        y=sub_data[offset:],
                        mode='lines',
                        line=styles[2],
                        name=self.mean.id + "_" + names[2])
Exemplo n.º 3
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
Exemplo n.º 5
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
Exemplo n.º 6
0
def _plot(data: SampledField,
          fig: graph_objects.Figure,
          size: tuple,
          colormap: str or None,
          show_color_bar: bool,
          row: int = None, col: int = None,
          ):
    subplot = fig.get_subplot(row, col)
    vector = data.points.shape['vector']
    if data.spatial_rank == 1 and isinstance(data, Grid):
        x = data.points.vector[0].numpy().flatten()
        channels = data.values.shape.channel
        if channels.rank == 1 and channels.get_item_names(0) is not None:
            for i, name in enumerate(channels.get_item_names(0)):
                y = math.reshaped_native(real_values(data[{channels.name: i}]), [data.shape.spatial], to_numpy=True)
                fig.add_trace(graph_objects.Scatter(x=x, y=y, mode='lines+markers', name=name), row=row, col=col)
            fig.update_layout(showlegend=True)
        else:
            for ch_idx in channels.meshgrid():
                y = math.reshaped_native(real_values(data[ch_idx]), [data.shape.spatial], to_numpy=True)
                fig.add_trace(graph_objects.Scatter(x=x, y=y, mode='lines+markers', name='Multi-channel'), row=row, col=col)
            fig.update_layout(showlegend=False)
    elif data.spatial_rank == 2 and isinstance(data, Grid) and 'vector' not in data.shape:  # heatmap
        dims = spatial(data)
        values = real_values(data).numpy(dims.reversed)
        x = data.points.vector[dims[0].name].dimension(dims[1].name)[0].numpy()
        y = data.points.vector[dims[1].name].dimension(dims[0].name)[0].numpy()
        min_val, max_val = numpy.nanmin(values), numpy.nanmax(values)
        min_val, max_val = min_val if numpy.isfinite(min_val) else 0, max_val if numpy.isfinite(max_val) else 0
        color_scale = get_div_map(min_val, max_val, equal_scale=True, colormap=colormap)
        # color_bar = graph_objects.heatmap.ColorBar(x=1.15)   , colorbar=color_bar
        fig.add_heatmap(row=row, col=col, x=x, y=y, z=values, zauto=False, zmin=min_val, zmax=max_val, colorscale=color_scale, showscale=show_color_bar)
        subplot.xaxis.update(scaleanchor=f'y{subplot.yaxis.plotly_name[5:]}', scaleratio=1, constrain='domain', title=dims.names[0])
        subplot.yaxis.update(constrain='domain', title=dims.names[1])
    elif data.spatial_rank == 2 and isinstance(data, Grid):  # vector field
        if isinstance(data, StaggeredGrid):
            data = data.at_centers()
        x, y = math.reshaped_native(data.points.vector[spatial(data)], [vector, data.shape.without(vector)], to_numpy=True, force_expand=True)
        extra_channels = data.shape.channel.without('vector')
        data_x, data_y = math.reshaped_native(data.values, [vector, extra_channels, spatial(data)], to_numpy=True, force_expand=True)
        lower_x, lower_y = [float(l) for l in data.bounds.lower.vector.unstack_spatial('x,y')]
        upper_x, upper_y = [float(u) for u in data.bounds.upper.vector.unstack_spatial('x,y')]
        x_range = [lower_x, upper_x]
        y_range = [lower_y, upper_y]
        for ch in range(data_x.shape[0]):
            # quiver = figure_factory.create_quiver(x, y, data_x[ch], data_y[ch], scale=1.0)  # 7 points per arrow
            # fig.add_trace(quiver, row=row, col=col)
            data_y_flat = data_y[ch].flatten()
            data_x_flat = data_x[ch].flatten()
            # lines_y = numpy.stack([y, y + data_y_flat, [None] * len(x)], -1).flatten()  # 3 points per arrow
            # lines_x = numpy.stack([x, x + data_x_flat, [None] * len(x)], -1).flatten()
            lines_y = numpy.stack([y - data_y_flat / 2, y + data_y_flat / 2, [None] * len(x)], -1).flatten()  # 3 points per arrow
            lines_x = numpy.stack([x - data_x_flat / 2, x + data_x_flat / 2, [None] * len(x)], -1).flatten()
            name = extra_channels.get_item_names(0)[ch] if extra_channels.rank == 1 and extra_channels.get_item_names(0) is not None else None
            fig.add_scatter(x=lines_x, y=lines_y, mode='lines', row=row, col=col, name=name)
        if data_x.shape[0] == 1:
            fig.update_layout(showlegend=False)
        subplot.xaxis.update(range=x_range)
        subplot.yaxis.update(range=y_range)
        subplot.xaxis.update(scaleanchor=f'y{subplot.yaxis.plotly_name[5:]}', scaleratio=1, constrain='domain')
        subplot.yaxis.update(constrain='domain')
    elif data.spatial_rank == 3 and isinstance(data, Grid) and data.shape.channel.volume == 1:  # 3D heatmap
        values = real_values(data).numpy('z,y,x')
        x = data.points.vector['x'].numpy('z,y,x')
        y = data.points.vector['y'].numpy('z,y,x')
        z = data.points.vector['z'].numpy('z,y,x')
        min_val, max_val = numpy.nanmin(values), numpy.nanmax(values)
        min_val, max_val = min_val if numpy.isfinite(min_val) else 0, max_val if numpy.isfinite(max_val) else 0
        color_scale = get_div_map(min_val, max_val, equal_scale=True, colormap=colormap)
        fig.add_volume(x=x.flatten(), y=y.flatten(), z=z.flatten(), value=values.flatten(),
                       showscale=show_color_bar, colorscale=color_scale, cmin=min_val, cmax=max_val, cauto=False,
                       isomin=0.1, isomax=0.8,
                       opacity=0.1,  # needs to be small to see through all surfaces
                       surface_count=17,  # needs to be a large number for good volume rendering
                       row=row, col=col)
        fig.update_layout(uirevision=True)
    elif data.spatial_rank == 3 and isinstance(data, Grid):  # 3D vector field
        if isinstance(data, StaggeredGrid):
            data = data.at_centers()
        u = real_values(data).vector['x'].numpy('z,y,x')
        v = real_values(data).vector['y'].numpy('z,y,x')
        w = real_values(data).vector['z'].numpy('z,y,x')
        x = data.points.vector['x'].numpy('z,y,x')
        y = data.points.vector['y'].numpy('z,y,x')
        z = data.points.vector['z'].numpy('z,y,x')
        fig.add_cone(x=x.flatten(), y=y.flatten(), z=z.flatten(), u=u.flatten(), v=v.flatten(), w=w.flatten(),
                     colorscale='Blues',
                     sizemode="absolute", sizeref=1,
                     row=row, col=col)
    elif isinstance(data, PointCloud) and data.spatial_rank == 2 and 'vector' in channel(data):
        x, y = math.reshaped_native(data.points, [vector, data.shape.without('vector')], to_numpy=True, force_expand=True)
        u, v = math.reshaped_native(data.values, [vector, data.shape.without('vector')], to_numpy=True, force_expand=True)
        lower_x, lower_y = [float(d) for d in data.bounds.lower.vector]
        upper_x, upper_y = [float(d) for d in data.bounds.upper.vector]
        subplot.xaxis.update(range=[lower_x, upper_x])
        subplot.yaxis.update(range=[lower_y, upper_y])
        quiver = figure_factory.create_quiver(x, y, u, v, scale=1.0).data[0]  # 7 points per arrow
        if data.color.shape:
            # color = data.color.numpy(data.shape.non_channel).reshape(-1)
            warnings.warn("Multi-colored vector plots not yet supported")
        else:
            color = data.color.native()
            quiver.line.update(color=color)
        fig.add_trace(quiver, row=row, col=col)
        if data.points.vector.item_names:
            subplot.xaxis.update(title=data.points.vector.item_names[0])
            subplot.yaxis.update(title=data.points.vector.item_names[1])
        subplot.xaxis.update(scaleanchor=f'y{subplot.yaxis.plotly_name[5:]}', scaleratio=1, constrain='domain')
        subplot.yaxis.update(constrain='domain')
    elif isinstance(data, PointCloud) and data.spatial_rank == 2:
        lower_x, lower_y = [float(d) for d in data.bounds.lower.vector]
        upper_x, upper_y = [float(d) for d in data.bounds.upper.vector]
        if data.points.shape.non_channel.rank > 1:
            data_list = field.unstack(data, data.points.shape.non_channel[0].name)
            for d in data_list:
                _plot(d, fig, size, colormap, show_color_bar, row, col)
        else:
            x, y = [d.numpy() for d in data.points.vector.unstack_spatial('x,y')]
            color = data.color.native()
            subplot_height = (subplot.yaxis.domain[1] - subplot.yaxis.domain[0]) * size[1]
            if isinstance(data.elements, Sphere):
                symbol = 'circle'
                marker_size = data.elements.bounding_radius().numpy() * 1.9
            elif isinstance(data.elements, BaseBox):
                symbol = 'square'
                marker_size = math.mean(data.elements.bounding_half_extent(), 'vector').numpy() * 1
            elif isinstance(data.elements, Point):
                symbol = 'x'
                marker_size = 12 / (subplot_height / (upper_y - lower_y))
            else:
                symbol = 'asterisk'
                marker_size = data.elements.bounding_radius().numpy()
            marker_size *= subplot_height / (upper_y - lower_y)
            marker = graph_objects.scatter.Marker(size=marker_size, color=color, sizemode='diameter', symbol=symbol)
            fig.add_scatter(mode='markers', x=x, y=y, marker=marker, row=row, col=col)
        subplot.xaxis.update(range=[lower_x, upper_x])
        subplot.yaxis.update(range=[lower_y, upper_y])
        fig.update_layout(showlegend=False)
        subplot.xaxis.update(scaleanchor=f'y{subplot.yaxis.plotly_name[5:]}', scaleratio=1, constrain='domain')
        subplot.yaxis.update(constrain='domain')
    elif isinstance(data, PointCloud) and data.spatial_rank == 3:
        lower_x, lower_y, lower_z = [float(d) for d in data.bounds.lower.vector.unstack_spatial('x,y,z')]
        upper_x, upper_y, upper_z = [float(d) for d in data.bounds.upper.vector.unstack_spatial('x,y,z')]
        if data.points.shape.non_channel.rank > 1:
            data_list = field.unstack(data, data.points.shape.non_channel[0].name)
            for d in data_list:
                _plot(d, fig, size, colormap, show_color_bar, row, col)
        else:
            x, y, z = [d.numpy() for d in data.points.vector.unstack_spatial('x,y,z')]
            color = data.color.native()
            # if data.color.shape.instance_rank == 0:
            #     color = str(data.color)
            # else:
            #     color = [str(d) for d in math.unstack(data.color, instance)]
            domain_y = fig.layout[subplot.plotly_name].domain.y
            if isinstance(data.elements, Sphere):
                symbol = 'circle'
                marker_size = data.elements.bounding_radius().numpy() * 2
            elif isinstance(data.elements, BaseBox):
                symbol = 'square'
                marker_size = math.mean(data.elements.bounding_half_extent(), 'vector').numpy() * 1
            elif isinstance(data.elements, Point):
                symbol = 'x'
                marker_size = 4 / (size[1] * (domain_y[1] - domain_y[0]) / (upper_y - lower_y) * 0.5)
            else:
                symbol = 'asterisk'
                marker_size = data.elements.bounding_radius().numpy()
            marker_size *= size[1] * (domain_y[1] - domain_y[0]) / (upper_y - lower_y) * 0.5
            marker = graph_objects.scatter3d.Marker(size=marker_size, color=color, sizemode='diameter', symbol=symbol)
            fig.add_scatter3d(mode='markers', x=x, y=y, z=z, marker=marker, row=row, col=col)
        subplot.xaxis.update(range=[lower_x, upper_x])
        subplot.yaxis.update(range=[lower_y, upper_y])
        subplot.zaxis.update(range=[lower_z, upper_z])
        fig.update_layout(showlegend=False)
    else:
        raise NotImplementedError(f"No figure recipe for {data}")
Exemplo n.º 7
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
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