Skip to content

flixopt.plotting

Comprehensive visualization toolkit for flixopt optimization results and data analysis.

This module provides a unified plotting interface supporting both Plotly (interactive) and Matplotlib (static) backends for visualizing energy system optimization results. It offers specialized plotting functions for time series, heatmaps, network diagrams, and statistical analyses commonly needed in energy system modeling.

Key Features

Dual Backend Support: Seamless switching between Plotly and Matplotlib Energy System Focus: Specialized plots for power flows, storage states, emissions Color Management: Intelligent color processing and palette management Export Capabilities: High-quality export for reports and publications Integration Ready: Designed for use with CalculationResults and standalone analysis

Main Plot Types
  • Time Series: Flow rates, power profiles, storage states over time
  • Heatmaps: High-resolution temporal data visualization with customizable aggregation
  • Network Diagrams: System topology with flow visualization
  • Statistical Plots: Distribution analysis, correlation studies, performance metrics
  • Comparative Analysis: Multi-scenario and sensitivity study visualizations

The module integrates seamlessly with flixopt's result classes while remaining accessible for standalone data visualization tasks.

Attributes

ColorType module-attribute

Python
ColorType = str | list[str] | dict[str, str]

Flexible color specification type supporting multiple input formats for visualization.

Color specifications can take several forms to accommodate different use cases:

Named colorscales (str): - Standard colorscales: 'turbo', 'plasma', 'cividis', 'tab10', 'Set1' - Energy-focused: 'portland' (custom flixopt colorscale for energy systems) - Backend-specific maps available in Plotly and Matplotlib

Color Lists (list[str]): - Explicit color sequences: ['red', 'blue', 'green', 'orange'] - HEX codes: ['#FF0000', '#0000FF', '#00FF00', '#FFA500'] - Mixed formats: ['red', '#0000FF', 'green', 'orange']

Label-to-Color Mapping (dict[str, str]): - Explicit associations: {'Wind': 'skyblue', 'Solar': 'gold', 'Gas': 'brown'} - Ensures consistent colors across different plots and datasets - Ideal for energy system components with semantic meaning

Examples:

Python
# Named colorscale
colors = 'turbo'  # Automatic color generation

# Explicit color list
colors = ['red', 'blue', 'green', '#FFD700']

# Component-specific mapping
colors = {
    'Wind_Turbine': 'skyblue',
    'Solar_Panel': 'gold',
    'Natural_Gas': 'brown',
    'Battery': 'green',
    'Electric_Load': 'darkred'
}
Color Format Support
  • Named Colors: 'red', 'blue', 'forestgreen', 'darkorange'
  • HEX Codes: '#FF0000', '#0000FF', '#228B22', '#FF8C00'
  • RGB Tuples: (255, 0, 0), (0, 0, 255) [Matplotlib only]
  • RGBA: 'rgba(255,0,0,0.8)' [Plotly only]
References
  • HTML Color Names: https://htmlcolorcodes.com/color-names/
  • Matplotlib colorscales: https://matplotlib.org/stable/tutorials/colors/colorscales.html
  • Plotly Built-in Colorscales: https://plotly.com/python/builtin-colorscales/

PlottingEngine module-attribute

Python
PlottingEngine = Literal['plotly', 'matplotlib']

Identifier for the plotting engine to use.

Classes

Functions

with_plotly

Python
with_plotly(data: Dataset | DataFrame | Series, mode: Literal['stacked_bar', 'line', 'area', 'grouped_bar'] = 'stacked_bar', colors: ColorType | None = None, title: str = '', ylabel: str = '', xlabel: str = '', facet_by: str | list[str] | None = None, animate_by: str | None = None, facet_cols: int | None = None, shared_yaxes: bool = True, shared_xaxes: bool = True, **px_kwargs: Any) -> go.Figure

Plot data with Plotly using facets (subplots) and/or animation for multidimensional data.

Uses Plotly Express for convenient faceting and animation with automatic styling.

Parameters:

Name Type Description Default
data Dataset | DataFrame | Series

