Overview
Plot is a graphical way to represent a value in a report. Other names it might be referred to are chart or graph, but for clarity we will use plot in the documentation.
Plotly
As an underlying plot engine for plot generation, we use Plotly for Python. It's an open source library that allows a generation of plots that can be viewed and interacted with in a browser when working with the interactive version of the report document (Dash). Additionally, with the help of kaleido package, those interactive plots can be rendered to static images, and added to the static report document (Word).
This feature was essential when choosing the solution for our plotting engine, since we wanted to serve both interactive and static reports with the same tool. With Plotly, the plot can be defined only once, and depending on the report output you are working with, the appropriate format of the plot is added to the report document.
Combine it with great documentation, flexibility and extensibility, and you have a really nice solution for working with the plots in our reporting engine.
General concepts
To integrate well with the selected plotting library, we have adopted our solution to work well with general Plotly concepts.
In the Plotly library for Python, the key conceptual unit is the Figure. A figure in Plotly effectively serves as a container that encompasses all the various elements of the plot, including the data, layout, and annotations, all of which collaborate to define the final visual representation of the plot.
The data in a Plotly figure is represented as a list of Traces. A trace is an object that describes a single type of visual data representation on the plot. This can be anything from a line chart to a bar chart, scatter plot, or many other types of graphical representations. Each trace contains information about the data that is being represented, as well as how to style and render that data. Importantly, you can have multiple traces in a single figure, which allows for complex plots with multiple types of data represented simultaneously.
Each trace is drawn on axes that provide a framework within which the data can be understood. These axes can be adjusted and manipulated to change the scale, labels, and orientation of the visualized data. They essentially set the coordinate system for the traces and provide context to help interpret the data.
Lastly, the "layout" of a Plotly figure represents the higher-level aspects of the figure's appearance. This includes elements like the title of the plot, any legends or color scales, and the axis labels. The layout can also dictate the overall theme or style of the plot, setting aspects such as the background color, font styles, and grid lines. Essentially, the layout allows you to adjust the non-data elements of the figure to ensure that the final plot communicates the data effectively and in a visually appealing manner.
Figures
Because, the figure is the center component of the plotting in the smartreport solution.
Report Outputs have implemented method called add_figure that can be used to
add a Figure to the report document.
Any valid Plotly figure can be added to the report document!
However, to make the report look coherent, and not to reinvent each plot over and over again, we have developed several functions that return a figure based on provided data, and optional styling arguments.
As an outcome, you will receive a plot that conforms to the ABB UX standards, and handles the edge cases when dealing with incomplete or partially corrupted data.
Documentation for the available figure-making functions can be found in Figures section of the API documentation.
Developing new plot
Figures are composed of data (traces) and layout. This structure is reflected in how we develop a new figure.
When creating a new plot, we need to take data as an input, and then add it as one or more traces to the figure. Finally, we need to define a layout for the figure.
Because, quite often, the final figure is a combination of similar trace types and layouts, we propose to extract trace drawing logic into separate functions that can be reused and to create layout building classes.
Existing trace drawing functions are described in Traces docs, while the layout documentation can be found in the Layout section.
Example
To make a new plotting function that can be used to create a figure, that we can later add to the report document follow the example below:
from plotly.graph_objects import Figure
from smartreport.plot.layout.vertical import VerticalPlotLayout
from smartreport.datatypes.trend import Trend
from smartreport.datatypes.threshold import Threshold
from smartreport.v3.plot.traces.line import draw_trend_line
from smartreport.v3.plot.traces.threshold import draw_threshold
def plot_trend_line_with_threshold(trend: Trend, threshold: Threshold, **kwargs) -> Figure:
# Initialize layout
layout = VerticalPlotLayout()
# Each layout should implement an empty plot property, which is returned when the data is not enough.
if trend.empty:
return layout.empty_plot
# Initialize basic figure object
fig = Figure()
# Add a trace with trend line to the figure
fig = draw_trend_line(figure=fig, data=trend, **kwargs)
# Draw Threshold trace
fig = draw_threshold(figure=fig, threshold=threshold, **kwargs)
# Apply layout to the figure.
# We do it at the end because some logic in the layout making code might require data inspection in the figure.
# For example, setting the plot range requires the knowledge about the min max values in the data.
layout.apply_to_figure(figure=fig)
return fig
API documentation
In this section you can find the details about the following components of the v3.plot module: