Skip to content

Latest commit

 

History

History
525 lines (399 loc) · 22.3 KB

File metadata and controls

525 lines (399 loc) · 22.3 KB

Plot Node

The Plot Node defines a data visualization within the report. It specifies the data to be used, how that data should be mapped to the figure’s axes and dimensions, and what transformations should be applied before rendering.

PlotNode Schema (Container)

Field Type Description Default Value

id

string

Optional. Identifies the plot node within the report. Used for internal cross referencing

null

type

string

Must be set to "plot".

"plot"

caption

string

Optional. A descriptive caption for the figure.

null

ref

string

The unique name of the data file (from the root data list) to reference for building the figure.

Required

plot

object

The nested configuration object (Plot schema) defining the figure’s dimensions, type, and transformation.

Required

Plot Configuration (plot Field)

The core configuration is provided here, defining the geometry and data logic of the figure.

Field Type Description Default Value

title

string

The title displayed at the top of the figure.

Required

plot_types

array of strings

A list of one or more visualization types to generate from the same configuration (e.g., ["scatter", "table"]).

Required

transformation

string

Defines how the input data should be processed and normalized before plotting.

"performance"

aggregations

array of objects

A sequential list of instructions to filter and summarize the dataset before mapping to axes.

null

xaxis

object

The configuration for the horizontal axis (PlotAxis schema).

Required

yaxis

object

The configuration for the vertical axis (PlotAxis schema).

Required

secondary_axis

object

A second independent axis used for animation (sliders) or defining a third dimension.

null

color_axis

object

The parameter used to define distinct lines or groups, mapping data values to the trace color/legend.

null

extra_axes

array of objects

Additional parameters used for filtering, grouping, or serving as a fourth dimension in complex plots (e.g., 3D or parallel coordinates).

[]

layout_modifiers

object

Allows passing raw configuration options to the underlying plotting library (Plotly) for fine-grained control (e.g., log scale).

{}


Dimensions and Axes (PlotAxis Schema)

All axis fields (xaxis, yaxis, secondary_axis, color_axis, extra_axes) use the PlotAxis schema to define which data column maps to which dimension.

Field Type Description Default Value

parameter

string

The name of the data column to be mapped to this axis. Use dot notation (parameter.subparameter) for nested data.

Required

label

string

The display label for the axis in the final figure.

Inferred from parameter

filter

string, array, or object

Allows explicit filtering or renaming of values within this dimension. (See Filtering section below.)

[]

Dimension Filtering and Renaming

The filter field within an axis allows you to select specific values from that column to include in the plot, and optionally rename them for display.

Syntax Action Example

Single string

Filters by the value, keeps the value as the label.

"filter": "ValueA"

Array of strings

Filters by multiple values, keeps values as labels.

"filter": ["ValueA", "ValueB"]

Map of strings

Filters by keys, renames to values.

"filter": {"old_name": "New Label"}

"xaxis": {
    "parameter": "System",
    "filter": {
        "cluster_a": "Cluster A (Production)",
        "dev_box": "Development System"
    }
}

Data Transformations

The transformation field defines how the data is restructured and normalized before being plotted.

Transformation Purpose Output Focus

"performance"

The base and default strategy. Data is restructured (pivoted) using the axes dimensions but values remain absolute.

Absolute Values

"relative_performance"

Data is restructured, and each value is normalized by the total sum of its row (e.g., component percentages of total time).

Percentage/Proportion

"speedup"

Computes the speedup relative to the smallest value found along the X-axis dimension (often used to show parallel scaling).

Scaling Factors

To explain how transformation and plot types work, we can consider the following example.

