From bcaa5c7735eb00ccfd120aeefb7c9544350b1634 Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Tue, 17 Mar 2026 17:07:19 +0000 Subject: [PATCH 1/6] Align dict name with pybamm.Solution --- pybop/simulators/solution.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pybop/simulators/solution.py b/pybop/simulators/solution.py index f23eed152..fd364751b 100644 --- a/pybop/simulators/solution.py +++ b/pybop/simulators/solution.py @@ -21,7 +21,7 @@ class Solution: """ def __init__(self, inputs: Inputs = None): - self._dict = {} + self._variables = {} self.all_inputs = [inputs] if inputs is not None else [] def set_solution_variable( @@ -30,9 +30,9 @@ def set_solution_variable( data: np.ndarray, sensitivities: dict[str, np.ndarray] | None = None, ): - self._dict[variable_name] = SolutionVariable( + self._variables[variable_name] = SolutionVariable( data=data, sensitivities=sensitivities ) def __getitem__(self, key): - return self._dict[key] + return self._variables[key] From ad70d52701bde591196ad943059a2fc619915cfe Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Tue, 17 Mar 2026 17:07:36 +0000 Subject: [PATCH 2/6] Update axis labels --- pybop/plot/dataset.py | 2 +- pybop/plot/problem.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pybop/plot/dataset.py b/pybop/plot/dataset.py index b6b20a7d7..24257a732 100644 --- a/pybop/plot/dataset.py +++ b/pybop/plot/dataset.py @@ -34,7 +34,7 @@ def dataset(dataset, signal=None, trace_names=None, show=True, **layout_kwargs): # Compile ydata and labels or legend y = [dataset[s] for s in signal] if len(signal) == 1: - yaxis_title = signal[0] + yaxis_title = StandardPlot.remove_brackets(signal[0]) if trace_names is None: trace_names = ["Data"] else: diff --git a/pybop/plot/problem.py b/pybop/plot/problem.py index f87e6f88a..0372601e6 100644 --- a/pybop/plot/problem.py +++ b/pybop/plot/problem.py @@ -73,7 +73,7 @@ def problem( plot_dict = StandardPlot( layout_options=dict( title="Scatter Plot", - xaxis_title="Time / s", + xaxis_title=StandardPlot.remove_brackets(domain), yaxis_title=StandardPlot.remove_brackets(var), ) ) From 7980ad83cbac5ea2539ba2d089d16eccce7eba4c Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Wed, 18 Mar 2026 17:06:41 +0000 Subject: [PATCH 3/6] Allow len(dataset) --- examples/scripts/battery_parameterisation/gitt_fitting.py | 2 +- pybop/processing/dataset.py | 4 ++++ tests/unit/test_dataset.py | 8 ++++---- tests/unit/test_problem.py | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/scripts/battery_parameterisation/gitt_fitting.py b/examples/scripts/battery_parameterisation/gitt_fitting.py index b36996fc0..0dd11e88c 100644 --- a/examples/scripts/battery_parameterisation/gitt_fitting.py +++ b/examples/scripts/battery_parameterisation/gitt_fitting.py @@ -35,7 +35,7 @@ # Determine the indices corresponding to each pulse in the dataset nonzero_index = np.concatenate( - ([-1], np.flatnonzero(dataset["Current [A]"]), [len(dataset["Current [A]"]) + 1]) + ([-1], np.flatnonzero(dataset["Current [A]"]), [len(dataset) + 1]) ) pulse_starts = np.extract( nonzero_index[1:] - nonzero_index[:-1] != 1, # check if there is a gap diff --git a/pybop/processing/dataset.py b/pybop/processing/dataset.py index 4a4a9c640..89050198e 100644 --- a/pybop/processing/dataset.py +++ b/pybop/processing/dataset.py @@ -66,6 +66,10 @@ def __getitem__(self, key): return self.data[key] + def __len__(self) -> int: + """Return the length of the data, based on the length of the domain data.""" + return len(self.data[self.domain]) + def check(self, domain: str = None, signal: str | list[str] = None) -> bool: """ Check the consistency of a PyBOP Dataset against the expected format. diff --git a/tests/unit/test_dataset.py b/tests/unit/test_dataset.py index 282b41939..b20c25f4d 100644 --- a/tests/unit/test_dataset.py +++ b/tests/unit/test_dataset.py @@ -63,7 +63,7 @@ def test_dataset(self): # Test get subset dataset = dataset.get_subset(list(range(5))) - assert len(dataset[dataset.domain]) == 5 + assert len(dataset) == 5 # Form frequency dataset data_dictionary = { @@ -259,7 +259,7 @@ def dataset(self): def test_current_data_processing(self, dataset): # Test generation of a current consistent with the charge throughput data consistent_dataset = pybop.generate_consistent_current(dataset, tolerance=1e-2) - assert len(consistent_dataset["Time [s]"]) >= len(dataset["Time [s]"]) + assert len(consistent_dataset) >= len(dataset) for var in ["Time [s]", "Current [A]", "Discharge capacity [A.h]"]: assert consistent_dataset[var][0] == dataset[var][0] @@ -275,7 +275,7 @@ def test_current_data_processing(self, dataset): # Test downsampling of constant current sections downsampled_dataset = pybop.downsample_constant_current(dataset, tolerance=1e-4) - assert len(downsampled_dataset["Time [s]"]) < len(dataset["Time [s]"]) + assert len(downsampled_dataset) < len(dataset) for var in ["Time [s]", "Current [A]", "Discharge capacity [A.h]"]: assert downsampled_dataset[var][0] == dataset[var][0] @@ -302,7 +302,7 @@ def test_current_data_processing(self, dataset): } ) ds_dataset = pybop.downsample_constant_current(dataset_wo_ct, tolerance=1e-4) - assert len(ds_dataset["Time [s]"]) < len(dataset["Time [s]"]) + assert len(ds_dataset) < len(dataset) for var in ["Time [s]", "Current [A]"]: assert ds_dataset[var][0] == dataset_wo_ct[var][0] diff --git a/tests/unit/test_problem.py b/tests/unit/test_problem.py index edbedce4e..18f75bb9a 100644 --- a/tests/unit/test_problem.py +++ b/tests/unit/test_problem.py @@ -106,7 +106,7 @@ def test_fitting_problem(self, simulator, dataset): assert_array_equal(target_data, dataset["Voltage [V]"]) # Test set target - dataset["Voltage [V]"] += np.random.normal(0, 0.05, len(dataset["Voltage [V]"])) + dataset["Voltage [V]"] += np.random.normal(0, 0.05, len(dataset)) cost.set_target("Voltage [V]", dataset) problem = pybop.Problem(simulator, cost) From 3bb0e26adc74f53d1813ae6544600eccd4c109d6 Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Wed, 18 Mar 2026 17:09:18 +0000 Subject: [PATCH 4/6] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfcd681e7..25a90f3a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ## Bug Fixes +- [#915](https://github.com/pybop-team/PyBOP/pull/915) - Fixes the axis labels for non-standard domain names and adds Dataset length property. - [#911](https://github.com/pybop-team/PyBOP/pull/911) - Fixes the passing of the cost log to the Voronoi surface plot. - [#905](https://github.com/pybop-team/PyBOP/pull/905) - Remove restriction on numpy. From 4d7c73676281471281f5105c93d86adca97d86c9 Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:20:34 +0000 Subject: [PATCH 5/6] Add kind option to interpolant --- pybop/models/lithium_ion/utils.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pybop/models/lithium_ion/utils.py b/pybop/models/lithium_ion/utils.py index 8144463ae..be95bd80d 100644 --- a/pybop/models/lithium_ion/utils.py +++ b/pybop/models/lithium_ion/utils.py @@ -29,6 +29,8 @@ class Interpolant: Output values corresponding to x. name : str, optional Name for the interpolant when used in PyBaMM. + kind: str, optional + Which kind of interpolator to use. Can be "linear" (default) or "cubic". bounds_error : bool, optional If True, raise error when interpolating outside bounds. fill_value : str or float, optional @@ -42,6 +44,7 @@ def __init__( x: np.ndarray, y: np.ndarray, name: str | None = None, + kind: str | None = None, bounds_error: bool = False, fill_value: str | float = "extrapolate", axis: int = 0, @@ -49,6 +52,7 @@ def __init__( self.x = np.asarray(x) self.y = np.asarray(y) self.name = name + self.kind = kind or "linear" self._interp_func = self._create_interpolant(bounds_error, fill_value, axis) def _create_interpolant( @@ -58,6 +62,7 @@ def _create_interpolant( return interpolate.interp1d( self.x, self.y, + kind=self.kind, bounds_error=bounds_error, fill_value=fill_value, axis=axis, @@ -82,7 +87,9 @@ def __call__(self, x: float | np.ndarray): return self._interp_func(x) except Exception: # Fall back to PyBaMM interpolant for symbolic evaluation - return PybammInterpolant(self.x, self.y, x, name=self.name) + return PybammInterpolant( + self.x, self.y, x, name=self.name, interpolator=self.kind + ) class InverseOCV: From 904b9c8f8c3d0f52fb4e265f801fe9958c7cc4b4 Mon Sep 17 00:00:00 2001 From: NicolaCourtier <45851982+NicolaCourtier@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:22:16 +0000 Subject: [PATCH 6/6] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25a90f3a4..de8015701 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ ## Bug Fixes -- [#915](https://github.com/pybop-team/PyBOP/pull/915) - Fixes the axis labels for non-standard domain names and adds Dataset length property. +- [#915](https://github.com/pybop-team/PyBOP/pull/915) - Fixes axis labels for non-standard domain names, adds `Dataset` length property and adds `kind` property to `Interpolant`. - [#911](https://github.com/pybop-team/PyBOP/pull/911) - Fixes the passing of the cost log to the Voronoi surface plot. - [#905](https://github.com/pybop-team/PyBOP/pull/905) - Remove restriction on numpy.