Skip to content

OptimizationSession

The high-level interface that runs the optimization loop.

OptimizationSession

OptimizationSession(search_space: Optional[SearchSpace] = None, experiment_manager: Optional[ExperimentManager] = None, event_emitter: Optional[EventEmitter] = None, session_metadata: Optional[SessionMetadata] = None)

High-level interface for Bayesian optimization workflows.

This class orchestrates the complete optimization loop: 1. Define search space 2. Load/add experimental data 3. Train surrogate model 4. Run acquisition to suggest next experiments 5. Iterate

Example
from alchemist_core import OptimizationSession

session = OptimizationSession()
session.add_variable("temperature", "real", bounds=(300, 500))
session.add_variable("pressure", "real", bounds=(1, 10))
session.add_variable("catalyst", "categorical", categories=["A", "B", "C"])

session.load_data("experiments.csv", target_columns="yield")
session.train_model(backend="botorch", kernel="Matern")
next_point = session.suggest_next(strategy="EI", goal="maximize")

Initialize optimization session.

Parameters:

Name Type Description Default
search_space Optional[SearchSpace]

Pre-configured SearchSpace object (optional)

None
experiment_manager Optional[ExperimentManager]

Pre-configured ExperimentManager (optional)

None
event_emitter Optional[EventEmitter]

EventEmitter for progress notifications (optional)

None
session_metadata Optional[SessionMetadata]

Pre-configured session metadata (optional)

None

is_multi_objective property

is_multi_objective: bool

Whether this session has multiple target objectives.

n_objectives property

n_objectives: int

Number of target objectives.

objective_names property

objective_names: List[str]

Names of target objectives.

get_objective_metadata

get_objective_metadata() -> Dict[str, Dict[str, Any]]

Return the opaque per-objective label/unit map (never parsed).

Returns a deep-ish copy so callers cannot mutate internal state.

set_objective_metadata

set_objective_metadata(metadata: Dict[str, Dict[str, Any]]) -> None

Set/update opaque per-objective display metadata.

Parameters:

Name Type Description Default
metadata Dict[str, Dict[str, Any]]

{objective_name: {"label": str, "unit": Optional[str]}} Each field is merged per objective: passing only "label" leaves an existing "unit" intact (and vice versa).

required

Writes an audit entry ONLY when the effective metadata actually changes. ALchemist stores and displays these strings but never interprets them (keeps the toolkit domain-agnostic).

get_control

get_control() -> Dict[str, Any]

Return a copy of the consumer control record.

A copy, so a caller cannot mutate session state through the getter -- same reason get_objective_metadata copies.

set_control_request

set_control_request(requested: str, requested_by: Optional[str] = None) -> Dict[str, Any]

Record what a human is asking the driving consumer to do.

ALchemist does not act on this and never will: under the consumer's own safety model it may be the only process allowed to touch the physical system. This is a mailbox, not a command.

set_control_report

set_control_report(reported: str, reported_by: Optional[str] = None, detail: Optional[str] = None) -> Dict[str, Any]

Record the driving consumer's own state. Only it may call this.

Doubles as a heartbeat: reported_at moves on every call, so an observer can tell "quiet for 40 s" from "paused" -- which is the difference between an unknown state and a known one.

check_objective_label

check_objective_label(expected: Optional[Dict[str, str]]) -> None

Raise ValueError if any expected label does not match the current one.

Parameters:

Name Type Description Default
expected Optional[Dict[str, str]]

{objective_name: label}. None or {} is a no-op.

required

Comparison is pure opaque-string equality; ALchemist never interprets the labels. A currently-unset objective has label None, so expecting a non-None label for it is a mismatch by design — call set_objective_metadata to configure the label before guarding with an expected value.

objective_display_label

objective_display_label(objective_name: str) -> str

Human display string for an objective: 'label (unit)' or raw name.

Opaque: ALchemist never parses the label/unit. Falls back to the raw objective (column) name when no label is set.

add_variable

add_variable(name: str, var_type: str, **kwargs) -> None

Add a variable to the search space.

Parameters:

Name Type Description Default
name str

Variable name

required
var_type str

Type ('real', 'integer', 'categorical')

required
**kwargs

Type-specific parameters, plus two optional settings that pass straight through to SearchSpace.add_variable: - role: 'controllable' (default) or 'observed'. An observed variable is measured, never optimized or sampled by DoE. - changes: 'easy' (default), 'hard' or 'very_hard'; controllable variables only. - For 'real'/'integer': bounds=(min, max) or min=..., max=... - For 'categorical': categories=[list of values] or values=[list]

{}
Example
session.add_variable('x1', 'real', bounds=(0.0, 1.0))
session.add_variable('c', 'categorical', categories=['a', 'b', 'c'], changes='hard')
session.add_variable('z', 'real', bounds=(0.0, 5.0), role='observed')
session.add_variable('k', 'categorical', categories=['p', 'q'], role='observed')

add_derived_variable

add_derived_variable(name: str, func: Callable, input_cols: List[str], description: str = '') -> None

Register a derived (non-tunable) feature for use in model training.

Derived variables are deterministic functions of existing input variables. They augment the GP's feature matrix at train and predict time, but the acquisition function always suggests in the original base variable space.

Only supported with the BoTorch backend. For sklearn, derived features must be pre-computed and added to the experiment data manually.

Parameters:

Name Type Description Default
name str

Column name for the derived feature. Must not conflict with existing variable names or target column names.

required
func Callable

Callable with signature func(row: dict) -> float. The dict contains all base variable values for a single experiment row.

required
input_cols List[str]

Names of base variables this feature depends on. Used for documentation and validation; the full row is still passed to func.

required
description str

Optional human-readable description (stored in session JSON).

''
Example

session.add_derived_variable( ... name="eq_dme_yield", ... func=compute_eq_dme_yield, ... input_cols=["T", "P", "H2", "CO", "CO2"], ... description="Thermodynamic equilibrium DME yield" ... ) session.fit_model(backend="botorch") suggestions = session.suggest_next() # returns T, P, H2, CO, CO2 only

register_derived_variable

register_derived_variable(name: str, func: Callable) -> None

Re-attach a callable to a derived variable after loading a session.

Derived variable callables are not serialized to JSON. After loading a session that contained derived variables, call this method once per derived variable before calling fit_model().

Parameters:

Name Type Description Default
name str

Name of the derived variable (as saved in the session JSON).

required
func Callable

Callable with signature func(row: dict) -> float.

required
Example

session = OptimizationSession.load_session("my_session.json") session.register_derived_variable("eq_dme_yield", compute_eq_dme_yield) session.fit_model(backend="botorch")

load_search_space

load_search_space(filepath: str) -> None

Load search space from JSON or CSV file.

Parameters:

Name Type Description Default
filepath str

Path to search space definition file

required

get_search_space_summary

get_search_space_summary() -> Dict[str, Any]

Get summary of current search space.

Returns:

Type Description
Dict[str, Any]

Dictionary with variable information

add_input_constraint

add_input_constraint(constraint_type: str, coefficients: Dict[str, float], rhs: float, name: Optional[str] = None)

Add linear input constraint: sum(coeff_i * x_i) <= rhs or == rhs.

Delegates to :meth:SearchSpace.add_constraint; the validation described below is performed there.

Parameters:

Name Type Description Default
constraint_type str

'inequality' (<=) or 'equality' (==)

required
coefficients Dict[str, float]

{variable_name: coefficient} mapping. Every coefficient must be a finite number, and every variable must exist in the search space and be numeric (real, integer or discrete).

required
rhs float

right-hand side value. Must be a finite number.

required
name Optional[str]

optional human-readable name. Auto-generated as constraint_N when omitted. Names identify a constraint for removal, so an explicit name that duplicates an existing one raises ValueError.

None

Raises:

Type Description
ValueError

unknown constraint_type, a coefficient variable that is missing or non-numeric, a non-numeric or non-finite rhs or coefficient, or a duplicate explicit name. Never TypeError.

Example

session.add_input_constraint('inequality', {'x1': 1.0, 'x2': 1.0}, rhs=1.5)

add_outcome_constraint

add_outcome_constraint(objective_name: str, bound_type: str, value: float)

Add outcome constraint on a modeled output.

Parameters:

Name Type Description Default
objective_name str

Name of the target column to constrain

required
bound_type str

