tools_fes — free-energy surfaces

Plotting helpers for free-energy surfaces (FES) and other PLUMED output.

The module is organised in three layers so that anything that can be turned into a free-energy surface can be plotted by the same handful of functions:

  1. Readers – read_plumed_file() parses any PLUMED-style file (COLVAR, fes.dat, HILLS, FES_from_State.py output) into a PlumedData container of numeric columns, field names and #! SET metadata.

  2. Container – FES normalises 1-D and 2-D free-energy data into a common form (collective-variable grids, energies, labels). Anything a user is likely to have – a file path, a (2, N)/(N, 2) array, a stacked (3, ny, nx) array, a (x, y, Z) tuple or scattered (N, 3) columns – is accepted by as_fes().

  3. Plotters – plot_fes_1d(), plot_fes_2d(), plot_fes_path(), plot_fes_2d_overlay() and plot_fes_slices() cover profiles, surfaces, paths through CV space and comparisons. plot_fes() dispatches on dimensionality when the caller does not care.

Every plotting function shares the same conventions:

  • sources may be mixed and matched (paths, arrays, FES objects),

  • energy_unit converts the file/array energies on the way in,

  • max_energy masks poorly sampled regions instead of letting them dominate the colour scale,

  • filename=None means do not write anything; passing a name without an extension writes every format in formats,

  • the return value is always (fig, ax).

Energies are assumed to be in kJ/mol unless told otherwise, because that is what PLUMED writes when it is driven from OpenMM. Runs driven from ASE are in eV instead, so pass source_unit="eV" – which is what the thin wrappers plot_plumed() and plot_plumed_multi() do.

The units themselves – ENERGY_UNITS, convert_energy() and unit_label() – live in reactiontools.tools_units and are re-exported here, so that the script builders can convert energies without importing matplotlib through this module.

class FES(cvs: list[~numpy.ndarray], energy: ~numpy.ndarray, cv_labels: list[str] = <factory>, energy_unit: str | None = None, energy_label: str | None = None, regular: bool = True)[source]

Bases: object

A free-energy surface in a form the plotting functions understand.

Variables:
  • cvs (list of numpy.ndarray) – One entry per collective variable. For a 1-D surface this is a single 1-D array; for a 2-D surface on a regular grid the two arrays have the same shape as energy; for scattered 2-D data they are flat coordinate arrays.

  • energy (numpy.ndarray) – Free energies, shaped like the entries of cvs.

  • cv_labels (list of str) – Axis label for each collective variable.

  • energy_unit (str or None) – Unit energy is expressed in, or None when unknown.

  • energy_label (str or None) – Explicit colour-bar/y-axis label. Derived from energy_unit when left as None.

  • regular (bool) – True when the data lies on a regular grid and can be drawn with contourf; False when it must be triangulated.

property ndim: int

Number of collective variables (1 or 2).

Type:

int

property label: str

Label to use for the free-energy axis or colour bar.

Type:

str

finite_range() → tuple[float, float][source]

Return the range spanned by the finite energies.

Returns:

tuple of float – (minimum, maximum), or (nan, nan) when nothing is finite.

slice_at(value: float, axis: int = 0) → tuple[ndarray, ndarray, float][source]

Take a 1-D cut through a 2-D surface at a fixed value of one CV.

Parameters:
  • value (float) – Value of the collective variable held fixed. The nearest grid point is used.

  • axis (int, optional) – Index of the collective variable held fixed.

Returns:

tuple – (x, energy, held_value) where x runs along the free collective variable and held_value is the grid value actually used.

Raises:

ValueError – If the surface is not a 2-D surface on a regular grid.

class FESSummary(minimum_a: float, minimum_b: float, depth_a: float, depth_b: float, delta_f: float, barrier_position: float, forward_barrier: float, reverse_barrier: float, energy_unit: str | None = None)[source]

Bases: object

The numbers read off a free-energy profile.