An xarray Dataset, pandas DataFrame, or pandas Series to plot.

required
mode Literal['stacked_bar', 'line', 'area', 'grouped_bar']

The plotting mode. Use 'stacked_bar' for stacked bar charts, 'line' for lines, 'area' for stacked area charts, or 'grouped_bar' for grouped bar charts.

'stacked_bar'
colors ColorType | None

Color specification (colorscale, list, or dict mapping labels to colors).

None
title str

The main title of the plot.

''
ylabel str

The label for the y-axis.

''
xlabel str

The label for the x-axis.

''
facet_by str | list[str] | None

Dimension(s) to create facets for. Creates a subplot grid. Can be a single dimension name or list of dimensions (max 2 for facet_row and facet_col). If the dimension doesn't exist in the data, it will be silently ignored.

None
animate_by str | None

Dimension to animate over. Creates animation frames. If the dimension doesn't exist in the data, it will be silently ignored.

None
facet_cols int | None

Number of columns in the facet grid (used when facet_by is single dimension).

None
shared_yaxes bool

Whether subplots share y-axes.

True
shared_xaxes bool

Whether subplots share x-axes.

True
**px_kwargs Any

Additional keyword arguments passed to the underlying Plotly Express function (px.bar, px.line, px.area). These override default arguments if provided. Examples: range_x=[0, 100], range_y=[0, 50], category_orders={...}, line_shape='linear'

{}

Returns:

Type Description
Figure

A Plotly figure object containing the faceted/animated plot. You can further customize

Figure

the returned figure using Plotly's methods (e.g., fig.update_traces(), fig.update_layout()).

Examples:

Simple plot:

Python
fig = with_plotly(dataset, mode='area', title='Energy Mix')

Facet by scenario:

Python
fig = with_plotly(dataset, facet_by='scenario', facet_cols=2)

Animate by period:

Python
fig = with_plotly(dataset, animate_by='period')

Facet and animate:

Python
fig = with_plotly(dataset, facet_by='scenario', animate_by='period')

Customize with Plotly Express kwargs:

Python
fig = with_plotly(dataset, range_y=[0, 100], line_shape='linear')

Further customize the returned figure:

Python
fig = with_plotly(dataset, mode='line')
fig.update_traces(line={'width': 5, 'dash': 'dot'})
fig.update_layout(template='plotly_dark', width=1200, height=600)

with_matplotlib

Python
with_matplotlib(data: Dataset | DataFrame | Series, mode: Literal['stacked_bar', 'line'] = 'stacked_bar', colors: ColorType | None = None, title: str = '', ylabel: str = '', xlabel: str = 'Time in h', figsize: tuple[int, int] = (12, 6), plot_kwargs: dict[str, Any] | None = None) -> tuple[plt.Figure, plt.Axes]

Plot data with Matplotlib using stacked bars or stepped lines.

Parameters:

Name Type Description Default
data Dataset | DataFrame | Series

An xarray Dataset, pandas DataFrame, or pandas Series to plot. After conversion to DataFrame, the index represents time and each column represents a separate data series (variables).

required
mode Literal['stacked_bar', 'line']

Plotting mode. Use 'stacked_bar' for stacked bar charts or 'line' for stepped lines.

'stacked_bar'
colors ColorType | None

Color specification. Can be: - A colorscale name (e.g., 'turbo', 'plasma') - A list of color strings (e.g., ['#ff0000', '#00ff00']) - A dict mapping column names to colors (e.g., {'Column1': '#ff0000'})

None
title str

The title of the plot.

''
ylabel str

The ylabel of the plot.

''
xlabel str

The xlabel of the plot.

'Time in h'
figsize tuple[int, int]

Specify the size of the figure (width, height) in inches.

(12, 6)
plot_kwargs dict[str, Any] | None

Optional dict of parameters to pass to ax.bar() or ax.step() plotting calls. Use this to customize plot properties (e.g., linewidth, alpha, edgecolor).

None

Returns:

Type Description
tuple[Figure, Axes]