'lower' (output >= value) or 'upper' (output <= value)

required
value float

The constraint threshold

required
Example

session.add_outcome_constraint('selectivity', 'lower', 80.0)

get_outcome_constraints

get_outcome_constraints() -> List[Dict]

Return list of outcome constraint dicts.

load_data

load_data(filepath: str, target_columns: Union[str, List[str]] = 'Output', noise_column: Optional[str] = None) -> None

Load experimental data from CSV file.

Parameters:

Name Type Description Default
filepath str

Path to CSV file

required
target_columns Union[str, List[str]]

Target column name(s). Can be: - String for single-objective: 'yield' - List for multi-objective: ['yield', 'selectivity'] Default: 'Output'

'Output'
noise_column Optional[str]

Optional column holding each row's noise variance (σ², the square of its standard deviation); the models use it as a variance

None

Examples:

Single-objective:

>>> session.load_data('experiments.csv', target_columns='yield')
>>> session.load_data('experiments.csv', target_columns=['yield'])  # also works

Multi-objective:

>>> session.load_data('experiments.csv', target_columns=['yield', 'selectivity'])
Note

If the CSV doesn't have columns matching target_columns, an error will be raised. Target columns will be preserved with their original names internally.

add_experiment

add_experiment(inputs: Dict[str, Any], output: Union[float, Dict[str, float], Sequence[float]], noise: Optional[float] = None, iteration: Optional[int] = None, reason: Optional[str] = None, provenance_id: Optional[str] = None, plot: Optional[Dict[str, int]] = None, _skip_categorical_check: bool = False) -> None

Add a single experiment to the dataset.

Parameters:

Name Type Description Default
inputs Dict[str, Any]

Dictionary mapping variable names to values

required
output Union[float, Dict[str, float], Sequence[float]]

Target/output value. A float on a single-objective session; on a multi-objective session a dict {objective: value} or a sequence in target order, one finite value per objective (a bare float is refused).

required
noise Optional[float]

Optional noise variance (σ²) of the measurement, in the output's squared units. Both backends treat it as a variance (BoTorch train_Yvar, scikit-learn alpha), so square a standard deviation before passing it.

None
iteration Optional[int]

Iteration number (auto-assigned if None)

None
reason Optional[str]

Reason for this experiment (e.g., 'Manual', 'Expected Improvement')

None
plot Optional[Dict[str, int]]

WholePlot/Subplot/RunOrder values for a split-plot run

None
_skip_categorical_check bool

Internal. Used when restoring a saved session: the row is kept and an undeclared label fails at training as before.

False
Example
session.add_experiment(
    inputs={'temperature': 350, 'catalyst': 'A'},
    output=0.85,
    reason='Manual'
)

get_data_summary

get_data_summary() -> Dict[str, Any]

Get summary of current experimental data.

Every value is JSON-safe: a statistic that is undefined for the current data is None, never NaN or inf. In particular the sample standard deviation (ddof=1) needs at least two observed outputs, so target_stats['std'] is None with zero or one observed output (e.g. right after the first Add Point on an empty session). Rows whose output is still missing are counted in n_experiments but ignored by the statistics; if no row has an output yet, every statistic is None.

Returns:

Type Description
Dict[str, Any]

Dictionary with data statistics

get_provenance

get_provenance() -> list

Return all provenance records (suggested vs actual per experiment).

Deep-copied so callers cannot mutate the internal audit trail (records contain nested suggested/actual/delta/acq_params dicts).

complete_experiment

complete_experiment(item_id: str, actual_inputs: dict, output: float, noise: Optional[float] = None, iteration: Optional[int] = None, reason: Optional[str] = None) -> None

Complete a staged queue item using the ACTUAL run conditions, recording provenance (suggested vs actual).

Parameters:

Name Type Description Default
noise Optional[float]

Optional noise variance (σ²) of the measurement.

None
iteration Optional[int]

Iteration to record the row under (auto-assigned if None). Lets a whole acquisition batch share one iteration.

None
reason Optional[str]

Replaces the item's staged reason when given (the user edited it while recording the result).

None

add_staged_experiment

add_staged_experiment(inputs: Dict[str, Any])

Add an experiment to the staging area (awaiting evaluation).

Staged experiments are typically suggested by acquisition functions but not yet evaluated. They can be retrieved, evaluated externally, and then added to the dataset with add_experiment().

Parameters:

Name Type Description Default
inputs Dict[str, Any]

Dictionary mapping variable names to values

required

Returns:

Type Description

The staged QueueItem (its id completes it later).

Example
# Generate suggestions and stage them
suggestions = session.suggest_next(strategy='qEI', n_suggestions=3)
for point in suggestions.to_dict('records'):
    session.add_staged_experiment(point)

# Later, evaluate and add
staged = session.get_staged_experiments()
for point in staged:
    output = run_experiment(**point)
    session.add_experiment(point, output=output)
session.clear_staged_experiments()

get_staged_experiments

get_staged_experiments() -> List[Dict[str, Any]]

Get all staged experiments awaiting evaluation.

Returns:

Type Description
List[Dict[str, Any]]

List of experiment input dictionaries

clear_staged_experiments

clear_staged_experiments() -> int

Clear all staged experiments.

Returns:

Type Description
int

Number of experiments cleared

move_staged_to_experiments

move_staged_to_experiments(outputs: List[float], noises: Optional[List[float]] = None, iteration: Optional[int] = None, reason: Optional[str] = None) -> int

Evaluate staged experiments and add them to the dataset in batch.

Convenience method that pairs staged inputs with outputs and adds them all to the experiment manager, then clears the staging area.

Parameters:

Name Type Description Default
outputs List[float]

List of output values (must match length of staged experiments)

required
noises Optional[List[float]]

Optional list of noise variances (σ²), one per staged experiment

None
iteration Optional[int]

Iteration number for all experiments (auto-assigned if None)

None
reason Optional[str]

Reason for these experiments (e.g., 'Expected Improvement')

None

Returns:

Type Description
int

Number of experiments added

Example
# Stage some experiments
session.add_staged_experiment({'x': 1.0, 'y': 2.0})
session.add_staged_experiment({'x': 3.0, 'y': 4.0})

# Evaluate them
outputs = [run_experiment(**point) for point in session.get_staged_experiments()]

# Add to dataset and clear staging
session.move_staged_to_experiments(outputs, reason='LogEI')

generate_initial_design

generate_initial_design(method: str = 'lhs', n_points: Optional[int] = None, random_seed: Optional[int] = None, **kwargs) -> List[Dict[str, Any]]

Generate initial experimental design (Design of Experiments).

Creates a set of experimental conditions to evaluate before starting Bayesian optimization. This does NOT add the experiments to the session - you must evaluate them and add the results using add_experiment().

Space-filling methods (take n_points as input): - 'random': Uniform random sampling - 'lhs': Latin Hypercube Sampling (recommended, good space-filling) - 'sobol': Sobol quasi-random sequences (low discrepancy) - 'halton': Halton sequences - 'hammersly': Hammersly sequences (low discrepancy)

Classical RSM methods (run count determined by design structure): - 'full_factorial': All combinations of factor levels - 'fractional_factorial': Subset of full factorial using generators - 'ccd': Central Composite Design (factorial + axial + center) - 'box_behnken': Box-Behnken design (3+ continuous factors)

Screening methods (run count determined by design structure): - 'plackett_burman': Ultra-efficient 2-level screening (continuous only) - 'gsd': Generalized Subset Design (mixed categorical/continuous)

Optimal design (user-specified model structure): - 'optimal': Statistically efficient design optimized for estimating specific model terms. Requires n_points and either model_type or effects.

Linear input constraints (see add_input_constraint) are honored by every method, but not in the same way:

  • Space-filling methods reject and resample until enough strictly feasible points are found.
  • Classical methods drop the structural points that violate the constraints and then check whether the survivors can still estimate the design's implied model. If they cannot, the call raises DesignNotEstimableError rather than returning a rank-deficient remnant. Pass allow_infeasible=True to return the remnant anyway.
  • 'optimal' selects from a candidate set that is filtered and augmented with points on the feasible region's boundary.

Parameters:

Name Type Description Default
method str

Sampling strategy to use

'lhs'
n_points Optional[int]

Number of points (default 10 for space-filling; required for optimal; ignored for classical)

None
random_seed Optional[int]