Variables:
  • minimum_b (minimum_a,) – Where each basin bottoms out, in collective-variable units.

  • depth_b (depth_a,) – The free energy there. The barriers are measured from these, since a barrier is a barrier out of the bottom of a well.

  • delta_f (float) – Free energy of basin B relative to basin A. The difference of the two depths, or of the two Boltzmann-integrated basin free energies when summarise_fes() was given a temperature — which is the one that accounts for a wide basin being more probable than a narrow one of equal depth.

  • barrier_position (float) – Where the profile peaks between the basins.

  • reverse_barrier (forward_barrier,) – Height of that peak above basin A and above basin B.

  • energy_unit (str or None) – Unit the energies are in, for reporting.

class PlumedData(data: ndarray, fields: list[str] = <factory>, metadata: dict[str, str]=<factory>)[source]

Bases: object

Container for the contents of a PLUMED-style data file.

Variables:
  • data (numpy.ndarray) – Numeric columns with shape (n_rows, n_fields).

  • fields (list of str) – Column names taken from the #! FIELDS header. Empty when the file carries no header.

  • metadata (dict) – Key/value pairs collected from #! SET key value lines.

index(name: str | int) → int[source]

Return the column index of a field.

Parameters:

name (str or int) – Field name, or an integer index which is returned unchanged after bounds checking.

Returns:

int – Index of the requested column.

Raises:
  • KeyError – If the named field is not present.

  • IndexError – If an integer index is out of range.

column(name: str | int) → ndarray[source]

Return a single column by field name or index.

Parameters:

name (str or int) – Field name or column index.

Returns:

numpy.ndarray – The requested column.

label(index: int, default: str = '') → str[source]

Return the field name of a column, falling back to default.

Parameters:
  • index (int) – Column index.

  • default (str, optional) – Label used when the file carried no #! FIELDS header.

Returns:

str – The field name or default.

to_dataframe() → DataFrame[source]

Return the data as a pandas.DataFrame.

Returns:

pandas.DataFrame – Columns are named after the fields, or col0, col1, … when no header was present.

as_fes(source: FES | str | Path | ndarray | Sequence[Any], energy_unit: str | None = None, source_unit: str | None = 'kJ/mol', shift_min_to_zero: bool = True, max_energy: float | None = None, columns: Sequence[str | int] | None = None, cv_labels: Sequence[str] | None = None, energy_label: str | None = None) → FES[source]

Coerce anything FES-shaped into a prepared FES.

This is the single entry point used by every plotting function, so all of them accept file paths, raw arrays and FES objects interchangeably.

Parameters:
  • source (str, array_like or FES) – A PLUMED FES file, an array in one of the layouts documented in _fes_from_array(), or an already-built surface.

  • energy_unit (str or None, optional) – Unit to convert the energies to, e.g. "eV". None, the default, leaves them untouched. Surfaces that already carry this unit are not converted twice.

  • source_unit (str, optional) – Unit the incoming energies are expressed in. Left at kJ/mol, which is what PLUMED writes when driven from OpenMM; an ASE-driven run needs "eV".

  • shift_min_to_zero (bool, optional) – Whether to subtract the global minimum so the surface starts at zero. The operation is idempotent.

  • max_energy (float or None, optional) – Energies above this value (in the output unit, after shifting) are replaced by NaN so that poorly sampled regions do not dominate the colour scale. None, the default, keeps everything.

  • columns (sequence of (str or int) or None, optional) – Which file columns to use, ordered (cv1, energy) or (cv1, cv2, energy). Only meaningful for file sources.

  • cv_labels (sequence of str or None, optional) – Override the collective-variable labels.

  • energy_label (str or None, optional) – Override the free-energy label.

Returns:

FES – A new, prepared surface. The input is never modified in place.

Raises:
  • ValueError – If the source cannot be read as a surface, or if energy_unit is asked for without a source_unit to convert from.

  • KeyError – If either unit is not one of ENERGY_UNITS.

convert_energy(values: float | Sequence[float] | ndarray, source: str = 'kJ/mol', target: str | None = None) → ndarray | float64[source]

Convert energies between the units listed in ENERGY_UNITS.

Parameters:
  • values (array_like) – Energies expressed in source units.

  • source (str, optional) – Unit of values.

  • target (str or None, optional) – Unit to convert to. None, the default, returns values unchanged.

Returns:

numpy.ndarray – The converted energies.

fes_convergence(sources: FES | str | Path | ndarray | Sequence[Any], basin_a: Sequence[float], basin_b: Sequence[float], temperature: float | None = None, **kwargs: Any) → list[FESSummary][source]

Summarise each surface of a series, to see whether the numbers settle.

A metadynamics run is converged when the barrier and the basin difference stop moving, not when the surface stops looking different. Feed it the series sum_hills_files() collects from a strided sum_hills.

Parameters:
  • sources (sequence of FES source) – The surfaces, in order.

  • basin_a (sequence of float) – Basin windows, the same for every surface — that is the point of fixing them rather than finding them per surface.

  • basin_b (sequence of float) – Basin windows, the same for every surface — that is the point of fixing them rather than finding them per surface.

  • temperature (float or None, optional) – See summarise_fes().

  • **kwargs – Forwarded to as_fes().

Returns:

list of FESSummary – One per surface, in the order given.

Raises:

ValueError – If sources is empty, or for any of the reasons summarise_fes() raises on one of the surfaces.

fes_series_files(directory: str | Path = '.', pattern: str = '^fes_?(\\d+)\\.dat$') → list[Path][source]

Find the numbered free-energy surfaces in a directory, in index order.

The counterpart of sum_hills_files() for the other two ways a convergence series gets written: the bundled OPES FES_from_* scripts, and any run that numbered its own output. Both produce fes_1.dat, fes2.dat and the like, which sorting by name puts in the wrong order the moment there are ten of them – and for a convergence series the order is the entire point.

Parameters:
  • directory (str or path-like, optional) – Directory to search.

  • pattern (str, optional) – Regular expression matched against each file name, case-insensitively. Its first capture group, if present, is the sort key. The default matches fes_<n>.dat and fes<n>.dat.

Returns:

list of pathlib.Path – Matching files, ordered by the index they carry, ready to hand to plot_fes_1d() or fes_convergence().

See also

reactiontools.tools_plumed.sum_hills_files

For a strided sum_hills run, which numbers its files differently again.

Examples

A convergence series written by the OPES scripts:

plot_fes_1d(fes_series_files("."), source_unit="kJ/mol")
load_fes_series(directory: str | Path = '.', energy_unit: str | None = 'eV', source_unit: str | None = 'kJ/mol', pattern: str = '^fes_?(\\d+)\\.dat$', verbose: bool = True) → list[FES][source]

Load the numbered free-energy surfaces in a directory, in index order.

fes_series_files() followed by as_fes() on each, so 1-D and 2-D surfaces are both handled and the result goes straight to plot_fes_1d(), plot_fes_2d() or fes_convergence().

Parameters:
  • directory (str or path-like, optional) – Directory containing the surfaces.

  • energy_unit (str, optional) – Unit to convert the free energies to. Default is "eV".

  • source_unit (str, optional) – Unit the files are written in. The default is kJ/mol, which is what PLUMED writes when driven from OpenMM; a run driven from ASE through PLUMED_ASE_UNITS writes eV.

  • pattern (str, optional) – Regular expression selecting the files; see fes_series_files().

  • verbose (bool, optional) – Report each file as it is loaded.

Returns:

list of FES – One surface per file, ordered by file index.

plot_fes(sources: FES | str | Path | ndarray | Sequence[Any], **kwargs: Any) → tuple[Figure, Axes | ndarray][source]

Plot a free-energy surface, dispatching on its dimensionality.

Sends 1-D data to plot_fes_1d() and 2-D data to plot_fes_2d(), which is convenient when the dimensionality is decided by the PLUMED input rather than by the caller. Sources are read once here and handed on as FES objects. Options that only make sense for contour plots (levels, cmap, colorbar) are ignored for 1-D data instead of raising.

Parameters:
  • sources (FES source or sequence of FES sources) – Paths, arrays or FES objects; see as_fes().

  • **kwargs – Forwarded to the selected plotting function.

Returns:

tuple – (fig, ax) containing the matplotlib figure and axes.