records = [{"perfvalue": "elapsed_fill", "value": 28.9239, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 1.0, "elements": 10000.0}, {"perfvalue": "elapsed_compute", "value": 1.92806, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 1.0, "elements": 10000.0}, {"perfvalue": "elapsed_fill", "value": 63.0273, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 1.0, "elements": 20000.0}, {"perfvalue": "elapsed_compute", "value": 3.74504, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 1.0, "elements": 20000.0}, {"perfvalue": "elapsed_fill", "value": 92.358, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 1.0, "elements": 30000.0}, {"perfvalue": "elapsed_compute", "value": 3.29597, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 1.0, "elements": 30000.0}, {"perfvalue": "elapsed_fill", "value": 99.9142, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 1.0, "elements": 40000.0}, {"perfvalue": "elapsed_compute", "value": 2.37914, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 1.0, "elements": 40000.0}, {"perfvalue": "elapsed_fill", "value": 24.8636, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 2.0, "elements": 10000.0}, {"perfvalue": "elapsed_compute", "value": 0.629236, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 2.0, "elements": 10000.0}, {"perfvalue": "elapsed_fill", "value": 14.9139, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 2.0, "elements": 20000.0}, {"perfvalue": "elapsed_compute", "value": 0.498528, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 2.0, "elements": 20000.0}, {"perfvalue": "elapsed_fill", "value": 98.9536, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 2.0, "elements": 30000.0}, {"perfvalue": "elapsed_compute", "value": 2.3708, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 2.0, "elements": 30000.0}, {"perfvalue": "elapsed_fill", "value": 45.4764, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 2.0, "elements": 40000.0}, {"perfvalue": "elapsed_compute", "value": 1.56548, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 2.0, "elements": 40000.0}, {"perfvalue": "elapsed_fill", "value": 2.89716, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 4.0, "elements": 10000.0}, {"perfvalue": "elapsed_compute", "value": 0.0434488, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 4.0, "elements": 10000.0}, {"perfvalue": "elapsed_fill", "value": 36.537, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 4.0, "elements": 20000.0}, {"perfvalue": "elapsed_compute", "value": 0.519222, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 4.0, "elements": 20000.0}, {"perfvalue": "elapsed_fill", "value": 52.302, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 4.0, "elements": 30000.0}, {"perfvalue": "elapsed_compute", "value": 1.23368, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 4.0, "elements": 30000.0}, {"perfvalue": "elapsed_fill", "value": 98.397, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 4.0, "elements": 40000.0}, {"perfvalue": "elapsed_compute", "value": 1.55742, "unit": "s", "result": "pass", "system": "gaya", "partition": "public", "tasks": 4.0, "elements": 40000.0}]
import pandas as pd

master_df = pd.DataFrame.from_dict(records)
master_df.head(5)

We can see that this dataframe contains the parameters: - system - result - tasks - elements - value - perfvalue - unit

By having this common structure, we can make use of transformation strategies to manipulate values depending on the desired output.

Strategies will depend on the figure axis. All strategies will create a pivot dataframe that will contain the parameter specified as color_axis as columns, xaxis as first level index and secondary_axis as second level index. Values of the dataframe will always be the values of the master dataframe.

As an example, we will consider the following axis definitions:

"xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
"yaxis":{ "parameter":"value", "label":"Execution time (s)" },
"secondary_axis":{ "parameter":"elements", "label":"N" },
"color_axis":{ "parameter":"perfvalue", "label":"Performance variable" }

performance

This strategy should be seen as the "base" strategy. No transformation, other that a pivot, is done. For the given example, it produces the following dataframe

from feelpp.benchmarking.json_report.figures.transformationFactory import TransformationStrategyFactory
from feelpp.benchmarking.json_report.figures.schemas.plot import Plot
plot_config = Plot(**{
    "title": "Absolute performance",
    "plot_types": [ "stacked_bar", "grouped_bar" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)"},
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{"parameter":"elements", "label":"N"}
})
strategy = TransformationStrategyFactory.create(plot_config)
df = strategy.calculate(master_df)
print(df)

relative_performance

The relative performance strategy computes the proportion of the time that a a color_axis variable takes with regards of the total.

plot_config = Plot(**{
    "title": "Absolute performance",
    "plot_types": [ "stacked_bar", "grouped_bar" ],
    "transformation": "relative_performance",
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{"parameter":"value", "label":"Execution time (s)"},
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N"
    }
})
strategy = TransformationStrategyFactory.create(plot_config)
df = strategy.calculate(master_df)
print(df)

The sum along the column axis will always be equal to 100.

speedup

The speedup strategy computes the speedup of the color_axis variables. The minimum of the xaxis values is taken as the base of the speedup. For the example, this strategy will produce the following.

plot_config = Plot(**{
    "title": "Absolute performance",
    "plot_types": [ "stacked_bar", "grouped_bar" ],
    "transformation": "speedup",
    "xaxis":{"parameter":"tasks", "label":"Number of tasks"},
    "yaxis":{"parameter":"value", "label":"Execution time (s)"},
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{"parameter":"elements", "label":"N"}
})
strategy = TransformationStrategyFactory.create(plot_config)
df = strategy.calculate(master_df)
print(df)

Aggregations

The optional aggregations field allows for data reduction and filtering across the dataset before the final pivot structure is created. The order of these instructions matters.

Aggregation Field Type Description

column

string

The column to apply the aggregation or filter to.

agg

string

The aggregation function or filter instruction.

Available Aggregation Functions

Function Action

mean

Computes the arithmetic average of the column.

sum

Computes the total sum of the column.

max, min

Finds the maximum or minimum value in the column.

count, nunique

Counts the number of values or unique values.

filter:VALUE

Filters the column to keep only rows where the column value matches VALUE.

"aggregations":[
    {"column":"Date","agg":"max"}, // Keep only records with the latest date
    {"column":"System","agg":"filter:gaya"}, // Filter to only keep the 'gaya' system
    {"column":"Time","agg":"mean"} // Calculate the mean execution time
]