Random seed for reproducibility

None
**kwargs

Additional method-specific parameters: - lhs_criterion: For LHS method ("maximin", "correlation", "ratio") - n_levels: Levels per factor for full factorial (2 or 3), or candidate grid resolution for optimal design (default 5) - n_center: Center point replicates (classical designs) - generators: Fractional factorial generator string - ccd_alpha: CCD alpha ("orthogonal" or "rotatable") - ccd_face: CCD face ("circumscribed", "inscribed", "faced") - gsd_reduction: GSD reduction factor (>=2, larger = fewer runs) - model_type: Optimal design model shortcut ("linear", "interaction", "quadratic") - effects: Optimal design custom effects list using variable names (e.g., ["Temperature", "Temperature*Pressure", "Temperature**2"]) - criterion: Optimality criterion ("D", "A", or "I") - algorithm: Optimal design algorithm ("sequential", "simple_exchange", "fedorov", "modified_fedorov", "detmax") - allow_infeasible: For a constrained classical design, return the surviving points with a log warning instead of raising DesignNotEstimableError (default False)

{}

Returns:

Type Description
List[Dict[str, Any]]

List of dictionaries with variable names and values (no outputs)

Raises:

Type Description
DesignNotEstimableError

A constrained classical design lost structural points and the survivors can no longer estimate its implied model. Suppressed by allow_infeasible=True. Subclasses ValueError.

InfeasibleRegionError

The registered constraints leave no feasible point within the variable bounds, or restrict the region to a zero-volume slice a continuous sampler cannot reach. Subclasses ValueError.

Example
# Generate initial design
points = session.generate_initial_design('lhs', n_points=10)

# Run experiments and add results
for point in points:
    output = run_experiment(**point)  # Your experiment function
    session.add_experiment(point, output=output)

# Now ready to train model
session.train_model()

generate_split_plot_design

generate_split_plot_design(designs: Dict[str, Dict[str, Any]], **kwargs)

Split-plot design over the search space's change levels.

Existing design methods are nested by change difficulty (very_hard, then hard, then easy), so each hard setting is held while the easier variables are run under it. See alchemist_core.utils.split_plot.generate_split_plot_design for the full description of every argument. The points are not added to the session's experiments; stage or load them yourself.

Parameters:

Name Type Description Default
designs Dict[str, Dict[str, Any]]

One entry per change level present in the search space, mapping the level name to a design method plus its arguments.

required
**kwargs

replicates, easy_mode, middle_mode, reference, order and random_seed.

{}

Returns:

Type Description

(points, info). Each point is a dict with every controllable

variable plus WholePlot, Subplot (three levels only),

RunOrder and Reason. info carries the levels, plot and

run counts, and any warnings.

Raises:

Type Description
InfeasibleRegionError

when a plot's constraints leave no feasible design.

ValueError

when the levels in designs do not match the search space, or the design would exceed the run limit.

Example
session.add_variable('x1', 'real', bounds=(0.0, 1.0))
session.add_variable('h1', 'real', bounds=(0.0, 10.0), changes='hard')
points, info = session.generate_split_plot_design(
    designs={
        'hard': {'method': 'full_factorial', 'n_levels': 2},
        'easy': {'method': 'lhs', 'n_points': 4},
    },
    replicates={'hard': 2},
    random_seed=7,
)
print(info['n_plots'], info['n_runs'])

get_optimal_design_info

get_optimal_design_info(effects: Optional[List[str]] = None, model_type: Optional[str] = None) -> Dict[str, Any]

Dry-run model-term inspection for optimal designs.

Returns the model term names and parameter counts for a given effects specification without running the full exchange algorithm. Use this to verify your effects list and choose an appropriate n_points before calling generate_initial_design(method='optimal', ...).

Parameters:

Name Type Description Default
effects Optional[List[str]]

Explicit list of effect strings using variable names, e.g. ["Temperature", "Catalyst", "Temperature*Catalyst", "Metal Loading**2"].

None
model_type Optional[str]

Shortcut model type — one of "linear", "interaction", "quadratic". Mutually exclusive with effects.

None

Returns:

Type Description
Dict[str, Any]

Dict with:

Dict[str, Any]
  • "model_terms": Human-readable term names (list of str).
Dict[str, Any]
  • "p_columns": Total number of model columns, accounting for dummy coding of categorical variables.
Dict[str, Any]
  • "n_points_minimum": Smallest n_points that can fit the model (equals p_columns).
Dict[str, Any]
  • "n_points_recommended": Suggested n_points for a well-determined design (2 × p_columns).

Example::

info = session.get_optimal_design_info(
    effects=['Temperature', 'Catalyst', 'Metal Loading',
             'Metal Loading**2', 'Temperature*Metal Loading',
             'Zinc Fraction']
)
print(info['model_terms'])
# ['Intercept', 'Temperature', 'Catalyst', 'Metal Loading',
#  'Metal Loading^2', 'Temperature*Metal Loading', 'Zinc Fraction']
print(info['n_points_recommended'])  # 14 (2 × 7)

generate_optimal_design

generate_optimal_design(effects: Optional[List[str]] = None, model_type: Optional[str] = None, n_points: Optional[int] = None, p_multiplier: Optional[float] = None, criterion: str = 'D', algorithm: str = 'fedorov', n_levels: int = 5, max_iter: int = 200, random_seed: Optional[int] = None) -> Tuple[List[Dict[str, Any]], Dict[str, Any]]

Generate a statistically optimal experimental design.

Unlike generate_initial_design(method='optimal'), this method returns the full (points, info) tuple so callers can inspect design quality metrics (D_eff, A_eff, model_terms, etc.).

Specify the number of runs using one of:

  • n_points — an absolute run count.
  • p_multiplier — a multiplier applied to the number of model columns p, so n_points = ceil(p_multiplier * p). A value of 2.0 (two points per parameter) is a common starting point.

Parameters:

Name Type Description Default
effects Optional[List[str]]

Explicit list of effect strings using variable names, e.g. ["Temperature", "Pressure", "Temperature*Pressure", "Temperature**2"].

None
model_type Optional[str]

Shortcut model type — one of "linear", "interaction", "quadratic". Mutually exclusive with effects.

None
n_points Optional[int]

Absolute number of experimental runs to generate. Mutually exclusive with p_multiplier.

None
p_multiplier Optional[float]

Run count expressed as a multiple of the number of model columns p (e.g. 2.0 → 2p runs). Mutually exclusive with n_points.

None
criterion str

Optimality criterion — "D" (default), "A", or "I".

'D'
algorithm str

Exchange algorithm — "fedorov" (default), "sequential", "simple_exchange", "modified_fedorov", or "detmax".

'fedorov'
n_levels int

Candidate grid levels per continuous variable (default 5).

5
max_iter int

Maximum exchange iterations (default 200).

200
random_seed Optional[int]

Random seed for reproducibility.

None

Returns:

Type Description
Tuple[List[Dict[str, Any]], Dict[str, Any]]

Tuple of: - points: List of dicts with actual variable values. - info: Dict with design quality metrics::

{"criterion": "D", "algorithm": "fedorov",
 "score": 0.042, "D_eff": 89.3, "A_eff": 76.1,
 "p_columns": 6, "n_runs": 12,
 "model_terms": ["Intercept", "Temperature", ...]}

Raises:

Type Description
ValueError

If search space is empty; if both or neither of n_points / p_multiplier are given; if p_multiplier < 1.0; or if n_points < p (singular design matrix).

Example::

points, info = session.generate_optimal_design(
    model_type='quadratic', p_multiplier=2.0, criterion='D',
)
print(f"Generated {len(points)} runs, D_eff={info['D_eff']:.1f}%")
print("Model terms:", info['model_terms'])

train_model

train_model(backend: str = 'sklearn', kernel: str = 'Matern', kernel_params: Optional[Dict] = None, **kwargs) -> Dict[str, Any]

Train surrogate model on current data.

Parameters:

Name Type Description Default
backend str

'sklearn' or 'botorch'

'sklearn'
kernel str

Kernel type ('RBF', 'Matern', 'RationalQuadratic')

'Matern'
kernel_params Optional[Dict]

Additional kernel parameters (e.g., {'nu': 2.5} for Matern)

None
**kwargs

Backend-specific parameters

{}

Returns:

Type Description
Dict[str, Any]