plot_fes_1d(sources: FES | str | Path | ndarray | Sequence[Any], fig: Figure | None = None, ax: Axes | None = None, labels: Sequence[Any] | None = None, label_template: str | None = None, max_datasets: int | None = None, energy_unit: str | None = None, source_unit: str | None = 'kJ/mol', shift_min_to_zero: bool = True, max_energy: float | None = None, columns: Sequence[str | int] | None = None, x_lab: str | None = None, y_lab: str | None = None, filename: str | Path | None = None, show: bool = False, fig_size: tuple[float, float] = (8, 3), **plot_kwargs: Any) → tuple[Figure, Axes][source]

Plot one or more 1-D free-energy profiles on a single axes.

This covers a single profile, a convergence series over time and a method-to-method comparison, since they differ only in their labels.

Parameters:
  • sources (FES source or sequence of FES sources) – Paths, arrays or FES objects; see as_fes().

  • fig (matplotlib.figure.Figure, optional) – Figure to draw on. Inferred from ax when omitted.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on.

  • labels (sequence, optional) – Legend entries, one per dataset. Non-string values are formatted with label_template, which makes labels=times with label_template=r"$t={:g}$ ps" a convenient time series.

  • label_template (str, optional) – str.format template applied to non-string labels.

  • max_datasets (int, optional) – Keep only the last max_datasets surfaces. None, the default, plots all of them.

  • energy_unit (str, optional) – Unit to convert energies to, e.g. "eV".

  • source_unit (str, optional) – Unit the input energies are in.

  • shift_min_to_zero (bool, optional) – Whether to shift each surface so its minimum is zero.

  • max_energy (float, optional) – Mask energies above this value.

  • columns (sequence of (str or int), optional) – Columns to use for file sources, ordered (cv, energy).

  • x_lab (str, optional) – Axis labels. Taken from the data when not given.

  • y_lab (str, optional) – Axis labels. Taken from the data when not given.

  • filename (str, optional) – Output path; None, the default, writes nothing. A bare stem writes both PNG and PDF.

  • show (bool, optional) – Whether to display the figure.

  • fig_size (tuple, optional) – Figure size in inches.

  • **plot_kwargs – Extra keyword arguments forwarded to Axes.plot.

Returns:

tuple – (fig, ax) containing the matplotlib figure and axes.

Raises:

ValueError – If any source is not a 1-D surface.

plot_fes_2d(sources: FES | str | Path | ndarray | Sequence[Any], fig: Figure | None = None, ax: Axes | Sequence[Axes] | ndarray | None = None, labels: Sequence[Any] | None = None, label_template: str | None = None, max_datasets: int | None = None, energy_unit: str | None = None, source_unit: str | None = 'kJ/mol', shift_min_to_zero: bool = True, max_energy: float | None = None, columns: Sequence[str | int] | None = None, levels: int | Sequence[float] | ndarray = 30, cmap: str | Colormap | None = None, x_lab: str | None = None, y_lab: str | None = None, colorbar: bool = True, filename: str | Path | None = None, show: bool = False, fig_size: tuple[float, float] | None = None, **contour_kwargs: Any) → tuple[Figure, ndarray][source]

Plot one or more 2-D free-energy surfaces as filled contours.

A single surface gives one panel; several surfaces are drawn side by side with shared axes, shared contour levels and one colour bar, which covers both convergence series and method comparisons.

