bifurcation
analysis.bifurcation
Bifurcation analysis result objects and helpers.
Contains the BifurcationResult class whose instances are returned by model.run(format="bifurcation-julia", ...).
Key attributes
df : pandas.DataFrame Continuation branch points with columns (x, param, itnewton, itlinear, ds, n_unstable, n_imag, stable, step, specialpoint, …). hopf_indices / bp_indices : list[int] Row indices in df where Hopf / Branch (bp) special points occur. hopf_steps / bp_steps : list[int] Corresponding continuation step values. periodic_orbits : list[BifurcationResult | Any] If periodic orbits were computed in Julia (po_results), each periodic orbit branch is wrapped as a child BifurcationResult when possible; otherwise the raw Julia object is stored.
Backend extractors convert a backend-native object — a PyCoBi ODESystem, an AUTO-07p bifDiag — into the unified DataFrame schema this class consumes, as backend_object → _extract_<backend>_df(...) → BifurcationResult(df=...). They sit at module level rather than nested in subclasses, which makes that flow explicit and lets one set of plotting, legend and export code serve every backend without inheritance.
Special-point labels are normalised to canonical short codes (LP, HB, BP). The authoritative source is the ontology’s bifurcation taxonomy in ontology/tvb-o-bifurcation.ttl, merged into tvbo.owl, where each type carries a tvbo:canonicalCode and a skos:altLabel for every backend spelling. _TY_ALIASES_FALLBACK is a built-in fallback used verbatim only when the ontology cannot be read, on a headless or minimal install; the ontology is layered over it so it stays the single source of truth.
Attributes
| Name | Description |
|---|---|
| BIF_STYLES | |
| PO_REDUCTIONS |
Classes
| Name | Description |
|---|---|
| BifurcationResult | Backend-agnostic bifurcation result. |
| CurvePicker | Click any branch line to inspect the underlying point. |
BifurcationResult
analysis.bifurcation.BifurcationResult(br=None, *, df=None, **kwargs)Backend-agnostic bifurcation result.
A single BifurcationResult represents one continuation branch (equilibrium, periodic orbit, or codim-2 curve) regardless of the backend that produced it (BifurcationKit.jl, PyRates/PyCoBi, AUTO-07p/numcont). Once the data lives in self.df and the nested periodic_orbits / codim2_curves lists, all plotting, legend, and export methods (plot, plot_3d, bif_legend, enable_picker, …) work uniformly across backends.
There are no backend-specific result subclasses. Each adapter extracts a unified DataFrame and either calls the constructor directly with df=... or one of the factory shortcuts:
BifurcationResult.from_bifkit(br, ...)— BifurcationKit.jlContResult(juliacall).BifurcationResult.from_pycobi(ode, cont_name, ...)— PyRates / PyCoBiODESystemcontinuations.BifurcationResult.from_auto(bd, ...)— in-tree AUTO-07pbifDiag(numcont backend).
All visual differences between backends are encoded in the unified :data:BIF_STYLES registry, not in subclasses.
Methods
| Name | Description |
|---|---|
| animate | Animate dynamics alongside this 3D bifurcation diagram. |
| bif_legend | Add a curated legend listing the selected TYs. |
| extract_orbit_meshes | Extract full periodic orbit solution meshes from a PO branch. |
| from_auto | Wrap an AUTO-07p bifDiag (numcont backend). |
| from_bifkit | Wrap a BifurcationKit.jl ContResult (juliacall object). |
| from_pycobi | Wrap a PyRates / PyCoBi continuation by name. |
| plot | Render the full bifurcation diagram for this branch. |
| plot_3d | Plot 3D bifurcation diagram with periodic orbit surfaces. |
| plot_branch | Draw the continuation branch as stability-coded line segments. |
| plot_equilibrium_branch | Draw the equilibrium branch and overlay its special points. |
| plot_special_points | Mark codim-1 special points (LP/HB/BP/PD/TR/…) on ax. |
| to_dataset | Return the continuation branch as a native, self-describing xarray Dataset. |
animate
analysis.bifurcation.BifurcationResult.animate(
dynamics,
parameter,
values,
*dims,
kind='phaseplane',
VOI=None,
interval=80,
figsize=(11, 4.8),
title_fmt='{name} = {value:+.2f}',
marker_kwargs=None,
simulation=False,
simulation_duration=200.0,
simulation_dt=0.01,
simulation_backend='tvboptim',
simulation_initial_values=None,
trajectory_kwargs=None,
show_periodic_orbit=True,
orbit_kwargs=None,
**plot_kwargs,
)Animate dynamics alongside this 3D bifurcation diagram.
For each value of parameter a left panel re-renders a Dynamics plot (kind forwarded to :func:plot_dynamics, defaults to "phaseplane"), while a right panel shows :meth:plot_3d once with a moving marker that tracks the current parameter value on the equilibrium backbone.
Parameters
dynamics : Dynamics Model whose parameter is being swept. parameter : str Parameter name (must exist in dynamics.parameters and match this result’s continuation parameter). values : sequence of float Parameter values, one per frame. *dims, **plot_kwargs Forwarded to :func:tvbo.plot.dynamics.plot_dynamics. kind : str Plot kind for the left panel (default "phaseplane"). VOI : str, optional State variable plotted on the z-axis of the 3D diagram. interval : int Delay between frames in ms. figsize : (float, float) title_fmt : str Title format with {name} and {value} placeholders. marker_kwargs : dict, optional Style overrides for the moving marker. simulation : bool If true, overlay a trajectory computed with :class:tvbo.classes.experiment.SimulationExperiment for each frame. This keeps animated trajectories on the same backend path as full experiments instead of using Dynamics.run. simulation_duration, simulation_dt : float Integration settings used when simulation is true. simulation_backend : str Backend passed to SimulationExperiment.run. simulation_initial_values : dict or callable, optional State-variable initial values used for each simulated frame. If a callable is supplied, it receives the current parameter value and returns a mapping for that frame. Returning None skips the simulated trajectory for that frame. trajectory_kwargs : dict, optional Style overrides for simulated trajectory overlays. show_periodic_orbit : bool Draw the current periodic orbit in phase-plane coordinates when a periodic-orbit ring is also available in the bifurcation panel. orbit_kwargs : dict, optional Style overrides for the phase-plane periodic-orbit circle.
Returns:
matplotlib.animation.FuncAnimation
bif_legend
analysis.bifurcation.BifurcationResult.bif_legend(
ax,
tys,
labels=None,
**lgd_kwargs,
)Add a curated legend listing the selected TYs.
Mirrors ContinuationPlot.BifLegend: draws an off-screen artist per TY using the central style registry and feeds them to a single ax.legend call so the user can pin exactly which entries appear.
extract_orbit_meshes
analysis.bifurcation.BifurcationResult.extract_orbit_meshes(n_samples=40)Extract full periodic orbit solution meshes from a PO branch.
Works with BifurcationKit.jl ContResult objects that store .sol (vector of orbit solutions at each continuation step).
Parameters
n_samples : int Number of orbits to sample evenly across the branch.
Returns:
list[dict] Each dict has keys: param (float), state variable names (1D arrays of the orbit trace), and t (mesh times). Returns empty list if orbit data is unavailable.
from_auto
analysis.bifurcation.BifurcationResult.from_auto(
bd,
*,
cont_name=None,
model=None,
continuation=None,
ICS=None,
periodic_orbits_raw=None,
codim2_raw=None,
workdir=None,
**kwargs,
)Wrap an AUTO-07p bifDiag (numcont backend).
Parameters
bd : auto.bifDiag The codim-1 equilibrium continuation result. codim2_raw : list, optional [(name, source_type, fp1_name, fp2_name, R_c2), …] — codim-2 fold/Hopf/BP curves produced by NumContAdapter._run_codim2_branches. Each entry is wrapped as a child BifurcationResult and attached to self.codim2_curves with metadata (_source_type, _fp2_name) that _plot_codim2 consumes.
from_bifkit
analysis.bifurcation.BifurcationResult.from_bifkit(br, **kwargs)Wrap a BifurcationKit.jl ContResult (juliacall object).
from_pycobi
analysis.bifurcation.BifurcationResult.from_pycobi(
ode,
cont_name,
*,
model=None,
state_var_names=None,
icp=1,
fp_name='param',
periodic_orbit_results=None,
codim2_results=None,
**kwargs,
)Wrap a PyRates / PyCoBi continuation by name.
All visualisation/export logic lives on this class – the adapter just hands the extracted DataFrame straight to __init__.
plot
analysis.bifurcation.BifurcationResult.plot(
ax=None,
ICS=None,
VOI=None,
save=None,
**kwargs,
)Render the full bifurcation diagram for this branch.
Draws the equilibrium branch, its special points and any periodic-orbit envelopes (a filled min/max region, or a max line when only maxima are available), labels the axes, adds a legend and applies publication styling. When nested continuation produced codim-2 curves, dispatches to the codim-2 renderer instead.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| ax | Existing axes to draw on; a new figure is created when None. |
None |
|
| ICS | Label for the x-axis (the free/continuation parameter); defaults to self.ICS or "param". |
None |
|
| VOI | Variable of interest plotted on the y-axis; resolved to a default branch column when None. |
None |
|
| save | File path to write the figure to (at 500 dpi); skipped when None. |
None |
|
| **kwargs | Style overrides forwarded to plot_branch and plot_special_points. |
{} |
Returns
| Name | Type | Description |
|---|---|---|
| The matplotlib axes the diagram was drawn on. |
plot_3d
analysis.bifurcation.BifurcationResult.plot_3d(
ax=None,
ICS=None,
ICS2=None,
VOI=None,
save=None,
n_orbit_samples=40,
**kwargs,
)Plot 3D bifurcation diagram with periodic orbit surfaces.
Shows: - Codim-1 equilibrium backbone (stable=solid, unstable=dashed) - Periodic orbit tube surface with W displacement cross-sections - Codim-2 curves (Hopf/fold loci) - Special codim-2 points (BT, GH, cusp, ZH)
Axis convention
x = primary free parameter (codim-1, e.g. I) y = secondary parameter (codim-2, e.g. b) z = state variable (VOI, e.g. V)
plot_branch
analysis.bifurcation.BifurcationResult.plot_branch(
ax,
ICS=None,
VOI=None,
**kwargs,
)Draw the continuation branch as stability-coded line segments.
Splits the branch into contiguous stable/unstable runs (and, when a branch_id column is present, per branch) and plots each segment with the style from the central registry — SFP/UFP for equilibria or SLC/ULC for periodic orbits. Does nothing when the branch is empty.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| ax | Matplotlib axes to draw on. | required | |
| ICS | Free (continuation) parameter name; accepted for parity with the other plot methods and not used here. | None |
|
| VOI | Variable of interest plotted on the y-axis; resolved to a default branch column when None. |
None |
|
| **kwargs | Line-style overrides forwarded to matplotlib (e.g. linewidth/lw, color, linestyle); continuation-config keys are filtered out before plotting. |
{} |
plot_equilibrium_branch
analysis.bifurcation.BifurcationResult.plot_equilibrium_branch(
ax,
ICS=None,
VOI=None,
**kwargs,
)Draw the equilibrium branch and overlay its special points.
Convenience wrapper that calls plot_branch and then plot_special_points on the same axes.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| ax | Matplotlib axes to draw on. | required | |
| ICS | Free (continuation) parameter name, passed through to the underlying calls. | None |
|
| VOI | Variable of interest plotted on the y-axis; resolved to a default branch column when None. |
None |
|
| **kwargs | Style overrides forwarded to plot_branch and plot_special_points. |
{} |
plot_special_points
analysis.bifurcation.BifurcationResult.plot_special_points(
VOI,
ax=None,
types=None,
**kwargs,
)Mark codim-1 special points (LP/HB/BP/PD/TR/…) on ax.
Parameters
types : iterable[str], optional Restrict markers to these canonical TYs (e.g. ['LP','HB']). By default every TY found in df.specialpoint is plotted (except endpoint).
to_dataset
analysis.bifurcation.BifurcationResult.to_dataset()Return the continuation branch as a native, self-describing xarray Dataset.
The branch is a labelled table indexed by continuation step; the continuation parameter (ICS, e.g. G) is a coordinate along it and every recorded observable / stability flag becomes a data variable. This is the same labelled container the rest of tvbo uses (ExperimentResult holds it under continuations), so continuation results persist through the standard result format instead of any ad-hoc per-figure array dump.
CurvePicker
analysis.bifurcation.CurvePicker(fig, result, callback=None)Click any branch line to inspect the underlying point.
Activated via BifurcationResult.enable_picker(ax, callback=...). Each branch line drawn by plot_branch carries picker=True so matplotlib raises a pick_event on click; the picker resolves the nearest df row and forwards it to callback(result, row_index).
Methods
| Name | Description |
|---|---|
| disconnect | Detach the pick-event handler so clicks are no longer captured. |
disconnect
analysis.bifurcation.CurvePicker.disconnect()Detach the pick-event handler so clicks are no longer captured.
Safe to call more than once; the connection id is cleared after the first disconnect.
Functions
| Name | Description |
|---|---|
| canonical_ty | Normalise any backend label to a key in BIF_STYLES. |
| get_bif_style | Look up the merged style dict for a TY (e.g. ‘LP’, ‘fold’, ‘SLC’). |
| resolve_coord | Evaluate one coord expression against df (and optionally PO meshes). |
| resolve_coords | Normalise the user’s coords argument to a tuple of arrays. |
canonical_ty
analysis.bifurcation.canonical_ty(ty)Normalise any backend label to a key in BIF_STYLES.
get_bif_style
analysis.bifurcation.get_bif_style(ty, base=None)Look up the merged style dict for a TY (e.g. ‘LP’, ‘fold’, ‘SLC’).
base defaults to the line/marker base style depending on whether the entry is a branch (no marker) or a point (marker is present).
resolve_coord
analysis.bifurcation.resolve_coord(
df,
expr,
state_var_index=None,
po_orbits=None,
)Evaluate one coord expression against df (and optionally PO meshes).
Accepts
- a column name in
df(e.g.'x','param') - a sympy-parseable expression of column names (e.g.
'V**2 + W') - a reduction call
'minmax(V)'/'avg(V)'/'norm(V)'which uses the PO orbit meshes if available, else falls back to the column itself.
Returns a pandas Series (or ndarray for minmax → shape (2, N)).
resolve_coords
analysis.bifurcation.resolve_coords(
coords,
df,
state_var_index=None,
po_orbits=None,
default_voi=None,
default_param='param',
)Normalise the user’s coords argument to a tuple of arrays.
coords accepts: * None → (param, default_voi) * 'V' → (param, V) * 'minmax(V)' → (param, [Vmin, Vmax]) * (p, V) → 2D * (p, V, W) → 3D Each element may itself be a string or already-resolved array.