Dictionary with training results and hyperparameters

Example
results = session.train_model(backend='botorch', kernel='Matern')
print(results['metrics'])

get_last_training_config

get_last_training_config() -> Optional[Dict[str, Any]]

Return the arguments of the most recent successful train_model() call.

The dict holds backend, kernel, kernel_params and every backend kwarg exactly as passed (e.g. input_transform_type, output_transform_type, calibration_enabled), before train_model applies its own defaults. A value passed explicitly as None is kept, because for BoTorch an explicit None transform means "no transform" while an omitted one means "use the default". Replay it with session.train_model(**config).

The config is saved with the session (model_config.training_config) and restored by load_session.

Returns:

Type Description
Optional[Dict[str, Any]]

A copy of the config, or None if no model has been trained.

get_model_summary

get_model_summary() -> Optional[Dict[str, Any]]

Get summary of trained model.

Returns:

Type Description
Optional[Dict[str, Any]]

Dictionary with model information, or None if no model trained

suggest_next

suggest_next(strategy: str = 'EI', goal: Union[str, List[str]] = 'maximize', n_suggestions: int = 1, ref_point: Optional[List[float]] = None, context: Optional[Dict[str, Any]] = None, hold: Optional[Dict[str, Any]] = None, observed: Optional[Dict[str, Any]] = None, **kwargs) -> pd.DataFrame

Suggest next experiment(s) using acquisition function.

Parameters:

Name Type Description Default
strategy str

Acquisition strategy - 'EI': Expected Improvement - 'PI': Probability of Improvement - 'UCB': Upper Confidence Bound - 'LogEI': Log Expected Improvement (BoTorch only) - 'LogPI': Log Probability of Improvement (BoTorch only) - 'qEI', 'qUCB', 'qIPV': Batch acquisition (BoTorch only) - 'qEHVI', 'qNEHVI': Multi-objective acquisition (BoTorch only)

'EI'
goal Union[str, List[str]]

'maximize' or 'minimize' (str), or list of per-objective directions

'maximize'
n_suggestions int

Number of suggestions (batch acquisition)

1
ref_point Optional[List[float]]

Reference point for MOBO hypervolume (list of floats, optional)

None
context Optional[Dict[str, Any]]

Older name for observed.

None
hold Optional[Dict[str, Any]]

Controllable variable name -> value to keep fixed for this call. Example: hold={"c": "a"}.

None
observed Optional[Dict[str, Any]]

Observed variable name -> measured value. Required when any observed variable is registered. Keys that are not variables are ignored. Example: observed={"k": "p", "z": 0.42}.

None
**kwargs

Strategy-specific parameters:

Sklearn backend: - xi (float): Exploration parameter for EI/PI (default: 0.01) - kappa (float): Exploration parameter for UCB (default: 1.96)

BoTorch backend: - beta (float): Exploration parameter for UCB (default: 0.5) - mc_samples (int): Monte Carlo samples for batch acquisition (default: 128)

{}

Returns:

Type Description
DataFrame

DataFrame with suggested experiment(s). Held values are repeated in

DataFrame

every row. The suggestion also reports, per row, how much the model

DataFrame

knows there: see session.last_suggestion_diagnostics.

Raises:

Type Description
InfeasibleRegionError

when hold leaves no point that satisfies the input constraints.

ValueError

when a hold or observed name or value is not valid for its variable, or an observed variable has no value.

ValueError

when n_suggestions > 1 is combined with a one-point strategy (EI, LogEI, PI, LogPI, UCB) or the sklearn backend; use 'qEI', 'qUCB' or 'qIPV' on BoTorch for a batch.

TypeError

when a keyword argument is not an acquisition parameter of any strategy (for example n_candidates).

Notes

With anything held, the improvement baseline of the EI family (EI, LogEI, PI, LogPI, qEI) is the best posterior mean at the training inputs moved into the held slice, so a suggestion improves on what is attainable there.

After each call session.last_suggestion_diagnostics is a list with one dict per suggested row: held (the held variable names), knowledge_ratio (0 where the data pins the function, 1 where the model is at its prior; None when it cannot be computed) and warnings. A warning is added when the ratio exceeds 0.9 and something is held or observed.

Examples:

Single-objective:

next_point = session.suggest_next(strategy='EI', goal='maximize')

Keep a hard-to-change variable at its current setting for this call:

next_point = session.suggest_next(strategy='EI', goal='maximize', hold={'c': 'a'})
print(session.last_suggestion_diagnostics[0]['knowledge_ratio'])

With observed variables registered, supply their measured values:

next_point = session.suggest_next(observed={'z': 0.42, 'k': 'p'})

Multi-objective:

suggestions = session.suggest_next(
    strategy='qNEHVI',
    goal=['maximize', 'maximize'],
    ref_point=[0.0, 0.0],
)

find_optimum

find_optimum(goal: Union[str, List[str]] = 'maximize', n_grid_points: int = 10000, observed: Optional[Dict[str, Any]] = None) -> Dict[str, Any]

Find the point where the model predicts the optimal value.

For single-objective: returns the predicted optimum via grid search. For multi-objective: returns the predicted Pareto frontier from observed data.

Parameters:

Name Type Description Default
goal Union[str, List[str]]

'maximize' or 'minimize' (str), or list of per-objective directions

'maximize'
n_grid_points int

Target number of grid points for search (default: 10000)

10000
observed Optional[Dict[str, Any]]

Observed variable name -> value to condition the search on. Observed variables are measured, not optimized: the optimum is the best controllable setting at these values, and 'x_opt' carries them. Defaults to the latest experiment's values. Ignored, with a warning, for multi-objective problems.

None

Returns:

Type Description
Dict[str, Any]

Single-objective dict with 'x_opt', 'value', 'std'.

Dict[str, Any]

Multi-objective dict with 'pareto_frontier', 'predicted_values',

Dict[str, Any]

'objective_names', 'n_pareto'.

Example
best = session.find_optimum(goal='maximize')
conditioned = session.find_optimum(goal='maximize', observed={'z': 0.42})
print(conditioned['x_opt'], conditioned['value'])

predict

predict(inputs: DataFrame) -> Dict[str, Tuple[np.ndarray, np.ndarray]]

Make predictions at new points.

Parameters:

Name Type Description Default
inputs DataFrame

DataFrame with input features

required

Returns:

Type Description
Dict[str, Tuple[ndarray, ndarray]]

Dict mapping objective/target name to (predictions, uncertainties) tuple.

Dict[str, Tuple[ndarray, ndarray]]

Single-objective example: {'yield': (means, stds)}

Dict[str, Tuple[ndarray, ndarray]]

Multi-objective example: {'yield': (means, stds), 'selectivity': (means, stds)}

on

on(event: str, callback: Callable) -> None

Register event listener.

Parameters:

Name Type Description Default
event str

Event name

required
callback Callable

Callback function

required
Example
def on_training_done(data):
    print(f"Training completed with R² = {data['metrics']['r2']}")

session.on("training_completed", on_training_done)

set_config

set_config(**kwargs) -> None

Update session configuration.

Parameters:

Name Type Description Default
**kwargs

Configuration parameters to update

{}
Example
session.set_config(random_state=123, verbose=False)

lock_data

lock_data(notes: str = '', extra_parameters: Optional[Dict[str, Any]] = None) -> AuditEntry

Lock in current experimental data configuration.

Creates an immutable audit log entry capturing the current data state. This should be called when you're satisfied with your experimental dataset and ready to proceed with modeling.

Parameters:

Name Type Description Default
notes str

Optional user notes about this data configuration

''

Returns:

Type Description
AuditEntry

Created AuditEntry

Example
session.add_experiment({'temp': 100, 'pressure': 5}, output=85.2)
session.lock_data(notes="Initial screening dataset")

lock_model

lock_model(notes: str = '') -> AuditEntry

Lock in current trained model configuration.

Creates an immutable audit log entry capturing the trained model state. This should be called when you're satisfied with your model performance and ready to use it for acquisition.

Parameters:

Name Type Description Default
notes str

Optional user notes about this model

''

Returns:

Type Description
AuditEntry

Created AuditEntry

Raises:

Type Description
ValueError

If no model has been trained

Example
session.train_model(backend='sklearn', kernel='matern')
session.lock_model(notes="Best cross-validation performance")

lock_acquisition

