Objectives

Experiment-specific objective schemas. Mirrors ionworkspipeline.data_fits.objectives.

Schemas for objectives.

class ionworks_schema.objectives.BaseObjective(options=None, callbacks=None, custom_parameters=None, cost=None, constraints=None, penalties=None, parameters=None)

Bases: BaseSchema

Shared base for every objective. Not used directly.

Concrete subclasses (Pulse, EIS, CycleAgeing, MSMRHalfCell, DesignObjective, …) inherit from here. An objective tells the pipeline what to fit (or optimize) and which data to compare against — pick a concrete subclass that matches your experiment.

Parameters

optionsdict, optional

Objective-specific settings. The supported keys depend on the subclass — see each subclass’s docstring for the list.

callbacksCallback or list of Callback, optional

Callback(s) that run at various points during the fit (logging, plotting, early stopping).

costCost or dict, optional

The cost function used to score the fit (e.g. RMSE, MAE, GaussianLogLikelihood). If None, the optimizer’s default cost is used.

constraintslist of Constraint, optional

Equality or inequality constraints that must hold during the fit.

penaltieslist of Penalty, optional

Soft penalties added to the cost.

parametersdict or pybamm.ParameterValues, optional

Parameter overrides applied only to this objective.

Extends: ionworks_schema.base.BaseSchema

options: dict[str, Any] | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
to_config() dict

Serialise, routing parameters through the shared serialiser.

parameters may hold an interpolant or other pybamm symbol (e.g. a measured temperature-vs-time profile for this objective); the shared helper converts it to wire form exactly as DirectEntry does.

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.CalendarAgeing(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['CalendarAgeing'] = 'CalendarAgeing')

Bases: SimulationObjective

Fit degradation parameters (loss of lithium inventory, loss of active material) to calendar-ageing data for a full cell.

Parameters

data_inputDataLoader, DataFrame, str, or dict

The calendar-ageing data — see FittingObjective.

optionsCalendarAgeingOptions or dict, optional

See CalendarAgeingOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.CalendarAgeing(
...     data_input="path/to/calendar.csv",
...     options={"model": "SPM", "modes": ["LLI [%]", "LAM_pe [%]"]},
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.SimulationObjective

type: Literal['CalendarAgeing']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: CalendarAgeingOptions | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.CurrentDriven(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['CurrentDriven'] = 'CurrentDriven')

Bases: SimulationObjective

Fit a model against any current-driven experiment — pulse trains, drive cycles, custom load profiles.

Pass in the recorded current/voltage data along with the model and the objective will simulate the same current profile and compare voltages (or any other variable you ask for).

Parameters

data_inputDataLoader, DataFrame, str, or dict

The current/voltage data — see FittingObjective.

optionsCurrentDrivenOptions or dict, optional

See CurrentDrivenOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.CurrentDriven(
...     data_input="path/to/drive_cycle.csv",
...     options={"model": "SPM", "objective variables": ["Voltage [V]"]},
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.SimulationObjective

type: Literal['CurrentDriven']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: CurrentDrivenOptions | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.CycleAgeing(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['CycleAgeing'] = 'CycleAgeing')

Bases: SimulationObjective

Fit summary variables (capacity, resistance, LLI, LAM) against cell-cycling data.

Each row in the data is one summary measurement across a cycle (or a small group of cycles). The objective runs the requested cycling experiment, extracts the same summary variables from the simulation, and compares the two.

Parameters

data_inputDataLoader, DataFrame, str, or dict

The cycling summary data — see FittingObjective.

optionsCycleAgeingOptions or dict, optional

See CycleAgeingOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.CycleAgeing(
...     data_input="path/to/cycling_summary.csv",
...     options={
...         "model": "SPM",
...         "objective variables": ["Discharge capacity [A.h]"],
...     },
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.SimulationObjective

type: Literal['CycleAgeing']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: CycleAgeingOptions | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.DesignObjective(actions, constraints=None, options=None, callbacks=None, custom_parameters=None, cost=None, validate_against_experiment_steps=True, output_variables_full=None, save_at_cycles=None, penalties=None, parameters=None)

Bases: BaseObjective

Objective for design optimisation — maximise (or minimise) one or more cell metrics by adjusting design parameters.

You describe each design target as an Action wrapping a Metric (e.g. maximise energy density, hit a target fast-charge time) and pass them in via actions. The optimiser then searches the parameter space to find the design that best satisfies all of them, subject to any constraints you specify.

The objective handles simulation failures and edge-case parameter combinations automatically — failed simulations receive large penalties so the optimiser steers away from those regions.

Parameters

actionsdict[str, Any]

Mapping of action name to an Action-wrapped Metric defining each design target.

constraintsdict[str, BaseAction] or list of Constraint, optional

Hard limits on the design. For design optimization this may be either a dict of Action-wrapped metrics (e.g. minimum capacity) or a list of Constraint terms on pybamm symbols.

optionsdict, optional

Settings for the design simulation (model, experiment, simulation kwargs).

callbacksCallback or list of Callback, optional

Callback(s) invoked at various points during optimisation.

costCost or dict, optional

Cost function used to combine the actions into a single design score. If None, the optimizer’s default design cost is used.

penaltieslist of Penalty, optional

Soft penalties added to the cost.

parametersdict or pybamm.ParameterValues, optional

Parameter overrides applied only to this objective.

Extends: ionworks_schema.objectives.objectives.BaseObjective

actions: dict[str, Any]
constraints: dict[str, Any] | list[Constraint] | None
options: dict[str, Any] | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None
validate_against_experiment_steps: bool
output_variables_full: list[str] | None
save_at_cycles: list[int] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
to_config() dict

Build the dict you submit through ionworks-api.

Same as the base to_config, with actions folded under the "options" key so the payload matches the structure the Ionworks API expects for cycling objectives.

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.EIS(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['EIS'] = 'EIS')

Bases: SimulationObjective

Fit a model against electrochemical impedance spectroscopy (EIS) data.

Simulates the model response at the supplied frequencies and compares the predicted impedance to the measured spectrum. Uses pybamm’s frequency-domain EIS simulator under the hood.

Parameters

data_inputDataLoader, DataFrame, str, or dict

The EIS data — see FittingObjective.

optionsEISOptions or dict, optional

See EISOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.EIS(data_input="path/to/eis.csv", options={"model": "SPM"})
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.SimulationObjective

type: Literal['EIS']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: EISOptions | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.ElectrodeBalancing(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['ElectrodeBalancing'] = 'ElectrodeBalancing')

Bases: FittingObjective

Find the electrode capacities and stoichiometry windows that best reconstruct a full-cell OCV curve from the underlying half-cell OCPs.

Parameters

data_inputDataLoader, DataFrame, str, or dict

The full-cell OCV data — see FittingObjective.

optionsElectrodeBalancingOptions or dict, optional

See ElectrodeBalancingOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.ElectrodeBalancing(
...     data_input="path/to/full_cell_ocv.csv",
...     options={"direction": "discharge"},
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.FittingObjective

type: Literal['ElectrodeBalancing']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: ElectrodeBalancingOptions | None
callbacks: Any | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
custom_parameters: dict[str, Any] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.ElectrodeBalancingHalfCell(electrode=None, data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['ElectrodeBalancingHalfCell'] = 'ElectrodeBalancingHalfCell')

Bases: FittingObjective

Find the starting capacity and total capacity of one electrode, given a known OCV function for that electrode.

Useful for aligning a fresh experiment (for example a GITT scan) to a previously measured OCV curve — the fit slides and scales the data so it lines up with the OCV in stoichiometry.

Parameters

electrodestr

The electrode to fit — "positive" or "negative".

data_inputDataLoader, DataFrame, str, or dict

The half-cell data — see FittingObjective.

optionsElectrodeBalancingHalfCellOptions or dict, optional

See ElectrodeBalancingHalfCellOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.ElectrodeBalancingHalfCell(
...     electrode="positive",
...     data_input="path/to/half_cell.csv",
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.FittingObjective

type: Literal['ElectrodeBalancingHalfCell']
electrode: Literal['positive', 'negative']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: ElectrodeBalancingHalfCellOptions | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.FittingObjective(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None)

Bases: BaseObjective

Shared base for objectives that fit a model to measured data.

On top of BaseObjective this adds data_input — the experimental data the model is compared against. Pick a concrete subclass that matches your experiment (Pulse, EIS, OCPHalfCell, CycleAgeing, …).

Parameters

data_inputDataLoader, DataFrame, str, or dict

The measured data. Accepts an ionworksdata.DataLoader (constructed directly from DataFrames, or via DataLoader.from_local(path) / DataLoader.from_db(measurement_id)), a path to a data file, a pandas or polars DataFrame, or a dict with keys data (DataFrame of raw values) and metadata (dict describing the experiment).

optionsdict, optional

Objective-specific settings — see each subclass for supported keys.

callbacksCallback or list of Callback, optional

Callback(s) invoked at various points during the fit.

costCost or dict, optional

Cost function used to score the fit. If None, the optimizer’s default cost is used.

constraintslist of Constraint, optional

Equality or inequality constraints that must hold during the fit.

penaltieslist of Penalty, optional

Soft penalties added to the cost.

parametersdict or pybamm.ParameterValues, optional

Parameter overrides applied only to this objective.

Extends: ionworks_schema.objectives.objectives.BaseObjective

data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: dict[str, Any] | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.MSMRFullCell(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['MSMRFullCell'] = 'MSMRFullCell')

Bases: FittingObjective

Fit an MSMR model to full-cell open-circuit voltage data.

Compares both the capacity-vs-voltage curve and the differential voltage dU/dQ of the full cell — fitting both together gives much tighter constraints on the underlying half-cell MSMR parameters than fitting the OCV alone [1].

Parameters

data_inputDataLoader, DataFrame, str, or dict

The full-cell OCV data — see FittingObjective.

optionsMSMRFullCellOptions or dict, optional

See MSMRFullCellOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

References

Examples

>>> obj = iws.objectives.MSMRFullCell(
...     data_input="path/to/full_cell_ocv.csv",
...     options={
...         "negative voltage limits": (0.005, 1.5),
...         "positive voltage limits": (3.0, 4.3),
...     },
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.FittingObjective

type: Literal['MSMRFullCell']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: MSMRFullCellOptions | None
callbacks: Any | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
custom_parameters: dict[str, Any] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.MSMRHalfCell(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['MSMRHalfCell'] = 'MSMRHalfCell')

Bases: FittingObjective

Fit an MSMR model to half-cell open-circuit potential data.

Compares the capacity-vs-voltage curve and (optionally) the differential voltage dU/dQ of one electrode to a measured half-cell OCP.

Parameters

data_inputDataLoader, DataFrame, str, or dict

The half-cell OCP data — see FittingObjective.

optionsMSMRHalfCellOptions or dict, optional

See MSMRHalfCellOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.MSMRHalfCell(
...     data_input="path/to/half_cell.csv",
...     options={"model": iws.models.MSMRHalfCellModel(electrode="positive")},
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.FittingObjective

type: Literal['MSMRHalfCell']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: MSMRHalfCellOptions | None
callbacks: Any | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
custom_parameters: dict[str, Any] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.OCPHalfCell(electrode=None, data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['OCPHalfCell'] = 'OCPHalfCell')

Bases: FittingObjective

Fit a smooth open-circuit-potential function to half-cell OCP data.

Parameters

electrodestr

The electrode to fit — "positive" or "negative".

data_inputDataLoader, DataFrame, str, or dict

The half-cell OCP data — see FittingObjective.

optionsOCPHalfCellOptions or dict, optional

See OCPHalfCellOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.OCPHalfCell(
...     electrode="positive",
...     data_input="path/to/ocp.csv",
...     options={"stoichiometry limits": (0.05, 0.95)},
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.FittingObjective

type: Literal['OCPHalfCell']
electrode: Literal['positive', 'negative']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: OCPHalfCellOptions | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.Objective(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['Objective'] = 'Objective')

Bases: FittingObjective

Deprecated alias for FittingObjective.

Extends: ionworks_schema.objectives.objectives.FittingObjective

type: Literal['Objective']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.Pulse(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['Pulse'] = 'Pulse')

Bases: SimulationObjective

Fit a model against pulse experiments — GITT, HPPC, ICI, and similar.

By default the fit compares simulated voltage against measured voltage, but you can swap in a different objective variables function to compare overpotentials, resistances, or ICI/GITT features instead.

Parameters

data_inputDataLoader, DataFrame, str, or dict

The pulse data — see FittingObjective.

optionsPulseOptions or dict, optional

See PulseOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.Pulse(
...     data_input="path/to/gitt.csv", options={"model": "SPM"}
... )
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.SimulationObjective

type: Literal['Pulse']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: PulseOptions | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.Resistance(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None, type: Literal['Resistance'] = 'Resistance')

Bases: FittingObjective

Fit a cell-resistance curve against measured resistance vs SOC.

Parameters

data_inputDataLoader, DataFrame, str, or dict

Resistance data — see FittingObjective. Must contain columns "SOC" and "Resistance [Ohm]", plus any extra columns the resistance model needs.

optionsResistanceOptions or dict, optional

See ResistanceOptions for the available keys.

callbacks, constraints, penalties, parameters

Shared with BaseObjective.

Examples

>>> obj = iws.objectives.Resistance(data_input="path/to/resistance.csv")
>>> # slot into a DataFit (parameters omitted for brevity)

Extends: ionworks_schema.objectives.objectives.FittingObjective

type: Literal['Resistance']
data_input: Annotated[str | DataFrame | DataFrame | DataLoader | TimeSeriesSpec | DataPayloadSpec | MetadataSpec | dict[str, Any], BeforeValidator(func=_route_measurement_input, json_schema_input_type=PydanticUndefined)]
options: ResistanceOptions | None
callbacks: Any | None
custom_parameters: dict[str, Any] | None
constraints: list[Constraint] | None
penalties: list[Penalty] | None
parameters: dict[str, Any] | ParameterValues | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.objectives.SimulationObjective(data=None, options=None, callbacks=None, custom_parameters=None, constraints=None, penalties=None, parameters=None, *, cost: Annotated[RMSE | MAE | MSE | Max | SSE | Wasserstein | ChiSquare | MultiCost | GaussianLogLikelihood | DesignFunction, FieldInfo(annotation=NoneType, required=True, discriminator='type')] | None = None)

Bases: FittingObjective

Shared base for objectives that run a pybamm simulation and compare the output to measured data.

Subclasses such as Pulse, CurrentDriven, CalendarAgeing, CycleAgeing, and EIS inherit from here. The arguments are the same as FittingObjective — pick a concrete subclass that matches your experiment.

Every subclass needs a model to fit against, given either as options={"model": ...} or, for a model stored on the platform, as options={"parameterized_model_id": ...}. Construction fails without one.

Extends: ionworks_schema.objectives.objectives.FittingObjective

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.