Plotting heatmaps
When running a set of KMC simulations at various operating conditions, 2D heatmaps can be created using various specialized plot_X functions such as plot_tof or plot_selectivity.
Parameters
Mandatory parameters for all plot types
ax(matplotlib.axes.Axes): Axis object where the contour plot should be created.scan_path(str): Path of the directory containing all the scan jobs.x(str): Magnitude to plot on the x-axis. Possible values:'pressure_X', whereXis a gas species.'temperature'.'total_pressure'.
y(str): Magnitude to plot on the y-axis. Possible values:'pressure_Y', whereYis a gas species.'temperature'.'total_pressure'.
Depending on the type of plot, some additional parameters might be needed (see below).
Optional parameters
cmap(str): Colormap used to map scalar data to colors. Accepts colormap instances or registered names.
Default: depends on the function.show_points(bool): Displays grid points as black dots ifTrue.
Default:False.show_colorbar(bool): Displays the colorbar ifTrue.
Default:True.auto_title(bool): Automatically generates titles for subplots ifTrue.
Default:False.
Heatmap types
TOF (Turnover Frequency)
Plot the TOF (in molec·s⁻¹·Å⁻²) of a given gas-phase species.
Additional parameters:
Mandatory:
gas_spec(str): Name of the gas-phase species for the TOF difference calculation.
Optional:
min_molec(int): Minimum total production in both main and reference simulations to consider the result valid.
Default:1.weights(str): Weights for the averages. Possible values:'time''events'None(all weights are set to 1)
Default:None.
levels(listornp.ndarray): Contour levels to use in the plot. When provided, TOF values are clipped to the minimum and maximum values in this list.analysis_range(list): Portion of the simulation data to analyze.
Default:[0, 100].range_type(str): The type of window to apply. Possible values:'time'(based on simulated time)'nevents'(based on the number of events)
Default:'time'.
show_max(bool): Display a golden'*'marker at the point with the highest TOF.
Default:False.
Example:
import numpy as np
import matplotlib.pyplot as plt
from zacrostools.plot_functions.tof import plot_tof
fig, axs = plt.subplots(1, figsize=(4.3, 3.5))
plot_tof(
ax=axs,
scan_path='simulation_results',
x='pressure_CH4',
y='pressure_CO2',
gas_spec='H2',
# Changed default is now 1, but we can override as needed:
min_molec=0,
# analysis_range is used to specify which portion of the simulation to analyze:
analysis_range=[50, 100],
range_type='time',
# If levels are not provided, the function auto-scales the TOF data:
levels=np.logspace(-1, 4, num=11),
auto_title=True,
show_points=False,
show_colorbar=True
)
plt.tight_layout()
plt.savefig('tof_heatmap.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
∆TOF (Delta TOF)
Plot the difference in Turnover Frequencies (TOF) between a main simulation and a reference simulation for a specified gas-phase species. The difference can be either absolute (main - reference) or relative (percentage difference).
Additional parameters:
Mandatory:
gas_spec(str): Name of the gas-phase species for the TOF difference calculation.scan_path_ref(str): Path to the reference simulation directories.
Optional:
difference_type(str): Type of TOF difference to compute. Must be either'absolute'or'relative'.
Default:'absolute'.scale(str): Determines the color scaling of the difference. Possible values:'log''lin'
Default:'log'.
min_molec(int): Minimum total production in both main and reference simulations to consider the result valid.
Default:1.max_dtof(float): Maximum absolute value for (\Delta)TOF. For relative differences, the default is 100. If provided, values above (or below the negative) limit are clipped.min_dtof(float): Threshold that defines the smallest nonzero (\Delta)TOF to display. By default, it’s set automatically (depending onmax_dtof).nlevels(int): Number of discrete boundaries if you want to segment the (\Delta)TOF scale.0: use continuous normalization.Must be a positive odd integer (
>=3) for discrete normalization.
Default:0.
weights(str): Weights for the averages. Possible values:'time''events'None(all weights are set to 1)
Default:None.
analysis_range(list): Portion of the simulation data to analyze.
Default:[0, 100].range_type(str): The type of window to apply. Possible values:'time''nevents'
Default:'time'.
Example:
import matplotlib.pyplot as plt
from zacrostools.plot_functions.dtof import plot_dtof
fig, ax = plt.subplots(1, figsize=(4.3, 3.5))
plot_dtof(
ax=ax,
scan_path='simulation_results',
scan_path_ref='reference_results',
x='pressure_CH4',
y='pressure_CO2',
gas_spec='H2',
difference_type='absolute',
scale='log',
min_molec=0,
nlevels=11,
analysis_range=[50, 100],
range_type='time',
auto_title=True,
show_points=False,
show_colorbar=True
)
plt.tight_layout()
plt.savefig('dtof_heatmap.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
Selectivity (%)
Plot the selectivity (in %) of a main product with respect to one or more side products.
Additional parameters:
Mandatory:
main_product(str): Name of the main product for the selectivity calculation.side_products(list): List of side products for the selectivity calculation.
Optional:
min_molec(int): Minimum combined production (main + side products) required for a valid selectivity value.
Default:1.weights(str): Weights for the averages. Possible values:'time''events'None(all weights are set to 1)
Default:None.
levels(listornp.ndarray): Contour levels to use in the plot (e.g.,np.linspace(0, 100, 11, dtype=int)). If provided, selectivity values are clipped to the minimum and maximum values in this list.
Default:np.linspace(0, 100, 11, dtype=int).analysis_range(list): Portion of the simulation data to analyze.
Default:[0, 100].range_type(str): The type of window to apply. Possible values:'time''nevents'
Default:'time'.
cmap(str): Colormap used to map scalar data to colors.
Default:'Greens'.
Example:
import numpy as np
import matplotlib.pyplot as plt
from zacrostools.plot_functions.selectivity import plot_selectivity
fig, ax = plt.subplots(1, figsize=(4.3, 3.5))
plot_selectivity(
ax=ax,
scan_path='simulation_results',
x='pressure_CH4',
y='pressure_CO2',
main_product='H2',
side_products=['H2O'],
min_molec=100,
analysis_range=[50, 100],
range_type='time',
auto_title=True,
show_points=False,
show_colorbar=True
)
plt.tight_layout()
plt.savefig('selectivity_heatmap.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
Coverage (%)
Plot the coverage (in %) of specified surface species (or total coverage) on a given site type.
Additional parameters:
Mandatory:
surf_spec(strorlist): Surface species to include in the coverage calculation.'all': Total coverage (of all adsorbates) is shown.A single species name (
'CO*') or a list of species (['CH*', 'C*']) can also be provided.
Optional:
site_type(str): The site type on which coverage is computed.
Default:'default'.weights(str): Weights for the averages. Possible values:'time''events'None(all weights are set to 1)
Default:None.
levels(listornp.ndarray): Contour levels to use in the plot (e.g.,np.linspace(0, 100, 11, dtype=int)). If provided, coverage values are clipped to the minimum and maximum values in this list.
Default:np.linspace(0, 100, 11, dtype=int).analysis_range(list): Portion of the simulation data to analyze.
Default:[0, 100].range_type(str): The type of window to apply. Possible values:'time''nevents'
Default:'time'.
cmap(str): Colormap used to map scalar data to colors.
Default:'Oranges'.
Example:
import numpy as np
import matplotlib.pyplot as plt
from zacrostools.plot_functions.coverage import plot_coverage
fig, ax = plt.subplots(1, figsize=(4.3, 3.5))
plot_coverage(
ax=ax,
scan_path='simulation_results',
x='pressure_CH4',
y='pressure_CO2',
surf_spec='all',
site_type='tC',
weights='time',
analysis_range=[50, 100],
range_type='time',
auto_title=True,
show_points=False,
show_colorbar=True
)
plt.tight_layout()
plt.savefig('coverage_heatmap.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
Phase Diagram
Plot a phase diagram where each point is assigned a dominant surface species (or NaN if coverage is too low). The color encodes these dominant species, grouped according to user-provided or auto-generated labels.
Additional parameters:
(No additional mandatory parameters are required.)
Optional:
site_type(str): Site type to consider when retrieving the dominant surface species.
Default:'default'.min_coverage(floatorint): Minimum coverage threshold (%) for a species to be considered dominant.
Default:50.0.tick_labels(dict): Custom mapping for species grouping and colorbar labels. The keys are used as colorbar labels (e.g.,'$CH_{x}$'), and the values are lists of species names (e.g.,['CH3', 'CH2', 'C']). When not provided, the function automatically parses asimulation_input.datfile from the first simulation directory to assign each species to its own group.weights(str): Weights for the averages. Possible values:'time''events'None(all weights are set to 1)
Default:None.
analysis_range(list): Portion of the simulation data to analyze.
Default:[0, 100].range_type(str): The type of window to apply. Possible values:'time''nevents'
Default:'time'.
Example:
import matplotlib.pyplot as plt
from zacrostools.plot_functions.phasediagram import plot_phasediagram
tick_labels = {
'$CH_{x}$': ['CH3', 'CH3_Pt', 'CH2', 'CH2_Pt', 'CH',
'CH_Pt', 'C', 'C_Pt'],
'$CHO/COH$': ['CHO', 'CHO_Pt', 'COH', 'COH_Pt'],
'$CO$': ['CO', 'CO_Pt'],
'$COOH$': ['COOH', 'COOH_Pt'],
'$CO_{2}$': ['CO2', 'CO2_Pt'],
'$H$': ['H', 'H_Pt'],
'$H_{2}O$': ['H2O', 'H2O_Pt'],
'$OH$': ['OH', 'OH_Pt'],
'$O$': ['O', 'O_Pt']
}
fig, ax = plt.subplots(1, figsize=(4.3, 3.5))
plot_phasediagram(
ax=ax,
scan_path='simulation_results',
x='pressure_CO2',
y='pressure_CH4',
site_type='tC',
min_coverage=50.0,
tick_labels=tick_labels,
weights='time',
analysis_range=[50, 100],
range_type='time',
auto_title=True,
show_points=False,
show_colorbar=True
)
plt.tight_layout()
plt.savefig('phase_diagram.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
Final Time (s)
Plot the final simulation time (in seconds) for each job in a 2D heatmap. The color scale is logarithmically normalized.
Additional parameters:
(No additional mandatory parameters are required.)
Optional:
levels(listornp.ndarray): Contour levels for the plot. If provided, final time values are clipped to the minimum and maximum in this list.
Default:None.
Example:
import numpy as np
import matplotlib.pyplot as plt
from zacrostools.plot_functions.finaltime import plot_finaltime
fig, ax = plt.subplots(1, figsize=(4.3, 3.5))
plot_finaltime(
ax=ax,
scan_path='simulation_results',
x='pressure_CH4',
y='pressure_CO2',
levels=np.logspace(-5, 7, num=13),
show_points=False,
show_colorbar=True,
auto_title=True
)
plt.tight_layout()
plt.savefig('finaltime_heatmap.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
Energy Slope
Plot the energy slope computed during the KMC simulation in a 2D heatmap. By default, data are shown on a logarithmic scale (using LogNorm).
Additional parameters:
(No additional mandatory parameters are required.)
Optional:
levels(listornp.ndarray): Levels for normalization. If provided, the color scale is clipped betweenmin(levels)andmax(levels).
Default:np.logspace(-11, -8, num=7).analysis_range(list): Portion of the simulation data to analyze.
Default:[0, 100].range_type(str): The dimension considered in the analysis. Possible values:'time''nevents'
Default:'time'.
Example:
import matplotlib.pyplot as plt
import numpy as np
from zacrostools.plot_functions.energyslope import plot_energyslope
fig, ax = plt.subplots(1, figsize=(4.3, 3.5))
plot_energyslope(
ax=ax,
scan_path='simulation_results',
x='pressure_CH4',
y='pressure_CO2',
analysis_range=[50, 100],
range_type='time',
auto_title=True,
show_points=False,
show_colorbar=True
)
plt.tight_layout()
plt.savefig('energyslope_heatmap.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
Issues
Check each simulation for issues and visualize the results in a yes/no heatmap.
Additional parameters:
Mandatory:
analysis_range(list): Portion of the simulation data to analyze (e.g.,[0, 100]). IfNone, it is internally set to[0, 100].
Optional:
range_type(str): The dimension used for slicing the simulation data. Possible values:'time''nevents'
Default:'time'.
cmap(str): Colormap used for plotting.
Default:'RdYlGn'.verbose(bool): IfTrue, prints the paths of simulations that contain issues.
Default:False.
Example:
import matplotlib.pyplot as plt
from zacrostools.plot_functions.issues import plot_issues
fig, ax = plt.subplots(1, figsize=(4.3, 3.5))
plot_issues(
ax=ax,
scan_path='simulation_results',
x='pressure_CH4',
y='pressure_CO2',
analysis_range=[50, 100],
range_type='time',
verbose=True,
auto_title=True,
show_colorbar=True,
show_points=False
)
plt.tight_layout()
plt.savefig('issues_heatmap.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
Figure with multiple heatmaps
Different specialized plotting functions can be combined in a single figure, as illustrated below. Each function (plot_tof, plot_coverage, plot_phasediagram, plot_selectivity, plot_finaltime, etc.) handles a particular type of heatmap.
import numpy as np
import matplotlib.pyplot as plt
# Import the specialized plotting functions
from zacrostools.plot_functions.tof import plot_tof
from zacrostools.plot_functions.coverage import plot_coverage
from zacrostools.plot_functions.phasediagram import plot_phasediagram
from zacrostools.plot_functions.selectivity import plot_selectivity
from zacrostools.plot_functions.finaltime import plot_finaltime
# General parameters
scan_path = 'simulation_results'
x_variable = 'pressure_CH4'
y_variable = 'pressure_CO2'
analysis_range = [50, 100] # (in %) Ignore first X% of the total simulated time (e.g., initial equilibration)
range_type = 'time'
weights = 'time'
min_molec_tof = 0
min_molec_selectivity = 100
min_coverage = 50 # (in %) Minimum coverage threshold for phase diagrams
auto_title = True
show_points = False
show_colorbar = True
fig, axs = plt.subplots(4, 3, figsize=(8.8, 8), sharey='row', sharex='col')
# --- First row: TOF for different products ---
for n, product in enumerate(['CO', 'H2', 'H2O']):
plot_tof(
ax=axs[0, n],
scan_path=scan_path,
x=x_variable,
y=y_variable,
gas_spec=product,
min_molec=min_molec_tof,
analysis_range=analysis_range,
range_type=range_type,
levels=np.logspace(-1, 4, num=11),
auto_title=auto_title,
show_points=show_points,
show_colorbar=show_colorbar
)
# --- Second row: Coverage for different site types ---
for n, site_type in enumerate(['tC', 'tM', 'Pt']):
plot_coverage(
ax=axs[1, n],
scan_path=scan_path,
x=x_variable,
y=y_variable,
surf_spec='all',
site_type=site_type,
analysis_range=analysis_range,
range_type=range_type,
weights=weights,
auto_title=auto_title,
show_points=show_points,
show_colorbar=show_colorbar
)
# --- Third row: Phase diagram for different site types ---
# Example grouping of species into labeled categories for the colorbar
tick_labels = {
'$CH_{x}$': ['CH3', 'CH3_Pt', 'CH2', 'CH2_Pt', 'CH', 'CH_Pt', 'C', 'C_Pt'],
'$CHO/COH$': ['CHO', 'CHO_Pt', 'COH', 'COH_Pt'],
'$CO$': ['CO', 'CO_Pt'],
'$COOH$': ['COOH', 'COOH_Pt'],
'$CO_{2}$': ['CO2', 'CO2_Pt'],
'$H$': ['H', 'H_Pt'],
'$H_{2}O$': ['H2O', 'H2O_Pt'],
'$OH$': ['OH', 'OH_Pt'],
'$O$': ['O', 'O_Pt']
}
for n, site_type in enumerate(['tC', 'tM', 'Pt']):
plot_phasediagram(
ax=axs[2, n],
scan_path=scan_path,
x=x_variable,
y=y_variable,
site_type=site_type,
min_coverage=min_coverage,
tick_labels=tick_labels,
analysis_range=analysis_range,
range_type=range_type,
auto_title=auto_title,
show_points=show_points,
show_colorbar=show_colorbar
)
# --- Fourth row: Selectivity and Final Time ---
# Selectivity
plot_selectivity(
ax=axs[3, 0],
scan_path=scan_path,
x=x_variable,
y=y_variable,
main_product='H2',
side_products=['H2O'],
min_molec=min_molec_selectivity,
analysis_range=analysis_range,
range_type=range_type,
auto_title=auto_title,
show_points=show_points,
show_colorbar=show_colorbar
)
# Final time
plot_finaltime(
ax=axs[3, 1],
scan_path=scan_path,
x=x_variable,
y=y_variable,
levels=np.logspace(-7, 7, num=15),
auto_title=auto_title,
show_points=show_points,
show_colorbar=show_colorbar
)
# Hide the third subplot in the last row
axs[3, 2].axis('off')
# Optional: clean up labels in intermediate subplots
for i in range(3):
for j in range(3):
axs[i, j].set_xlabel('')
for i in range(3):
for j in range(1, 3):
axs[i, j].set_ylabel('')
plt.tight_layout()
plt.savefig('multiple_heatmaps.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()
Customization
The size of axis ticks and font size of axis labels and titles can be adjusted with Matplotlib. Below is an example (shown here for a single heatmap, but the same approach applies to multi-plot figures as well):
import numpy as np
import matplotlib.pyplot as plt
from zacrostools.plot_functions.tof import plot_tof
fig, axs = plt.subplots(1, figsize=(4.3, 3.5))
cp = plot_tof(
ax=axs,
scan_path='simulation_results',
x='pressure_CH4',
y='pressure_CO2',
gas_spec='H2',
min_molec=0,
analysis_range=[50, 100],
range_type='time',
levels=np.logspace(-1, 4, num=11),
auto_title=True,
show_points=False,
show_colorbar=False
)
# Adjust size of axis ticks
axs.tick_params(axis='both', which='major', labelsize=14)
# Adjust font size of axis labels
axs.set_xlabel(axs.get_xlabel(), fontsize=18)
axs.set_ylabel(axs.get_ylabel(), fontsize=18)
# Adjust font size and position of the title
axs.set_title(axs.get_title(), fontsize=20, loc='center', pad=-170)
# Create colorbar and adjust the size of its tick labels
cbar = plt.colorbar(cp, ax=axs)
cbar.ax.tick_params(labelsize=14)
plt.tight_layout()
plt.savefig('tof_heatmap_custom.png', dpi=300, bbox_inches='tight', transparent=False)
plt.show()