Parameters:
  • sources (FES source or sequence of FES sources) – Paths, arrays or FES objects; see as_fes().

  • fig (matplotlib.figure.Figure, optional) – Figure to draw on. Inferred from ax when omitted.

  • ax (matplotlib.axes.Axes or sequence of Axes, optional) – Axes to draw on; must provide one per surface.

  • labels (sequence, optional) – Panel titles, one per dataset. Non-string values are formatted with label_template.

  • label_template (str, optional) – str.format template applied to non-string labels, e.g. r"$t={:g}$ ps".

  • max_datasets (int, optional) – Keep only the last max_datasets surfaces. None, the default, plots all of them.

  • energy_unit (str, optional) – Unit to convert energies to, e.g. "eV".

  • source_unit (str, optional) – Unit the input energies are in.

  • shift_min_to_zero (bool, optional) – Whether to shift each surface so its minimum is zero.

  • max_energy (float, optional) – Mask energies above this value, leaving unsampled regions blank.

  • columns (sequence of (str or int), optional) – Columns to use for file sources, ordered (cv1, cv2, energy).

  • levels (int or array_like, optional) – Number of contour levels, or explicit level values. An integer is expanded to levels spanning every panel.

  • cmap (str or matplotlib.colors.Colormap, optional) – Colour map passed to contourf.

  • x_lab (str, optional) – Axis labels. Taken from the data when not given.

  • y_lab (str, optional) – Axis labels. Taken from the data when not given.

  • colorbar (bool, optional) – Whether to draw the shared colour bar.

  • filename (str, optional) – Output path; None, the default, writes nothing.

  • show (bool, optional) – Whether to display the figure.

  • fig_size (tuple, optional) – Figure size in inches. Scales with the number of panels by default.

  • **contour_kwargs – Extra keyword arguments forwarded to contourf/tricontourf.

Returns:

tuple – (fig, axes) with axes always a 1-D array, even for a single panel.

Raises:

ValueError – If any source is not a 2-D surface, or if the supplied axes do not match the number of surfaces.

plot_fes_2d_overlay(sources: FES | str | Path | ndarray | Sequence[Any], fig: Figure | None = None, ax: Axes | None = None, labels: Sequence[Any] | None = None, label_template: str | None = None, energy_unit: str | None = None, source_unit: str | None = 'kJ/mol', shift_min_to_zero: bool = True, max_energy: float | None = None, columns: Sequence[str | int] | None = None, levels: int | Sequence[float] | ndarray = 6, colors: str | Sequence[str | tuple[float, ...]] | None = None, x_lab: str | None = None, y_lab: str | None = None, filename: str | Path | None = None, show: bool = False, fig_size: tuple[float, float] = (5, 4), **contour_kwargs: Any) → tuple[Figure, Axes][source]

Overlay the contour lines of several 2-D free-energy surfaces.

Drawing the surfaces on the same axes in different colours makes small shifts between them, such as the effect of nuclear quantum effects on a barrier, easy to see.

Parameters:
  • sources (FES source or sequence of FES sources) – Paths, arrays or FES objects; see as_fes().

  • fig (matplotlib.figure.Figure, optional) – Figure to draw on. Inferred from ax when omitted.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on.

  • labels (sequence, optional) – Legend entries, one per dataset.

  • label_template (str, optional) – str.format template applied to non-string labels.

  • energy_unit (str, optional) – Unit to convert energies to, e.g. "eV".

  • source_unit (str, optional) – Unit the input energies are in.

  • shift_min_to_zero (bool, optional) – Whether to shift each surface so its minimum is zero.

  • max_energy (float, optional) – Mask energies above this value.

  • columns (sequence of (str or int), optional) – Columns to use for file sources, ordered (cv1, cv2, energy).

  • levels (int or array_like, optional) – Number of contour lines, or explicit level values. The levels are shared by every surface so the comparison is fair.

  • colors (sequence, optional) – One colour per surface. Defaults to the active colour cycle.

  • x_lab (str, optional) – Axis labels. Taken from the data when not given.

  • y_lab (str, optional) – Axis labels. Taken from the data when not given.

  • filename (str, optional) – Output path; None, the default, writes nothing.

  • show (bool, optional) – Whether to display the figure.

  • fig_size (tuple, optional) – Figure size in inches.

  • **contour_kwargs – Extra keyword arguments forwarded to contour/tricontour.

Returns:

tuple – (fig, ax) containing the matplotlib figure and axes.

Raises:

ValueError – If any source is not a 2-D surface.

plot_fes_convergence(sources: FES | str | Path | ndarray | Sequence[Any], basin_a: Sequence[float], basin_b: Sequence[float], times: Sequence[float] | ndarray | None = None, temperature: float | None = None, fig: Figure | None = None, ax: Axes | None = None, x_lab: str | None = None, y_lab: str | None = None, filename: str | Path | None = None, show: bool = False, fig_size: tuple[float, float] = (8, 3), **kwargs: Any) → tuple[Figure, Axes][source]