A tuple containing the Matplotlib figure and axes objects used for the plot.

Notes
  • If mode is 'stacked_bar', bars are stacked for both positive and negative values. Negative values are stacked separately without extra labels in the legend.
  • If mode is 'line', stepped lines are drawn for each data series.

reshape_data_for_heatmap

Python
reshape_data_for_heatmap(data: DataArray, reshape_time: tuple[Literal['YS', 'MS', 'W', 'D', 'h', '15min', 'min'], Literal['W', 'D', 'h', '15min', 'min']] | Literal['auto'] | None = 'auto', facet_by: str | list[str] | None = None, animate_by: str | None = None, fill: Literal['ffill', 'bfill'] | None = 'ffill') -> xr.DataArray

Reshape data for heatmap visualization, handling time dimension intelligently.

This function decides whether to reshape the 'time' dimension based on the reshape_time parameter: - 'auto': Automatically reshapes if only 'time' dimension would remain for heatmap - Tuple: Explicitly reshapes time with specified parameters - None: No reshaping (returns data as-is)

All non-time dimensions are preserved during reshaping.

Parameters:

Name Type Description Default
data DataArray

DataArray to reshape for heatmap visualization.

required
reshape_time tuple[Literal['YS', 'MS', 'W', 'D', 'h', '15min', 'min'], Literal['W', 'D', 'h', '15min', 'min']] | Literal['auto'] | None

Reshaping configuration: - 'auto' (default): Auto-reshape if needed based on facet_by/animate_by - Tuple (timeframes, timesteps_per_frame): Explicit time reshaping - None: No reshaping

'auto'
facet_by str | list[str] | None

Dimension(s) used for faceting (used in 'auto' decision).

None
animate_by str | None

Dimension used for animation (used in 'auto' decision).

None
fill Literal['ffill', 'bfill'] | None

Method to fill missing values: 'ffill' or 'bfill'. Default is 'ffill'.

'ffill'

Returns:

Type Description
DataArray

Reshaped DataArray. If time reshaping is applied, 'time' dimension is replaced

DataArray

by 'timestep' and 'timeframe'. All other dimensions are preserved.

Examples:

Auto-reshaping:

Python
# Will auto-reshape because only 'time' remains after faceting/animation
data = reshape_data_for_heatmap(data, reshape_time='auto', facet_by='scenario', animate_by='period')

Explicit reshaping:

Python
# Explicitly reshape to daily pattern
data = reshape_data_for_heatmap(data, reshape_time=('D', 'h'))

No reshaping:

Python
# Keep data as-is
data = reshape_data_for_heatmap(data, reshape_time=None)

plot_network

Python
plot_network(node_infos: dict, edge_infos: dict, path: str | Path | None = None, controls: bool | list[Literal['nodes', 'edges', 'layout', 'interaction', 'manipulation', 'physics', 'selection', 'renderer']] = True, show: bool = False) -> pyvis.network.Network | None

Visualizes the network structure of a FlowSystem using PyVis, using info-dictionaries.

Parameters:

Name Type Description Default
path str | Path | None

Path to save the HTML visualization. False: Visualization is created but not saved. str or Path: Specifies file path (default: 'results/network.html').

None
controls bool | list[Literal['nodes', 'edges', 'layout', 'interaction', 'manipulation', 'physics', 'selection', 'renderer']]

UI controls to add to the visualization. True: Enables all available controls. list: Specify controls, e.g., ['nodes', 'layout']. Options: 'nodes', 'edges', 'layout', 'interaction', 'manipulation', 'physics', 'selection', 'renderer'. You can play with these and generate a Dictionary from it that can be applied to the network returned by this function. network.set_options() https://pyvis.readthedocs.io/en/latest/tutorial.html

True
show bool

Whether to open the visualization in the web browser. The calculation must be saved to show it. If no path is given, it defaults to 'network.html'.

False

Returns: The Network instance representing the visualization, or None if pyvis is not installed.

