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
Flexible color specification type supporting multiple input formats for visualization.
Color specifications can take several forms to accommodate different use cases:
Named Colormaps (str): - Standard colormaps: 'viridis', 'plasma', 'cividis', 'tab10', 'Set1' - Energy-focused: 'portland' (custom flixopt colormap 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:
# Named colormap
colors = 'viridis' # 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 Colormaps: https://matplotlib.org/stable/tutorials/colors/colormaps.html
- Plotly Built-in Colorscales: https://plotly.com/python/builtin-colorscales/
PlottingEngine
module-attribute
Identifier for the plotting engine to use.
Classes
ColorProcessor
Intelligent color management system for consistent multi-backend visualization.
This class provides unified color processing across Plotly and Matplotlib backends, ensuring consistent visual appearance regardless of the plotting engine used. It handles color palette generation, named colormap translation, and intelligent color cycling for complex datasets with many categories.
Key Features
Backend Agnostic: Automatic color format conversion between engines Palette Management: Support for named colormaps, custom palettes, and color lists Intelligent Cycling: Smart color assignment for datasets with many categories Fallback Handling: Graceful degradation when requested colormaps are unavailable Energy System Colors: Built-in palettes optimized for energy system visualization
Color Input Types
- Named Colormaps: 'viridis', 'plasma', 'portland', 'tab10', etc.
- Color Lists: ['red', 'blue', 'green'] or ['#FF0000', '#0000FF', '#00FF00']
- Label Dictionaries: {'Generator': 'red', 'Storage': 'blue', 'Load': 'green'}
Examples:
Basic color processing:
# Initialize for Plotly backend
processor = ColorProcessor(engine='plotly', default_colormap='viridis')
# Process different color specifications
colors = processor.process_colors('plasma', ['Gen1', 'Gen2', 'Storage'])
colors = processor.process_colors(['red', 'blue', 'green'], ['A', 'B', 'C'])
colors = processor.process_colors({'Wind': 'skyblue', 'Solar': 'gold'}, ['Wind', 'Solar', 'Gas'])
# Switch to Matplotlib
processor = ColorProcessor(engine='matplotlib')
mpl_colors = processor.process_colors('tab10', component_labels)
Energy system visualization:
# Specialized energy system palette
energy_colors = {
'Natural_Gas': '#8B4513', # Brown
'Electricity': '#FFD700', # Gold
'Heat': '#FF4500', # Red-orange
'Cooling': '#87CEEB', # Sky blue
'Hydrogen': '#E6E6FA', # Lavender
'Battery': '#32CD32', # Lime green
}
processor = ColorProcessor('plotly')
flow_colors = processor.process_colors(energy_colors, flow_labels)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
engine
|
PlottingEngine
|
Plotting backend ('plotly' or 'matplotlib'). Determines output color format. |
'plotly'
|
default_colormap
|
str
|
Fallback colormap when requested palettes are unavailable. Common options: 'viridis', 'plasma', 'tab10', 'portland'. |
'viridis'
|
Initialize the color processor with specified backend and defaults.
Functions
process_colors
process_colors(colors: ColorType, labels: list[str], return_mapping: bool = False) -> list[Any] | dict[str, Any]
Process colors for the specified labels.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
colors
|
ColorType
|
Color specification (colormap name, list of colors, or label-to-color mapping) |
required |
labels
|
list[str]
|
list of data labels that need colors assigned |
required |
return_mapping
|
bool
|
If True, returns a dictionary mapping labels to colors; if False, returns a list of colors in the same order as labels |
False
|
Returns:
Type | Description |
---|---|
list[Any] | dict[str, Any]
|
Either a list of colors or a dictionary mapping labels to colors |
Functions
with_plotly
with_plotly(data: DataFrame, style: Literal['stacked_bar', 'line', 'area', 'grouped_bar'] = 'stacked_bar', colors: ColorType = 'viridis', title: str = '', ylabel: str = '', xlabel: str = 'Time in h', fig: Figure | None = None) -> go.Figure
Plot a DataFrame with Plotly, using either stacked bars or stepped lines.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
DataFrame
|
A DataFrame containing the data to plot, where the index represents time (e.g., hours), and each column represents a separate data series. |
required |
style
|
Literal['stacked_bar', 'line', 'area', 'grouped_bar']
|
The plotting style. Use 'stacked_bar' for stacked bar charts, 'line' for stepped lines, or 'area' for stacked area charts. |
'stacked_bar'
|
colors
|
ColorType
|
Color specification, can be: - A string with a colorscale name (e.g., 'viridis', 'plasma') - A list of color strings (e.g., ['#ff0000', '#00ff00']) - A dictionary mapping column names to colors (e.g., {'Column1': '#ff0000'}) |
'viridis'
|
title
|
str
|
The title of the plot. |
''
|
ylabel
|
str
|
The label for the y-axis. |
''
|
xlabel
|
str
|
The label for the x-axis. |
'Time in h'
|
fig
|
Figure | None
|
A Plotly figure object to plot on. If not provided, a new figure will be created. |
None
|
Returns:
Type | Description |
---|---|
Figure
|
A Plotly figure object containing the generated plot. |
with_matplotlib
with_matplotlib(data: DataFrame, style: Literal['stacked_bar', 'line'] = 'stacked_bar', colors: ColorType = 'viridis', title: str = '', ylabel: str = '', xlabel: str = 'Time in h', figsize: tuple[int, int] = (12, 6), fig: Figure | None = None, ax: Axes | None = None) -> tuple[plt.Figure, plt.Axes]
Plot a DataFrame with Matplotlib using stacked bars or stepped lines.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
DataFrame
|
A DataFrame containing the data to plot. The index should represent time (e.g., hours), and each column represents a separate data series. |
required |
style
|
Literal['stacked_bar', 'line']
|
Plotting style. Use 'stacked_bar' for stacked bar charts or 'line' for stepped lines. |
'stacked_bar'
|
colors
|
ColorType
|
Color specification, can be: - A string with a colormap name (e.g., 'viridis', 'plasma') - A list of color strings (e.g., ['#ff0000', '#00ff00']) - A dictionary mapping column names to colors (e.g., {'Column1': '#ff0000'}) |
'viridis'
|
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 |
(12, 6)
|
fig
|
Figure | None
|
A Matplotlib figure object to plot on. If not provided, a new figure will be created. |
None
|
ax
|
Axes | None
|
A Matplotlib axes object to plot on. If not provided, a new axes will be created. |
None
|
Returns:
Type | Description |
---|---|
tuple[Figure, Axes]
|
A tuple containing the Matplotlib figure and axes objects used for the plot. |
Notes
- If
style
is 'stacked_bar', bars are stacked for both positive and negative values. Negative values are stacked separately without extra labels in the legend. - If
style
is 'line', stepped lines are drawn for each data series.
heat_map_matplotlib
heat_map_matplotlib(data: DataFrame, color_map: str = 'viridis', title: str = '', xlabel: str = 'Period', ylabel: str = 'Step', figsize: tuple[float, float] = (12, 6)) -> tuple[plt.Figure, plt.Axes]
Plots a DataFrame as a heatmap using Matplotlib. The columns of the DataFrame will be displayed on the x-axis, the index will be displayed on the y-axis, and the values will represent the 'heat' intensity in the plot.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
DataFrame
|
A DataFrame containing the data to be visualized. The index will be used for the y-axis, and columns will be used for the x-axis. The values in the DataFrame will be represented as colors in the heatmap. |
required |
color_map
|
str
|
The colormap to use for the heatmap. Default is 'viridis'. Matplotlib supports various colormaps like 'plasma', 'inferno', 'cividis', etc. |
'viridis'
|
title
|
str
|
The title of the plot. |
''
|
xlabel
|
str
|
The label for the x-axis. |
'Period'
|
ylabel
|
str
|
The label for the y-axis. |
'Step'
|
figsize
|
tuple[float, float]
|
The size of the figure to create. Default is (12, 6), which results in a width of 12 inches and a height of 6 inches. |
(12, 6)
|
Returns:
Type | Description |
---|---|
Figure
|
A tuple containing the Matplotlib |
Axes
|
where the heatmap is drawn. These can be used for further customization or saving the plot to a file. |
Notes
- The y-axis is flipped so that the first row of the DataFrame is displayed at the top of the plot.
- The color scale is normalized based on the minimum and maximum values in the DataFrame.
- The x-axis labels (periods) are placed at the top of the plot.
- The colorbar is added horizontally at the bottom of the plot, with a label.
heat_map_plotly
heat_map_plotly(data: DataFrame, color_map: str = 'viridis', title: str = '', xlabel: str = 'Period', ylabel: str = 'Step', categorical_labels: bool = True) -> go.Figure
Plots a DataFrame as a heatmap using Plotly. The columns of the DataFrame will be mapped to the x-axis, and the index will be displayed on the y-axis. The values in the DataFrame will represent the 'heat' in the plot.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
DataFrame
|
A DataFrame with the data to be visualized. The index will be used for the y-axis, and columns will be used for the x-axis. The values in the DataFrame will be represented as colors in the heatmap. |
required |
color_map
|
str
|
The color scale to use for the heatmap. Default is 'viridis'. Plotly supports various color scales like 'Cividis', 'Inferno', etc. |
'viridis'
|
title
|
str
|
The title of the heatmap. Default is an empty string. |
''
|
xlabel
|
str
|
The label for the x-axis. Default is 'Period'. |
'Period'
|
ylabel
|
str
|
The label for the y-axis. Default is 'Step'. |
'Step'
|
categorical_labels
|
bool
|
If True, the x and y axes are treated as categorical data (i.e., the index and columns will not be interpreted as continuous data). Default is True. If False, the axes are treated as continuous, which may be useful for time series or numeric data. |
True
|
Returns:
Type | Description |
---|---|
Figure
|
A Plotly figure object containing the heatmap. This can be further customized and saved |
Figure
|
or displayed using |
Notes
The color bar is automatically scaled to the minimum and maximum values in the data. The y-axis is reversed to display the first row at the top.
reshape_to_2d
Reshapes a 1D numpy array into a 2D array suitable for plotting as a colormap.
The reshaped array will have the number of rows corresponding to the steps per column (e.g., 24 hours per day) and columns representing time periods (e.g., days or months).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data_1d
|
ndarray
|
A 1D numpy array with the data to reshape. |
required |
nr_of_steps_per_column
|
int
|
The number of steps (rows) per column in the resulting 2D array. For example, this could be 24 (for hours) or 31 (for days in a month). |
required |
Returns:
Type | Description |
---|---|
ndarray
|
The reshaped 2D array. Each internal array corresponds to one column, with the specified number of steps. |
ndarray
|
Each column might represents a time period (e.g., day, month, etc.). |
heat_map_data_from_df
heat_map_data_from_df(df: DataFrame, periods: Literal['YS', 'MS', 'W', 'D', 'h', '15min', 'min'], steps_per_period: Literal['W', 'D', 'h', '15min', 'min'], fill: Literal['ffill', 'bfill'] | None = None) -> pd.DataFrame
Reshapes a DataFrame with a DateTime index into a 2D array for heatmap plotting,
based on a specified sample rate.
Only specific combinations of periods
and steps_per_period
are supported; invalid combinations raise an assertion.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
df
|
DataFrame
|
A DataFrame with a DateTime index containing the data to reshape. |
required |
periods
|
Literal['YS', 'MS', 'W', 'D', 'h', '15min', 'min']
|
The time interval of each period (columns of the heatmap), such as 'YS' (year start), 'W' (weekly), 'D' (daily), 'h' (hourly) etc. |
required |
steps_per_period
|
Literal['W', 'D', 'h', '15min', 'min']
|
The time interval within each period (rows in the heatmap), such as 'YS' (year start), 'W' (weekly), 'D' (daily), 'h' (hourly) etc. |
required |
fill
|
Literal['ffill', 'bfill'] | None
|
Method to fill missing values: 'ffill' for forward fill or 'bfill' for backward fill. |
None
|
Returns:
Type | Description |
---|---|
DataFrame
|
A DataFrame suitable for heatmap plotting, with rows representing steps within each period |
DataFrame
|
and columns representing each period. |
plot_network
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. |
None
|
controls
|
bool | list[Literal['nodes', 'edges', 'layout', 'interaction', 'manipulation', 'physics', 'selection', 'renderer']]
|
UI controls to add to the visualization. |
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.
pie_with_plotly
pie_with_plotly(data: DataFrame, colors: ColorType = 'viridis', title: str = '', legend_title: str = '', hole: float = 0.0, fig: Figure | None = None) -> go.Figure
Create a pie chart with Plotly to visualize the proportion of values in a DataFrame.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
DataFrame
|
A DataFrame containing the data to plot. If multiple rows exist, they will be summed unless a specific index value is passed. |
required |
colors
|
ColorType
|
Color specification, can be: - A string with a colorscale name (e.g., 'viridis', 'plasma') - A list of color strings (e.g., ['#ff0000', '#00ff00']) - A dictionary mapping column names to colors (e.g., {'Column1': '#ff0000'}) |
'viridis'
|
title
|
str
|
The title of the plot. |
''
|
legend_title
|
str
|
The title for the legend. |
''
|
hole
|
float
|
Size of the hole in the center for creating a donut chart (0.0 to 1.0). |
0.0
|
fig
|
Figure | None
|
A Plotly figure object to plot on. If not provided, a new figure will be created. |
None
|
Returns:
Type | Description |
---|---|
Figure
|
A Plotly figure object containing the generated pie chart. |
Notes
- Negative values are not appropriate for pie charts and will be converted to absolute values with a warning.
- If the data contains very small values (less than 1% of the total), they can be grouped into an "Other" category for better readability.
- By default, the sum of all columns is used for the pie chart. For time series data, consider preprocessing.
pie_with_matplotlib
pie_with_matplotlib(data: DataFrame, colors: ColorType = 'viridis', title: str = '', legend_title: str = 'Categories', hole: float = 0.0, figsize: tuple[int, int] = (10, 8), fig: Figure | None = None, ax: Axes | None = None) -> tuple[plt.Figure, plt.Axes]
Create a pie chart with Matplotlib to visualize the proportion of values in a DataFrame.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data
|
DataFrame
|
A DataFrame containing the data to plot. If multiple rows exist, they will be summed unless a specific index value is passed. |
required |
colors
|
ColorType
|
Color specification, can be: - A string with a colormap name (e.g., 'viridis', 'plasma') - A list of color strings (e.g., ['#ff0000', '#00ff00']) - A dictionary mapping column names to colors (e.g., {'Column1': '#ff0000'}) |
'viridis'
|
title
|
str
|
The title of the plot. |
''
|
legend_title
|
str
|
The title for the legend. |
'Categories'
|
hole
|
float
|
Size of the hole in the center for creating a donut chart (0.0 to 1.0). |
0.0
|
figsize
|
tuple[int, int]
|
The size of the figure (width, height) in inches. |
(10, 8)
|
fig
|
Figure | None
|
A Matplotlib figure object to plot on. If not provided, a new figure will be created. |
None
|
ax
|
Axes | None
|
A Matplotlib axes object to plot on. If not provided, a new axes will be created. |
None
|
Returns:
Type | Description |
---|---|
tuple[Figure, Axes]
|
A tuple containing the Matplotlib figure and axes objects used for the plot. |
Notes
- Negative values are not appropriate for pie charts and will be converted to absolute values with a warning.
- If the data contains very small values (less than 1% of the total), they can be grouped into an "Other" category for better readability.
- By default, the sum of all columns is used for the pie chart. For time series data, consider preprocessing.
dual_pie_with_plotly
dual_pie_with_plotly(data_left: Series, data_right: Series, colors: ColorType = 'viridis', title: str = '', subtitles: tuple[str, str] = ('Left Chart', 'Right Chart'), legend_title: str = '', hole: float = 0.2, lower_percentage_group: float = 5.0, hover_template: str = '%{label}: %{value} (%{percent})', text_info: str = 'percent+label', text_position: str = 'inside') -> go.Figure
Create two pie charts side by side with Plotly, with consistent coloring across both charts.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data_left
|
Series
|
Series for the left pie chart. |
required |
data_right
|
Series
|
Series for the right pie chart. |
required |
colors
|
ColorType
|
Color specification, can be: - A string with a colorscale name (e.g., 'viridis', 'plasma') - A list of color strings (e.g., ['#ff0000', '#00ff00']) - A dictionary mapping category names to colors (e.g., {'Category1': '#ff0000'}) |
'viridis'
|
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
|
A Plotly figure object containing the generated dual pie chart. |
dual_pie_with_matplotlib
dual_pie_with_matplotlib(data_left: Series, data_right: Series, colors: ColorType = 'viridis', 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), fig: Figure | None = None, axes: list[Axes] | None = None) -> tuple[plt.Figure, list[plt.Axes]]
Create two pie charts side by side with Matplotlib, with consistent coloring across both charts. Leverages the existing pie_with_matplotlib function.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
data_left
|
Series
|
Series for the left pie chart. |
required |
data_right
|
Series
|
Series for the right pie chart. |
required |
colors
|
ColorType
|
Color specification, can be: - A string with a colormap name (e.g., 'viridis', 'plasma') - A list of color strings (e.g., ['#ff0000', '#00ff00']) - A dictionary mapping category names to colors (e.g., {'Category1': '#ff0000'}) |
'viridis'
|
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)
|
fig
|
Figure | None
|
A Matplotlib figure object to plot on. If not provided, a new figure will be created. |
None
|
axes
|
list[Axes] | None
|
A list of Matplotlib axes objects to plot on. If not provided, new axes will be created. |
None
|
Returns:
Type | Description |
---|---|
tuple[Figure, list[Axes]]
|
A tuple containing the Matplotlib figure and list of axes objects used for the plot. |
export_figure
export_figure(figure_like: Figure | tuple[Figure, Axes], default_path: Path, default_filetype: str | None = None, user_path: Path | None = None, show: bool = True, save: bool = False) -> 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
|
Whether to display the figure (default: True). |
True
|
save
|
bool
|
Whether to save the figure (default: False). |
False
|
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. |