rxnfit.solv_ode module — rxnfit 20260314 documentation

# 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