Notes: - This function requires pyvis. If not installed, the function prints a warning and returns None. - Nodes are styled based on type (e.g., circles for buses, boxes for components) and annotated with node information.

preprocess_data_for_pie

Python
preprocess_data_for_pie(data: Dataset | DataFrame | Series, lower_percentage_threshold: float = 5.0) -> pd.Series

Preprocess data for pie chart display.

Groups items that are individually below the threshold percentage into an "Other" category. Converts various input types to a pandas Series for uniform handling.

Parameters:

Name Type Description Default
data Dataset | DataFrame | Series

Input data (xarray Dataset, DataFrame, or Series)

required
lower_percentage_threshold float

Percentage threshold - items below this are grouped into "Other"

5.0

Returns:

Type Description
Series

Processed pandas Series with small items grouped into "Other"

dual_pie_with_plotly

Python
dual_pie_with_plotly(data_left: Dataset | DataFrame | Series, data_right: Dataset | DataFrame | Series, colors: ColorType | None = None, title: str = '', subtitles: tuple[str, str] = ('Left Chart', 'Right Chart'), legend_title: str = '', hole: float = 0.2, lower_percentage_group: float = 5.0, text_info: str = 'percent+label', text_position: str = 'inside', hover_template: str = '%{label}: %{value} (%{percent})') -> go.Figure

Create two pie charts side by side with Plotly.

Parameters:

Name Type Description Default
data_left Dataset | DataFrame | Series

Data for the left pie chart. Variables are summed across all dimensions.

required
data_right Dataset | DataFrame | Series

Data for the right pie chart. Variables are summed across all dimensions.

required
colors ColorType | None

Color specification (colorscale name, list of colors, or dict mapping)

None
title str

The main title of the plot.

''
subtitles tuple[str, str]

Tuple containing the subtitles for (left, right) charts.

('Left Chart', 'Right Chart')
legend_title str

The title for the legend.

''
hole float

Size of the hole in the center for creating donut charts (0.0 to 1.0).

0.2
lower_percentage_group float

Group segments whose cumulative share is below this percentage (0–100) into "Other".

5.0
hover_template str

Template for hover text. Use %{label}, %{value}, %{percent}.

'%{label}: %{value} (%{percent})'
text_info str

What to show on pie segments: 'label', 'percent', 'value', 'label+percent', 'label+value', 'percent+value', 'label+percent+value', or 'none'.

'percent+label'
text_position str

Position of text: 'inside', 'outside', 'auto', or 'none'.

'inside'

Returns:

Type Description
Figure

Plotly Figure object

dual_pie_with_matplotlib

Python
dual_pie_with_matplotlib(data_left: Dataset | DataFrame | Series, data_right: Dataset | DataFrame | Series, colors: ColorType | None = None, title: str = '', subtitles: tuple[str, str] = ('Left Chart', 'Right Chart'), legend_title: str = '', hole: float = 0.2, lower_percentage_group: float = 5.0, figsize: tuple[int, int] = (14, 7)) -> tuple[plt.Figure, list[plt.Axes]]

Create two pie charts side by side with Matplotlib.

Parameters:

Name Type Description Default
data_left Dataset | DataFrame | Series

Data for the left pie chart.

required
data_right Dataset | DataFrame | Series

Data for the right pie chart.

required
colors ColorType | None

Color specification (colorscale name, list of colors, or dict mapping)

None
title str

The main title of the plot.

''
subtitles tuple[str, str]

Tuple containing the subtitles for (left, right) charts.

('Left Chart', 'Right Chart')
legend_title str

The title for the legend.

''
hole float

Size of the hole in the center for creating donut charts (0.0 to 1.0).

0.2
lower_percentage_group float

Whether to group small segments (below percentage) into an "Other" category.

5.0
figsize tuple[int, int]

The size of the figure (width, height) in inches.

(14, 7)

Returns:

Type Description
tuple[Figure, list[Axes]]

Tuple of (Figure, list of Axes)

heatmap_with_plotly