Plot Types

The engine supports a diverse range of visualizations, grouped into 2D, 3D, and specialized formats. The definition of each axis depends on the plot type.

2D Visualizations

These are standard 2D plots that support the xaxis, yaxis, and often the color_axis and secondary_axis (for animation/faceting).

For examples in this section, we will define the axis as:

"xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
"yaxis":{ "parameter":"value", "label":"Execution time (s)" },
"color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
"secondary_axis":{ "parameter":"elements", "label":"N" }

scatter: Standard scatter plot, typically showing performance trends.

Axis definition:

  • secondary_axis : represents the figure slider

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Scatter Plot",
    "plot_types": [ "scatter" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

marked_scatter: Enhanced scatter plot where the symbol/mark shape can be mapped to an additional dimension.

Axis definition:

  • secondary_axis : represents the marks

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Marked Scatter Plot",
    "plot_types": [ "marked_scatter" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

stacked_bar: Displays cumulative values, useful for showing the proportion of components (e.g., relative_performance transformation).

Axis definition:

  • xaxis : represents the subplot dimension. A subplot is created for each value in the x axis.

  • secondary_axis : represents the x axis of each subplot.

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Stacked Bar Plot",
    "plot_types": [ "stacked_bar" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

grouped_bar: Displays values side-by-side for easy comparison.

Axis definition:

  • secondary_axis : represents the figure slider

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Grouped Bar Plot",
    "plot_types": [ "grouped_bar" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

heatmap: Displays data values as colors on a 2D grid defined by the X and Color axes.

Axis definition:

  • yaxis: Is given by the color scale (I know it is counter-intuitive).

  • xaxis: Represents the columns of the heatmap

  • color_axis: Represents the rows of the heatmap

  • secondary_axis : Represents the figure slider

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Heatmap",
    "plot_types": [ "heatmap" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

Specialized Visualizations

table: Renders the processed data directly into a styled, tabular format (similar to the Table Node, but generated through the figure pipeline).

Axis definition: Columns are displayed in the following order, from left to right: [extra_axes] → secondary_axisxaxis → [all values in color_axis].

Cell values correspond to yaxis.

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Table",
    "plot_types": [ "table" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

sunburst: Displays hierarchical data as a multi-layered ring chart, useful for showing partitions.

Dimensions are mapped to the rings: From inner to outer: secondary_axisxaxis→ [extra_axes] → color_axis (outer).

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Sunburst",
    "plot_types": [ "sunburst" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

parallelcoordinates: Displays multidimensional data where each variable is represented by a vertical axis, and data points are drawn as colored lines connecting the axes.

Axes will be shown on the following order from left to right: secondary_axisxaxis, [extra_axes] → color_axis. The yaxis will be shown in the line color.

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Parallel Coordinates",
    "plot_types": [ "parallelcoordinates" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

3D Visualizations

These plots are used for visualizing three or four variables. At least three dimensions are required (xaxis, yaxis, and secondary_axis).

  • scatter3d: Displays individual data points in three dimensions.

  • surface3d: Displays values as a 3D surface grid.

3D Axis

Mapped Parameter

X-axis

xaxis parameter

Y-axis

secondary_axis parameter (or first extra_axes element if provided)

Z-axis

yaxis parameter (the measured value)

Color/Trace

color_axis parameter


scatter3d

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Scatter 3D",
    "plot_types": [ "scatter3d" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

surface3d

from feelpp.benchmarking.json_report.figures.figureFactory import FigureFactory
figures = FigureFactory.create(Plot(**{
    "title": "Absolute performance - Surface 3D",
    "plot_types": [ "surface3d" ],
    "xaxis":{ "parameter":"tasks", "label":"Number of tasks" },
    "yaxis":{ "parameter":"value", "label":"Execution time (s)" },
    "color_axis":{ "parameter":"perfvalue", "label":"Performance variable" },
    "secondary_axis":{ "parameter":"elements", "label":"N" }
}))
fig = figures[0].createFigure(master_df)
fig.show()

Custom Layouts (layout_modifiers)

The layout_modifiers field allows expert users to pass raw configuration dictionaries to the underlying plotting engine (Plotly). This is useful for advanced styling not covered by the standard schema.

These options correspond to the accepted layout reference for Plotly: Plotly layout reference It accepts a nested dictionnary just as Plotly does.

For example, we could customize a figure to have have its x-axis on a logscale.

"layout_modifiers":{
    "xaxis":{
        "type":"log"
    }
}
details>.title::before, details>.title::after { visibility: hidden; } details>.content>.dynamic-py-result>.content>pre { max-height: 100%; padding: 0; margin:16px; background-color: white; }