lock_acquisition(strategy: str, parameters: Dict[str, Any], suggestions: List[Dict[str, Any]], notes: str = '') -> AuditEntry

Lock in acquisition function decision and suggested experiments.

Creates an immutable audit log entry capturing the acquisition decision. This should be called when you've reviewed the suggestions and are ready to run the recommended experiments.

Parameters:

Name Type Description Default
strategy str

Acquisition strategy name ('EI', 'PI', 'UCB', etc.)

required
parameters Dict[str, Any]

Acquisition function parameters (xi, kappa, etc.)

required
suggestions List[Dict[str, Any]]

List of suggested experiment dictionaries

required
notes str

Optional user notes about this decision

''

Returns:

Type Description
AuditEntry

Created AuditEntry

Example
suggestions = session.suggest_next(strategy='qEI', n_suggestions=3)
session.lock_acquisition(
    strategy='qEI',
    parameters={'goal': 'maximize', 'mc_samples': 128},
    suggestions=suggestions,
    notes="Top 3 candidates for next batch"
)

get_audit_log

get_audit_log() -> List[Dict[str, Any]]

Get complete audit log as list of dictionaries.

Returns:

Type Description
List[Dict[str, Any]]

List of audit entry dictionaries

export_audit_markdown

export_audit_markdown() -> str

Export audit log as markdown for publications.

Returns:

Type Description
str

Markdown-formatted audit trail

save_session

save_session(filepath: str)

Save complete session state to JSON file.

Saves all session data including: - Session metadata (name, description, tags) - Search space definition (variables, derived variables, and the linear input constraints registered on it) - Outcome constraints - Experimental data - Trained model state (if available) - Complete audit log

Parameters:

Name Type Description Default
filepath str

Path to save session file (.json extension recommended)

required
Example
session.save_session("~/ALchemist_Sessions/catalyst_study_nov2025.json")

export_session_json

export_session_json() -> str

Export current session state as a JSON string (no filesystem side-effects for caller).

Returns:

Type Description
str

JSON string of session data

load_session

load_session(filepath: str = None, retrain_on_load: bool = True) -> OptimizationSession

Load session from JSON file.

This method works both as a static method (creating a new session) and as an instance method (loading into existing session):

Static usage (returns new session):

session = OptimizationSession.load_session("my_session.json")

Instance usage (loads into existing session):

session = OptimizationSession()
session.load_session("my_session.json")
# session.experiment_manager.df is now populated

Parameters:

Name Type Description Default
filepath str

Path to session file (required when called as static method, can be self when called as instance method)

None
retrain_on_load bool

Whether to retrain model if config exists (default: True)

True

Returns:

Type Description
OptimizationSession

OptimizationSession (new or modified instance)

update_metadata

update_metadata(name: Optional[str] = None, description: Optional[str] = None, tags: Optional[List[str]] = None, author: Optional[str] = None)

Update session metadata.

Parameters:

Name Type Description Default
name Optional[str]

New session name (optional)

None
description Optional[str]

New description (optional)

None
tags Optional[List[str]]

New tags (optional)

None
Example
session.update_metadata(
    name="Catalyst Screening - Final",
    description="Optimized Pt/Pd ratios",
    tags=["catalyst", "platinum", "palladium", "final"]
)

plot_parity

plot_parity(use_calibrated: bool = False, sigma_multiplier: float = 1.96, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, show_metrics: bool = True, show_error_bars: bool = True, target_columns: Optional[str] = None, ax: Optional[Axes] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create parity plot of actual vs predicted values from cross-validation.

This plot shows how well the model's predictions match the actual experimental values, with optional error bars indicating prediction uncertainty.

Parameters:

Name Type Description Default
use_calibrated bool

Use calibrated uncertainty estimates if available

False
sigma_multiplier float

Error bar size (1.96 = 95% CI, 1.0 = 68% CI, 2.58 = 99% CI)

1.96
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated with metrics)

None
show_metrics bool

Include RMSE, MAE, R² in title

True
show_error_bars bool

Display uncertainty error bars

True
target_columns Optional[str]

For multi-objective: objective name, 'all', or None. Single-objective sessions ignore this parameter.

None
ax Optional[Axes]

Existing matplotlib Axes to draw on (creates new figure if None). Cannot be used with multi-objective 'all' mode.

None
subplot_labels Optional[Union[bool, str, List[str]]]

Add panel labels to axes. True → auto (a), (b), …; str → single label; list[str] → one label per subplot.

None

Returns:

Type Description
Figure

matplotlib Figure object (displays inline in Jupyter)

Example

fig = session.plot_parity() fig.savefig('parity.png', bbox_inches='tight')

Note

Requires model to be trained with cross-validation (default behavior). Error bars are only shown if model provides uncertainty estimates.

plot_slice

plot_slice(x_var: str, fixed_values: Optional[Dict[str, Any]] = None, n_points: int = 100, show_uncertainty: Union[bool, List[float]] = True, show_experiments: bool = True, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 1D slice plot showing model predictions along one variable.

Parameters:

Name Type Description Default
x_var str

Variable name to vary along X axis (must be 'real' or 'integer')

required
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables.

None
n_points int

Number of points to evaluate along the slice

100
show_uncertainty Union[bool, List[float]]

Show uncertainty bands (True, False, or list of sigma values)

True
show_experiments bool

Plot experimental data points as scatter

True
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated)

None
target_columns Optional[str]

For multi-objective: objective name, 'all', or None.

None

Returns:

Type Description
Figure

matplotlib Figure object

plot_contour

plot_contour(x_var: str, y_var: str, fixed_values: Optional[Dict[str, Any]] = None, grid_resolution: int = 50, show_experiments: bool = True, show_suggestions: bool = False, cmap: str = 'viridis', figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, ax: Optional[Axes] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 2D contour plot of model predictions over a variable space.

Visualizes the model's predicted response surface by varying two variables while holding others constant. Useful for understanding variable interactions and identifying optimal regions.

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (must be 'real' type)

required
y_var str

Variable name for Y axis (must be 'real' type)

required
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables. If not provided, uses midpoint for real/integer, first category for categorical.

None
grid_resolution int

Grid density (NxN points)

50
show_experiments bool

Plot experimental data points as scatter

True
show_suggestions bool

Plot last suggested points (if available)

False
cmap str

Matplotlib colormap name (e.g., 'viridis', 'coolwarm', 'plasma')

'viridis'
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: "Contour Plot of Model Predictions")

None

Returns:

Type Description
Figure

matplotlib Figure object (displays inline in Jupyter)

Example

Basic contour plot

fig = session.plot_contour('temperature', 'pressure')

With fixed values for other variables

fig = session.plot_contour( ... 'temperature', 'pressure', ... fixed_values={'catalyst': 'Pt', 'flow_rate': 50}, ... cmap='coolwarm', ... grid_resolution=100 ... ) fig.savefig('contour.png', dpi=300, bbox_inches='tight')

Note
  • Requires at least 2 'real' type variables
  • Model must be trained before plotting
  • Categorical variables are automatically encoded using model's encoding

plot_surface

plot_surface(x_var: str, y_var: str, fixed_values: Optional[Dict[str, Any]] = None, grid_resolution: int = 50, show_experiments: bool = True, show_suggestions: bool = False, cmap: str = 'viridis', alpha: float = 0.9, figsize: Tuple[float, float] = (10, 8), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, ax: Optional[Any] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 3D surface plot of model predictions over a variable space.

Like plot_contour, varies two variables while holding others constant, but renders the predicted output on the Z axis as a 3D surface colored by the prediction values.

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (must be 'real' type)

required
y_var str

Variable name for Y axis (must be 'real' type)

required
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables. If not provided, uses midpoint for real/integer, first category for categorical.

None
grid_resolution int

Grid density (NxN points)

50
show_experiments bool

Plot experimental data points as 3D scatter

True
show_suggestions bool

Plot last suggested points (if available)

False
cmap str

Matplotlib colormap name (e.g., 'viridis', 'coolwarm', 'plasma')

'viridis'
alpha float

Surface transparency (0=transparent, 1=opaque, default: 0.9)

0.9
figsize Tuple[float, float]

Figure size as (width, height) in inches

(10, 8)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: "3D Surface Plot of Model Predictions")

None
target_columns Optional[str]

Target column name (for multi-objective)