Python
heatmap_with_plotly(data: DataArray, colors: ColorType | None = None, title: str = '', facet_by: str | list[str] | None = None, animate_by: str | None = None, facet_cols: int | None = None, reshape_time: tuple[Literal['YS', 'MS', 'W', 'D', 'h', '15min', 'min'], Literal['W', 'D', 'h', '15min', 'min']] | Literal['auto'] | None = 'auto', fill: Literal['ffill', 'bfill'] | None = 'ffill', **imshow_kwargs: Any) -> go.Figure

Plot a heatmap visualization using Plotly's imshow with faceting and animation support.

This function creates heatmap visualizations from xarray DataArrays, supporting multi-dimensional data through faceting (subplots) and animation. It automatically handles dimension reduction and data reshaping for optimal heatmap display.

Automatic Time Reshaping

If only the 'time' dimension remains after faceting/animation (making the data 1D), the function automatically reshapes time into a 2D format using default values (timeframes='D', timesteps_per_frame='h'). This creates a daily pattern heatmap showing hours vs days.

Parameters:

Name Type Description Default
data DataArray

An xarray DataArray containing the data to visualize. Should have at least 2 dimensions, or a 'time' dimension that can be reshaped into 2D.

required
colors ColorType | None

Color specification (colorscale name, list, or dict). Common options: 'turbo', 'plasma', 'RdBu', 'portland'.

None
title str

The main title of the heatmap.

''
facet_by str | list[str] | None

Dimension to create facets for. Creates a subplot grid. Can be a single dimension name or list (only first dimension used). Note: px.imshow only supports single-dimension faceting. If the dimension doesn't exist in the data, it will be silently ignored.

None
animate_by str | None

Dimension to animate over. Creates animation frames. If the dimension doesn't exist in the data, it will be silently ignored.

None
facet_cols int | None

Number of columns in the facet grid (used with facet_by).

None
reshape_time tuple[Literal['YS', 'MS', 'W', 'D', 'h', '15min', 'min'], Literal['W', 'D', 'h', '15min', 'min']] | Literal['auto'] | None

Time reshaping configuration: - 'auto' (default): Automatically applies ('D', 'h') if only 'time' dimension remains - Tuple like ('D', 'h'): Explicit time reshaping (days vs hours) - None: Disable time reshaping (will error if only 1D time data)

'auto'
fill Literal['ffill', 'bfill'] | None

Method to fill missing values when reshaping time: 'ffill' or 'bfill'. Default is 'ffill'.

'ffill'
**imshow_kwargs Any

Additional keyword arguments to pass to plotly.express.imshow. Common options include: - aspect: 'auto', 'equal', or a number for aspect ratio - zmin, zmax: Minimum and maximum values for color scale - labels: Dict to customize axis labels

{}

Returns:

Type Description
Figure

A Plotly figure object containing the heatmap visualization.

Examples:

Simple heatmap:

Python
fig = heatmap_with_plotly(data_array, colors='RdBu', title='Temperature Map')

Facet by scenario:

Python
fig = heatmap_with_plotly(data_array, facet_by='scenario', facet_cols=2)

Animate by period:

Python
fig = heatmap_with_plotly(data_array, animate_by='period')

Automatic time reshaping (when only time dimension remains):

Python
# Data with dims ['time', 'scenario', 'period']
# After faceting and animation, only 'time' remains -> auto-reshapes to (timestep, timeframe)
fig = heatmap_with_plotly(data_array, facet_by='scenario', animate_by='period')

Explicit time reshaping:

Python
fig = heatmap_with_plotly(data_array, facet_by='scenario', animate_by='period', reshape_time=('W', 'D'))

heatmap_with_matplotlib

Python
heatmap_with_matplotlib(data: DataArray, colors: ColorType | None = None, title: str = '', figsize: tuple[float, float] = (12, 6), reshape_time: tuple[Literal['YS', 'MS', 'W', 'D', 'h', '15min', 'min'], Literal['W', 'D', 'h', '15min', 'min']] | Literal['auto'] | None = 'auto', fill: Literal['ffill', 'bfill'] | None = 'ffill', vmin: float | None = None, vmax: float | None = None, imshow_kwargs: dict[str, Any] | None = None, cbar_kwargs: dict[str, Any] | None = None, **kwargs: Any) -> tuple[plt.Figure, plt.Axes]