Plot how the barrier and the basin difference settle over a series.

The convergence test that matters: a run is done when these two numbers stop moving, which a series of surfaces plotted on top of each other shows only loosely.

Parameters:
  • sources (sequence of FES source) – The surfaces, in order; see fes_convergence().

  • basin_a (sequence of float) – Basin windows, held fixed across the series.

  • basin_b (sequence of float) – Basin windows, held fixed across the series.

  • times (sequence of float, optional) – X values — simulated time, or hills deposited. None, the default, numbers the surfaces from one.

  • temperature (float or None, optional) – See summarise_fes().

  • fig (matplotlib.figure.Figure, optional) – Figure to draw on. Inferred from ax when omitted.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on.

  • x_lab (str, optional) – Axis labels. Taken from the data when not given: "Surface", or "Time" when times is given, and the energy unit of the first surface.

  • y_lab (str, optional) – Axis labels. Taken from the data when not given: "Surface", or "Time" when times is given, and the energy unit of the first surface.

  • filename (str, optional) – Output path; None, the default, writes nothing.

  • show (bool, optional) – Whether to display the figure.

  • fig_size (tuple, optional) – Figure size in inches.

  • **kwargs – Forwarded to as_fes().

Returns:

tuple – (fig, ax) containing the matplotlib figure and axes.

Raises:

ValueError – If times does not have one value per surface.

plot_fes_path(source: FES | str | Path | ndarray | Sequence[Any], path: str | Path | PlumedData | ndarray | Sequence[Any], fig: Figure | None = None, ax: Axes | None = None, energy_unit: str | None = None, source_unit: str | None = 'kJ/mol', shift_min_to_zero: bool = True, max_energy: float | None = None, columns: Sequence[str | int] | None = None, path_columns: Sequence[str | int] | None = None, levels: int | Sequence[float] | ndarray = 30, cmap: str | Colormap | None = None, x_lab: str | None = None, y_lab: str | None = None, colorbar: bool = True, path_label: str | None = 'Path', path_kwargs: Mapping[str, Any] | None = None, filename: str | Path | None = None, show: bool = False, fig_size: tuple[float, float] = (6, 5), **contour_kwargs: Any) → tuple[Figure, Axes][source]

Plot a path through collective-variable space over a 2-D FES.

The path can come straight from a PLUMED COLVAR file. If its header contains fields with the same names as the FES axes, those fields are selected automatically, so a leading time column and trailing bias columns are ignored. Raw (n_points, 2) and (2, n_points) arrays are also accepted.

Parameters:
  • source (FES source) – One 2-D surface accepted by as_fes().

  • path (str, path-like, PlumedData or array_like) – Ordered CV coordinates, or a PLUMED file containing them.

  • fig (matplotlib.figure.Figure, optional) – Figure to draw on. Inferred from ax when omitted.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on.

  • energy_unit – FES preparation options; see plot_fes_2d().

  • source_unit – FES preparation options; see plot_fes_2d().

  • shift_min_to_zero – FES preparation options; see plot_fes_2d().

  • max_energy – FES preparation options; see plot_fes_2d().

  • columns – FES preparation options; see plot_fes_2d().

  • path_columns (sequence of (str or int), optional) – Two path columns, ordered (cv1, cv2). Field names matching the FES axes are used automatically when this is omitted.

  • levels – Surface appearance options; see plot_fes_2d().

  • cmap – Surface appearance options; see plot_fes_2d().

  • x_lab – Surface appearance options; see plot_fes_2d().

  • y_lab – Surface appearance options; see plot_fes_2d().

  • colorbar – Surface appearance options; see plot_fes_2d().

  • path_label (str or None, optional) – Legend label for the path. None suppresses the legend.

  • path_kwargs (mapping, optional) – Appearance options forwarded to Axes.plot. Defaults to a semi-transparent white line like the conventional trajectory-on-FES plot.

  • filename (str, optional) – Output path; None, the default, writes nothing.

  • show (bool, optional) – Whether to display the figure.

  • fig_size (tuple, optional) – Figure size in inches.

  • **contour_kwargs – Extra keyword arguments forwarded to contourf/tricontourf.