None
ax Optional[Any]

Existing 3D axes (creates new if None)

None

Returns:

Type Description
Figure

matplotlib Figure object with 3D axes

Example

fig = session.plot_surface('temperature', 'pressure') fig = session.plot_surface( ... 'temperature', 'pressure', ... fixed_values={'catalyst': 'Pt', 'flow_rate': 50}, ... cmap='coolwarm', alpha=0.8 ... ) fig.savefig('surface.png', dpi=300, bbox_inches='tight')

plot_uncertainty_surface

plot_uncertainty_surface(x_var: str, y_var: str, fixed_values: Optional[Dict[str, Any]] = None, grid_resolution: int = 50, show_experiments: bool = True, show_suggestions: bool = False, cmap: str = 'Reds', alpha: float = 0.9, figsize: Tuple[float, float] = (10, 8), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, ax: Optional[Any] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 3D surface plot of posterior uncertainty.

Like plot_surface, but renders the prediction standard deviation on the Z axis. Useful for identifying under-explored regions.

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (must be 'real' type)

required
y_var str

Variable name for Y axis (must be 'real' type)

required
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables.

None
grid_resolution int

Grid density (NxN points)

50
show_experiments bool

Plot experimental data points

True
show_suggestions bool

Plot last suggested points

False
cmap str

Matplotlib colormap name (default: 'Reds')

'Reds'
alpha float

Surface transparency (0=transparent, 1=opaque)

0.9
figsize Tuple[float, float]

Figure size as (width, height) in inches

(10, 8)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title

None
target_columns Optional[str]

Target column name (for multi-objective)

None
ax Optional[Any]

Existing 3D axes (creates new if None)

None

Returns:

Type Description
Figure

matplotlib Figure object with 3D axes

Example

fig = session.plot_uncertainty_surface('temperature', 'pressure')

plot_voxel

plot_voxel(x_var: str, y_var: str, z_var: str, fixed_values: Optional[Dict[str, Any]] = None, grid_resolution: int = 15, show_experiments: bool = True, show_suggestions: bool = False, cmap: str = 'viridis', alpha: float = 0.5, use_log_scale: bool = False, figsize: Tuple[float, float] = (10, 8), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 3D voxel plot of model predictions over a variable space.

Visualizes the model's predicted response surface by varying three variables while holding others constant. Uses volumetric rendering to show the 3D prediction landscape with adjustable transparency.

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (must be 'real' or 'integer' type)

required
y_var str

Variable name for Y axis (must be 'real' or 'integer' type)

required
z_var str

Variable name for Z axis (must be 'real' or 'integer' type)

required
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables. If not provided, uses midpoint for real/integer, first category for categorical.

None
grid_resolution int

Grid density (NxNxN points, default: 15) Note: 15³ = 3375 points, scales as N³

15
show_experiments bool

Plot experimental data points as scatter

True
show_suggestions bool

Plot last suggested points (if available)

False
cmap str

Matplotlib colormap name (e.g., 'viridis', 'coolwarm', 'plasma')

'viridis'
alpha float

Transparency level (0.0=transparent, 1.0=opaque, default: 0.5) Lower values reveal interior structure better

0.5
use_log_scale bool

Use logarithmic color scale for values spanning orders of magnitude

False
figsize Tuple[float, float]

Figure size as (width, height) in inches

(10, 8)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: "3D Voxel Plot of Model Predictions")

None

Returns:

Type Description
Figure

matplotlib Figure object with 3D axes

Example

Basic 3D voxel plot

fig = session.plot_voxel('temperature', 'pressure', 'flow_rate')

With transparency to see interior

fig = session.plot_voxel( ... 'temperature', 'pressure', 'flow_rate', ... alpha=0.3, ... grid_resolution=20 ... ) fig.savefig('voxel_plot.png', dpi=150, bbox_inches='tight')

With fixed values for other variables

fig = session.plot_voxel( ... 'temperature', 'pressure', 'flow_rate', ... fixed_values={'catalyst': 'Pt', 'pH': 7.0}, ... cmap='coolwarm' ... )

Raises:

Type Description
ValueError

If search space doesn't have at least 3 continuous variables

Note
  • Requires at least 3 'real' or 'integer' type variables
  • Model must be trained before plotting
  • Computationally expensive: O(N³) evaluations
  • Lower grid_resolution for faster rendering
  • Use alpha < 0.5 to see interior structure
  • Interactive rotation available in some backends (notebook)

plot_metrics

plot_metrics(metric: Literal['rmse', 'mae', 'r2', 'mape'] = 'rmse', cv_splits: int = 5, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, use_cached: bool = True, target_columns: Optional[str] = None, ax: Optional[Axes] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Plot cross-validation metrics as a function of training set size.

Parameters:

Name Type Description Default
metric Literal['rmse', 'mae', 'r2', 'mape']

Which metric to plot ('rmse', 'mae', 'r2', or 'mape')

'rmse'
cv_splits int

Number of cross-validation folds (default: 5)

5
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
use_cached bool

Use cached metrics if available (default: True)

True
target_columns Optional[str]

For multi-objective: objective name, 'all', or None.

None

Returns:

Type Description
Figure

matplotlib Figure object

Note

Calls model.evaluate() if metrics not cached, which can be computationally expensive for large datasets. Set use_cached=False to force recomputation.

plot_qq

plot_qq(use_calibrated: bool = False, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, ax: Optional[Axes] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create Q-Q (quantile-quantile) plot for model residuals normality check.

Parameters:

Name Type Description Default
use_calibrated bool

Use calibrated uncertainty estimates if available

False
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated)

None
target_columns Optional[str]

For multi-objective: objective name, 'all', or None.

None
ax Optional[Axes]

Existing matplotlib Axes to draw on (creates new figure if None). Cannot be used with multi-objective 'all' mode.

None

Returns:

Type Description
Figure

matplotlib Figure object

plot_calibration

plot_calibration(use_calibrated: bool = False, n_bins: int = 10, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, ax: Optional[Axes] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create calibration plot showing reliability of uncertainty estimates.

Parameters:

Name Type Description Default
use_calibrated bool

Use calibrated uncertainty estimates if available

False
n_bins int

Number of bins for grouping predictions (default: 10)

10
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated)

None
target_columns Optional[str]

For multi-objective: objective name, 'all', or None.

None
ax Optional[Axes]

Existing matplotlib Axes to draw on (creates new figure if None). Cannot be used with multi-objective 'all' mode.

None

Returns:

Type Description
Figure

matplotlib Figure object

plot_pareto_frontier

plot_pareto_frontier(directions: Optional[List[str]] = None, ref_point: Optional[List[float]] = None, show_hypervolume: bool = True, constraint_boundaries: Optional[Dict[str, float]] = None, suggested_points_override: Optional[ndarray] = None, figsize=(8, 6), dpi=100, title=None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None)

Plot the Pareto frontier for multi-objective optimization.

Currently supports 2-objective optimization only.

Parameters:

Name Type Description Default
directions Optional[List[str]]

Per-objective direction ('maximize'/'minimize'). Default: all maximize.

None
ref_point Optional[List[float]]

Reference point for hypervolume shading.

None
show_hypervolume bool

Whether to shade dominated hypervolume.

True
constraint_boundaries Optional[Dict[str, float]]

{objective_name: value} for constraint lines.

None
suggested_points_override Optional[ndarray]

(n, n_obj) array of points to overlay as suggestions.

None
figsize

Figure size.

(8, 6)
dpi

Figure DPI.

100
title

Optional plot title.

None

Returns:

Type Description

matplotlib Figure

plot_regret

plot_regret(goal: Union[str, List[str]] = 'maximize', include_predictions: bool = True, show_cumulative: bool = False, backend: Optional[str] = None, kernel: Optional[str] = None, n_grid_points: int = 1000, sigma_bands: Optional[List[float]] = None, start_iteration: int = 5, reuse_hyperparameters: bool = True, use_calibrated_uncertainty: bool = False, ref_point: Optional[List[float]] = None, ax: Optional[Any] = None, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Plot optimization progress.

For single-objective: regret (incumbent trajectory) plot. For multi-objective: hypervolume convergence plot.

Parameters:

Name Type Description Default
goal Union[str, List[str]]

'maximize' or 'minimize' (str), or list of per-objective directions.

'maximize'
include_predictions bool

Overlay model predictions (single-obj only).

True
show_cumulative bool

Show cumulative best line.

False
backend Optional[str]

Model backend. Uses session default if None.

None
kernel Optional[str]

Kernel type. Uses session default if None.

None
n_grid_points int

Grid points for prediction overlay.

1000
sigma_bands Optional[List[float]]

Sigma values for uncertainty bands.

None
start_iteration int

First iteration for predictions.

5
reuse_hyperparameters bool

Reuse final model's hyperparameters.

True
use_calibrated_uncertainty bool

Use calibrated uncertainties.

False
ref_point Optional[List[float]]

Reference point for hypervolume (MOBO only, required).

None
ax Optional[Any]

Existing matplotlib Axes to draw on (creates new figure if None).

None
figsize Tuple[float, float]

Figure size.

(8, 6)
dpi int

DPI.

100
title Optional[str]

Custom title.

None

Returns:

Type Description
Figure

matplotlib Figure object

plot_acquisition_slice

plot_acquisition_slice(x_var: str, acq_func: str = 'ei', fixed_values: Optional[Dict[str, Any]] = None, n_points: int = 100, acq_func_kwargs: Optional[Dict[str, Any]] = None, goal: str = 'maximize', show_experiments: bool = True, show_suggestions: bool = True, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 1D slice plot showing acquisition function along one variable.

Visualizes how the acquisition function value changes as one variable is varied while all other variables are held constant. This shows which regions along that variable axis are most promising for the next experiment.

Parameters:

Name Type Description Default
x_var str

Variable name to vary along X axis (must be 'real' or 'integer')

required
acq_func str

Acquisition function name ('ei', 'pi', 'ucb', 'logei', 'logpi')

'ei'
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables. If not provided, uses midpoint for real/integer, first category for categorical.

None
n_points int

Number of points to evaluate along the slice

100
acq_func_kwargs Optional[Dict[str, Any]]

Additional acquisition parameters (xi, kappa, beta)

None
goal str

'maximize' or 'minimize' - optimization direction

'maximize'
show_experiments bool

Plot experimental data points as scatter

True
show_suggestions bool

Plot last suggested points (if available)

True
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated)

None

Returns:

Type Description
Figure

matplotlib Figure object

Example

Visualize Expected Improvement along temperature

fig = session.plot_acquisition_slice( ... 'temperature', ... acq_func='ei', ... fixed_values={'pressure': 5.0, 'catalyst': 'Pt'} ... ) fig.savefig('acq_slice.png', dpi=300)

See where UCB is highest

fig = session.plot_acquisition_slice( ... 'pressure', ... acq_func='ucb', ... acq_func_kwargs={'beta': 0.5} ... )

Note
  • Model must be trained before plotting
  • Higher acquisition values indicate more promising regions
  • Use this to understand where the algorithm wants to explore next

plot_acquisition_contour

plot_acquisition_contour(x_var: str, y_var: str, acq_func: str = 'ei', fixed_values: Optional[Dict[str, Any]] = None, grid_resolution: int = 50, acq_func_kwargs: Optional[Dict[str, Any]] = None, goal: str = 'maximize', show_experiments: bool = True, show_suggestions: bool = True, cmap: str = 'viridis', use_log_scale: Optional[bool] = None, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 2D contour plot of acquisition function over variable space.

Visualizes the acquisition function surface by varying two variables while holding others constant. Shows "hot spots" where the algorithm believes the next experiment should be conducted. Higher values indicate more promising regions to explore.

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (must be 'real' type)

required
y_var str

Variable name for Y axis (must be 'real' type)

required
acq_func str

Acquisition function name ('ei', 'pi', 'ucb', 'logei', 'logpi')

'ei'
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables. If not provided, uses midpoint for real/integer, first category for categorical.

None
grid_resolution int

Grid density (NxN points)

50
acq_func_kwargs Optional[Dict[str, Any]]

Additional acquisition parameters (xi, kappa, beta)

None
goal str

'maximize' or 'minimize' - optimization direction

'maximize'
show_experiments bool

Plot experimental data points as scatter

True
show_suggestions bool

Plot last suggested points (if available)

True
cmap str

Matplotlib colormap name (e.g., 'viridis', 'hot', 'plasma')

'viridis'
use_log_scale Optional[bool]

Use logarithmic color scale (default: auto-enable for logei/logpi)

None
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated)

None

Returns:

Type Description
Figure

matplotlib Figure object

Example

Visualize Expected Improvement surface

fig = session.plot_acquisition_contour( ... 'temperature', 'pressure', ... acq_func='ei' ... ) fig.savefig('acq_contour.png', dpi=300)

See UCB landscape with custom exploration

fig = session.plot_acquisition_contour( ... 'temperature', 'pressure', ... acq_func='ucb', ... acq_func_kwargs={'beta': 1.0}, ... cmap='hot' ... )

Note
  • Requires at least 2 'real' type variables
  • Model must be trained before plotting
  • Higher acquisition values = more promising regions
  • Suggestions are overlaid to show why they were chosen

plot_uncertainty_contour

plot_uncertainty_contour(x_var: str, y_var: str, fixed_values: Optional[Dict[str, Any]] = None, grid_resolution: int = 50, show_experiments: bool = True, show_suggestions: bool = False, cmap: str = 'Reds', figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 2D contour plot of posterior uncertainty over a variable space.

Visualizes where the model is most uncertain about predictions, showing regions that may benefit from additional sampling. Higher values indicate greater uncertainty (standard deviation).

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (must be 'real' type)

required
y_var str

Variable name for Y axis (must be 'real' type)

required
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables. If not provided, uses midpoint for real/integer, first category for categorical.

None
grid_resolution int

Grid density (NxN points)

50
show_experiments bool

Plot experimental data points as scatter

True
show_suggestions bool

Plot last suggested points (if available)

False
cmap str

Matplotlib colormap name (default: 'Reds' - darker = more uncertain)

'Reds'
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated)

None

Returns:

Type Description
Figure

matplotlib Figure object

Example

Visualize uncertainty landscape

fig = session.plot_uncertainty_contour('temperature', 'pressure')

Custom colormap

fig = session.plot_uncertainty_contour( ... 'temperature', 'pressure', ... cmap='YlOrRd', ... grid_resolution=100 ... ) fig.savefig('uncertainty_contour.png', dpi=300)

Note
  • Requires at least 2 'real' type variables
  • Model must be trained and support std predictions
  • High uncertainty near data gaps is expected
  • Useful for planning exploration strategies

plot_uncertainty_voxel

plot_uncertainty_voxel(x_var: str, y_var: str, z_var: str, fixed_values: Optional[Dict[str, Any]] = None, grid_resolution: int = 15, show_experiments: bool = True, show_suggestions: bool = False, cmap: str = 'Reds', alpha: float = 0.5, figsize: Tuple[float, float] = (10, 8), dpi: int = 100, title: Optional[str] = None, target_columns: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 3D voxel plot of posterior uncertainty over variable space.

Visualizes where the model is most uncertain in 3D, helping identify under-explored regions that may benefit from additional sampling. Higher values indicate greater uncertainty (standard deviation).

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (must be 'real' or 'integer' type)

required
y_var str

Variable name for Y axis (must be 'real' or 'integer' type)

required
z_var str

Variable name for Z axis (must be 'real' or 'integer' type)

required
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables. If not provided, uses midpoint for real/integer, first category for categorical.

None
grid_resolution int

Grid density (NxNxN points, default: 15)

15
show_experiments bool

Plot experimental data points as scatter

True
show_suggestions bool

Plot last suggested points (if available)

False
cmap str

Matplotlib colormap name (default: 'Reds')

'Reds'
alpha float

Transparency level (0=transparent, 1=opaque)

0.5
figsize Tuple[float, float]

Figure size as (width, height) in inches

(10, 8)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated)

None

Returns:

Type Description
Figure

matplotlib Figure object with 3D axes

Example

Visualize uncertainty in 3D

fig = session.plot_uncertainty_voxel('temperature', 'pressure', 'flow_rate')

With transparency to see interior

fig = session.plot_uncertainty_voxel( ... 'temperature', 'pressure', 'flow_rate', ... alpha=0.3, ... grid_resolution=20 ... ) fig.savefig('uncertainty_voxel.png', dpi=150)

Raises:

Type Description
ValueError

If search space doesn't have at least 3 continuous variables

Note
  • Requires at least 3 'real' or 'integer' type variables
  • Model must be trained and support std predictions
  • Computationally expensive: O(N³) evaluations
  • Useful for planning exploration in 3D space

plot_acquisition_voxel

plot_acquisition_voxel(x_var: str, y_var: str, z_var: str, acq_func: str = 'ei', fixed_values: Optional[Dict[str, Any]] = None, grid_resolution: int = 15, acq_func_kwargs: Optional[Dict[str, Any]] = None, goal: str = 'maximize', show_experiments: bool = True, show_suggestions: bool = True, cmap: str = 'hot', alpha: float = 0.5, use_log_scale: Optional[bool] = None, figsize: Tuple[float, float] = (10, 8), dpi: int = 100, title: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create 3D voxel plot of acquisition function over variable space.

Visualizes the acquisition function in 3D, showing "hot spots" where the optimization algorithm believes the next experiment should be conducted. Higher values indicate more promising regions.

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (must be 'real' or 'integer' type)

required
y_var str

Variable name for Y axis (must be 'real' or 'integer' type)

required
z_var str

Variable name for Z axis (must be 'real' or 'integer' type)

required
acq_func str

Acquisition function name ('ei', 'pi', 'ucb', 'logei', 'logpi')

'ei'
fixed_values Optional[Dict[str, Any]]

Dict of {var_name: value} for other variables. If not provided, uses midpoint for real/integer, first category for categorical.

None
grid_resolution int

Grid density (NxNxN points, default: 15)

15
acq_func_kwargs Optional[Dict[str, Any]]

Additional acquisition parameters (xi, kappa, beta)

None
goal str

'maximize' or 'minimize' - optimization direction

'maximize'
show_experiments bool

Plot experimental data points as scatter

True
show_suggestions bool

Plot last suggested points (if available)

True
cmap str

Matplotlib colormap name (default: 'hot')

'hot'
alpha float

Transparency level (0=transparent, 1=opaque)

0.5
use_log_scale Optional[bool]

Use logarithmic color scale (default: auto for logei/logpi)

None
figsize Tuple[float, float]

Figure size as (width, height) in inches

(10, 8)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom title (default: auto-generated)

None

Returns:

Type Description
Figure

matplotlib Figure object with 3D axes

Example

Visualize Expected Improvement in 3D

fig = session.plot_acquisition_voxel( ... 'temperature', 'pressure', 'flow_rate', ... acq_func='ei' ... )

UCB with custom exploration

fig = session.plot_acquisition_voxel( ... 'temperature', 'pressure', 'flow_rate', ... acq_func='ucb', ... acq_func_kwargs={'beta': 1.0}, ... alpha=0.3 ... ) fig.savefig('acq_voxel.png', dpi=150)

Raises:

Type Description
ValueError

If search space doesn't have at least 3 continuous variables

Note
  • Requires at least 3 'real' or 'integer' type variables
  • Model must be trained before plotting
  • Computationally expensive: O(N³) evaluations
  • Higher values = more promising for next experiment
  • Suggestions should align with high-value regions

plot_suggested_next

plot_suggested_next(x_var: str, y_var: Optional[str] = None, z_var: Optional[str] = None, acq_func: Optional[str] = None, fixed_values: Optional[Dict[str, Any]] = None, suggestion_index: int = 0, n_points: int = 100, grid_resolution: int = 50, show_uncertainty: Optional[Union[bool, List[float]]] = [1.0, 2.0], show_experiments: bool = True, acq_func_kwargs: Optional[Dict[str, Any]] = None, goal: Optional[str] = None, figsize: Tuple[float, float] = (10, 12), dpi: int = 100, title_prefix: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Create visualization of suggested next experiment with posterior and acquisition.

This creates a stacked subplot showing: - Top: Posterior mean prediction (slice/contour/voxel) - Bottom: Acquisition function with suggested point marked

The fixed values for non-varying dimensions are automatically extracted from the suggested point coordinates, making it easy to visualize why that point was chosen.

Parameters:

Name Type Description Default
x_var str

Variable name for X axis (required)

required
y_var Optional[str]

Variable name for Y axis (optional, creates 2D plot if provided)

None
z_var Optional[str]

Variable name for Z axis (optional, creates 3D plot if provided with y_var)

None
acq_func Optional[str]

Acquisition function used (if None, extracts from last run or defaults to 'ei')

None
fixed_values Optional[Dict[str, Any]]

Override automatic fixed values from suggestion (optional)

None
suggestion_index int

Which suggestion to visualize if multiple (default: 0 = most recent)

0
n_points int

Points to evaluate for 1D slice (default: 100)

100
grid_resolution int

Grid density for 2D/3D plots (default: 50)

50
show_uncertainty Optional[Union[bool, List[float]]]

For posterior plot - True, False, or list of sigma values (e.g., [1.0, 2.0])

[1.0, 2.0]
show_experiments bool

Overlay experimental data points

True
acq_func_kwargs Optional[Dict[str, Any]]

Additional acquisition parameters (xi, kappa, beta)

None
goal Optional[str]

'maximize' or 'minimize' (if None, uses session's last goal)

None
figsize Tuple[float, float]

Figure size as (width, height) in inches

(10, 12)
dpi int

Dots per inch

100
title_prefix Optional[str]

Custom prefix for titles (default: auto-generated)

None

Returns:

Type Description
Figure

matplotlib Figure object with 2 subplots

Example

After running suggest_next()

session.suggest_next(strategy='ei')

Visualize the suggestion in 1D

fig = session.plot_suggested_next('temperature')

Visualize in 2D

fig = session.plot_suggested_next('temperature', 'pressure')

Visualize in 3D

fig = session.plot_suggested_next('temperature', 'pressure', 'time') fig.savefig('suggestion_3d.png', dpi=300)

Note
  • Must call suggest_next() before using this function
  • Automatically extracts fixed values from the suggested point
  • Creates intuitive visualization showing why the point was chosen

plot_probability_of_improvement

plot_probability_of_improvement(goal: Literal['maximize', 'minimize'] = 'maximize', backend: Optional[str] = None, kernel: Optional[str] = None, n_grid_points: int = 1000, start_iteration: int = 5, reuse_hyperparameters: bool = True, xi: float = 0.01, figsize: Tuple[float, float] = (8, 6), dpi: int = 100, title: Optional[str] = None, subplot_labels: Optional[Union[bool, str, List[str]]] = None, formatters: Optional[Dict[str, Any]] = None) -> Figure

Plot maximum probability of improvement over optimization iterations.

Retroactively computes how the probability of finding a better solution evolved during optimization. At each iteration: 1. Trains GP on observations up to that point (reusing hyperparameters) 2. Computes PI across the search space using native acquisition functions 3. Records the maximum PI value

Uses native PI implementations: - sklearn backend: skopt.acquisition.gaussian_pi - botorch backend: botorch.acquisition.ProbabilityOfImprovement

Decreasing max(PI) indicates the optimization is converging and has less potential for improvement remaining.

Parameters:

Name Type Description Default
goal Literal['maximize', 'minimize']

'maximize' or 'minimize' - optimization direction

'maximize'
backend Optional[str]

Model backend to use (defaults to session's model_backend)

None
kernel Optional[str]

Kernel type for GP (defaults to session's kernel type)

None
n_grid_points int

Number of points to sample search space

1000
start_iteration int

Minimum observations before computing PI (default: 5)

5
reuse_hyperparameters bool

If True, use final model's optimized hyperparameters for all iterations (much faster, recommended)

True
xi float

PI parameter controlling improvement threshold (default: 0.01)

0.01
figsize Tuple[float, float]

Figure size as (width, height) in inches

(8, 6)
dpi int

Dots per inch for figure resolution

100
title Optional[str]

Custom plot title (auto-generated if None)

None

Returns:

Type Description
Figure

matplotlib Figure object

Example

After running optimization

fig = session.plot_probability_of_improvement(goal='maximize') fig.savefig('pi_convergence.png')

Note
  • Requires at least start_iteration experiments
  • Use fewer n_grid_points for faster computation
  • PI values near 0 suggest little room for improvement
  • Reusing hyperparameters (default) is much faster and usually sufficient
  • Uses rigorous acquisition function implementations (not approximations)