Plot a heatmap visualization using Matplotlib's imshow.

This function creates a basic 2D heatmap from an xarray DataArray using matplotlib's imshow function. For multi-dimensional data, only the first two dimensions are used.

Parameters:

Name Type Description Default
data DataArray

An xarray DataArray containing the data to visualize. Should have at least 2 dimensions. If more than 2 dimensions exist, additional dimensions will be reduced by taking the first slice.

required
colors ColorType | None

Color specification. Should be a colorscale name (e.g., 'turbo', 'RdBu').

None
title str

The title of the heatmap.

''
figsize tuple[float, float]

The size of the figure (width, height) in inches.

(12, 6)
reshape_time tuple[Literal['YS', 'MS', 'W', 'D', 'h', '15min', 'min'], Literal['W', 'D', 'h', '15min', 'min']] | Literal['auto'] | None

Time reshaping configuration: - 'auto' (default): Automatically applies ('D', 'h') if only 'time' dimension - Tuple like ('D', 'h'): Explicit time reshaping (days vs hours) - None: Disable time reshaping

'auto'
fill Literal['ffill', 'bfill'] | None

Method to fill missing values when reshaping time: 'ffill' or 'bfill'. Default is 'ffill'.

'ffill'
vmin float | None

Minimum value for color scale. If None, uses data minimum.

None
vmax float | None

Maximum value for color scale. If None, uses data maximum.

None
imshow_kwargs dict[str, Any] | None

Optional dict of parameters to pass to ax.imshow(). Use this to customize image properties (e.g., interpolation, aspect).

None
cbar_kwargs dict[str, Any] | None

Optional dict of parameters to pass to plt.colorbar(). Use this to customize colorbar properties (e.g., orientation, label).

None
**kwargs Any

Additional keyword arguments passed to ax.imshow(). Common options include: - interpolation: 'nearest', 'bilinear', 'bicubic', etc. - alpha: Transparency level (0-1) - extent: [left, right, bottom, top] for axis limits

{}

Returns:

Type Description
tuple[Figure, Axes]

A tuple containing the Matplotlib figure and axes objects used for the plot.

Notes
  • Matplotlib backend doesn't support faceting or animation. Use plotly engine for those features.
  • The y-axis is automatically inverted to display data with origin at top-left.
  • A colorbar is added to show the value scale.

Examples:

Python
fig, ax = heatmap_with_matplotlib(data_array, colors='RdBu', title='Temperature')
plt.savefig('heatmap.png')

Time reshaping:

Python
fig, ax = heatmap_with_matplotlib(data_array, reshape_time=('D', 'h'))

export_figure

Python
export_figure(figure_like: Figure | tuple[Figure, Axes], default_path: Path, default_filetype: str | None = None, user_path: Path | None = None, show: bool | None = None, save: bool = False, dpi: int | None = None) -> go.Figure | tuple[plt.Figure, plt.Axes]

Export a figure to a file and or show it.

Parameters:

Name Type Description Default
figure_like Figure | tuple[Figure, Axes]

The figure to export. Can be a Plotly figure or a tuple of Matplotlib figure and axes.

required
default_path Path

The default file path if no user filename is provided.

required
default_filetype str | None

The default filetype if the path doesnt end with a filetype.

None
user_path Path | None

An optional user-specified file path.

None
show bool | None

Whether to display the figure. If None, uses CONFIG.Plotting.default_show (default: None).

None
save bool

Whether to save the figure (default: False).

False
dpi int | None

DPI (dots per inch) for saving Matplotlib figures. If None, uses CONFIG.Plotting.default_dpi.

None

Raises:

Type Description
ValueError

If no default filetype is provided and the path doesn't specify a filetype.

TypeError

If the figure type is not supported.