Returns:

tuple – (fig, ax) containing the matplotlib figure and axes.

Raises:

ValueError – If source is not one 2-D FES or path does not contain two CVs.

plot_fes_slices(sources: FES | str | Path | ndarray | Sequence[Any], at: float | Sequence[float] | ndarray, axis: int = 0, fig: Figure | None = None, ax: Axes | None = None, labels: Sequence[Any] | None = None, energy_unit: str | None = None, source_unit: str | None = 'kJ/mol', shift_min_to_zero: bool = True, max_energy: float | None = None, columns: Sequence[str | int] | None = None, slice_format: str = '{label}, {cv}$={value:.2f}$', colors: str | Sequence[str | tuple[float, ...]] | None = None, linestyles: Sequence[str] = ('-', '--', ':', '-.'), x_lab: str | None = None, y_lab: str | None = None, filename: str | Path | None = None, show: bool = False, fig_size: tuple[float, float] = (8, 3), **plot_kwargs: Any) → tuple[Figure, Axes][source]

Plot 1-D cuts through 2-D free-energy surfaces at fixed CV values.

Each surface gets its own colour and each requested cut its own line style, so several surfaces can be compared at several slices at once. Slices are requested by collective-variable value; the nearest grid point is used and reported in the legend.

Parameters:
  • sources (FES source or sequence of FES sources) – 2-D surfaces to slice; see as_fes().

  • at (float or sequence of float) – Value(s) of the held collective variable at which to cut.

  • axis (int, optional) – Index of the collective variable held fixed, so the default cuts along CV2.

  • fig (matplotlib.figure.Figure, optional) – Figure to draw on. Inferred from ax when omitted.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on.

  • labels (sequence, optional) – Name for each surface, used in the legend.

  • energy_unit (str, optional) – Unit to convert energies to, e.g. "eV".

  • source_unit (str, optional) – Unit the input energies are in.

  • shift_min_to_zero (bool, optional) – Whether to shift each surface so its minimum is zero.

  • max_energy (float, optional) – Mask energies above this value.

  • columns (sequence of (str or int), optional) – Columns to use for file sources, ordered (cv1, cv2, energy).

  • slice_format (str, optional) – str.format template for the legend entries, receiving label, cv and value.

  • colors (sequence, optional) – One colour per surface. Defaults to the active colour cycle.

  • linestyles (sequence, optional) – One line style per slice value.

  • x_lab (str, optional) – Axis labels. Taken from the data when not given.

  • y_lab (str, optional) – Axis labels. Taken from the data when not given.

  • filename (str, optional) – Output path; None, the default, writes nothing.

  • show (bool, optional) – Whether to display the figure.

  • fig_size (tuple, optional) – Figure size in inches.

  • **plot_kwargs – Extra keyword arguments forwarded to Axes.plot.

Returns:

tuple – (fig, ax) containing the matplotlib figure and axes.

Raises:

ValueError – If any source is not a 2-D surface on a regular grid.

plot_plumed_colvar(path: str | Path, x_axis: str = 'time', columns: Sequence[str] | None = None, fig: Figure | None = None, axes: Axes | Sequence[Axes] | ndarray | None = None, filename: str | Path | None = None, show: bool = False, figsize: tuple[float, float] = (10, 8)) → tuple[Figure, ndarray][source]

Plot collective variables from a PLUMED COLVAR file.

Reads the #! FIELDS header to determine the column names and creates a vertically stacked subplot for each variable.

Parameters:
  • path (str) – Path to the PLUMED COLVAR file.

  • x_axis (str, optional) – Column name to use as the x-axis. If the column is not found, the row index is used instead.

  • columns (sequence of str, optional) – Restrict the plot to these columns. By default every column other than x_axis is plotted.

  • fig (matplotlib.figure.Figure, optional) – Figure to draw on. Inferred from axes when omitted.

  • axes (sequence of matplotlib.axes.Axes, optional) – Axes to draw on; must provide one per plotted column.

  • filename (str, optional) – Output path; None, the default, writes nothing. A bare stem writes both PNG and PDF.

  • show (bool, optional) – Whether to display the figure.

  • figsize (tuple of float, optional) – Figure size in inches (width, height).

