rxnfit.solv_ode module

Calculate and visualize the time evolution of chemical species based on reaction rate equations with all rate constants known.

class rxnfit.solv_ode.RxnODEsolver(builder: RxnODEbuild, config: SolverConfig)

Bases: object

Solver for ODE systems representing chemical reaction kinetics.

This class integrates ODE systems using scipy.solve_ivp and provides methods to visualize the time evolution of chemical species and to compare the solution with experimental data (eval_fit_metrics).

builder

The ODE builder instance containing the reaction system definition.

Type:

RxnODEbuild

config

Configuration parameters for the solver.

Type:

SolverConfig

ode_construct

ODE system construction data. Set after calling solve_system().

Type:

tuple, optional

solution

Solution from numerical integration. Set after calling solve_system().

Type:

scipy.integrate.OdeResult, optional

eval_fit_metrics(expdata_df, solution=None, verbose=True, recompute=True)

Compute RSS, TSS, and R² for solution vs. experimental data.

Uses the same valid points for RSS and TSS (NaNs excluded). TSS uses per-species means. R² = 1 - RSS/TSS. Returns the same dict shape as fit_metrics.fit_metrics(datasets, rss).

Parameters:
  • expdata_df (pandas.DataFrame) – Time-course data. First column is time; remaining columns are species concentrations. Column names must match function_names.

  • solution (scipy.integrate.OdeResult, optional) – Solution to use when recompute=False. If None, uses the result of solve_system(). Defaults to None.

  • verbose (bool, optional) – If True, print RSS and R². Defaults to True.

  • recompute (bool, optional) – If True, re-integrate at experimental times for RSS. If False, use interpolation. Defaults to True.

Returns:

Keys ‘rss’, ‘tss’, ‘r2’ (all float).

Return type:

dict

Raises:

RuntimeError – If no solution is available, or if recompute=True but solve_system() has not been called.

solution_plot(solution=None, expdata_df: DataFrame | List[DataFrame] | None = None, species: List[str] | None = None, subplot_layout: Tuple[int, int] | None = None)

Plot the time evolution of chemical species.

Creates a time-course plot showing the simulated concentration of each species over time. Optionally overlays experimental data points with colors matching the simulation lines. Also prints the final concentrations at the last time point.

Parameters:
  • solution (scipy.integrate.OdeResult, optional) – Solution object from solve_ivp to plot. If None, uses the solution stored internally from solve_system(). Defaults to None.

  • expdata_df (pandas.DataFrame or list of DataFrame, optional) –

    Experimental data for overlay. Can be a single DataFrame or a list of DataFrames (e.g. from multiple CSVs). Format: - First column: time values (column name used for x-axis

    label unit, e.g. “t_s” -> “Time (s)”).

    • Subsequent columns: concentrations for each species.

    • Column names must match species names (e.g. from self.builder.function_names).

    If a list with more than one DataFrame is given, one subplot is drawn per DataFrame (same solution curve, scatter from that DataFrame). If a single DataFrame or a list of length one is given, one figure with one axes is drawn. When a list is passed, the 0th column name must be identical across all DataFrames; otherwise a warning is emitted. Defaults to None.

  • species (list[str], optional) – List of species names to plot. If None, all species in the ODE system are plotted. If provided, only these species are drawn. Any name not in the ODE system triggers a warning and ValueError. Defaults to None.

  • subplot_layout (tuple[int, int], optional) – (n_rows, n_cols) for the subplot grid when expdata_df is a list of multiple DataFrames. If None, defaults to (len(expdata_df), 1) (one column). Ignored when expdata_df is None or a single DataFrame. Defaults to None.

Returns:

None

Raises:

ValueError – If a name in species is not in the ODE system.

solve_system()

Solve the ODE system numerically.

Performs numerical integration of the ODE system using scipy.solve_ivp. The solution is stored internally and also returned. When config has rate_const_values and symbolic_rate_const_keys set, uses the rate-constants ODE path; otherwise uses the standard path.

Returns:

A tuple containing:
  • ode_construct (tuple): ODE system construction data including

    system_of_equations, sympy_symbol_dict, ode_system, function_names, and rate_consts_dict.

  • solution (scipy.integrate.OdeResult): Solution object from

    scipy.solve_ivp containing time points and concentrations. May be None if integration fails.

Return type:

tuple

to_dataframe_list(solution=None, time_column_name='time')

Return the solution(s) as a list of DataFrames.

Works for both single and multiple datasets. Always returns a list; single solution yields a 1-element list.

Parameters:
  • solution (scipy.integrate.OdeResult, optional) – Solution to convert. If None, uses the solution from solve_system(). Defaults to None.

  • time_column_name (str, optional) – Name of the time column (first column). Defaults to “time”.

Returns:

One DataFrame per solution. Each has one row

per time point; first column is time, following columns are species concentrations (names from function_names).

Return type:

list[pd.DataFrame]

Raises:

RuntimeError – If no solution is available (solve_system not run).

class rxnfit.solv_ode.SolverConfig(y0: list, t_span: tuple, t_eval: ndarray | None = None, method: str = 'RK45', rtol: float = 1e-06, rate_const_values: Dict[str, float] | Callable[[float], Dict[str, float]] | None = None, symbolic_rate_const_keys: List[str] | None = None)

Bases: object

Configuration parameters for the ODE solver.

y0

Initial concentrations for all species (required).

Type:

list

t_span

Time span for integration as (t_start, t_end) (required).

Type:

tuple

t_eval

Time points at which to evaluate the solution. If None, the solver chooses the time points.

Type:

Optional[np.ndarray]

method

Integration method to use. Defaults to “RK45”.

Type:

str

rtol

Relative tolerance for the solver. Defaults to 1e-6.

Type:

float

rate_const_values

When provided with symbolic_rate_const_keys, the solver uses the rate-constants ODE path: either a dict of rate constant values, or a callable (t) -> dict for time-dependent rates. Must be used together with symbolic_rate_const_keys (both or neither).

Type:

Optional[Union[dict, Callable[[float], dict]]]

symbolic_rate_const_keys

Order of rate constant names passed to the ODE. Required when rate_const_values is set. Both must be set or both omitted; otherwise an error is raised.

Type:

Optional[List[str]]

method: str = 'RK45'
rate_const_values: Dict[str, float] | Callable[[float], Dict[str, float]] | None = None
rtol: float = 1e-06
symbolic_rate_const_keys: List[str] | None = None
t_eval: ndarray | None = None
t_span: tuple
y0: list