Returns:

tuple – (fig, axes), with one axes per plotted variable.

Raises:

ValueError – If no #! FIELDS header is found, or if there is nothing to plot.

plot_plumed_fes(path: str | Path, ax: Axes | None = None, shift_min_to_zero: bool = True, levels: int = 30, **kwargs: Any) → tuple[Figure, Axes | ndarray][source]

Plot a PLUMED free-energy surface from a data file.

Thin wrapper around plot_fes() kept for the example and test workflows. Whether the surface is 1-D or 2-D is determined from the file; a 1-D FES is drawn as a line, a 2-D FES as filled contours with a colour bar.

Parameters:
  • path (str) – Path to the PLUMED FES data file.

  • ax (matplotlib.axes.Axes, optional) – Axes to draw on. A new figure is created when None.

  • shift_min_to_zero (bool, optional) – Whether to shift the surface so its minimum is zero.

  • levels (int, optional) – Number of contour levels for 2-D plots.

  • **kwargs – Further options forwarded to plot_fes_1d() / plot_fes_2d(), such as energy_unit, max_energy, filename or show.

Returns:

tuple – (fig, ax), with ax an array of axes when several were drawn.

read_plumed_file(path: str | Path, drop_der: bool = True) → PlumedData[source]

Read a PLUMED-style data file.

Handles the files produced by plumed sum_hills, PRINT/COLVAR output and the bundled OPES FES_from_* scripts: the #! FIELDS header gives the column names, #! SET lines are collected as metadata, and blank block separators (used between rows of a 2-D grid) are ignored.

Parameters:
  • path (str) – Path to the PLUMED data file.

  • drop_der (bool, optional) – Whether to discard derivative columns whose field name starts with der_. Ignored when the header and the data do not agree on the number of columns.

Returns:

PlumedData – The parsed file contents.

Raises:

ValueError – If the file contains no numeric rows.

summarise_fes(source: FES | str | Path | ndarray | Sequence[Any], basin_a: Sequence[float], basin_b: Sequence[float], temperature: float | None = None, **kwargs: Any) → FESSummary[source]

Measure the barrier and basin free-energy difference off a 1-D surface.

The two basins are given as windows on the collective variable rather than found automatically, which keeps the answer predictable on a noisy surface and, more to the point, keeps it comparable across the surfaces of a convergence series.

Parameters:
  • source (FES source) – A PLUMED file, an array or an FES; see as_fes(). Must be one-dimensional.

  • basin_a (sequence of float) – (low, high) bounds of each basin. They may be given in either order but must not overlap, and there must be grid points between them for the barrier to sit on.

  • basin_b (sequence of float) – (low, high) bounds of each basin. They may be given in either order but must not overlap, and there must be grid points between them for the barrier to sit on.

  • temperature (float or None, optional) – Temperature in kelvin. Given one, delta_f comes from integrating the Boltzmann weight across each basin, so that a wide basin counts for more than a narrow one of the same depth. None, the default, just compares the two minima. The barriers are measured from the minima either way.

  • **kwargs – Forwarded to as_fes(): energy_unit, source_unit, shift_min_to_zero, max_energy, columns and the label overrides.

Returns:

FESSummary – Barriers, basin minima and their free-energy difference.

Raises:

ValueError – If the surface is not one-dimensional, if either basin holds no sampled point, if the basins overlap, if nothing lies between them, or if a temperature is given for a surface whose energy unit is unknown.

Examples

>>> summary = summarise_fes("fes.dat", basin_a=(1.0, 2.0),
...                         basin_b=(3.0, 4.5), source_unit="eV")
>>> print(summary)
Barrier A->B:  0.352 eV
Barrier B->A:  0.418 eV
Delta F (B-A): -0.066 eV
Minima at:     1.5, 3.75
Barrier at:    2.6
unit_label(unit: str | None) → str[source]

Return the axis label for an energy unit.

Parameters:

unit (str or None) – Energy unit name.

Returns:

str – A LaTeX-ready label such as "$F$ (eV)", or "$F$" when the unit is unknown.