diff --git a/.all-contributorsrc b/.all-contributorsrc index 2be30620d..304a73ce6 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -16,7 +16,8 @@ "infra", "test", "code", - "example" + "example", + "review" ] }, { @@ -26,7 +27,9 @@ "profile": "https://github.com/NicolaCourtier", "contributions": [ "code", - "review" + "review", + "example", + "test" ] }, { @@ -46,7 +49,35 @@ "profile": "http://www.rse.ox.ac.uk", "contributions": [ "ideas", - "mentoring" + "mentoring", + "review" + ] + }, + { + "login": "brosaplanella", + "name": "Ferran Brosa Planella", + "avatar_url": "https://avatars.githubusercontent.com/u/28443643?v=4", + "profile": "https://www.brosaplanella.xyz", + "contributions": [ + "review" + ] + }, + { + "login": "FaradayInstitution", + "name": "Faraday Institution", + "avatar_url": "/assets/UKRI.svg", + "profile": "https://faraday.ac.uk", + "contributions": [ + "financial" + ] + }, + { + "login": "UKRI", + "name": "UK Research and Innovation", + "avatar_url": "/assets/UKRI.svg", + "profile": "https://www.ukri.org/", + "contributions": [ + "financial" ] } ], diff --git a/.github/workflows/release-action.yaml b/.github/workflows/release-action.yaml index c2cd834b2..8cbaa5f4f 100644 --- a/.github/workflows/release-action.yaml +++ b/.github/workflows/release-action.yaml @@ -1,6 +1,9 @@ name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI -on: push +on: + workflow_dispatch: + release: + types: [published, prereleased] jobs: build: @@ -30,7 +33,9 @@ jobs: publish-to-pypi: name: >- Publish Python 🐍 distribution 📦 to PyPI - if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes + if: > + startsWith(github.ref, 'refs/tags/') && + !contains(github.ref, 'rc') needs: - build runs-on: ubuntu-latest diff --git a/.github/workflows/scheduled_tests.yaml b/.github/workflows/scheduled_tests.yaml index 2de1a0f83..83a0d986b 100644 --- a/.github/workflows/scheduled_tests.yaml +++ b/.github/workflows/scheduled_tests.yaml @@ -12,10 +12,11 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: + os: [ubuntu-latest, windows-latest, macos-latest] python-version: ["3.8", "3.9", "3.10", "3.11"] steps: @@ -32,7 +33,7 @@ jobs: python -m nox -s unit python -m nox -s notebooks - #M-series Mac Mini + #M-series Mac Mini build-apple-mseries: runs-on: [self-hosted, macOS, ARM64] env: diff --git a/.github/workflows/test_on_push.yaml b/.github/workflows/test_on_push.yaml index 959e4c826..5df3c8155 100644 --- a/.github/workflows/test_on_push.yaml +++ b/.github/workflows/test_on_push.yaml @@ -1,7 +1,6 @@ name: test_on_push on: - push: workflow_dispatch: pull_request: @@ -30,10 +29,11 @@ jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: + os: [ubuntu-latest, windows-latest, macos-latest] python-version: ["3.8", "3.9", "3.10", "3.11"] steps: diff --git a/.gitignore b/.gitignore index 838f372b0..bc3caa2c5 100644 --- a/.gitignore +++ b/.gitignore @@ -175,6 +175,9 @@ instance/ # Sphinx documentation docs/_build/ +docs/examples/generated/ +docs/api/ +warnings.txt # PyBuilder .pybuilder/ @@ -304,3 +307,6 @@ $RECYCLE.BIN/ # Visual Studio Code settings .vscode/* + +# Output JSON files +**/fit_ecm_parameters.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5270e26ff..732d6cc31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ ci: repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.1.5" + rev: "v0.1.7" hooks: - id: ruff args: [--fix, --show-fixes] diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..aaeb9cfcf --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,20 @@ +version: 2 + +build: + os: ubuntu-20.04 + tools: + python: "3.11" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + +formats: + - htmlzip + - pdf + - epub + +python: + install: + - method: pip + path: .[docs] diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..3269d5696 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,28 @@ +# [Unreleased](https://github.com/pybop-team/PyBOP) + +## Features + +## Bug Fixes + +# [v23.12](https://github.com/pybop-team/PyBOP/tree/v23.12) - 2023-12-19 +## Features + +- [#141](https://github.com/pybop-team/PyBOP/pull/141) - Adds documentation with Sphinx and PyData Sphinx Theme. Updates docstrings across package, relocates `costs` and `dataset` to top-level of package. Adds noxfile session and deployment workflow for docs. +- [#131](https://github.com/pybop-team/PyBOP/issues/131) - Adds `SciPyDifferentialEvolution` optimiser, adds functionality for user-selectable maximum iteration limit to `SciPyMinimize`, `NLoptOptimize`, and `BaseOptimiser` classes. +- [#107](https://github.com/pybop-team/PyBOP/issues/107) - Adds Equivalent Circuit Model (ECM) with examples, Import/Export parameter methods `ParameterSet.import_parameter` and `ParameterSet.export_parameters`, updates default FittingProblem.signal definition to `"Voltage [V]"`, and testing infrastructure +- [#127](https://github.com/pybop-team/PyBOP/issues/127) - Adds Windows and macOS runners to the `test_on_push` action +- [#114](https://github.com/pybop-team/PyBOP/issues/114) - Adds standard plotting class `pybop.StandardPlot()` via plotly backend +- [#114](https://github.com/pybop-team/PyBOP/issues/114) - Adds `quick_plot()`, `plot_convergence()`, and `plot_cost2d()` methods +- [#114](https://github.com/pybop-team/PyBOP/issues/114) - Adds a SciPy minimize example and logging for non-Pints optimisers +- [#116](https://github.com/pybop-team/PyBOP/issues/116) - Adds PSO, SNES, XNES, ADAM, and IPropMin optimisers to PintsOptimisers() class +- [#38](https://github.com/pybop-team/PyBOP/issues/38) - Restructures the Problem classes ahead of adding a design optimisation example +- [#120](https://github.com/pybop-team/PyBOP/issues/120) - Updates the parameterisation test settings including the number of iterations +- [#145](https://github.com/pybop-team/PyBOP/issues/145) - Reformats Dataset to contain a dictionary and signal into a list of strings + +## Bug Fixes + +# [v23.11](https://github.com/pybop-team/PyBOP/releases/tag/v23.11) +- Initial release +- Adds Pints, NLOpt, and SciPy optimisers +- Adds SumofSquareError and RootMeanSquareError cost functions +- Adds Parameter and Dataset classes diff --git a/CITATION.cff b/CITATION.cff index e1efab891..11ce822fd 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -11,4 +11,5 @@ authors: family-names: Courtier - given-names: David family-names: Howey +version: "23.12" # Update this when you release a new version repository-code: 'https://www.github.com/pybop-team/pybop' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d1ea9db24..9fecf0c01 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,10 +1,23 @@ -# Contributing to PyBOP +# Contributing -If you'd like to contribute to PyBOP, please have a look at the [pre-commit](#pre-commit-checks) and the [workflow](#workflow) guidelines below. +If you'd like to contribute to PyBOP, please have a look at the guidelines below. +## Developer-Installation + +To install PyBOP for development purposes, which includes the testing and plotting dependencies, use the `[all]` flag as demonstrated below: + +For `zsh`: + +```sh +pip install -e '.[all]' +``` +For `bash`: +```sh +pip install -e .[all] +``` ## Pre-commit checks -Before you commit any code, please perform the following checks: +Before you commit any code, please perform the following checks using [Nox](https://nox.thea.codes/en/stable/index.html): - [All tests pass](#testing): `$ nox -s unit` @@ -17,7 +30,7 @@ pip install pre-commit pre-commit install ``` -This would run the checks every time a commit is created locally. The checks will only run on the files modified by that commit, but the checks can be triggered for all the files using - +This would run the checks every time a commit is created locally. The checks will only run on the files modified by that commit, but the checks can be triggered for all the files using, ```bash pre-commit run --all-files @@ -34,7 +47,7 @@ We use [GIT](https://en.wikipedia.org/wiki/Git) and [GitHub](https://en.wikipedi 1. Create an [issue](https://guides.github.com/features/issues/) where new proposals can be discussed before any coding is done. 2. Create a [branch](https://help.github.com/articles/creating-and-deleting-branches-within-your-repository/) of this repo (ideally on your own [fork](https://help.github.com/articles/fork-a-repo/)), where all changes will be made 3. Download the source code onto your local system, by [cloning](https://help.github.com/articles/cloning-a-repository/) the repository (or your fork of the repository). -4. [Install](Developer-Install) PyBOP with the developer options. +4. [Install](#developer-installation) PyBOP with the developer options. 5. [Test](#testing) if your installation worked: `$ pytest --unit -v`. You now have everything you need to start making changes! @@ -69,7 +82,7 @@ python -m pip install pre-commit pre-commit run ruff ``` -ruff is configured inside the file `pre-commit-config.yaml`, allowing us to ignore some errors. If you think this should be added or removed, please submit an [issue](#issues) +ruff is configured inside the file `pre-commit-config.yaml`, allowing us to ignore some errors. If you think this should be added or removed, please submit an [issue](https://guides.github.com/features/issues/). When you commit your changes they will be checked against ruff automatically (see [Pre-commit checks](#pre-commit-checks)). @@ -113,6 +126,16 @@ def plot_great_things(self, x, y, z): This allows people to (1) use PyBOP without ever importing Matplotlib and (2) configure Matplotlib's back-end in their scripts, which _must_ be done before e.g. `pyplot` is first imported. +### Building documentation + +We use [Sphinx](http://www.sphinx-doc.org/en/stable/) to build our documentation. A [Nox](https://nox.thea.codes/en/stable/index.html) session has been created to reduce the overhead when building the documentation locally. To run this session, type + +```bash +nox -s docs +``` + +This will build the docs using sphinx-autobuild and render them in your browser. + ## Testing All code requires testing. We use the [pytest](https://docs.pytest.org/en/) package for our tests. (These tests typically just check that the code runs without error, and so, are more _debugging_ than _testing_ in a strict sense. Nevertheless, they are very useful to have!) @@ -123,7 +146,7 @@ If you have nox installed, to run unit tests, type nox -s unit ``` -else, type +Alternatively, to run tests standalone with pytest, run, ```bash pytest --unit -v @@ -270,7 +293,7 @@ Configuration files: setup.py ``` -Note that this file must be kept in sync with the version number in [pybop/**init**.py](pybop/__init__.py). +Note that this file must be kept in sync with the version number in [pybop/**init**.py](https://github.com/pybop-team/PyBOP/blob/develop/pybop/__init__.py). ### Continuous Integration using GitHub actions @@ -293,11 +316,10 @@ Code coverage (how much of our code is seen by the (Linux) unit tests) is tested GitHub does some magic with particular filenames. In particular: -- The first page people see when they go to [our GitHub page](https://github.com/pybop-team/PyBOP) displays the contents of [README.md](README.md), which is written in the [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) format. Some guidelines can be found [here](https://help.github.com/articles/about-readmes/). -- The license for using PyBOP is stored in [LICENSE](LICENSE.txt), and [automatically](https://help.github.com/articles/adding-a-license-to-a-repository/) linked to by GitHub. -- This file, [CONTRIBUTING.md](CONTRIBUTING.md) is recognised as the contribution guidelines and a link is [automatically](https://github.com/blog/1184-contributing-guidelines) displayed when new issues or pull requests are created. +- The first page people see when they go to [our GitHub page](https://github.com/pybop-team/PyBOP) displays the contents of [README.md](https://github.com/pybop-team/PyBOP/blob/develop/README.md), which is written in the [Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) format. Some guidelines can be found [here](https://help.github.com/articles/about-readmes/). +- The license for using PyBOP is stored in [LICENSE](https://github.com/pybop-team/PyBOP/blob/develop/LICENSE), and [automatically](https://help.github.com/articles/adding-a-license-to-a-repository/) linked to by GitHub. +- This file, [CONTRIBUTING.md](https://github.com/pybop-team/PyBOP/blob/develop/CONTRIBUTING.md) is recognised as the contribution guidelines and a link is [automatically](https://github.com/blog/1184-contributing-guidelines) displayed when new issues or pull requests are created. ## Acknowledgements -This CONTRIBUTING.md file, along with large sections of the code infrastructure, -was copied from the excellent [Pints repo](https://github.com/pints-team/pints), and [PyBaMM repo](https://github.com/pybamm-team/PyBaMM) +This CONTRIBUTING.md file, along with large sections of the code infrastructure, was copied from the excellent [Pints repo](https://github.com/pints-team/pints), and [PyBaMM repo](https://github.com/pybamm-team/PyBaMM) diff --git a/README.md b/README.md index 11d7e9be8..bf5f66c6e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ logo

Python Battery Optimisation and Parameterisation

-

+ Scheduled @@ -29,8 +29,11 @@ license - Open In Colab -

+ open In colab + + + releases + @@ -48,52 +51,55 @@ The diagram below presents PyBOP's conceptual framework. The PyBOP software spec ## Getting Started -### Prerequisites -To use and/or contribute to PyBOP, first install Python (3.8-3.11). On a Debian-based distribution, this looks like: +### Installation + +Within your virtual environment, install PyBOP: ```bash -sudo apt update -sudo apt install python3 python3-virtualenv +pip install pybop ``` -For further information, please refer to the similar [installation instructions for PyBaMM](https://docs.pybamm.org/en/latest/source/user_guide/installation/GNU-linux.html). - -### Installation - -Create a virtual environment called `pybop-env` within your current directory: +To install the most recent state of PyBOP, install from the `develop` branch, ```bash -virtualenv pybop-env +pip install git+https://github.com/pybop-team/PyBOP.git@develop ``` -Activate the environment: +To alternatively install PyBOP from a local directory, use the following template, substituting in the relevant path: ```bash -source pybop-env/bin/activate +pip install -e "path/to/pybop" ``` -Later, you can deactivate the environment: +To check whether PyBOP has been installed correctly, run one of the examples in the following section. For a development installation, please refer to the [contributing guide](https://github.com/pybop-team/PyBOP/blob/develop/CONTRIBUTING.md#Installation). + +### Prerequisites +To use and/or contribute to PyBOP, first install Python (3.8-3.11). On a Debian-based distribution, this looks like: ```bash -deactivate +sudo apt update +sudo apt install python3 python3-virtualenv ``` -Within your virtual environment, install the `develop` branch of PyBOP: +For further information, please refer to the similar [installation instructions for PyBaMM](https://docs.pybamm.org/en/latest/source/user_guide/installation/GNU-linux.html). + +### Virtual Environments +To create a virtual environment called `pybop-env` within your current directory: ```bash -pip install git+https://github.com/pybop-team/PyBOP.git@develop +virtualenv pybop-env ``` -To alternatively install PyBOP from a local directory, use the following template, substituting in the relevant path: +Activate the environment: ```bash -pip install -e "PATH_TO_PYBOP" +source pybop-env/bin/activate ``` -To check whether PyBOP has been installed correctly, run one of the examples in the following section or the full set of unit tests: +Later, you can deactivate the environment: ```bash -pytest --unit -v +deactivate ``` ### Using PyBOP @@ -136,10 +142,13 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d - - + + - + + + +
Brady Planden
Brady Planden

🚇 ⚠️ 💻 💡
NicolaCourtier
NicolaCourtier

💻 👀
Brady Planden
Brady Planden

🚇 ⚠️ 💻 💡 👀
NicolaCourtier
NicolaCourtier

💻 👀 💡 ⚠️
David Howey
David Howey

🤔 🧑‍🏫
Martin Robinson
Martin Robinson

🤔 🧑‍🏫
Martin Robinson
Martin Robinson

🤔 🧑‍🏫 👀
Ferran Brosa Planella
Ferran Brosa Planella

👀
UKRI
UKRI

💵
Faraday Institution
Faraday Institution

💵
diff --git a/assets/UKRI.png b/assets/UKRI.png new file mode 100644 index 000000000..a3a0ba3e6 Binary files /dev/null and b/assets/UKRI.png differ diff --git a/assets/UKRI.svg b/assets/UKRI.svg new file mode 100644 index 000000000..a16a21cf7 --- /dev/null +++ b/assets/UKRI.svg @@ -0,0 +1 @@ + diff --git a/conftest.py b/conftest.py index b37cbd0f5..c632f3e50 100644 --- a/conftest.py +++ b/conftest.py @@ -1,6 +1,8 @@ import pytest import matplotlib +import plotly +plotly.io.renderers.default = None matplotlib.use("Template") @@ -8,17 +10,43 @@ def pytest_addoption(parser): parser.addoption( "--unit", action="store_true", default=False, help="run unit tests" ) + parser.addoption( + "--examples", action="store_true", default=False, help="run examples tests" + ) + + +def pytest_terminal_summary(terminalreporter, exitstatus, config): + """Add additional section to terminal summary reporting.""" + total_time = sum([x.duration for x in terminalreporter.stats.get("passed", [])]) + num_tests = len(terminalreporter.stats.get("passed", [])) + print(f"\nTotal number of tests completed: {num_tests}") + print(f"Total time taken: {total_time:.2f} seconds") def pytest_configure(config): config.addinivalue_line("markers", "unit: mark test as a unit test") + config.addinivalue_line("markers", "examples: mark test as an example") def pytest_collection_modifyitems(config, items): - if config.getoption("--unit"): - # --unit given in cli: do not skip unit tests - return - skip_unit = pytest.mark.skip(reason="need --unit option to run") - for item in items: - if "unit" in item.keywords: - item.add_marker(skip_unit) + unit_option = config.getoption("--unit") + examples_option = config.getoption("--examples") + + if not unit_option and not examples_option: + skip_all = pytest.mark.skip(reason="need --unit or --examples option to run") + for item in items: + item.add_marker(skip_all) + + elif unit_option and not examples_option: + skip_examples = pytest.mark.skip( + reason="need --examples option to run examples tests" + ) + for item in items: + if "examples" in item.keywords: + item.add_marker(skip_examples) + + if examples_option and not unit_option: + skip_unit = pytest.mark.skip(reason="need --unit option to run unit tests") + for item in items: + if "unit" in item.keywords: + item.add_marker(skip_unit) diff --git a/docs/Contributing.md b/docs/Contributing.md new file mode 100644 index 000000000..ab90a2bb6 --- /dev/null +++ b/docs/Contributing.md @@ -0,0 +1,8 @@ +--- +myst: + html_meta: + "description lang=en": | + Contributing docs.. +--- + +```{include} ../CONTRIBUTING.md diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 000000000..d4bb2cbb9 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/_extension/gallery_directive.py b/docs/_extension/gallery_directive.py new file mode 100644 index 000000000..4dcc2c63a --- /dev/null +++ b/docs/_extension/gallery_directive.py @@ -0,0 +1,145 @@ +"""A directive to generate a gallery of images from structured data. + +Generating a gallery of images that are all the same size is a common +pattern in documentation, and this can be cumbersome if the gallery is +generated programmatically. This directive wraps this particular use-case +in a helper-directive to generate it with a single YAML configuration file. + +It currently exists for maintainers of the pydata-sphinx-theme, +but might be abstracted into a standalone package if it proves useful. + +Credit: PyData Sphinx Theme +""" +from pathlib import Path +from typing import Any, Dict, List + +from docutils import nodes +from docutils.parsers.rst import directives +from sphinx.application import Sphinx +from sphinx.util import logging +from sphinx.util.docutils import SphinxDirective +from yaml import safe_load + +logger = logging.getLogger(__name__) + + +TEMPLATE_GRID = """ +`````{{grid}} {columns} +{options} + +{content} + +````` +""" + +GRID_CARD = """ +````{{grid-item-card}} {title} +{options} + +{content} +```` +""" + + +class GalleryGridDirective(SphinxDirective): + """A directive to show a gallery of images and links in a Bootstrap grid. + + The grid can be generated from a YAML file that contains a list of items, or + from the content of the directive (also formatted in YAML). Use the parameter + "class-card" to add an additional CSS class to all cards. When specifying the grid + items, you can use all parameters from "grid-item-card" directive to customize + individual cards + ["image", "header", "content", "title"]. + + Danger: + This directive can only be used in the context of a Myst documentation page as + the templates use Markdown flavored formatting. + """ + + name = "gallery-grid" + has_content = True + required_arguments = 0 + optional_arguments = 1 + final_argument_whitespace = True + option_spec = { + # A class to be added to the resulting container + "grid-columns": directives.unchanged, + "class-container": directives.unchanged, + "class-card": directives.unchanged, + } + + def run(self) -> List[nodes.Node]: + """Create the gallery grid.""" + if self.arguments: + # If an argument is given, assume it's a path to a YAML file + # Parse it and load it into the directive content + path_data_rel = Path(self.arguments[0]) + path_doc, _ = self.get_source_info() + path_doc = Path(path_doc).parent + path_data = (path_doc / path_data_rel).resolve() + if not path_data.exists(): + logger.info(f"Could not find grid data at {path_data}.") + nodes.text("No grid data found at {path_data}.") + return + yaml_string = path_data.read_text() + else: + yaml_string = "\n".join(self.content) + + # Use all the element with an img-bottom key as sites to show + # and generate a card item for each of them + grid_items = [] + for item in safe_load(yaml_string): + # remove parameters that are not needed for the card options + title = item.pop("title", "") + + # build the content of the card using some extra parameters + header = f"{item.pop('header')} \n^^^ \n" if "header" in item else "" + image = f"![image]({item.pop('image')}) \n" if "image" in item else "" + content = f"{item.pop('content')} \n" if "content" in item else "" + + # optional parameter that influence all cards + if "class-card" in self.options: + item["class-card"] = self.options["class-card"] + + loc_options_str = "\n".join(f":{k}: {v}" for k, v in item.items()) + " \n" + + card = GRID_CARD.format( + options=loc_options_str, content=header + image + content, title=title + ) + grid_items.append(card) + + # Parse the template with Sphinx Design to create an output container + # Prep the options for the template grid + class_ = "gallery-directive" + f' {self.options.get("class-container", "")}' + options = {"gutter": 2, "class-container": class_} + options_str = "\n".join(f":{k}: {v}" for k, v in options.items()) + + # Create the directive string for the grid + grid_directive = TEMPLATE_GRID.format( + columns=self.options.get("grid-columns", "1 2 3 4"), + options=options_str, + content="\n".join(grid_items), + ) + + # Parse content as a directive so Sphinx Design processes it + container = nodes.container() + self.state.nested_parse([grid_directive], 0, container) + + # Sphinx Design outputs a container too, so just use that + return [container.children[0]] + + +def setup(app: Sphinx) -> Dict[str, Any]: + """Add custom configuration to sphinx app. + + Args: + app: the Sphinx application + + Returns: + the 2 parallel parameters set to ``True``. + """ + app.add_directive("gallery-grid", GalleryGridDirective) + + return { + "parallel_read_safe": True, + "parallel_write_safe": True, + } diff --git a/docs/_static/custom-icon.js b/docs/_static/custom-icon.js new file mode 100644 index 000000000..ac9c6c91e --- /dev/null +++ b/docs/_static/custom-icon.js @@ -0,0 +1,17 @@ +/******************************************************************************* + * Set a custom icon for pypi as it's not available in the fa built-in brands + * Taken from: https://github.com/pydata/pydata-sphinx-theme/blob/main/docs/_static/custom-icon.js + */ +FontAwesome.library.add( + (faListOldStyle = { + prefix: "fa-custom", + iconName: "pypi", + icon: [ + 17.313, // viewBox width + 19.807, // viewBox height + [], // ligature + "e001", // unicode codepoint - private use area + "m10.383 0.2-3.239 1.1769 3.1883 1.1614 3.239-1.1798zm-3.4152 1.2411-3.2362 1.1769 3.1855 1.1614 3.2369-1.1769zm6.7177 0.00281-3.2947 1.2009v3.8254l3.2947-1.1988zm-3.4145 1.2439-3.2926 1.1981v3.8254l0.17548-0.064132 3.1171-1.1347zm-6.6564 0.018325v3.8247l3.244 1.1805v-3.8254zm10.191 0.20931v2.3137l3.1777-1.1558zm3.2947 1.2425-3.2947 1.1988v3.8254l3.2947-1.1988zm-8.7058 0.45739c0.00929-1.931e-4 0.018327-2.977e-4 0.027485 0 0.25633 0.00851 0.4263 0.20713 0.42638 0.49826 1.953e-4 0.38532-0.29327 0.80469-0.65542 0.93662-0.36226 0.13215-0.65608-0.073306-0.65613-0.4588-6.28e-5 -0.38556 0.2938-0.80504 0.65613-0.93662 0.068422-0.024919 0.13655-0.038114 0.20156-0.039466zm5.2913 0.78369-3.2947 1.1988v3.8247l3.2947-1.1981zm-10.132 1.239-3.2362 1.1769 3.1883 1.1614 3.2362-1.1769zm6.7177 0.00213-3.2926 1.2016v3.8247l3.2926-1.2009zm-3.4124 1.2439-3.2947 1.1988v3.8254l3.2947-1.1988zm-6.6585 0.016195v3.8275l3.244 1.1805v-3.8254zm16.9 0.21143-3.2947 1.1988v3.8247l3.2947-1.1981zm-3.4145 1.2411-3.2926 1.2016v3.8247l3.2926-1.2009zm-3.4145 1.2411-3.2926 1.2016v3.8247l3.2926-1.2009zm-3.4124 1.2432-3.2947 1.1988v3.8254l3.2947-1.1988zm-6.6585 0.019027v3.8247l3.244 1.1805v-3.8254zm13.485 1.4497-3.2947 1.1988v3.8247l3.2947-1.1981zm-3.4145 1.2411-3.2926 1.2016v3.8247l3.2926-1.2009zm2.4018 0.38127c0.0093-1.83e-4 0.01833-3.16e-4 0.02749 0 0.25633 0.0085 0.4263 0.20713 0.42638 0.49826 1.97e-4 0.38532-0.29327 0.80469-0.65542 0.93662-0.36188 0.1316-0.65525-0.07375-0.65542-0.4588-1.95e-4 -0.38532 0.29328-0.80469 0.65542-0.93662 0.06842-0.02494 0.13655-0.03819 0.20156-0.03947zm-5.8142 0.86403-3.244 1.1805v1.4201l3.244 1.1805z", // svg path (https://simpleicons.org/icons/pypi.svg) + ], + }) +); diff --git a/docs/_static/switcher.json b/docs/_static/switcher.json new file mode 100644 index 000000000..682d19994 --- /dev/null +++ b/docs/_static/switcher.json @@ -0,0 +1,12 @@ +[ + { + "version": "latest", + "url": "https://pybop-docs.readthedocs.io/en/latest/", + "preferred": true + }, + { + "name": "v23.11 (stable)", + "version": "v23.11", + "url": "https://pybop-docs.readthedocs.io/en/latest/" + } + ] diff --git a/docs/_templates/autoapi/index.rst b/docs/_templates/autoapi/index.rst new file mode 100644 index 000000000..d60759952 --- /dev/null +++ b/docs/_templates/autoapi/index.rst @@ -0,0 +1,18 @@ +.. _api-reference: + +API Reference +============= + +This page contains auto-generated API reference documentation [#f1]_. + +.. toctree:: + :titlesonly: + :maxdepth: 2 + + {% for page in pages %} + {% if page.top_level_object and page.display %} + {{ page.include_path }} + {% endif %} + {% endfor %} + +.. [#f1] Created with `sphinx-autoapi `_ diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 000000000..2b8b9278e --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,106 @@ +# Configuration file for the Sphinx documentation builder. + + +# -- Path setup -------------------------------------------------------------- +import os +import sys + +root_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) +sys.path.insert(0, root_path) + +from pybop.version import __version__ # noqa: E402 + +# -- Project information ----------------------------------------------------- +project = "PyBOP" +copyright = "2023, The PyBOP Team" +author = "The PyBOP Team" +release = f"v{__version__}" + +# -- General configuration --------------------------------------------------- +extensions = [ + "sphinx.ext.napoleon", + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.todo", + "sphinx.ext.viewcode", + "sphinx_design", + "sphinx_copybutton", + "autoapi.extension", + # custom extentions + "_extension.gallery_directive", + # For extension examples and demos + "myst_parser", + "sphinx_favicon", +] + +templates_path = ["_templates"] +autoapi_template_dir = "_templates/autoapi" +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + +# -- Options for autoapi ------------------------------------------------------- +autoapi_type = "python" +autoapi_dirs = ["../pybop"] +autoapi_keep_files = True +autoapi_root = "api" +autoapi_member_order = "groupwise" + +# -- Options for HTML output ------------------------------------------------- +# Define the json_url for our version switcher. +json_url = "https://pybop-docs.readthedocs.io/en/latest/_static/switcher.json" +version_match = os.environ.get("READTHEDOCS_VERSION") +release = f"v{__version__}" + +# If READTHEDOCS_VERSION doesn't exist, we're not on RTD +# If it is an integer, we're in a PR build and the version isn't correct. +# If it's "latest" → change to "dev" (that's what we want the switcher to call it) +# Credit: PyData Theme: https://github.com/pydata/pydata-sphinx-theme/blob/main/docs/conf.py +if not version_match or version_match.isdigit() or version_match == "latest": + # For local development, infer the version to match from the package. + if "latest" in release or "rc" in release: + version_match = "latest" + # We want to keep the relative reference if we are in dev mode + # but we want the whole url if we are effectively in a released version + json_url = "_static/switcher.json" + else: + version_match = release +elif version_match == "stable": + version_match = release + +html_theme = "pydata_sphinx_theme" +html_show_sourcelink = False +html_title = "PyBOP Documentation" + +# html_theme options +html_theme_options = { + "header_links_before_dropdown": 4, + "icon_links": [ + { + "name": "PyPI", + "url": "https://pypi.org/project/pybop/", + "icon": "fa-custom fa-pypi", + }, + { + "name": "GitHub", + "url": "https://github.com/pybop-team/pybop", + "icon": "fab fa-github-square", + }, + ], + "search_bar_text": "Search the docs...", + "show_prev_next": False, + "navbar_align": "content", + "navbar_center": ["navbar-nav", "version-switcher"], + # "show_version_warning_banner": True, # Commented until we have a stable release with docs + "footer_start": ["copyright"], + "footer_center": ["sphinx-version"], + "switcher": { + "json_url": json_url, + "version_match": version_match, + }, +} + +html_static_path = ["_static"] +html_js_files = ["custom-icon.js"] + +# -- Language ---------------------------------------------------------------- + +language = "en" diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..d45182ae1 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,37 @@ +--- +myst: + html_meta: + "description lang=en": | + High-level documentation for PyBOP, and corresponding links to the site. +html_theme.sidebar_secondary.remove: true +--- + +# PyBOP: Optimise and Parameterise Battery Models + +Welcome to PyBOP, a Python package dedicated to the optimization and parameterization of battery models. PyBOP is designed to streamline your workflow, whether you are conducting academic research, working in industry, or simply interested in battery technology and modelling. + +```{gallery-grid} +:grid-columns: 1 2 2 2 + +- header: "{fas}`bolt;pst-color-primary` Installation" + content: "Setting up PyBOP is straightforward. Follow our step-by-step guide to install PyBOP on your system." + link: "installation.html" +- header: "{fas}`circle-half-stroke;pst-color-primary` Quick Start" + content: "Discover how to use PyBOP effectively. From basic tasks to advanced features, learn how to solve real-world problems with PyBOP." + link: "quick_start.html" +- header: "{fab}`python;pst-color-primary` Contributing" + content: "Contribute to the PyBOP project and become a part of our growing community." + link: "Contributing.html" +- header: "{fab}`bootstrap;pst-color-primary` API Reference" + content: "Get detailed information on functions, classes, and modules that allow you to fully leverage the power of PyBOP in your own projects." + link: "api/index.html" +``` + +```{toctree} +:maxdepth: 2 +:hidden: + +installation +quick_start +Contributing +``` diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 000000000..3c0080c1d --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,71 @@ +.. _installation: + +Installation +***************************** + +PyBOP is a versatile Python package designed for optimization and parameterization of battery models. Follow the instructions below to install PyBOP and set up your environment to begin utilizing its capabilities. + +Installing PyBOP with pip +------------------------- + +The simplest method to install PyBOP is using pip. Run the following command in your terminal: + +.. code-block:: console + + pip install pybop + +This command will download and install the latest stable version of PyBOP. If you want to install a specific version, you can specify the version number using the following command: + +.. code-block:: console + + pip install pybop==23.11 + +Installing the Development Version +---------------------------------- + +If you're interested in the cutting-edge features and want to try out the latest enhancements, you can install the development version directly from the ``develop`` branch on GitHub: + +.. code-block:: console + + pip install git+https://github.com/pybop-team/PyBOP.git@develop + +Please note that the development version may be less stable than the official releases. + +Local Installation from Source +------------------------------ + +For those who prefer to install PyBOP from a local clone of the repository or wish to modify the source code, you can use pip to install the package in "editable" mode. Replace "path/to/pybop" with the actual path to your local PyBOP directory: + +.. code-block:: console + + pip install -e "path/to/pybop" + +In editable mode, changes you make to the source code will immediately affect the PyBOP installation without the need for reinstallation. + +Verifying Installation +---------------------- + +To verify that PyBOP has been installed successfully, try running one of the provided example scripts included in the documentation or repository. If the example executes without any errors, PyBOP is ready to use. Alternatively, you can run the following command in your terminal to check the version of PyBOP that is installed: + +.. code-block:: console + + python -c "import pybop; print(pybop.__version__)" + + +For Developers +-------------- + +If you are installing PyBOP for development purposes, such as contributing to the project, please ensure that you follow the guidelines outlined in the `Contributing Guide <../Contributing.html>`_. It includes additional steps that might be necessary for setting up a development environment, including the installation of dependencies and setup of pre-commit hooks. + +Further Assistance +------------------ + +If you encounter any issues during the installation process or have any questions regarding the use of PyBOP, feel free to reach out to the community via the `PyBOP GitHub Discussions `_. + +Next Steps +---------- + +After installing PyBOP, you might want to: + +* Explore the `Quick Start Guide `_ to begin using PyBOP. +* Check out the `API Reference <../api/index.html>`_ for detailed information on PyBOP's programming interface. diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 000000000..32bb24529 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/quick_start.rst b/docs/quick_start.rst new file mode 100644 index 000000000..683c82b40 --- /dev/null +++ b/docs/quick_start.rst @@ -0,0 +1,58 @@ +Quick Start +**************************** + +Welcome to the Quick Start Guide for PyBOP. This guide will help you get up and running with PyBOP. If you're new to PyBOP, we recommend you start here to learn the basics and get a feel for the package. + +Getting Started with PyBOP +-------------------------- + +PyBOP is equipped with a series of robust tools that can help you optimize various parameters within your battery models to better match empirical data or to explore the effects of different parameters on battery behavior. + +To begin using PyBOP: + +1. Install the package using pip: + + .. code-block:: console + + pip install pybop + + For detailed installation instructions, including how to install specific versions or from source, see the :ref:`installation` section. + +2. Once PyBOP is installed, you can import it in your Python scripts or Jupyter notebooks: + + .. code-block:: python + + import pybop + + Now you're ready to utilize PyBOP's functionality in your projects! + +Exploring Examples +------------------ + +To help you get acquainted with PyBOP's capabilities, we provide a collection of examples that demonstrate common use cases and features of the package: + +- **Jupyter Notebooks**: Interactive notebooks that include detailed explanations alongside the live code, visualizations, and results. These are an excellent resource for learning and can be easily modified and executed to suit your needs. + +- **Python Scripts**: For those who prefer working in a text editor, IDE, or for integrating into larger projects, we provide equivalent examples in plain Python script format. + +You can find these resources in the ``examples`` folder of the PyBOP repository. To access the examples, navigate to the following path after cloning or downloading the repository: + +.. code-block:: console + + path/to/pybop/examples + +These examples are also available on our `GitHub repository `_. + +Next Steps +---------- + +Once you're comfortable with the basics demonstrated in the examples, you can dive deeper into the functionality of PyBOP by delving into the :ref:`api-reference` for detailed API documentation. + +Support and Contributions +------------------------- + +If you encounter any issues or have questions as you start using PyBOP, don't hesitate to reach out to our community: + +- **GitHub Issues**: Report bugs or request new features by opening an `Issue `_ +- **GitHub Discussions**: Post your questions or feedback on our `GitHub Discussions `_ +- **Contributions**: Interested in contributing to PyBOP? Check out our `Contributing Guide <../Contributing.html>`_ for guidelines. diff --git a/examples/costs/standalone.py b/examples/costs/standalone.py new file mode 100644 index 000000000..9836a7e7d --- /dev/null +++ b/examples/costs/standalone.py @@ -0,0 +1,72 @@ +import pybop +import numpy as np + + +class StandaloneCost(pybop.BaseCost): + """ + A standalone cost function example that inherits from pybop.BaseCost. + + This class represents a simple cost function without a problem object, used for demonstration purposes. + It is a quadratic function of one variable with a constant term, defined by + the formula: cost(x) = x^2 + 42. + + Parameters + ---------- + problem : object, optional + A dummy problem instance used to initialize the superclass. This is not + used in the current class but is accepted for compatibility with the + BaseCost interface. + x0 : array-like + The initial guess for the optimization problem, set to [4.2]. + n_parameters : int + The number of parameters in the model, which is 1 in this case. + bounds : dict + A dictionary containing the lower and upper bounds for the parameter, + set to [-1] and [10], respectively. + + Methods + ------- + __call__(x, grad=None) + Calculate the cost for a given parameter value. + """ + + def __init__(self, problem=None): + """ + Initialize the StandaloneCost class with optional problem instance. + + The problem parameter is not utilized in this subclass. The initial guess, + number of parameters, and bounds are predefined for the standalone cost function. + """ + super().__init__(problem) + + self.x0 = np.array([4.2]) + self.n_parameters = len(self.x0) + + self.bounds = dict( + lower=[-1], + upper=[10], + ) + + def __call__(self, x, grad=None): + """ + Calculate the cost for a given parameter value. + + The cost function is defined as cost(x) = x^2 + 42, where x is the + parameter value. + + Parameters + ---------- + x : array-like + A one-element array containing the parameter value for which to + evaluate the cost. + grad : array-like, optional + Unused parameter, present for compatibility with gradient-based + optimizers. + + Returns + ------- + float + The calculated cost value for the given parameter. + """ + + return x[0] ** 2 + 42 diff --git a/examples/notebooks/spm_nlopt.ipynb b/examples/notebooks/spm_nlopt.ipynb index 811575160..baf89804c 100644 --- a/examples/notebooks/spm_nlopt.ipynb +++ b/examples/notebooks/spm_nlopt.ipynb @@ -23,8 +23,8 @@ }, "outputs": [ { - "output_type": "stream", "name": "stdout", + "output_type": "stream", "text": [ "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.1/2.1 MB\u001b[0m \u001b[31m19.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m139.4/139.4 kB\u001b[0m \u001b[31m14.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", @@ -191,38 +191,38 @@ }, "outputs": [ { - "output_type": "display_data", "data": { - "text/plain": [ - "interactive(children=(FloatSlider(value=0.0, description='t', max=1.1333333333333333, step=0.01133333333333333…" - ], "application/vnd.jupyter.widget-view+json": { + "model_id": "8d003c14da5f4fa68284b28c15cee6e6", "version_major": 2, - "version_minor": 0, - "model_id": "8d003c14da5f4fa68284b28c15cee6e6" - } + "version_minor": 0 + }, + "text/plain": [ + "interactive(children=(FloatSlider(value=0.0, description='t', max=1.1333333333333333, step=0.01133333333333333…" + ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" }, { - "output_type": "execute_result", "data": { "text/plain": [ "" ] }, + "execution_count": 25, "metadata": {}, - "execution_count": 25 + "output_type": "execute_result" }, { - "output_type": "display_data", "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABdEAAAKxCAYAAAC8BuXeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdeVxU1f8/8NeADKsDorIlAqYhmIDiRxzLHRnQj2n5KRdS3D8aaEhp8ckItcJc0ST5mAtW8nGpNFMDCUNccENHccMN0xIwU0BQAeH8/vDH/ToybIoMwuv5eNxH3Xve9973PTNzOZ65c45MCCFARERERERERERERETl6Ok6ASIiIiIiIiIiIiKi+oqd6EREREREREREREREFWAnOhERERERERERERFRBdiJTkRERERERERERERUAXaiExERERERERERERFVgJ3oREREREREREREREQVYCc6EREREREREREREVEF2IlORERERERERERERFQBdqITEREREREREREREVWAnehPyNHREZGRkbpOo1ZduXIFMpkMarW6WvFjxozBkCFDnmlOT2r//v3o2LEjDAwM6m2OpEkmk2Hr1q3P9Bzh4eGQyWSQyWR18vmti2uqrrq+9sasPr3ujwsPD4eHh4eu06Aq1EUbIyYmRronBAcHP9NzAfWr3VTX1061JykpCTKZDDk5OZXG1af3W21hO510ie30Z4vtdKL6o+zvrUwme6J/N5Xta2FhUeu5ke7Vu070MWPGQCaTYd68eRrbt27dCplMVuf5xMTEaH3zHzlyBJMmTarzfGqLtoa1vb09MjMz8fLLL+smqVoUEhICDw8PZGRkICYmRtfpPNcq+gw8qYo68TIzM+Hn51dr56lIhw4dkJmZ+Vx/fh+Xnp6OPn36wNraGkZGRmjTpg1mzZqF4uJiKeb9999HZmYmWrVqpcNMn39lf6MeX3x9fZ/ZOXX5j7za/vw/76rbgVddum5jKBQKZGZmYu7cuc/8XHXl77//hq+vL+zs7GBoaAh7e3sEBQUhLy9Pihk2bBgyMzOhVCp1mGnD9eh9Ui6Xo23btpgzZw4ePHjw1Mfu3r07MjMzYW5uDkD3n6Fnhe10qi620+s/ttOpIcrKysLUqVPRpk0bqb01aNAgJCYm6jq1StXk31W//vqr1uv5448/IJfLK/x7nJmZyS/DGrAmuk5A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SdsyMzMFAJGSklLhccoolUphaGgoAIhJkyaJkpKScjFsnD+dgIAAoa+vL0xNTTWWzz77TIp59HX/9ttvhbOzs9TZKMTDzlNjY2MRHx8vhKj83vP48cp88sknwsDAQKPxt2vXLqGvry+uXr0qbSv7PB8+fFja79HPwBdffCFcXFyk9R9++EGYmZlJnz1tn//ff/9d6Ovriz///FNje79+/URoaKjWa4iPjxd6enoiPT1da/nIkSNF//79NbbNmDFDuLq6SusODg7i7bffltZLS0uFlZWVWLFihRCi6ntuv379yjX4v/32W2FrayutV3XPfbQD71G9evUSnTp10nreRz1JG6O6r6uJiYnG39MZM2YILy+vCnOp7NyP1nPZPejjjz+WtpXdIzMzM4UQ1X/9qupEd3Bw0LhvOTs7ix49ekjrZffI//3vfxUep8zw4cOFsbGxACAGDRok7t27Vy6GnejPxqPtw9LSUpGQkCAMDQ3F+++/L86fPy8AiP3790vxN2/eFMbGxmLTpk1CCCE6duyo8eXWox7/DLKdzna6EGyns53OdjpRXTl06JAAIH788cdK42rSib5161aNfbW1q+fOnSt8fHw0tl27dk16uKVsv0c/s0II8Y9//EN88MEH0npVn/uKci8zcuRIjb9r7u7uWv+esRO94aqXw7mU+eKLL7Bu3TqcPXu2XNmJEycQExMjjR9mZmYGlUqF0tJSZGRkID09HU2aNEHnzp2lfdq2bVvuJ/e//vor+vXrhxdeeAFNmzbFqFGj8Pfff+Pu3bvVzrNJkyZ46623sH79egBAQUEBfvrpJ/j7+wMALl68iLt376J///4a+X7zzTcV/uSyzOOTXimVSo36qE7+crkcbm5u1b6eMmq1Gj169ICBgUGVsU9yjf3794eDgwPatGmDUaNGYf369TWq9zJdunSpVlxUVBQ8PT3RsmVLmJmZYeXKlbh69SoA4MaNG7h+/Tr69eundd8TJ04gPz8fzZs317i+jIyMCq9PrVajU6dOsLS01Fp+9uxZvPLKKxrbXnnllXLv90dfO1NTUygUCty4cUM6R0WvUUFBAS5duoTx48dr5Pzpp5+Wy/nRc9ja2kp1UhVtdb9x40a88sorsLGxgZmZGWbNmiXVc3WdPXsW7u7uMDU1lba98sorKC0tRXp6urStQ4cOGmMH2traVitvbR6t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9x3y8vIejuMOoGXLltDX18fPP/+M7OxsdOvWDUZGRkhISMDnn3+O999/XzrH5MmTsXz5csycORPjxo3D7t27sWnTJuzYsUOKCQkJQUBAALp06YKuXbsiMjJSo1OGiIjqh2HDhuGvv/5CWFgYsrKy4OHhgbi4OGlei6tXr0JP7/+exezevTtiY2Mxa9Ys/Oc//0G7du2wdetWvPzyy7q6BGpohNB1BkQSdqITETUwvXv3hqiksSGTyTBnzhyNzuvHWVpaIjY2ttLzuLm5Ye/evRWWjxkzBmPGjNHY5uDggJ07d1Z63N69e+P48eOVxhARUdVu3LiB0aNHIzMzE+bm5nBzc0N8fDz69++PpKQkHDp0CADQtm1bjf0yMjLg6OgIAwMDREVFYfr06RBCoG3btli8eDEmTpwoxVbny8+qOmWIiKj+CAoKqvBJ8qSkpHLb3nzzTbz55pvPOCtiZzI9tcb6HqrF62YnOhERERFRA7R69eoKy6r6whUAfH194evrW+V5qvPlZ2WdMkRERERE9R3HRCciIiIiIiIiIp2oalLrRk0m03UG9QPr4cmx7h6qhXpgJzoREREREREREemEXC7XdQpERFViJzoRERERERERERERUQXYiU5ERERERERERDpRWlqq6xSIiKrETnQiIiIiIiIiItKJe/fu6TqF+q+KycAbrMZ63c9CY63LWrxudqITEREREREREREREVWAnehERERERERERET1jUym6wzqB9bDk2PdPVQL9cBOdCIiIiIiIiIiIiKiCrATnYiIiIiIiIiIiIioAuxEJyIiIiIiIiIiIiKqADvRiYiIiIiIiIiIqH4RQtcZEEnYiU5ERERERERERDrRpEkTXadQ/7EzmZ5WY30P1eJ1sxOdiIiIiIiIiIh0wtDQUNcpEBFViZ3oRERERERERERE9Y1MpusM6gfWw5Nj3T1UC/XATnQiIiIiIiIiItIJ0ViHmSCi5wo70YmIiIiIiIiISCfu3r2r6xSIiKrETnQiIiIiIiIiIiKqX/grBapH2IlORERERERERERUX7EzmZ5WY30P1eJ1sxOdiIiIiKgBWrFiBdzc3KBQKKBQKKBUKvHLL78AAG7duoWpU6fC2dkZxsbGaN26NaZNm4bc3FyNY1y9ehUDBw6EiYkJrKysMGPGDDx48EAjJikpCZ07d4ahoSHatm2LmJiY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Rb1D5ERENU+l1kQvKCjAkSNH8P7778PR0RFNmjSBra2tQsmXmJgY5ObmwsHBQZxnaWmJZs2aITo6GoC8HleHDh1gbGwstnF0dERGRgauX78utnm9j8I2hX0Uh/W3iIiIiIiIiKg+MDIygqWlZamThoYG7OzskJaWhpiYGHHdyMhIFBQUwNbWtti+586diytXriAuLk6cAHlpxm3btlXH7tUPEomyI6gZeBzeHo+dXCUch0pNoqekpCAzMxNLly6Fk5MTfv/9dwwbNgzDhw/H8ePHAchrbWloaBT5tNLY2FistZWUlKSQQC9cXristDYZGRl4+fJlsfGx/hYRERERERER0f9YWVnByckJXl5eOH/+PE6fPg1vb2+MGTMGpqamAIBHjx7B0tIS58+fBwDIZDK0b99eYQKAZs2aoUWLFhXavopKpaamqC6pryVIqEaqcDmX0hQUFAAAhg4dCl9fXwBAp06dcObMGQQFBaF3796VubkKY/0tIiIiIiIiIiJFu3btgre3N/r37w8VFRWMGDEC69atE5fn5uYiPj4eL168qPRta2lpVXqfRESVrVKT6I0bN4aamhratm2rML+wXjkg/7QyJycHaWlpClejJycni7W2ZDKZ+Onm68sLlxX+LJz3ehs9PT0OwERERERERERE5WRoaIiQkJASl5ubm0Mo46rgspYTEdVmlfqdGQ0NDXTr1g3x8fEK82/duoXmzZsDAGxsbKCuro6IiAhxeXx8PB48eAA7OzsAgJ2dHa5evapwY4vw8HDo6emJCXo7OzuFPgrbFPZBRERERERERERERPSuKnwlemZmJu7cuSM+v3fvHuLi4mBoaIhmzZph9uzZGD16NHr16oW+ffvi6NGjOHTokHhnZn19fXh6esLPzw+GhobQ09PDtGnTYGdnhx49egAABgwYgLZt22L8+PFYvnw5kpKS8OWXX2Lq1KliOZbJkydjw4YN+PzzzzFhwgRERkZi7969OHLkSCUcFiIiIiIiIiIiqmovXryAnp6essOo2XiVP72r+vo7VIn7XeEk+sWLF9G3b1/xuZ+fHwDAzc0NwcHBGDZsGIKCghAYGIjp06fDwsIC+/btQ8+ePcV1Vq9eLdbYys7OhqOjI7799ltxuaqqKg4fPowpU6bAzs4O2tracHNzw1dffSW2adGiBY4cOQJfX1+sXbsWTZs2xfff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6h6O7UREVJIuXbrg+vXrMDc3R+vWrRUmbW1tZYdHdRCT6FSv5OTk4JNPPsHo0aOxePFiTJw4scJXlMTHx+PVq1cwNTUV50VHR+PRo0cKJ+NERFQ9OLYTEdU9HNuJiKg0U6dORWpqKsaOHYsLFy4gISEBYWFh8PDwQH5+vrLDozqISXSqV+bNm4f09HSsW7cOc+bMwfvvv48JEyZUqI+4uDgAwPr163H79m389ttvcHV1BSA/2SciourFsZ2IqO7h2E5ERKUxNTXF6dOnkZ+fjwEDBqBDhw7w8fGBgYEBVFSY7qTKx5roVG9ERUVhzZo1OHbsGPT09AAAO3fuhLW1NTZt2oQpU6aUq5+4uDg4Ojri7t276NChA9q2bYtFixZhypQpWLduHXbu3FmVu0FERK/h2E5EVPdwbCciqhvc3d3h7u5eZH5wcLDC86ioqCJtiivjJQiCwvM2bdrg559/focIS95W4QexRIWYRKd6o0+fPsjNzVWYZ25ujvT09Ar1c/nyZXTr1g3/+c9/FOa/fsOit30DICKiiuHYTkRU93BsJyKiqpKeng4dHR1MnTq12JuSlkRHRwd5eXnQ1NSswuioJuP3G4jK8O2330JHRwdXr14FID8Z79ChQ5Vsa/LkydDR0amSvomI6H84thMR1T0c24mIqDQjRozA7du3ERcXh9mzZ1do3bi4OFy7dg2xsbFVFB3VdBKBH6kTlejRo0d4+fIlAKBZs2ZITU2FiYkJrl+/jrZt21b69lJSUpCRkQEAMDEx4R2liYiqAMd2IqK6h2M7ERERVSUm0YmIiIiIiIiIiIiISsByLkREREREREREREREJWASnYiIiIiIiIiIiIioBEyiExERERERERERERGVgEl0IiIiIiIiIiIiIqISMIlORERERERERERERFQCJtGJiIiIiIiIiIiIiErAJDoRERERERERERERUQmYRCciIiIiIiIiIiIiKgGT6EREREREREREREREJWASnYiIiIiIiIiIiIioBEyiExERERERERERERGVgEl0IiIiIiIiIiIiIqISMIlORERERERERERERFQCJtGJiIiIiIiIiIiIiErAJDoRERERERERERERUQmYRCciIiIiIiIiIiIiKgGT6FQh5ubmWLNmjVJjCA4OhoGBgVJjqKiacNyUISAgAJ06darQOhKJBPv37y9xeZ8+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IiKq+xo0aKDsEIiIysQkOhERERERERERKYVEIlF2CEREZWISnYiIiIiIiIiIiIioBEyiExERERERERGRUmRnZys7BKqpnjwBLl1SdhRUm+XlASdOALm579wVk+hERERERERERKQUeXl5yg6BaqIXLwBbW6BrV+DuXWVHQ7WVhwfQuzewY8c7d8UkOhEREREREREREdUcgYHy5LkgAI8fKzsaqo2iooAffpA//vvvd+6OSXQiIiIiIiIiIiKqGe7cAZYvV3YUVJvl5gLe3pXaJZPoREREREREREREpHyCAEyfDuTkKDsSqs02bACuX6/ULplEJyIiIiIiIiIiIuU7eBD47TdAXR3Q15fPEwTlxkS1S2IisHCh/LGRkfxnJfwOMYlOREREREREREREyvXyJeDjI388cyZgbKzUcKiWmj0beP4c6N4dGDGi0rplEp2IiIiIiIiIiIiUKzAQuH8faNoU+PJLZUdDtdHx48CuXYBEAmzcCKhUXuqbSXQiIiIiIiIiIlKKBg0aKDsEqgni44Fly+SPV60CtLWVGw/VPjk5wJQp8seTJgFdu1Zq90yiExERERERERGRUkgkEmWHQMomCPLkZ04OMHAg8O9/F11OVJYVK4AbN4AmTeTfangda6ITERERERERERFRrfXDD8CxY4CmJrBhg7wUB/C/n0RlSUgAFi+WP161CmjYUP64En+HmEQnIiIiIiIiIiKlyM7OVnYIpEypqfKbiALAggVAy5bKjYdqH0EApk4FXr0C+vcHxo2rks0wiU5EREREREREREqRl5en7BBImebOBf75B2jb9n/JdKKKCA0FwsIADQ3g22+r7BsMTKITERERERERERFR9TpzBvjvf+WPg4LkSdDXFSZDWROdSpKeDsyYIX/8xRfA++8X34410YmIiIiIiIiIiKhWyc0FPv1U/njCBODDD5UbD9VO8+YBSUny5PncuUWXsyY6ERERERERERER1Upr1gDXrgGNGgHLlys7GqqNLlyQl28BgE2bAKm0SjfHJDoRERERERERERFVj7/+AgIC5I9XrJAn0okqIi9P/k0GQQA++QTo16/KN8kkOhFRPZOamgoXFxfo6enBwMAAnp6eyMzMLHWdzZs3o0+fPtDT04NEIkFaWlqx7Y4cOQJbW1toaWmhYcOGcHZ2FpcFBwdDIpEUO6WkpAAAoqKiil2elJRUWbtPREREREREyiIIgLc38OIF0Ls34OZWclvWRKeSbNwIxMYCBgbyD2LKUgm/Q2rv3AMREdUqLi4uSExMRHh4OHJzc+Hh4YFJkyYhJCSkxHVevHgBJycnODk5wd/fv9g2+/btg5eXF5YsWYJ+/fohLy8P165dE5ePHj0aTk5OCuu4u7vj1atXaNKkicL8+Ph46Onpic/fXE5ERERERES10C+/AIcPA+rq8hIclVizmuqJhw+BL7+UP162DDA2LrltbayJvnHjRpibm0NTUxO2trY4f/58iW379OlT7JWIgwcPFtu4u7sXWf5mcoaIiBTduHEDR48exffffw9bW1v07NkT69evx+7du/H48eMS1/Px8cHcuXPRo0ePYpfn5eVhxowZ+OabbzB58mS8//77aNu2LUaNGiW20dLSgkwmEydVVVVERkbC09OzSH9NmjRRaKuiwi9OERERERHVRVpaWsoOgarLs2fA1Knyx3PmAFZWyo2Hah9BAKZMATIzAXt7YOLEatt0tWQl9uzZAz8/PyxcuBCXLl2CtbU1HB0dxa/vv+nnn39GYmKiOF27dg2qqqoYOXKkQjsnJyeFdj/++GN17A4RUa0VHR0NAwMDdO3aVZzn4OAAFRUVnDt37q37vXTpEh49egQVFRV07twZJiYmGDhwoMKV6G/asWMHGjRogH//+99FlnXq1AkmJib46KOPcPr06VK3nZ2djYyMDIWJiIiIiIhqB14wU4/Mng0kJQEWFsC8ecqOhmqj3buBI0cADQ3gv/8FqnH8qJYtrVq1Cl5eXvDw8EDbtm0RFBSEBg0aYOvWrcW2NzQ0VLgCMTw8HA0aNCiSRJdKpQrtGjZsWGocTLQQUX2XlJRUpDSKmpoaDA0N36nu+N27dwEAAQEB+PLLL3H48GE0bNgQffr0QWpqarHrbNmyBePGjVO48sTExARBQUHYt28f9u3bBzMzM/Tp0weXLl0qcduBgYHQ19cXJzMzs7feDyIiIiIiIqoCkZHAli3yx99/D2hqlr0Oa6LT6548AaZPlz+eNw9o27b861bC71CVJ9FzcnIQExMDBweH/21URQUODg6Ijo4uVx9btmzBmDFjoK2trTA/KioKTZo0gYWFBaZMmYKnT5+W2g8TLURUV82dO7fEm3YWTjdv3qyy7RcUFAAA5s2bhxEjRsDGxgbbtm2DRCJBaGhokfbR0dG4ceNGkVIuFhYW+PTTT2FjYwN7e3ts3boV9vb2WL16dYnb9vf3R3p6ujg9fPiwcneOiIiIiIiqTE5OjrJDoKr24gUwaZL88WefAT17Kjceqp38/OSJ9Pbtgblzy7dOJdZEr/Ibiz558gT5+fkwfqPIu7GxcbkSOufPn8e1a9ewpfDTqv/n5OSE4cOHo0WLFkhISMAXX3yBgQMHIjo6GqqqqsX25e/vDz8/P/F5RkYGE+lEVCfMnDkT7u7upbZp2bIlZDJZkVJaeXl5SE1NhUwme+vtm5iYAADavvZJsFQqRcuWLfHgwYMi7b///nt06tQJNjY2ZfbdvXt3nDp1qsTlUqkUUqn0LaImIiIiIiJly83NVXYIVNUCAoCEBKBpUyAwUNnRUG109Ciwc6c8Kf799/JyLtWsxhee2rJlCzp06IDu3bsrzB8zZgw+/vhjdOjQAc7Ozjh8+DAuXLiAqKioEvuSSqXQ09NTmIiI6gIjIyNYWlqWOmloaMDOzg5paWmIiYkR142MjERBQQFsbW3fevs2NjaQSqWIj48X5+Xm5uL+/fto3ry5QtvMzEzs3bu32BuKFicuLk5M0hMRUdXatGkTOnbsKJ4r29nZ4bfffiuxfW5uLr766iu0atUKmpqasLa2xtGjR4u027hxI8zNzaGpqQlbW1ucP3++KneDiIhew7GdlComBli5Uv540yaAuTiqqMxM4NNP5Y9nzADeIXfxLqo8id64cWOoqqoiOTlZYX5ycnKZVz1mZWVh9+7d5Uq0tGzZEo0bN8adO3feKV4iorrMysoKTk5O8PLywvnz53H69Gl4e3tjzJgxMDU1BQA8evQIlpaWCifBSUlJiIuLE8fYq1evIi4uTqx3rqenh8mTJ2PhwoX4/fffER8fjylTpgBAkftZ7NmzB3l5efjkk0+KxLdmzRocOHAAd+7cwbVr1+Dj44PIyEhMLbyDOxERVammTZti6dKliImJwcWLF9GvXz8MHToU169fL7b9l19+ie+++w7r16/Hn3/+icmTJ2PYsGGIjY0V2+zZswd+fn5YuHAhLl26BGtrazg6Ohb5ZhQREVUNju2kNLm5gKcnUFAAjBkD/OtfFVufNdEJkNc/f/AAaN4cWLz47fqoDTXRNTQ0YGNjg4iICHFeQUEBIiIiYGdnV+q6oaGhyM7OLjbR8qa///4bT58+5dWKRERl2LVrFywtLdG/f38MGjQIPXv2xObNm8Xlubm5iI+Px4sXL8R5QUFB6Ny5M7y8vAAAvXr1QufOnXHw4EGxzTfffIMxY8Zg/Pjx6NatG/766y9ERkYWuenzli1bMHz4cBgYGBSJLScnBzNnzkSHDh3Qu3dvXL58GX/88Qf69+9fyUeBiIiKM2TIEAwaNAht2rTB+++/j6+//ho6Ojo4e/Zsse137tyJL774AoMGDULLli0xZcoUDBo0CCsLrzgDsGrVKnh5ecHDwwNt27ZFUFAQGjRogK1bt1bXbhER1Wsc20lpVq4ELl8GDA2BtWuVHQ3VRmfPAuvXyx9v3gzo6FRs/dpUEx0A/Pz84Obmhq5du6J79+5Ys2YNsrKy4OHhAQBwdXXFe++9h8A36iJt2bIFzs7OaNSokcL8zMxMLFq0CCNGjIBMJkNCQgI+//xztG7dGo6OjtWxS0REtZahoSFCQkJKXG5ubg7hjU9pAwICEBAQUGq/6urqWLFiBVasWFFquzNnzpS47PPPP8fnn39e6vpERFQ98vPzERoaiqysrBIvfsnOzoampqbCPC0tLfFeFjk5OYiJiYG/v7+4XEVFBQ4ODoiOji5x29nZ2cjOzhafZ2RkvMuuEBHR/+PYTtXm1i15LXQAWLMGaNJEmdFQbZSTA0ycKL+K3NUVGDBAqeFUSxJ99OjR+Oeff7BgwQIkJSWhU6dOOHr0qHiz0QcPHkBFRfGi+Pj4eJw6dQq///57kf5UVVVx5coVbN++HWlpaTA1NcWAAQOwePFi3lyOiIiIiOgdXL16FXZ2dnj16hV0dHTwyy+/KNw4+nWOjo5YtWoVevXqhVatWiEiIgI///wz8vPzAQBPnjxBfn6+eN5fyNjYGDdv3iwxhsDAQCxatKjydoqIqJ7j2E7VqqAA8PICsrMBR0egHBUmiIoIDASuXweMjIBVq5QdTfUk0QHA29sb3t7exS4r7magFhYWRa6ELKSlpYWwsLDKDI+IiIiIiCA/D4+Li0N6ejp++uknuLm54fjx48UmW9auXQsvLy9YWlpCIpGgVatW8PDweOev8/v7+8PPz098npGRATMzs3fqk4ioPuPYTtXq22+BEycAbW0gKOjtS2qwJnr9dfky8J//yB+vWwe8UaWkwmpDTXQiIiIiIqo9NDQ00Lp1a9jY2CAwMBDW1tZYW0IdUyMjI+zfvx9ZWVn466+/cPPmTejo6KBly5YAgMaNG0NVVRXJyckK6yUnJ0Mmk5UYg1QqhZ6ensJERERvryaP7VpaWpW0l1QjJCQAc+bIHy9bBpibKzUcqoVycgB3dyAvDxg2DBg9+u37qsSa6EyiExERERFRiQoKChRq2BZHU1MT7733HvLy8rBv3z4MHToUgDxpY2Njg4iICIX+IiIiSqzFS0REVa8mje1vlvelWqygAJgwAXjxAujbF5gyRdkRUW20ZAkQFye/+nzTpkpNhL+LaivnQkRERERENZu/vz8GDhyIZs2a4fnz5wgJCUFUVJRYStHV1RXvvfceAgMDAQDnzp3Do0eP0KlTJzx69AgBAQEoKChQuEm0n58f3Nzc0LVrV3Tv3h1r1qxBVlYWPDw8lLKPRET1Dcd2qjYbNvyvjMuWLcC7fkBSQ5KnVI1iY4Gvv5Y/3rgReOPeC8rEJDoREREREQEAUlJS4OrqisTEROjr66Njx44ICwvDRx99BAB48OCBwhWDr169wpdffom7d+9CR0cHgwYNws6dO2FgYCC2GT16NP755x8sWLAASUlJ6NSpE44ePVrkhnRERFQ1avrYnpOT8877SDXA7dvA3LnyxytWAC1aVF7frIleP+TkAG5u8jIuI0YAo0ZVXt+V8DvEJDoREREREQEAtmzZUuryqKgohee9e/fGn3/+WWa/3t7e8Pb2fpfQiIjoLdX0sT03N/ed+yAly88HPDyAly+B/v2BTz9VdkRUGy1eDFy9CjRuLL85bWV8E4E10YmIiIiIiIiIiEjp1q0DTp8GdHTkZVxYhoUqKiYG+P+SUvj2W6BJE+XGUwwm0YmIiIiIiIiIiKji4uOBL76QP165EmjevPL6ZjK+fsjOlpdxyc+Xl3AZOVLZERWLSXQiIiIiIiIiIiKqmMIyLq9eAR99BHh5Vc12WBO9bvvqK+D6dcDISH5z2qpQCb9DTKITERERERERERFRxXzzDRAdDejqAt9/zyvHqeKio4GlS+WPN22SJ9IrE2uiExERERERERERkVLExgILFsgfr10LNGum3Hio9snMBMaPBwoKABcXYMQIZUdUKibRiYiIiIiIiIiIqHxevpQnPXNzgWHDAHf3qtkOr2yv23x9gYQEwMys6sq4VCIm0YmIiIiIiIiISCk0NTWVHQJV1Jw5wI0bgEwGbN5c9clu1kSvew4e/F8JoB07AAODqt0ea6ITEREREREREVFtpaqqquwQqCJ+/x1Yv17+eNs2oHFj5cZDtU9yMjBxovzxrFlAnz5Vty3WRCciIiIiIiIiIqJq8/Tp/0q3TJ0KODkpNRyqhQQB8PQE/vkHsLYGFi9WdkTlxiQ6EREREREREREpRU5OjrJDoPIQBGDyZCAxEbC0BJYvr/ptsiZ63bN5M3DkCCCVAj/8IP9ZSzCJTkRERERERERESpGbm6vsEKg8du4EfvoJUFOTJz8bNKi+bbMmet1w6xbg5yd/HBgItG9ffdtmTXQiIiIiIiIiIiKqMgkJgLe3/PGiRYCNjXLjodonJwdwcQFevAD69wdmzKie7bImOhEREREREREREVWpnBxgzBjg+XOgZ09gzpzq2zbLudQdX3wBXLwIGBoCwcGASu1LSde+iImIiIiIiIiIiKjqzZsnT342bAiEhACqqsqOiGqb334DVq6UP962DWjaVLnxvCUm0YmIiIiIiIiIiEjRb78BK1bIH2/bBpiZKScO1kSvvR4/Blxd5Y+nTQM+/lg5cbAmOhERVVRqaipcXFygp6cHAwMDeHp6IjMzs9R1Nm/ejD59+kBPTw8SiQRpaWkKy6OioiCRSIqdLly4ILa7cuUKPvzwQ2hqasLMzAzLi7mje2hoKCwtLaGpqYkOHTrg119/rZT9JiIiIiIionJ6M/k5dKhy46HaJz8fGD8eePIE6NQJKOb//yrHmuhERPS2XFxccP36dYSHh+Pw4cM4ceIEJk2aVOo6L168gJOTE7744otil9vb2yMxMVFhmjhxIlq0aIGuXbsCADIyMjBgwAA0b94cMTEx+OabbxAQEIDNmzeL/Zw5cwZjx46Fp6cnYmNj4ezsDGdnZ1y7dq3yDgARERERERGV7PXkp7W1cpKfAGui13ZLlwKRkYC2NrB7N6CpqeyI3km1JdE3btwIc3NzaGpqwtbWFufPny+xbXBwcJErGTXfONCCIGDBggUwMTGBlpYWHBwccPv27areDSKiWu3GjRs4evQovv/+e9ja2qJnz55Yv349du/ejcePH5e4no+PD+bOnYsePXoUu1xDQwMymUycGjVqhAMHDsDDwwOS/z/x2bVrF3JycrB161a0a9cOY8aMwfTp07Fq1Sqxn7Vr18LJyQmzZ8+GlZUVFi9ejC5dumDDhg2VeyCIiIiIiKhGeDPfQzXA68nPPXtqffKTlODUKWDhQvnjjRsBCwvlxlMJqiWJvmfPHvj5+WHhwoW4dOkSrK2t4ejoiJSUlBLX0dPTU7ii8a+//lJYvnz5cqxbtw5BQUE4d+4ctLW14ejoiFevXlX17hAR1VrR0dEwMDAQrw4HAAcHB6ioqODcuXOVtp2DBw/i6dOn8PDwUNh2r169oKGhIc5zdHREfHw8nj17JrZxcHBQ6MvR0RHR0dElbis7OxsZGRkKExERERER1Q6qvFFlzVITk5+siV67pKYC48bJv9HwySf/KwukTLWlJvqqVavg5eUFDw8PtG3bFkFBQWjQoAG2bt1a4joSiUThqkZjY2NxmSAIWLNmDb788ksMHToUHTt2xI4dO/D48WPs37+/xD6ZaCGi+i4pKQlNmjRRmKempgZDQ0MkJSVV2na2bNkCR0dHNH3trttJSUkKYzkA8XnhtktqU1psgYGB0NfXFyczZd3shoiIiIiIqDZLSQFGj5YnP11cakbyk2qXggJ54vzhQ6B1a+Dbb5Vblqc21UTPyclBTEyMwpWFKioqcHBwKPXKwszMTDRv3hxmZmYYOnQorl+/Li67d+8ekpKSFPrU19eHra1tqX0y0UJEddXcuXNLvLFn4XTz5s1qieXvv/9GWFgYPD09q2V7/v7+SE9PF6eHDx9Wy3aJiIiIiOjd5ebmKjsEAoC8PGDMGPkNRa2sgKAg5dckV/b2qeKWLAF++01eAuinnwBdXWVHVGnUqnoDT548QX5+frFXFpaU0LGwsMDWrVvRsWNHpKenY8WKFbC3t8f169fRtGlT8YrEil6t6O/vDz8/P/F5RkYGE+lEVCfMnDkT7u7upbZp2bIlZDJZkVJaeXl5SE1NhUwmq5RYtm3bhkaNGuHjjz9WmC+TyZCcnKwwr/B54bZLalNabFKpFFKptDJCJyIiIiKiapaTk6PsEAgAFiwAjh2T10Hftw/Q0VF2RFTbhIfLf48AYNMm+U1p65AqT6K/DTs7O9jZ2YnP7e3tYWVlhe+++w6LFy9+636ZaCGiusrIyAhGRkZltrOzs0NaWhpiYmJgY2MDAIiMjERBQQFsbW3fOQ5BELBt2za4urpCXV29yLbnzZuH3NxccVl4eDgsLCzQsGFDsU1ERAR8fHzE9cLDwxXeE4iIiIiIiKgSHToEBAbKH2/ZIr8SvSZhTfSa7+FDeR10QQAmTgTKuMiv2tWGmuiNGzeGqqpqha8sfJ26ujo6d+6MO3fuAPjfFYvv0icRUX1kZWUFJycneHl54fz58zh9+jS8vb0xZswYmJqaAgAePXoES0tLnD9/XlwvKSkJcXFx4jh89epVxMXFITU1VaH/yMhI3Lt3DxMnTiyy7XHjxkFDQwOenp64fv069uzZg7Vr1yp8Q2jGjBk4evQoVq5ciZs3byIgIAAXL16Et7d3VRwOIiIiIiKi+u3u3f/VPp82TV4TnagicnKAUaOAJ0+Azp2B9euVHdH/1Kaa6BoaGrCxsUFERIQ4r6CgABEREeW+sjA/Px9Xr16FiYkJAKBFixaQyWQKfWZkZODcuXO8WpGIqAy7du2CpaUl+vfvj0GDBqFnz57YvHmzuDw3Nxfx8fF48eKFOC8oKAidO3eGl5cXAKBXr17o3LkzDh48qND3li1bYG9vD0tLyyLb1dfXx++//4579+7BxsYGM2fOxIIFCzBp0iSxjb29PUJCQrB582ZYW1vjp59+wv79+9G+ffvKPgxERERERET126tXwL//DaSlAT16ACtWKDsiRayJXjvMmgWcPQsYGMjroGtqKjuiKlEt5Vz8/Pzg5uaGrl27onv37lizZg2ysrLg4eEBAHB1dcV7772HwP//6shXX32FHj16oHXr1khLS8M333yDv/76S7yyUSKRwMfHB//5z3/Qpk0btGjRAvPnz4epqSmcnZ2rY5eIiGotQ0NDhISElLjc3NwcwhtfdQoICEBAQECZfZfWLwB07NgRJ0+eLLXNyJEjMXLkyDK3RURERERERG9JEABvbyA2FmjcGAgNBTQ0lB0V1Ta7d//vyvOdO4GWLZUbTxWqliT66NGj8c8//2DBggVISkpCp06dcPToUfHGoA8ePICKyv8uin/27Bm8vLyQlJSEhg0bwsbGBmfOnEHbtm3FNp9//jmysrIwadIkpKWloWfPnjh69Cg06+inHURERERERERERJVi0yZ5/XOJBAgJAZo2VXZEJWNN9JopNhaYMEH+2N8f+Ne/lBtPaSrhd6jabizq7e1dYk3bqKgoheerV6/G6tWrS+1PIpHgq6++wldffVVZIRIREREREREREdVtUVHAjBnyx8uW31U/FAAAYmpJREFUAR99pNRwSsRyLjVXSgowdCjw8iXg5AQsXqzsiIpXm2qiExERERERERERFUcqlSo7hPrl/n15HfS8PGDcOHk9a6KKyMmR/w49fAi8/z7w44+Aqqqyo6pyTKITEREREREREZFSqKlVW5EEysqSXz389CnQpQvw/fe82psqbsYM4ORJQE8POHBAfkPReoBJdCIiIiIiIiIiorpMEAB3d+DKFaBJE2D/fkBLS9lRlQ9rotccQUHyqbCWvqWlsiMqn0r4HWISnYiIiIiIiIiIlCI3N1fZIdQPS5YAP/0EqKsD+/YBZmbKjqhsvEq+Zjl5Epg2Tf54yRJg8GDlxlMerIlORERERERERES1XU5OjrJDqPv27QPmz5c/3rgR6NlTufFQ7XP3LjB8uLyW/ujRwJw5yo6o2jGJTkREREREREREVBedOwd88om8nMXUqYCXl7Ijotrm2TNg0CDgyRN5Lf2tW+vltwSYRCciIiIiIiIiIqpr7t8HPv4YePVKngRds0bZEb0d1kRXnpwc+RXo8fHyEkCHDgENGig7qopjTXQiIiIiIiIiIiJSkJYmr1mdkgJYWwO7dwNqasqOqmLq4dXONYogAJ9+CkRFAbq6wOHDgKmpsqOqGNZEJyIiIiIiIiIioiJyc4GRI4E//5QnPQ8flidBiSpiyRIgOBhQVQX27gU6dlR2RErFJDoREREREREREVFdIAjAlCnAH38A2tryBHrTpsqOimqbH38EvvxS/nj9esDJSbnx1ABMohMREREREREREdUFy5cDW7YAKiryEi6dOys7orenqSn/+fy5cuOob06fBtzd5Y9nzpR/KFNbVeLvEJPoRERERERERESkFFKpVNkh1B179wJz58ofr10L/Otfyo3nXbVpI/9586Zy46hPbt8Ghg6V31B02DD5hzK1WeHv0I0b79wVk+hERERERERERKQUarXtZpc11YkTwPjx8sfTpwPe3sqNpzIUXkUfEaHcOOqLlBR52ZanT4GuXYEffpB/o6E269JF/vPiRfnNdt9BLT8SRERERERERERE9diNG4pXD69apeyIKsfQoYBEApw5A5w/r+xo6rasLGDIEODuXaBFC3kt/QYNlB3Vu3v/faBtW/nNdr/77p26YhKdiIiIiIiIiIiUIi8vT9kh1G6JicDAgfKrbO3sgF27AFVVZUdVOd57D/jkE/njTz6R7ytVvrw8YOxY+QcVhobAb78BxsbK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d+nSpTKZTDKZTBo5cqRlfoMGDTRr1qxC1726no+PT5nGCMflZu8AAAAAAAAAADg/k8lU6PKJEyfqzTfflGEYNorImpeXlw4ePKiqVave0HrJycn64IMPNHHixDKKDI6OkehAITp06GC52piUlFTm+xs4cKBlf5988kmZ7w8AKiL6dgAof+jbAcAxJCcnW6ZZs2bJy8vLat4zzzwjb29vu43oNplMCggIUPXq1W9ovYCAAHl7e5dRVHAGJNGBIkRFRSk5OVm33357me/rzTffVHJycpnvBwAqOvp2ACh/6NsBwP4CAgIsk7e3tyVpfXWqVq1annIuHTp00JNPPqmRI0eqRo0a8vf31zvvvKPMzEwNGjRI1atXV5MmTfTf//7Xal979+5Vly5dVK1aNfn7++uxxx7T2bNnixV3VlaWHn/8cVWvXl3169fXggULSvIyoBwiiQ4UoUqVKgoICJCbW9lXP/L29lZAQECZ7wcAKjr6dgAof+jbAcB5LVu2TL6+vtq+fbuefPJJDR8+XH379lW7du20c+dO3X///XrssceUlZUlSUpLS1PHjh0VFBSk77//XnFxcTp9+rQefvjhYu3/tddeU9u2bbVr1y498cQTGj58uA4ePFiahwgnRxIdFcZvv/2mgIAATZ061TJv8+bNcnd31/r1629oW99++60qVaqkixcvWuYdP35cJpNJP//8c7GvogIAbgx9OwCUP/TtAFDxtGrVSuPGjdMtt9yisWPHytPTU76+voqKitItt9yiCRMm6Ny5c/rhhx8kSW+99ZaCgoI0depUBQYGKigoSIsXL9bGjRv1008/3fD+u3btqieeeEJNmjTR888/L19fX23cuLG0DxNOjCQ6KoxatWpp8eLFmjRpkr7//nudP39ejz32mKKjo9WpU6cb2lZSUpKaNWsmT09Py7xdu3apRo0auvnmmyXd+FVUAMCNo28HgPKHvh0AKp6WLVtaHru6uuqmm25SixYtLPP8/f0lSWfOnJEk7d69Wxs3blS1atUsU2BgoCTpyJEjJdr/1RI0V/cFSCTRUcF07dpVUVFRCg8P17Bhw1S1alVNmzbthreze/duBQUFWc1LSkpSq1atLM9v9CoqAKB46NsBoPyhbweAiqVSpUpWz00mk9U8k8kkScrNzZUkXbhwQT169FBSUpLVdOjQId17772lsv+r+wIkkuiogGbOnKkrV65o9erVWr58uTw8PG54G0lJSWrdurXVvF27dlnNu9GrqACA4qNvB4Dyh74dAFCQO+64Q/v27VODBg3UpEkTq6lq1ar2Dg/lEEl0VDhHjhzRqVOnlJubq+PHj9/w+jk5Odq7d2+eES07d+60+jB+o1dRAQDFR98OAOUPfTsAoCAjRoxQamqq+vfvrx07dujIkSNat26dBg0apJycHHuHh3Ko7G9bDjiQS5cuacCAAXrkkUfUtGlTDRkyRHv27JGfn991b+PgwYO6ePGi6tSpY5m3ZcsW/frrr3lGuQAAyh59OwCUP/TtAIDC1KlTR999952ef/553X///crOztbNN9+ssLAwubgwZhiljyQ6KpQXX3xR6enpmj17tqpVq6YvvvhCjz/+uNauXXvd20hKSpIkzZkzR0899ZQOHz6sp556SpL5wz4AwLbo2wGg/KFvBwDnN3DgQA0cODDP/KVLl1o9T0hIyNMmv28gGYZh9fyWW27RRx99VIIIC97X1b8hwFVcmkGFkZCQoFmzZum9996Tl5eXXFxc9N577+mbb77R/Pnzr3s7SUlJCg0N1dGjR9WiRQu9+OKLeumll+Tl5aXZs2eX4REAAP6Kvh0Ayh/6dgBAWUlPT1e1atX0/PPP39B61apV07Bhw8ooKjgDRqKjwujQoYMuX75sNa9BgwZKT0+/oe3s3r1bd955p/71r39ZzX/00Uctj4t7FRUAcGPo2wGg/KFvBwCUhT59+qh9+/aSJB8fnxta9+rIdFdX11KOCs6CkehAEebNm6dq1appz549kswfxlu0aFEm+xo2bJiqVatWJtsGAPyJvh0Ayh/6dgBAYapXr64mTZqoSZMm8vX1vaF1r67XsGHDMooOjs5kcEkdKNCvv/6qP/74Q5JUv359paamqnbt2tq3b5+aN29e6vs7c+aMMjIyJEm1a9dW1apVS30fAFDR0bcDQPlD3w4AAMoSSXQAAAAAAAAAAApAORcAAAAAAAAAAApAEh0AAAAAAAAAgAKQRAcAAAAAAAAAoAAk0QEAAAAAAAAAKABJdAAAAAAAAAAACkASHQAAAAAAAACAApBEBwAAAAAAAACgACTRAQAAAAAAAAAoAEl0AAAAAAAAAAAKQBIdAAAAAAAAAIAC/D9pNV++FzK5QwAAAABJRU5ErkJggg==", "text/plain": [ "
" - ], - "image/png": "iVBORw0KGgoAAAANSUhEUgAABdEAAAKxCAYAAAC8BuXeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdeVxU1f8/8NeADKsDorIlAqYhmIDiRxzLHRnQj2n5KRdS3D8aaEhp8ckItcJc0ST5mAtW8nGpNFMDCUNccENHccMN0xIwU0BQAeH8/vDH/ToybIoMwuv5eNxH3Xve9973PTNzOZ65c45MCCFARERERERERERERETl6Ok6ASIiIiIiIiIiIiKi+oqd6EREREREREREREREFWAnOhERERERERERERFRBdiJTkRERERERERERERUAXaiExERERERERERERFVgJ3oREREREREREREREQVYCc6EREREREREREREVEF2IlORERERERERERERFQBdqITEREREREREREREVWAnehPyNHREZGRkbpOo1ZduXIFMpkMarW6WvFjxozBkCFDnmlOT2r//v3o2LEjDAwM6m2OpEkmk2Hr1q3P9Bzh4eGQyWSQyWR18vmti2uqrrq+9sasPr3ujwsPD4eHh4eu06Aq1EUbIyYmRronBAcHP9NzAfWr3VTX1061JykpCTKZDDk5OZXG1af3W21hO510ie30Z4vtdKL6o+zvrUwme6J/N5Xta2FhUeu5ke7Vu070MWPGQCaTYd68eRrbt27dCplMVuf5xMTEaH3zHzlyBJMmTarzfGqLtoa1vb09MjMz8fLLL+smqVoUEhICDw8PZGRkICYmRtfpPNcq+gw8qYo68TIzM+Hn51dr56lIhw4dkJmZ+Vx/fh+Xnp6OPn36wNraGkZGRmjTpg1mzZqF4uJiKeb9999HZmYmWrVqpcNMn39lf6MeX3x9fZ/ZOXX5j7za/vw/76rbgVddum5jKBQKZGZmYu7cuc/8XHXl77//hq+vL+zs7GBoaAh7e3sEBQUhLy9Pihk2bBgyMzOhVCp1mGnD9eh9Ui6Xo23btpgzZw4ePHjw1Mfu3r07MjMzYW5uDkD3n6Fnhe10qi620+s/ttOpIcrKysLUqVPRpk0bqb01aNAgJCYm6jq1StXk31W//vqr1uv5448/IJfLK/x7nJmZyS/DGrAmuk5A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SdsyMzMFAJGSklLhccoolUphaGgoAIhJkyaJkpKScjFsnD+dgIAAoa+vL0xNTTWWzz77TIp59HX/9ttvhbOzs9TZKMTDzlNjY2MRHx8vhKj83vP48cp88sknwsDAQKPxt2vXLqGvry+uXr0qbSv7PB8+fFja79HPwBdffCFcXFyk9R9++EGYmZlJnz1tn//ff/9d6Ovriz///FNje79+/URoaKjWa4iPjxd6enoiPT1da/nIkSNF//79NbbNmDFDuLq6SusODg7i7bffltZLS0uFlZWVWLFihRCi6ntuv379yjX4v/32W2FrayutV3XPfbQD71G9evUSnTp10nreRz1JG6O6r6uJiYnG39MZM2YILy+vCnOp7NyP1nPZPejjjz+WtpXdIzMzM4UQ1X/9qupEd3Bw0LhvOTs7ix49ekjrZffI//3vfxUep8zw4cOFsbGxACAGDRok7t27Vy6GnejPxqPtw9LSUpGQkCAMDQ3F+++/L86fPy8AiP3790vxN2/eFMbGxmLTpk1CCCE6duyo8eXWox7/DLKdzna6EGyns53OdjpRXTl06JAAIH788cdK42rSib5161aNfbW1q+fOnSt8fHw0tl27dk16uKVsv0c/s0II8Y9//EN88MEH0npVn/uKci8zcuRIjb9r7u7uWv+esRO94aqXw7mU+eKLL7Bu3TqcPXu2XNmJEycQExMjjR9mZmYGlUqF0tJSZGRkID09HU2aNEHnzp2lfdq2bVvuJ/e//vor+vXrhxdeeAFNmzbFqFGj8Pfff+Pu3bvVzrNJkyZ46623sH79egBAQUEBfvrpJ/j7+wMALl68iLt376J///4a+X7zzTcV/uSyzOOTXimVSo36qE7+crkcbm5u1b6eMmq1Gj169ICBgUGVsU9yjf3794eDgwPatGmDUaNGYf369TWq9zJdunSpVlxUVBQ8PT3RsmVLmJmZYeXKlbh69SoA4MaNG7h+/Tr69eundd8TJ04gPz8fzZs317i+jIyMCq9PrVajU6dOsLS01Fp+9uxZvPLKKxrbXnnllXLv90dfO1NTUygUCty4cUM6R0WvUUFBAS5duoTx48dr5Pzpp5+Wy/nRc9ja2kp1UhVtdb9x40a88sorsLGxgZmZGWbNmiXVc3WdPXsW7u7uMDU1lba98sorKC0tRXp6urStQ4cOGmMH2traVitvbR6t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9x3y8vIejuMOoGXLltDX18fPP/+M7OxsdOvWDUZGRkhISMDnn3+O999/XzrH5MmTsXz5csycORPjxo3D7t27sWnTJuzYsUOKCQkJQUBAALp06YKuXbsiMjJSo1OGiIjqh2HDhuGvv/5CWFgYsrKy4OHhgbi4OGlei6tXr0JP7/+exezevTtiY2Mxa9Ys/Oc//0G7du2wdetWvPzyy7q6BGpohNB1BkQSdqITETUwvXv3hqiksSGTyTBnzhyNzuvHWVpaIjY2ttLzuLm5Ye/evRWWjxkzBmPGjNHY5uDggJ07d1Z63N69e+P48eOVxhARUdVu3LiB0aNHIzMzE+bm5nBzc0N8fDz69++PpKQkHDp0CADQtm1bjf0yMjLg6OgIAwMDREVFYfr06RBCoG3btli8eDEmTpwoxVbny8+qOmWIiKj+CAoKqvBJ8qSkpHLb3nzzTbz55pvPOCtiZzI9tcb6HqrF62YnOhERERFRA7R69eoKy6r6whUAfH194evrW+V5qvPlZ2WdMkRERERE9R3HRCciIiIiIiIiIp2oalLrRk0m03UG9QPr4cmx7h6qhXpgJzoREREREREREemEXC7XdQpERFViJzoRERERERERERERUQXYiU5ERERERERERDpRWlqq6xSIiKrETnQiIiIiIiIiItKJe/fu6TqF+q+KycAbrMZ63c9CY63LWrxudqITEREREREREREREVWAnehERERERERERET1jUym6wzqB9bDk2PdPVQL9cBOdCIiIiIiIiIiIiKiCrATnYiIiIiIiIiIiIioAuxEJyIiIiIiIiIiIiKqADvRiYiIiIiIiIiIqH4RQtcZEEnYiU5ERERERERERDrRpEkTXadQ/7EzmZ5WY30P1eJ1sxOdiIiIiIiIiIh0wtDQUNcpEBFViZ3oRERERERERERE9Y1MpusM6gfWw5Nj3T1UC/XATnQiIiIiIiIiItIJ0ViHmSCi5wo70YmIiIiIiIiISCfu3r2r6xSIiKrETnQiIiIiIiIiIiKqX/grBapH2IlORERERERERERUX7EzmZ5WY30P1eJ1sxOdiIiIiKgBWrFiBdzc3KBQKKBQKKBUKvHLL78AAG7duoWpU6fC2dkZxsbGaN26NaZNm4bc3FyNY1y9ehUDBw6EiYkJrKysMGPGDDx48EAjJikpCZ07d4ahoSHatm2LmJiY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Rb1D5ERENU+l1kQvKCjAkSNH8P7778PR0RFNmjSBra2tQsmXmJgY5ObmwsHBQZxnaWmJZs2aITo6GoC8HleHDh1gbGwstnF0dERGRgauX78utnm9j8I2hX0Uh/W3iIiIiIiIiKg+MDIygqWlZamThoYG7OzskJaWhpiYGHHdyMhIFBQUwNbWtti+586diytXriAuLk6cAHlpxm3btlXH7tUPEomyI6gZeBzeHo+dXCUch0pNoqekpCAzMxNLly6Fk5MTfv/9dwwbNgzDhw/H8ePHAchrbWloaBT5tNLY2FistZWUlKSQQC9cXristDYZGRl4+fJlsfGx/hYRERERERER0f9YWVnByckJXl5eOH/+PE6fPg1vb2+MGTMGpqamAIBHjx7B0tIS58+fBwDIZDK0b99eYQKAZs2aoUWLFhXavopKpaamqC6pryVIqEaqcDmX0hQUFAAAhg4dCl9fXwBAp06dcObMGQQFBaF3796VubkKY/0tIiIiIiIiIiJFu3btgre3N/r37w8VFRWMGDEC69atE5fn5uYiPj4eL168qPRta2lpVXqfRESVrVKT6I0bN4aamhratm2rML+wXjkg/7QyJycHaWlpClejJycni7W2ZDKZ+Onm68sLlxX+LJz3ehs9PT0OwERERERERERE5WRoaIiQkJASl5ubm0Mo46rgspYTEdVmlfqdGQ0NDXTr1g3x8fEK82/duoXmzZsDAGxsbKCuro6IiAhxeXx8PB48eAA7OzsAgJ2dHa5evapwY4vw8HDo6emJCXo7OzuFPgrbFPZBRERERERERERERPSuKnwlemZmJu7cuSM+v3fvHuLi4mBoaIhmzZph9uzZGD16NHr16oW+ffvi6NGjOHTokHhnZn19fXh6esLPzw+GhobQ09PDtGnTYGdnhx49egAABgwYgLZt22L8+PFYvnw5kpKS8OWXX2Lq1KliOZbJkydjw4YN+PzzzzFhwgRERkZi7969OHLkSCUcFiIiIiIiIiIiqmovXryAnp6essOo2XiVP72r+vo7VIn7XeEk+sWLF9G3b1/xuZ+fHwDAzc0NwcHBGDZsGIKCghAYGIjp06fDwsIC+/btQ8+ePcV1Vq9eLdbYys7OhqOjI7799ltxuaqqKg4fPowpU6bAzs4O2tracHNzw1dffSW2adGiBY4cOQJfX1+sXbsWTZs2xfff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6h6O7UREVJIuXbrg+vXrMDc3R+vWrRUmbW1tZYdHdRCT6FSv5OTk4JNPPsHo0aOxePFiTJw4scJXlMTHx+PVq1cwNTUV50VHR+PRo0cKJ+NERFQ9OLYTEdU9HNuJiKg0U6dORWpqKsaOHYsLFy4gISEBYWFh8PDwQH5+vrLDozqISXSqV+bNm4f09HSsW7cOc+bMwfvvv48JEyZUqI+4uDgAwPr163H79m389ttvcHV1BSA/2SciourFsZ2IqO7h2E5ERKUxNTXF6dOnkZ+fjwEDBqBDhw7w8fGBgYEBVFSY7qTKx5roVG9ERUVhzZo1OHbsGPT09AAAO3fuhLW1NTZt2oQpU6aUq5+4uDg4Ojri7t276NChA9q2bYtFixZhypQpWLduHXbu3FmVu0FERK/h2E5EVPdwbCciqhvc3d3h7u5eZH5wcLDC86ioqCJtiivjJQiCwvM2bdrg559/focIS95W4QexRIWYRKd6o0+fPsjNzVWYZ25ujvT09Ar1c/nyZXTr1g3/+c9/FOa/fsOit30DICKiiuHYTkRU93BsJyKiqpKeng4dHR1MnTq12JuSlkRHRwd5eXnQ1NSswuioJuP3G4jK8O2330JHRwdXr14FID8Z79ChQ5Vsa/LkydDR0amSvomI6H84thMR1T0c24mIqDQjRozA7du3ERcXh9mzZ1do3bi4OFy7dg2xsbFVFB3VdBKBH6kTlejRo0d4+fIlAKBZs2ZITU2FiYkJrl+/jrZt21b69lJSUpCRkQEAMDEx4R2liYiqAMd2IqK6h2M7ERERVSUm0YmIiIiIiIiIiIiISsByLkREREREREREREREJWASnYiIiIiIiIiIiIioBEyiExERERERERERERGVgEl0IiIiIiIiIiIiIqISMIlORERERERERERERFQCJtGJiIiIiIiIiIiIiErAJDoRERERERERERERUQmYRCciIiIiIiIiIiIiKgGT6EREREREREREREREJWASnYiIiIiIiIiIiIioBEyiExERERERERERERGVgEl0IiIiIiIiIiIiIqISMIlORERERERERERERFQCJtGJiIiIiIiIiIiIiErAJDoRERERERERERERUQmYRCciIiIiIiIiIiIiKgGT6FQh5ubmWLNmjVJjCA4OhoGBgVJjqKiacNyUISAgAJ06darQOhKJBPv37y9xeZ8+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IiKq+xo0aKDsEIiIysQkOhERERERERERKYVEIlF2CEREZWISnYiIiIiIiIiIiIioBEyiExERERERERGRUmRnZys7BKqpnjwBLl1SdhRUm+XlASdOALm579wVk+hERERERERERKQUeXl5yg6BaqIXLwBbW6BrV+DuXWVHQ7WVhwfQuzewY8c7d8UkOhEREREREREREdUcgYHy5LkgAI8fKzsaqo2iooAffpA//vvvd+6OSXQiIiIiIiIiIiKqGe7cAZYvV3YUVJvl5gLe3pXaJZPoREREREREREREpHyCAEyfDuTkKDsSqs02bACuX6/ULplEJyIiIiIiIiIiIuU7eBD47TdAXR3Q15fPEwTlxkS1S2IisHCh/LGRkfxnJfwOMYlOREREREREREREyvXyJeDjI388cyZgbKzUcKiWmj0beP4c6N4dGDGi0rplEp2IiIiIiIiIiIiUKzAQuH8faNoU+PJLZUdDtdHx48CuXYBEAmzcCKhUXuqbSXQiIiIiIiIiIlKKBg0aKDsEqgni44Fly+SPV60CtLWVGw/VPjk5wJQp8seTJgFdu1Zq90yiExERERERERGRUkgkEmWHQMomCPLkZ04OMHAg8O9/F11OVJYVK4AbN4AmTeTfangda6ITERERERERERFRrfXDD8CxY4CmJrBhg7wUB/C/n0RlSUgAFi+WP161CmjYUP64En+HmEQnIiIiIiIiIiKlyM7OVnYIpEypqfKbiALAggVAy5bKjYdqH0EApk4FXr0C+vcHxo2rks0wiU5EREREREREREqRl5en7BBImebOBf75B2jb9n/JdKKKCA0FwsIADQ3g22+r7BsMTKITERERERERERFR9TpzBvjvf+WPg4LkSdDXFSZDWROdSpKeDsyYIX/8xRfA++8X34410YmIiIiIiIiIiKhWyc0FPv1U/njCBODDD5UbD9VO8+YBSUny5PncuUWXsyY6ERERERERERER1Upr1gDXrgGNGgHLlys7GqqNLlyQl28BgE2bAKm0SjfHJDoRERERERERERFVj7/+AgIC5I9XrJAn0okqIi9P/k0GQQA++QTo16/KN8kkOhFRPZOamgoXFxfo6enBwMAAnp6eyMzMLHWdzZs3o0+fPtDT04NEIkFaWlqx7Y4cOQJbW1toaWmhYcOGcHZ2FpcFBwdDIpEUO6WkpAAAoqKiil2e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5AQsXqzsiIpXm2qiExERERERERERFUcqlSo7hPrl/n15HfS8PGDcOHk9a6KKyMmR/w49fAi8/z7w44+Aqqqyo6pyTKITEREREREREZFSqKlVW5EEysqSXz389CnQpQvw/fe82psqbsYM4ORJQE8POHBAfkPReoBJdCIiIiIiIiIiorpMEAB3d+DKFaBJE2D/fkBLS9lRlQ9rotccQUHyqbCWvqWlsiMqn0r4HWISnYiIiIiIiIiIlCI3N1fZIdQPS5YAP/0EqKsD+/YBZmbKjqhsvEq+Zjl5Epg2Tf54yRJg8GDlxlMerIlORERERERERES1XU5OjrJDqPv27QPmz5c/3rgR6NlTufFQ7XP3LjB8uLyW/ujRwJw5yo6o2jGJTkREREREREREVBedOwd88om8nMXUqYCXl7Ijotrm2TNg0CDgyRN5Lf2tW+vltwSYRCciIiIiIiIiIqpr7t8HPv4YePVKngRds0bZEb0d1kRXnpwc+RXo8fHyEkCHDgENGig7qopjTXQiIiIiIiIiIiJSkJYmr1mdkgJYWwO7dwNqasqOqmLq4dXONYogAJ9+CkRFAbq6wOHDgKmpsqOqGNZEJyIiIiIiIiIioiJyc4GRI4E//5QnPQ8flidBiSpiyRIgOBhQVQX27gU6dlR2RErFJDoREREREREREVFdIAjAlCnAH38A2tryBHrTpsqOimqbH38EvvxS/nj9esDJSbnx1ABMohMREREREREREdUFy5cDW7YAKiryEi6dOys7orenqSn/+fy5cuOob06fBtzd5Y9nzpR/KFNbVeLvEJPoRERERERERESkFFKpVNkh1B179wJz58ofr10L/Otfyo3nXbVpI/9586Zy46hPbt8Ghg6V31B02DD5hzK1WeHv0I0b79wVk+hERERERERERKQUarXtZpc11YkTwPjx8sfTpwPe3sqNpzIUXkUfEaHcOOqLlBR52ZanT4GuXYEffpB/o6E269JF/vPiRfnNdt9BLT8SRERERERERERE9diNG4pXD69apeyIKsfQoYBEApw5A5w/r+xo6rasLGDIEODuXaBFC3kt/QYNlB3Vu3v/faBtW/nNdr/77p26YhKdiIiIiIiIiIiUIi8vT9kh1G6JicDAgfKrbO3sgF27AFVVZUdVOd57D/jkE/njTz6R7ytVvrw8YOxY+QcVhobAb78BxsbK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d+nSpTKZTDKZTBo5cqRlfoMGDTRr1qxC1726no+PT5nGCMflZu8AAAAAAAAAADg/k8lU6PKJEyfqzTfflGEYNorImpeXlw4ePKiqVave0HrJycn64IMPNHHixDKKDI6OkehAITp06GC52piUlFTm+xs4cKBlf5988kmZ7w8AKiL6dgAof+jbAcAxJCcnW6ZZs2bJy8vLat4zzzwjb29vu43oNplMCggIUPXq1W9ovYCAAHl7e5dRVHAGJNGBIkRFRSk5OVm33357me/rzTffVHJycpnvBwAqOvp2ACh/6NsBwP4CAgIsk7e3tyVpfXWqVq1annIuHTp00JNPPqmRI0eqRo0a8vf31zvvvKPMzEwNGjRI1atXV5MmTfTf//7Xal979+5Vly5dVK1aNfn7++uxxx7T2bNnixV3VlaWHn/8cVWvXl3169fXggULSvIyoBwiiQ4UoUqVKgoICJCbW9lXP/L29lZAQECZ7wcAKjr6dgAof+jbAcB5LVu2TL6+vtq+fbuefPJJDR8+XH379lW7du20c+dO3X///XrssceUlZUlSUpLS1PHjh0VFBSk77//XnFxcTp9+rQefvjhYu3/tddeU9u2bbVr1y498cQTGj58uA4ePFiahwgnRxIdFcZvv/2mgIAATZ061TJv8+bNcnd31/r1629oW99++60qVaqkixcvWuYdP35cJpNJP//8c7GvogIAbgx9OwCUP/TtAFDxtGrVSuPGjdMtt9yisWPHytPTU76+voqKitItt9yiCRMm6Ny5c/rhhx8kSW+99ZaCgoI0depUBQYGKigoSIsXL9bGjRv1008/3fD+u3btqieeeEJNmjTR888/L19fX23cuLG0DxNOjCQ6KoxatWpp8eLFmjRpkr7//nudP39ejz32mKKjo9WpU6cb2lZSUpKaNWsmT09Py7xdu3apRo0auvnmmyXd+FVUAMCNo28HgPKHvh0AKp6WLVtaHru6uuqmm25SixYtLPP8/f0lSWfOnJEk7d69Wxs3blS1atUsU2BgoCTpyJEjJdr/1RI0V/cFSCTRUcF07dpVUVFRCg8P17Bhw1S1alVNmzbthreze/duBQUFWc1LSkpSq1atLM9v9CoqAKB46NsBoPyhbweAiqVSpUpWz00mk9U8k8kkScrNzZUkXbhwQT169FBSUpLVdOjQId17772lsv+r+wIkkuiogGbOnKkrV65o9erVWr58uTw8PG54G0lJSWrdurXVvF27dlnNu9GrqACA4qNvB4Dyh74dAFCQO+64Q/v27VODBg3UpEkTq6lq1ar2Dg/lEEl0VDhHjhzRqVOnlJubq+PHj9/w+jk5Odq7d2+eES07d+60+jB+o1dRAQDFR98OAOUPfTsAoCAjRoxQamqq+vfvrx07dujIkSNat26dBg0apJycHHuHh3Ko7G9bDjiQS5cuacCAAXrkkUfUtGlTDRkyRHv27JGfn991b+PgwYO6ePGi6tSpY5m3ZcsW/frrr3lGuQAAyh59OwCUP/TtAIDC1KlTR999952ef/553X///crOztbNN9+ssLAwubgwZhiljyQ6KpQXX3xR6enpmj17tqpVq6YvvvhCjz/+uNauXXvd20hKSpIkzZkzR0899ZQOHz6sp556SpL5wz4AwLbo2wGg/KFvBwDnN3DgQA0cODDP/KVLl1o9T0hIyNMmv28gGYZh9fyWW27RRx99VIIIC97X1b8hwFVcmkGFkZCQoFmzZum9996Tl5eXXFxc9N577+mbb77R/Pnzr3s7SUlJCg0N1dGjR9WiRQu9+OKLeumll+Tl5aXZs2eX4REAAP6Kvh0Ayh/6dgBAWUlPT1e1atX0/PPP39B61apV07Bhw8ooKjgDRqKjwujQoYMuX75sNa9BgwZKT0+/oe3s3r1bd955p/71r39ZzX/00Uctj4t7FRUAcGPo2wGg/KFvBwCUhT59+qh9+/aSJB8fnxta9+rIdFdX11KOCs6CkehAEebNm6dq1appz549kswfxlu0aFEm+xo2bJiqVatWJtsGAPyJvh0Ayh/6dgBAYapXr64mTZqoSZMm8vX1vaF1r67XsGHDMooOjs5kcEkdKNCvv/6qP/74Q5JUv359paamqnbt2tq3b5+aN29e6vs7c+aMMjIyJEm1a9dW1apVS30fAFDR0bcDQPlD3w4AAMoSSXQAAAAAAAAAAApAORcAAAAAAAAAAApAEh0AAAAAAAAAgAKQRAcAAAAAAAAAoAAk0QEAAAAAAAAAKABJdAAAAAAAAAAACkASHQAAAAAAAACAApBEBwAAAAAAAACgACTRAQAAAAAAAAAoAEl0AAAAAAAAAAAKQBIdAAAAAAAAAIAC/D9pNV++FzK5QwAAAABJRU5ErkJggg==\n" + ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" } ], "source": [ @@ -277,11 +277,13 @@ "outputs": [], "source": [ "pyb_model = pybop.lithium_ion.SPM()\n", - "dataset = [\n", - " pybop.Dataset(\"Time [s]\", synthetic_sol[\"Time [s]\"].data),\n", - " pybop.Dataset(\"Current function [A]\", synthetic_sol[\"Current [A]\"].data),\n", - " pybop.Dataset(\"Terminal voltage [V]\", corrupt_V),\n", - "]" + "dataset = pybop.Dataset(\n", + " {\n", + " \"Time [s]\": synthetic_sol[\"Time [s]\"].data,\n", + " \"Current function [A]\": synthetic_sol[\"Current [A]\"].data,\n", + " \"Terminal voltage [V]\": corrupt_V,\n", + " }\n", + ")" ] }, { @@ -334,7 +336,7 @@ "source": [ "# Define the cost to optimise\n", "signal = \"Terminal voltage [V]\"\n", - "problem = pybop.Problem(pyb_model, parameters, dataset, signal=signal)\n", + "problem = pybop.FittingProblem(pyb_model, parameters, dataset, signal=signal)\n", "cost = pybop.RootMeanSquaredError(problem)" ] }, @@ -402,14 +404,14 @@ }, "outputs": [ { - "output_type": "execute_result", "data": { "text/plain": [ "array([0.48367449, 0.63380314])" ] }, + "execution_count": 69, "metadata": {}, - "execution_count": 69 + "output_type": "execute_result" } ], "source": [ @@ -473,24 +475,24 @@ }, "outputs": [ { - "output_type": "execute_result", "data": { "text/plain": [ "" ] }, + "execution_count": 71, "metadata": {}, - "execution_count": 71 + "output_type": "execute_result" }, { - "output_type": "display_data", "data": { + "image/png": "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", "text/plain": [ "
" - ], - "image/png": "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\n" + ] }, - "metadata": {} + "metadata": {}, + "output_type": "display_data" } ], "source": [ @@ -512,6 +514,9 @@ } ], "metadata": { + "colab": { + "provenance": [] + }, "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", @@ -529,91 +534,12 @@ "pygments_lexer": "ipython3", "version": "3.10.12" }, - "colab": { - "provenance": [] - }, "widgets": { "application/vnd.jupyter.widget-state+json": { - "8d003c14da5f4fa68284b28c15cee6e6": { - "model_module": "@jupyter-widgets/controls", - "model_name": "VBoxModel", - "model_module_version": "2.0.0", - "state": { - "_dom_classes": [ - "widget-interact" - ], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "2.0.0", - "_model_name": "VBoxModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "2.0.0", - "_view_name": "VBoxView", - "box_style": "", - "children": [ - "IPY_MODEL_aef2fa7adcc14ad0854b73d5910ae3b4", - "IPY_MODEL_7d46516469314b88be3500e2afcafcf6" - ], - "layout": "IPY_MODEL_423bffea3a1c42b49a9ad71218e5811b", - "tabbable": null, - "tooltip": null - } - }, - "aef2fa7adcc14ad0854b73d5910ae3b4": { - "model_module": "@jupyter-widgets/controls", - "model_name": "FloatSliderModel", - "model_module_version": "2.0.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/controls", - "_model_module_version": "2.0.0", - "_model_name": "FloatSliderModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/controls", - "_view_module_version": "2.0.0", - "_view_name": "FloatSliderView", - "behavior": "drag-tap", - "continuous_update": true, - "description": "t", - "description_allow_html": false, - "disabled": false, - "layout": "IPY_MODEL_06f2374f91c8455bb63252092512f2ed", - "max": 1.1333333333333333, - "min": 0, - "orientation": "horizontal", - "readout": true, - "readout_format": ".2f", - "step": 0.011333333333333332, - "style": "IPY_MODEL_56ff19291e464d63b23e63b8e2ac9ea3", - "tabbable": null, - "tooltip": null, - "value": 0 - } - }, - "7d46516469314b88be3500e2afcafcf6": { - "model_module": "@jupyter-widgets/output", - "model_name": "OutputModel", - "model_module_version": "1.0.0", - "state": { - "_dom_classes": [], - "_model_module": "@jupyter-widgets/output", - "_model_module_version": "1.0.0", - "_model_name": "OutputModel", - "_view_count": null, - "_view_module": "@jupyter-widgets/output", - "_view_module_version": "1.0.0", - "_view_name": "OutputView", - "layout": "IPY_MODEL_646a8670cb204a31bb56bc2380898093", - "msg_id": "", - "outputs": [], - "tabbable": null, - "tooltip": null - } - }, - "423bffea3a1c42b49a9ad71218e5811b": { + "06f2374f91c8455bb63252092512f2ed": { "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", "model_module_version": "2.0.0", + "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", @@ -663,10 +589,10 @@ "width": null } }, - "06f2374f91c8455bb63252092512f2ed": { + "423bffea3a1c42b49a9ad71218e5811b": { "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", "model_module_version": "2.0.0", + "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", @@ -718,8 +644,8 @@ }, "56ff19291e464d63b23e63b8e2ac9ea3": { "model_module": "@jupyter-widgets/controls", - "model_name": "SliderStyleModel", "model_module_version": "2.0.0", + "model_name": "SliderStyleModel", "state": { "_model_module": "@jupyter-widgets/controls", "_model_module_version": "2.0.0", @@ -734,8 +660,8 @@ }, "646a8670cb204a31bb56bc2380898093": { "model_module": "@jupyter-widgets/base", - "model_name": "LayoutModel", "model_module_version": "2.0.0", + "model_name": "LayoutModel", "state": { "_model_module": "@jupyter-widgets/base", "_model_module_version": "2.0.0", @@ -784,6 +710,82 @@ "visibility": null, "width": null } + }, + "7d46516469314b88be3500e2afcafcf6": { + "model_module": "@jupyter-widgets/output", + "model_module_version": "1.0.0", + "model_name": "OutputModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/output", + "_model_module_version": "1.0.0", + "_model_name": "OutputModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/output", + "_view_module_version": "1.0.0", + "_view_name": "OutputView", + "layout": "IPY_MODEL_646a8670cb204a31bb56bc2380898093", + "msg_id": "", + "outputs": [], + "tabbable": null, + "tooltip": null + } + }, + "8d003c14da5f4fa68284b28c15cee6e6": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "VBoxModel", + "state": { + "_dom_classes": [ + "widget-interact" + ], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "VBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "2.0.0", + "_view_name": "VBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_aef2fa7adcc14ad0854b73d5910ae3b4", + "IPY_MODEL_7d46516469314b88be3500e2afcafcf6" + ], + "layout": "IPY_MODEL_423bffea3a1c42b49a9ad71218e5811b", + "tabbable": null, + "tooltip": null + } + }, + "aef2fa7adcc14ad0854b73d5910ae3b4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "2.0.0", + "model_name": "FloatSliderModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "2.0.0", + "_model_name": "FloatSliderModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "2.0.0", + "_view_name": "FloatSliderView", + "behavior": "drag-tap", + "continuous_update": true, + "description": "t", + "description_allow_html": false, + "disabled": false, + "layout": "IPY_MODEL_06f2374f91c8455bb63252092512f2ed", + "max": 1.1333333333333333, + "min": 0, + "orientation": "horizontal", + "readout": true, + "readout_format": ".2f", + "step": 0.011333333333333332, + "style": "IPY_MODEL_56ff19291e464d63b23e63b8e2ac9ea3", + "tabbable": null, + "tooltip": null, + "value": 0 + } } } } diff --git a/examples/scripts/CMAES.py b/examples/scripts/CMAES.py deleted file mode 100644 index 65315b41e..000000000 --- a/examples/scripts/CMAES.py +++ /dev/null @@ -1,55 +0,0 @@ -import pybop -import numpy as np -import matplotlib.pyplot as plt - -parameter_set = pybop.ParameterSet("pybamm", "Chen2020") -model = pybop.lithium_ion.SPMe(parameter_set=parameter_set) - -# Fitting parameters -parameters = [ - pybop.Parameter( - "Negative electrode active material volume fraction", - prior=pybop.Gaussian(0.7, 0.05), - bounds=[0.6, 0.9], - ), - pybop.Parameter( - "Positive electrode active material volume fraction", - prior=pybop.Gaussian(0.58, 0.05), - bounds=[0.5, 0.8], - ), -] - -sigma = 0.001 -t_eval = np.arange(0, 900, 2) -values = model.predict(t_eval=t_eval) -CorruptValues = values["Terminal voltage [V]"].data + np.random.normal( - 0, sigma, len(t_eval) -) - -dataset = [ - pybop.Dataset("Time [s]", t_eval), - pybop.Dataset("Current function [A]", values["Current [A]"].data), - pybop.Dataset("Terminal voltage [V]", CorruptValues), -] - -# Generate problem, cost function, and optimisation class -problem = pybop.Problem(model, parameters, dataset) -cost = pybop.SumSquaredError(problem) -optim = pybop.Optimisation(cost, optimiser=pybop.CMAES) -optim.set_max_iterations(100) - -x, final_cost = optim.run() -print("Estimated parameters:", x) - -# Show the generated data -simulated_values = problem.evaluate(x) - -plt.figure(dpi=100) -plt.xlabel("Time", fontsize=12) -plt.ylabel("Values", fontsize=12) -plt.plot(t_eval, CorruptValues, label="Measured") -plt.fill_between(t_eval, simulated_values - sigma, simulated_values + sigma, alpha=0.2) -plt.plot(t_eval, simulated_values, label="Simulated") -plt.legend(bbox_to_anchor=(0.6, 1), loc="upper left", fontsize=12) -plt.tick_params(axis="both", labelsize=12) -plt.show() diff --git a/examples/scripts/ecm_CMAES.py b/examples/scripts/ecm_CMAES.py new file mode 100644 index 000000000..d60a8a8c8 --- /dev/null +++ b/examples/scripts/ecm_CMAES.py @@ -0,0 +1,101 @@ +import pybop +import numpy as np + +# Import the ECM parameter set from JSON +params = pybop.ParameterSet( + json_path="examples/scripts/parameters/initial_ecm_parameters.json" +) + +# Alternatively, define the initial parameter set with a dictionary +# Add definitions for R's, C's, and initial overpotentials for any additional RC elements +# params = pybop.ParameterSet( +# params_dict={ +# "chemistry": "ecm", +# "Initial SoC": 0.5, +# "Initial temperature [K]": 25 + 273.15, +# "Cell capacity [A.h]": 5, +# "Nominal cell capacity [A.h]": 5, +# "Ambient temperature [K]": 25 + 273.15, +# "Current function [A]": 5, +# "Upper voltage cut-off [V]": 4.2, +# "Lower voltage cut-off [V]": 3.0, +# "Cell thermal mass [J/K]": 1000, +# "Cell-jig heat transfer coefficient [W/K]": 10, +# "Jig thermal mass [J/K]": 500, +# "Jig-air heat transfer coefficient [W/K]": 10, +# "Open-circuit voltage [V]": pybop.empirical.Thevenin().default_parameter_values[ +# "Open-circuit voltage [V]" +# ], +# "R0 [Ohm]": 0.001, +# "Element-1 initial overpotential [V]": 0, +# "Element-2 initial overpotential [V]": 0, +# "R1 [Ohm]": 0.0002, +# "R2 [Ohm]": 0.0003, +# "C1 [F]": 10000, +# "C2 [F]": 5000, +# "Entropic change [V/K]": 0.0004, +# } +# ) + +# Define the model +model = pybop.empirical.Thevenin( + parameter_set=params.import_parameters(), options={"number of rc elements": 2} +) + +# Fitting parameters +parameters = [ + pybop.Parameter( + "R0 [Ohm]", + prior=pybop.Gaussian(0.0002, 0.0001), + bounds=[1e-4, 1e-2], + ), + pybop.Parameter( + "R1 [Ohm]", + prior=pybop.Gaussian(0.0001, 0.0001), + bounds=[1e-5, 1e-2], + ), +] + +sigma = 0.001 +t_eval = np.arange(0, 900, 2) +values = model.predict(t_eval=t_eval) +corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval)) + +# Form dataset +dataset = pybop.Dataset( + { + "Time [s]": t_eval, + "Current function [A]": values["Current [A]"].data, + "Voltage [V]": corrupt_values, + } +) + +# Generate problem, cost function, and optimisation class +problem = pybop.FittingProblem(model, parameters, dataset) +cost = pybop.SumSquaredError(problem) +optim = pybop.Optimisation(cost, optimiser=pybop.CMAES) +optim.set_max_iterations(100) + +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Export the parameters to JSON +params.export_parameters( + "examples/scripts/parameters/fit_ecm_parameters.json", fit_params=parameters +) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path and updated bounds +bounds = np.array([[1e-4, 1e-2], [1e-5, 1e-2]]) +pybop.plot_cost2d(cost, optim=optim, bounds=bounds, steps=15) diff --git a/examples/scripts/parameters/initial_ecm_parameters.json b/examples/scripts/parameters/initial_ecm_parameters.json new file mode 100644 index 000000000..8da710968 --- /dev/null +++ b/examples/scripts/parameters/initial_ecm_parameters.json @@ -0,0 +1,24 @@ +{ + "chemistry": "ecm", + "Initial SoC": 0.5, + "Initial temperature [K]": 298.15, + "Cell capacity [A.h]": 5, + "Nominal cell capacity [A.h]": 5, + "Ambient temperature [K]": 298.15, + "Current function [A]": 5, + "Upper voltage cut-off [V]": 4.2, + "Lower voltage cut-off [V]": 3.0, + "Cell thermal mass [J/K]": 1000, + "Cell-jig heat transfer coefficient [W/K]": 10, + "Jig thermal mass [J/K]": 500, + "Jig-air heat transfer coefficient [W/K]": 10, + "Open-circuit voltage [V]": "default", + "R0 [Ohm]": 0.001, + "Element-1 initial overpotential [V]": 0, + "Element-2 initial overpotential [V]": 0, + "R1 [Ohm]": 0.0002, + "R2 [Ohm]": 0.0003, + "C1 [F]": 10000, + "C2 [F]": 5000, + "Entropic change [V/K]": 0.0004 +} diff --git a/examples/scripts/spm_CMAES.py b/examples/scripts/spm_CMAES.py new file mode 100644 index 000000000..63aa0cc65 --- /dev/null +++ b/examples/scripts/spm_CMAES.py @@ -0,0 +1,61 @@ +import pybop +import numpy as np + +# Define model +parameter_set = pybop.ParameterSet.pybamm("Chen2020") +model = pybop.lithium_ion.SPM(parameter_set=parameter_set) + +# Fitting parameters +parameters = [ + pybop.Parameter( + "Negative electrode active material volume fraction", + prior=pybop.Gaussian(0.7, 0.05), + bounds=[0.6, 0.9], + ), + pybop.Parameter( + "Positive electrode active material volume fraction", + prior=pybop.Gaussian(0.58, 0.05), + bounds=[0.5, 0.8], + ), +] + +# Generate data +sigma = 0.001 +t_eval = np.arange(0, 900, 2) +values = model.predict(t_eval=t_eval) +corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval)) + +# Form dataset +dataset = pybop.Dataset( + { + "Time [s]": t_eval, + "Current function [A]": values["Current [A]"].data, + "Voltage [V]": corrupt_values, + } +) + +# Generate problem, cost function, and optimisation class +problem = pybop.FittingProblem(model, parameters, dataset) +cost = pybop.SumSquaredError(problem) +optim = pybop.Optimisation(cost, optimiser=pybop.CMAES) +optim.set_max_iterations(100) + +# Run the optimisation +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path and updated bounds +bounds = np.array([[0.6, 0.9], [0.5, 0.8]]) +pybop.plot_cost2d(cost, optim=optim, bounds=bounds, steps=15) diff --git a/examples/scripts/spm_IRPropMin.py b/examples/scripts/spm_IRPropMin.py new file mode 100644 index 000000000..b764184d3 --- /dev/null +++ b/examples/scripts/spm_IRPropMin.py @@ -0,0 +1,58 @@ +import pybop +import numpy as np + +# Define model +parameter_set = pybop.ParameterSet.pybamm("Chen2020") +model = pybop.lithium_ion.SPM(parameter_set=parameter_set) + +# Fitting parameters +parameters = [ + pybop.Parameter( + "Negative electrode active material volume fraction", + prior=pybop.Gaussian(0.7, 0.05), + bounds=[0.6, 0.9], + ), + pybop.Parameter( + "Positive electrode active material volume fraction", + prior=pybop.Gaussian(0.58, 0.05), + bounds=[0.5, 0.8], + ), +] + +sigma = 0.001 +t_eval = np.arange(0, 900, 2) +values = model.predict(t_eval=t_eval) +corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval)) + +# Form dataset +dataset = pybop.Dataset( + { + "Time [s]": t_eval, + "Current function [A]": values["Current [A]"].data, + "Voltage [V]": corrupt_values, + } +) + +# Generate problem, cost function, and optimisation class +problem = pybop.FittingProblem(model, parameters, dataset) +cost = pybop.SumSquaredError(problem) +optim = pybop.Optimisation(cost, optimiser=pybop.IRPropMin) +optim.set_max_iterations(100) + +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path +pybop.plot_cost2d(cost, optim=optim, steps=15) diff --git a/examples/scripts/spm_SNES.py b/examples/scripts/spm_SNES.py new file mode 100644 index 000000000..cc5995a99 --- /dev/null +++ b/examples/scripts/spm_SNES.py @@ -0,0 +1,57 @@ +import pybop +import numpy as np + +# Define model +parameter_set = pybop.ParameterSet.pybamm("Chen2020") +model = pybop.lithium_ion.SPM(parameter_set=parameter_set) + +# Fitting parameters +parameters = [ + pybop.Parameter( + "Negative electrode active material volume fraction", + prior=pybop.Gaussian(0.7, 0.05), + bounds=[0.6, 0.9], + ), + pybop.Parameter( + "Positive electrode active material volume fraction", + prior=pybop.Gaussian(0.58, 0.05), + bounds=[0.5, 0.8], + ), +] + +sigma = 0.001 +t_eval = np.arange(0, 900, 2) +values = model.predict(t_eval=t_eval) +corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval)) + +dataset = pybop.Dataset( + { + "Time [s]": t_eval, + "Current function [A]": values["Current [A]"].data, + "Voltage [V]": corrupt_values, + } +) + +# Generate problem, cost function, and optimisation class +problem = pybop.FittingProblem(model, parameters, dataset) +cost = pybop.SumSquaredError(problem) +optim = pybop.Optimisation(cost, optimiser=pybop.SNES) +optim.set_max_iterations(100) + +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path +pybop.plot_cost2d(cost, optim=optim, steps=15) diff --git a/examples/scripts/spm_XNES.py b/examples/scripts/spm_XNES.py new file mode 100644 index 000000000..7f46a352e --- /dev/null +++ b/examples/scripts/spm_XNES.py @@ -0,0 +1,58 @@ +import pybop +import numpy as np + +# Define model +parameter_set = pybop.ParameterSet.pybamm("Chen2020") +model = pybop.lithium_ion.SPM(parameter_set=parameter_set) + +# Fitting parameters +parameters = [ + pybop.Parameter( + "Negative electrode active material volume fraction", + prior=pybop.Gaussian(0.7, 0.05), + bounds=[0.6, 0.9], + ), + pybop.Parameter( + "Positive electrode active material volume fraction", + prior=pybop.Gaussian(0.58, 0.05), + bounds=[0.5, 0.8], + ), +] + +sigma = 0.001 +t_eval = np.arange(0, 900, 2) +values = model.predict(t_eval=t_eval) +corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval)) + +# Form dataset +dataset = pybop.Dataset( + { + "Time [s]": t_eval, + "Current function [A]": values["Current [A]"].data, + "Voltage [V]": corrupt_values, + } +) + +# Generate problem, cost function, and optimisation class +problem = pybop.FittingProblem(model, parameters, dataset) +cost = pybop.SumSquaredError(problem) +optim = pybop.Optimisation(cost, optimiser=pybop.XNES) +optim.set_max_iterations(100) + +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path +pybop.plot_cost2d(cost, optim=optim, steps=15) diff --git a/examples/scripts/spm_adam.py b/examples/scripts/spm_adam.py new file mode 100644 index 000000000..fba51adb3 --- /dev/null +++ b/examples/scripts/spm_adam.py @@ -0,0 +1,60 @@ +import pybop +import numpy as np + +# Parameter set and model definition +parameter_set = pybop.ParameterSet.pybamm("Chen2020") +model = pybop.lithium_ion.SPMe(parameter_set=parameter_set) + +# Fitting parameters +parameters = [ + pybop.Parameter( + "Negative electrode active material volume fraction", + prior=pybop.Gaussian(0.7, 0.05), + bounds=[0.6, 0.9], + ), + pybop.Parameter( + "Positive electrode active material volume fraction", + prior=pybop.Gaussian(0.58, 0.05), + bounds=[0.5, 0.8], + ), +] + +# Generate data +sigma = 0.001 +t_eval = np.arange(0, 900, 2) +values = model.predict(t_eval=t_eval) +corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval)) + +# Form dataset +dataset = pybop.Dataset( + { + "Time [s]": t_eval, + "Current function [A]": values["Current [A]"].data, + "Voltage [V]": corrupt_values, + } +) + +# Generate problem, cost function, and optimisation class +problem = pybop.FittingProblem(model, parameters, dataset) +cost = pybop.SumSquaredError(problem) +optim = pybop.Optimisation(cost, optimiser=pybop.Adam) +optim.set_max_iterations(100) + +# Run optimisation +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path +pybop.plot_cost2d(cost, optim=optim, steps=15) diff --git a/examples/scripts/spm_descent.py b/examples/scripts/spm_descent.py index 85f77f262..4f7ddf572 100644 --- a/examples/scripts/spm_descent.py +++ b/examples/scripts/spm_descent.py @@ -1,9 +1,8 @@ import pybop import numpy as np -import matplotlib.pyplot as plt # Parameter set and model definition -parameter_set = pybop.ParameterSet("pybamm", "Chen2020") +parameter_set = pybop.ParameterSet.pybamm("Chen2020") model = pybop.lithium_ion.SPMe(parameter_set=parameter_set) # Fitting parameters @@ -24,19 +23,19 @@ sigma = 0.001 t_eval = np.arange(0, 900, 2) values = model.predict(t_eval=t_eval) -corrupt_values = values["Terminal voltage [V]"].data + np.random.normal( - 0, sigma, len(t_eval) +corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval)) + +# Form dataset +dataset = pybop.Dataset( + { + "Time [s]": t_eval, + "Current function [A]": values["Current [A]"].data, + "Voltage [V]": corrupt_values, + } ) -# Dataset definition -dataset = [ - pybop.Dataset("Time [s]", t_eval), - pybop.Dataset("Current function [A]", values["Current [A]"].data), - pybop.Dataset("Terminal voltage [V]", corrupt_values), -] - # Generate problem, cost function, and optimisation class -problem = pybop.Problem(model, parameters, dataset) +problem = pybop.FittingProblem(model, parameters, dataset) cost = pybop.SumSquaredError(problem) optim = pybop.Optimisation(cost, optimiser=pybop.GradientDescent) optim.optimiser.set_learning_rate(0.025) @@ -46,15 +45,17 @@ x, final_cost = optim.run() print("Estimated parameters:", x) -# Show the generated data -simulated_values = problem.evaluate(x) - -plt.figure(dpi=100) -plt.xlabel("Time", fontsize=12) -plt.ylabel("Values", fontsize=12) -plt.plot(t_eval, corrupt_values, label="Measured") -plt.fill_between(t_eval, simulated_values - sigma, simulated_values + sigma, alpha=0.2) -plt.plot(t_eval, simulated_values, label="Simulated") -plt.legend(bbox_to_anchor=(0.6, 1), loc="upper left", fontsize=12) -plt.tick_params(axis="both", labelsize=12) -plt.show() +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path +pybop.plot_cost2d(cost, optim=optim, steps=15) diff --git a/examples/scripts/spm_nlopt.py b/examples/scripts/spm_nlopt.py index 19401ed45..7ba0acd8b 100644 --- a/examples/scripts/spm_nlopt.py +++ b/examples/scripts/spm_nlopt.py @@ -1,17 +1,18 @@ import pybop import pandas as pd -import matplotlib.pyplot as plt # Form dataset Measurements = pd.read_csv("examples/scripts/Chen_example.csv", comment="#").to_numpy() -dataset = [ - pybop.Dataset("Time [s]", Measurements[:, 0]), - pybop.Dataset("Current function [A]", Measurements[:, 1]), - pybop.Dataset("Terminal voltage [V]", Measurements[:, 2]), -] +dataset = pybop.Dataset( + { + "Time [s]": Measurements[:, 0], + "Current function [A]": Measurements[:, 1], + "Voltage [V]": Measurements[:, 2], + } +) # Define model -parameter_set = pybop.ParameterSet("pybamm", "Chen2020") +parameter_set = pybop.ParameterSet.pybamm("Chen2020") model = pybop.models.lithium_ion.SPM( parameter_set=parameter_set, options={"thermal": "lumped"} ) @@ -31,23 +32,28 @@ ] # Define the cost to optimise -signal = "Terminal voltage [V]" -problem = pybop.Problem(model, parameters, dataset, signal=signal, init_soc=0.98) +signal = ["Voltage [V]"] +problem = pybop.FittingProblem(model, parameters, dataset, signal=signal, init_soc=0.98) cost = pybop.RootMeanSquaredError(problem) # Build the optimisation problem -parameterisation = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize) +optim = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize) # Run the optimisation problem -x, final_cost = parameterisation.run() - -# Show the generated data -simulated_values = problem.evaluate(x) - -plt.figure() -plt.xlabel("Time") -plt.ylabel("Values") -plt.plot(dataset[0].data, dataset[2].data, label="Measured") -plt.plot(dataset[0].data, simulated_values, label="Simulated") -plt.legend(bbox_to_anchor=(0.6, 1), loc="upper left", fontsize=12) -plt.show() +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path +pybop.plot_cost2d(cost, optim=optim, steps=15) diff --git a/examples/scripts/spm_pso.py b/examples/scripts/spm_pso.py new file mode 100644 index 000000000..fd55552d1 --- /dev/null +++ b/examples/scripts/spm_pso.py @@ -0,0 +1,58 @@ +import pybop +import numpy as np + +# Define model +parameter_set = pybop.ParameterSet.pybamm("Chen2020") +model = pybop.lithium_ion.SPM(parameter_set=parameter_set) + +# Fitting parameters +parameters = [ + pybop.Parameter( + "Negative electrode active material volume fraction", + prior=pybop.Gaussian(0.7, 0.05), + bounds=[0.6, 0.9], + ), + pybop.Parameter( + "Positive electrode active material volume fraction", + prior=pybop.Gaussian(0.58, 0.05), + bounds=[0.5, 0.8], + ), +] + +sigma = 0.001 +t_eval = np.arange(0, 900, 2) +values = model.predict(t_eval=t_eval) +corrupt_values = values["Voltage [V]"].data + np.random.normal(0, sigma, len(t_eval)) + +# Form dataset +dataset = pybop.Dataset( + { + "Time [s]": t_eval, + "Current function [A]": values["Current [A]"].data, + "Voltage [V]": corrupt_values, + } +) + +# Generate problem, cost function, and optimisation class +problem = pybop.FittingProblem(model, parameters, dataset) +cost = pybop.SumSquaredError(problem) +optim = pybop.Optimisation(cost, optimiser=pybop.PSO) +optim.set_max_iterations(100) + +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path +pybop.plot_cost2d(cost, optim=optim, steps=15) diff --git a/examples/scripts/spm_scipymin.py b/examples/scripts/spm_scipymin.py new file mode 100644 index 000000000..af81b6c2f --- /dev/null +++ b/examples/scripts/spm_scipymin.py @@ -0,0 +1,59 @@ +import pybop +import pandas as pd + +# Form dataset +Measurements = pd.read_csv("examples/scripts/Chen_example.csv", comment="#").to_numpy() +dataset = pybop.Dataset( + { + "Time [s]": Measurements[:, 0], + "Current function [A]": Measurements[:, 1], + "Voltage [V]": Measurements[:, 2], + } +) + +# Define model +parameter_set = pybop.ParameterSet.pybamm("Chen2020") +model = pybop.models.lithium_ion.SPM( + parameter_set=parameter_set, options={"thermal": "lumped"} +) + +# Fitting parameters +parameters = [ + pybop.Parameter( + "Negative electrode active material volume fraction", + prior=pybop.Gaussian(0.75, 0.05), + bounds=[0.6, 0.9], + ), + pybop.Parameter( + "Positive electrode active material volume fraction", + prior=pybop.Gaussian(0.65, 0.05), + bounds=[0.5, 0.8], + ), +] + +# Define the cost to optimise +signal = ["Voltage [V]"] +problem = pybop.FittingProblem(model, parameters, dataset, signal=signal, init_soc=0.98) +cost = pybop.RootMeanSquaredError(problem) + +# Build the optimisation problem +optim = pybop.Optimisation(cost=cost, optimiser=pybop.SciPyMinimize) + +# Run the optimisation problem +x, final_cost = optim.run() +print("Estimated parameters:", x) + +# Plot the timeseries output +pybop.quick_plot(x, cost, title="Optimised Comparison") + +# Plot convergence +pybop.plot_convergence(optim) + +# Plot the parameter traces +pybop.plot_parameters(optim) + +# Plot the cost landscape +pybop.plot_cost2d(cost, steps=15) + +# Plot the cost landscape with optimisation path +pybop.plot_cost2d(cost, optim=optim, steps=15) diff --git a/noxfile.py b/noxfile.py index c88e483e4..ddb7bd191 100644 --- a/noxfile.py +++ b/noxfile.py @@ -6,21 +6,61 @@ @nox.session def unit(session): - session.run_always("pip", "install", "-e", ".") - session.install("pytest") - session.run("pytest", "--unit", "-v") + session.run_always("pip", "install", "-e", ".[all]") + session.install("pytest", "pytest-mock") + session.run("pytest", "--unit") @nox.session def coverage(session): - session.run_always("pip", "install", "-e", ".") - session.install("pytest-cov") - session.run("pytest", "--unit", "-v", "--cov", "--cov-report=xml") + session.run_always("pip", "install", "-e", ".[all]") + session.install("pytest", "pytest-cov", "pytest-mock") + session.run( + "pytest", + "--unit", + "--examples", + "--cov", + "--cov-report=xml", + ) @nox.session def notebooks(session): """Run the examples tests for Jupyter notebooks.""" - session.run_always("pip", "install", "-e", ".") + session.run_always("pip", "install", "-e", ".[all]") session.install("pytest", "nbmake") - session.run("pytest", "--nbmake", "examples/", external=True) + session.run("pytest", "--nbmake", "--examples", "examples/", external=True) + + +@nox.session +def docs(session): + """ + Build the documentation and load it in a browser tab, rebuilding on changes. + Credit: PyBaMM Team + """ + envbindir = session.bin + session.install("-e", ".[all,docs]") + session.chdir("docs") + # Local development + if session.interactive: + session.run( + "sphinx-autobuild", + "-j", + "auto", + "--open-browser", + "-qT", + ".", + f"{envbindir}/../tmp/html", + ) + # Runs in CI only, treating warnings as errors + else: + session.run( + "sphinx-build", + "-j", + "auto", + "-b", + "html", + "--keep-going", + ".", + "_build/html", + ) diff --git a/pybop/__init__.py b/pybop/__init__.py index 29dcd88b1..9c9a23e11 100644 --- a/pybop/__init__.py +++ b/pybop/__init__.py @@ -26,48 +26,61 @@ # # Cost function class # -from .costs.error_costs import BaseCost, RootMeanSquaredError, SumSquaredError +from ._costs import BaseCost, RootMeanSquaredError, SumSquaredError # # Dataset class # -from .datasets.base_dataset import Dataset +from ._dataset import Dataset # # Model classes # from .models.base_model import BaseModel from .models import lithium_ion +from .models import empirical # # Main optimisation class # -from .optimisation import Optimisation +from ._optimisation import Optimisation # # Optimiser class # from .optimisers.base_optimiser import BaseOptimiser from .optimisers.nlopt_optimize import NLoptOptimize -from .optimisers.scipy_minimize import SciPyMinimize -from .optimisers.pints_optimisers import GradientDescent, CMAES +from .optimisers.scipy_optimisers import SciPyMinimize, SciPyDifferentialEvolution +from .optimisers.pints_optimisers import ( + GradientDescent, + Adam, + CMAES, + IRPropMin, + PSO, + SNES, + XNES, +) # # Parameter classes # -from .parameters.base_parameter import Parameter -from .parameters.base_parameter_set import ParameterSet +from .parameters.parameter import Parameter +from .parameters.parameter_set import ParameterSet from .parameters.priors import Gaussian, Uniform, Exponential # # Problem class # -from ._problem import Problem +from ._problem import FittingProblem, DesignProblem # # Plotting class # -from .plotting.quick_plot import QuickPlot +from .plotting.plot_cost2d import plot_cost2d +from .plotting.quick_plot import StandardPlot, quick_plot +from .plotting.plot_convergence import plot_convergence +from .plotting.plot_parameters import plot_parameters +from .plotting.plotly_manager import PlotlyManager # # Remove any imported modules, so we don't expose them as part of pybop diff --git a/pybop/_costs.py b/pybop/_costs.py new file mode 100644 index 000000000..71ae6c980 --- /dev/null +++ b/pybop/_costs.py @@ -0,0 +1,229 @@ +import numpy as np + + +class BaseCost: + """ + Base class for defining cost functions. + + This class is intended to be subclassed to create specific cost functions + for evaluating model predictions against a set of data. The cost function + quantifies the goodness-of-fit between the model predictions and the + observed data, with a lower cost value indicating a better fit. + + Parameters + ---------- + problem : object + A problem instance containing the data and functions necessary for + evaluating the cost function. + _target : array-like + An array containing the target data to fit. + x0 : array-like + The initial guess for the model parameters. + bounds : tuple + The bounds for the model parameters. + n_parameters : int + The number of parameters in the model. + """ + + def __init__(self, problem): + self.problem = problem + if problem is not None: + self._target = problem._target + self.x0 = problem.x0 + self.bounds = problem.bounds + self.n_parameters = problem.n_parameters + + def __call__(self, x, grad=None): + """ + Calculate the cost function value for a given set of parameters. + + This method must be implemented by subclasses. + + Parameters + ---------- + x : array-like + The parameters for which to evaluate the cost. + grad : array-like, optional + An array to store the gradient of the cost function with respect + to the parameters. + + Returns + ------- + float + The calculated cost function value. + + Raises + ------ + NotImplementedError + If the method has not been implemented by the subclass. + """ + + raise NotImplementedError + + +class RootMeanSquaredError(BaseCost): + """ + Root mean square error cost function. + + Computes the root mean square error between model predictions and the target + data, providing a measure of the differences between predicted values and + observed values. + + Inherits all parameters and attributes from ``BaseCost``. + + """ + + def __init__(self, problem): + super(RootMeanSquaredError, self).__init__(problem) + + def __call__(self, x, grad=None): + """ + Calculate the root mean square error for a given set of parameters. + + Parameters + ---------- + x : array-like + The parameters for which to evaluate the cost. + grad : array-like, optional + An array to store the gradient of the cost function with respect + to the parameters. + + Returns + ------- + float + The root mean square error. + + Raises + ------ + ValueError + If an error occurs during the calculation of the cost. + """ + + try: + prediction = self.problem.evaluate(x) + + if len(prediction) < len(self._target): + return np.float64(np.inf) # simulation stopped early + else: + return np.sqrt(np.mean((prediction - self._target) ** 2)) + + except Exception as e: + raise ValueError(f"Error in cost calculation: {e}") + + +class SumSquaredError(BaseCost): + """ + Sum of squared errors cost function. + + Computes the sum of the squares of the differences between model predictions + and target data, which serves as a measure of the total error between the + predicted and observed values. + + Inherits all parameters and attributes from ``BaseCost``. + + Additional Attributes + --------------------- + _de : float + The gradient of the cost function to use if an error occurs during + evaluation. Defaults to 1.0. + + """ + + def __init__(self, problem): + super(SumSquaredError, self).__init__(problem) + + # Default fail gradient + self._de = 1.0 + + def __call__(self, x, grad=None): + """ + Calculate the sum of squared errors for a given set of parameters. + + Parameters + ---------- + x : array-like + The parameters for which to evaluate the cost. + grad : array-like, optional + An array to store the gradient of the cost function with respect + to the parameters. + + Returns + ------- + float + The sum of squared errors. + + Raises + ------ + ValueError + If an error occurs during the calculation of the cost. + """ + try: + prediction = self.problem.evaluate(x) + + if len(prediction) < len(self._target): + return np.float64(np.inf) # simulation stopped early + else: + return np.sum( + (np.sum(((prediction - self._target) ** 2), axis=0)), + axis=0, + ) + + except Exception as e: + raise ValueError(f"Error in cost calculation: {e}") + + def evaluateS1(self, x): + """ + Compute the cost and its gradient with respect to the parameters. + + Parameters + ---------- + x : array-like + The parameters for which to compute the cost and gradient. + + Returns + ------- + tuple + A tuple containing the cost and the gradient. The cost is a float, + and the gradient is an array-like of the same length as `x`. + + Raises + ------ + ValueError + If an error occurs during the calculation of the cost or gradient. + """ + try: + y, dy = self.problem.evaluateS1(x) + if len(y) < len(self._target): + e = np.float64(np.inf) + de = self._de * np.ones(self.problem.n_parameters) + else: + dy = dy.reshape( + ( + self.problem.n_time_data, + self.problem.n_outputs, + self.problem.n_parameters, + ) + ) + r = y - self._target + e = np.sum(np.sum(r**2, axis=0), axis=0) + de = 2 * np.sum(np.sum((r.T * dy.T), axis=2), axis=1) + + return e, de + + except Exception as e: + raise ValueError(f"Error in cost calculation: {e}") + + def set_fail_gradient(self, de): + """ + Set the fail gradient to a specified value. + + The fail gradient is used if an error occurs during the calculation + of the gradient. This method allows updating the default gradient value. + + Parameters + ---------- + de : float + The new fail gradient value to be used. + """ + de = float(de) + self._de = de diff --git a/pybop/_dataset.py b/pybop/_dataset.py new file mode 100644 index 000000000..1263ace3e --- /dev/null +++ b/pybop/_dataset.py @@ -0,0 +1,66 @@ +import pybamm + + +class Dataset: + """ + Represents a collection of experimental observations. + + This class provides a structured way to store and work with experimental data, + which may include applying operations such as interpolation. + + Parameters + ---------- + name : str + The name of the dataset, providing a label for identification. + data : array-like + The actual experimental data, typically in a structured form such as + a NumPy array or a pandas DataFrame. + + """ + + def __init__(self, data_dictionary): + """ + Initialize a Dataset instance with a name and data. + + Parameters + ---------- + data_dictionary : dict or instance of pybamm.solvers.solution.Solution + The experimental data to store within the dataset. + """ + + if isinstance(data_dictionary, pybamm.solvers.solution.Solution): + data_dictionary = data_dictionary.get_data_dict() + if not isinstance(data_dictionary, dict): + raise ValueError("The input to pybop.Dataset must be a dictionary.") + self.data = data_dictionary + self.names = self.data.keys() + + def __repr__(self): + """ + Return a string representation of the Dataset instance. + + Returns + ------- + str + A string that includes the type and contents of the dataset. + """ + return f"Dataset: {type(self.data)} \n Contains: {self.names}" + + def Interpolant(self): + """ + Create an interpolation function of the dataset based on the independent variable. + + Currently, only time-based interpolation is supported. This method modifies + the instance's Interpolant attribute to be an interpolation function that + can be evaluated at different points in time. + + Raises + ------ + NotImplementedError + If the independent variable for interpolation is not supported. + """ + + if self.variable == "time": + self.Interpolant = pybamm.Interpolant(self.x, self.y, pybamm.t) + else: + NotImplementedError("Only time interpolation is supported") diff --git a/pybop/optimisation.py b/pybop/_optimisation.py similarity index 70% rename from pybop/optimisation.py rename to pybop/_optimisation.py index 6dc947de7..8052298da 100644 --- a/pybop/optimisation.py +++ b/pybop/_optimisation.py @@ -5,14 +5,31 @@ class Optimisation: """ - Optimisation class for PyBOP. - This class provides functionality for PyBOP optimisers and Pints optimisers. - args: - cost: PyBOP cost function - optimiser: A PyBOP or Pints optimiser - sigma0: initial step size - verbose: print optimisation progress - + A class for conducting optimization using PyBOP or PINTS optimisers. + + Parameters + ---------- + cost : pybop.BaseCost or pints.ErrorMeasure + An objective function to be optimized, which can be either a pybop.Cost or PINTS error measure + optimiser : pybop.Optimiser or subclass of pybop.BaseOptimiser, optional + An optimiser from either the PINTS or PyBOP framework to perform the optimization (default: None). + sigma0 : float or sequence, optional + Initial step size or standard deviation for the optimiser (default: None). + verbose : bool, optional + If True, the optimization progress is printed (default: False). + + Attributes + ---------- + x0 : numpy.ndarray + Initial parameter values for the optimization. + bounds : dict + Dictionary containing the parameter bounds with keys 'lower' and 'upper'. + n_parameters : int + Number of parameters in the optimization problem. + sigma0 : float or sequence + Initial step size or standard deviation for the optimiser. + log : list + Log of the optimization process. """ def __init__( @@ -58,7 +75,9 @@ def __init__( if issubclass(self.optimiser, pybop.NLoptOptimize): self.optimiser = self.optimiser(self.n_parameters) - elif issubclass(self.optimiser, pybop.SciPyMinimize): + elif issubclass( + self.optimiser, (pybop.SciPyMinimize, pybop.SciPyDifferentialEvolution) + ): self.optimiser = self.optimiser() else: @@ -104,11 +123,14 @@ def __init__( def run(self): """ - Run the optimisation algorithm. - Selects between PyBOP backend or Pints backend. - returns: - x: best parameters - final_cost: final cost + Run the optimization and return the optimized parameters and final cost. + + Returns + ------- + x : numpy.ndarray + The best parameter set found by the optimization. + final_cost : float + The final cost associated with the best parameters. """ if self.pints: @@ -116,29 +138,47 @@ def run(self): elif not self.pints: x, final_cost = self._run_pybop() + # Store the optimised parameters + if self.cost.problem is not None: + self.store_optimised_parameters(x) + return x, final_cost def _run_pybop(self): """ - Run method for PyBOP based optimisers. - returns: - x: best parameters - final_cost: final cost + Internal method to run the optimization using a PyBOP optimiser. + + Returns + ------- + x : numpy.ndarray + The best parameter set found by the optimization. + final_cost : float + The final cost associated with the best parameters. """ x, final_cost = self.optimiser.optimise( cost_function=self.cost, x0=self.x0, bounds=self.bounds, + maxiter=self._max_iterations, ) + self.log = self.optimiser.log + return x, final_cost def _run_pints(self): """ - Run method for PINTS optimisers. + Internal method to run the optimization using a PINTS optimiser. + + Returns + ------- + x : numpy.ndarray + The best parameter set found by the optimization. + final_cost : float + The final cost associated with the best parameters. + + See Also + -------- This method is heavily based on the run method in the PINTS.OptimisationController class. - returns: - x: best parameters - final_cost: final cost """ # Check stopping criteria @@ -310,34 +350,37 @@ def _run_pints(self): def f_guessed_tracking(self): """ - Returns ``True`` if f_guessed instead of f_best is being tracked, - ``False`` otherwise. See also :meth:`set_f_guessed_tracking`. - + Check if f_guessed instead of f_best is being tracked. Credit: PINTS + + Returns + ------- + bool + True if f_guessed is being tracked, False otherwise. """ return self._use_f_guessed def set_f_guessed_tracking(self, use_f_guessed=False): """ - Sets the method used to track the optimiser progress to - :meth:`pints.Optimiser.f_guessed()` or - :meth:`pints.Optimiser.f_best()` (default). - - The tracked ``f`` value is used to evaluate stopping criteria. - + Set the method used to track the optimiser progress. Credit: PINTS + + Parameters + ---------- + use_f_guessed : bool, optional + If True, track f_guessed; otherwise, track f_best (default: False). """ self._use_f_guessed = bool(use_f_guessed) def set_max_evaluations(self, evaluations=None): """ - Adds a stopping criterion, allowing the routine to halt after the - given number of ``evaluations``. - - This criterion is disabled by default. To enable, pass in any positive - integer. To disable again, use ``set_max_evaluations(None)``. - + Set a maximum number of evaluations stopping criterion. Credit: PINTS + + Parameters + ---------- + evaluations : int, optional + The maximum number of evaluations after which to stop the optimization (default: None). """ if evaluations is not None: evaluations = int(evaluations) @@ -347,16 +390,14 @@ def set_max_evaluations(self, evaluations=None): def set_parallel(self, parallel=False): """ - Enables/disables parallel evaluation. - - If ``parallel=True``, the method will run using a number of worker - processes equal to the detected cpu core count. The number of workers - can be set explicitly by setting ``parallel`` to an integer greater - than 0. - Parallelisation can be disabled by setting ``parallel`` to ``0`` or - ``False``. - + Enable or disable parallel evaluation. Credit: PINTS + + Parameters + ---------- + parallel : bool or int, optional + If True, use as many worker processes as there are CPU cores. If an integer, use that many workers. + If False or 0, disable parallelism (default: False). """ if parallel is True: self._parallel = True @@ -368,15 +409,16 @@ def set_parallel(self, parallel=False): self._parallel = False self._n_workers = 1 - def set_max_iterations(self, iterations=10000): + def set_max_iterations(self, iterations=1000): """ - Adds a stopping criterion, allowing the routine to halt after the - given number of ``iterations``. - - This criterion is enabled by default. To disable it, use - ``set_max_iterations(None)``. - + Set the maximum number of iterations as a stopping criterion. Credit: PINTS + + Parameters + ---------- + iterations : int, optional + The maximum number of iterations to run (default is 1000). + Set to `None` to remove this stopping criterion. """ if iterations is not None: iterations = int(iterations) @@ -384,16 +426,18 @@ def set_max_iterations(self, iterations=10000): raise ValueError("Maximum number of iterations cannot be negative.") self._max_iterations = iterations - def set_max_unchanged_iterations(self, iterations=200, threshold=1e-11): + def set_max_unchanged_iterations(self, iterations=25, threshold=1e-5): """ - Adds a stopping criterion, allowing the routine to halt if the - objective function doesn't change by more than ``threshold`` for the - given number of ``iterations``. - - This criterion is enabled by default. To disable it, use - ``set_max_unchanged_iterations(None)``. - + Set the maximum number of iterations without significant change as a stopping criterion. Credit: PINTS + + Parameters + ---------- + iterations : int, optional + The maximum number of unchanged iterations to run (default is 25). + Set to `None` to remove this stopping criterion. + threshold : float, optional + The minimum significant change in the objective function value that resets the unchanged iteration counter (default is 1e-5). """ if iterations is not None: iterations = int(iterations) @@ -406,3 +450,17 @@ def set_max_unchanged_iterations(self, iterations=200, threshold=1e-11): self._unchanged_max_iterations = iterations self._unchanged_threshold = threshold + + def store_optimised_parameters(self, x): + """ + Update the problem parameters with optimized values. + + The optimized parameter values are stored within the associated PyBOP parameter class. + + Parameters + ---------- + x : array-like + Optimized parameter values. + """ + for i, param in enumerate(self.cost.problem.parameters): + param.update(value=x[i]) diff --git a/pybop/_problem.py b/pybop/_problem.py index 469b65047..ca5b7dd61 100644 --- a/pybop/_problem.py +++ b/pybop/_problem.py @@ -1,48 +1,47 @@ import numpy as np -class Problem: +class BaseProblem: """ - Defines a PyBOP single output problem, follows the PINTS interface. + Base class for defining a problem within the PyBOP framework, compatible with PINTS. + + Parameters + ---------- + parameters : list + List of parameters for the problem. + model : object, optional + The model to be used for the problem (default: None). + check_model : bool, optional + Flag to indicate if the model should be checked (default: True). + init_soc : float, optional + Initial state of charge (default: None). + x0 : np.ndarray, optional + Initial parameter values (default: None). """ def __init__( self, - model, parameters, - dataset, - signal="Terminal voltage [V]", + model=None, check_model=True, + signal=["Voltage [V]"], init_soc=None, x0=None, ): - self._model = model self.parameters = parameters - self.signal = signal - self._model.signal = self.signal - self._dataset = {o.name: o for o in dataset} + self._model = model self.check_model = check_model + if isinstance(signal, str): + signal = [signal] + elif not all(isinstance(item, str) for item in signal): + raise ValueError("Signal should be either a string or list of strings.") + self.signal = signal self.init_soc = init_soc self.x0 = x0 self.n_parameters = len(self.parameters) - self.n_outputs = len([self.signal]) - - # Check that the dataset contains time and current - for name in ["Time [s]", "Current function [A]", signal]: - if name not in self._dataset: - raise ValueError(f"expected {name} in list of dataset") - - self._time_data = self._dataset["Time [s]"].data - self.n_time_data = len(self._time_data) - self._target = self._dataset[signal].data - - if np.any(self._time_data < 0): - raise ValueError("Times can not be negative.") - if np.any(self._time_data[:-1] >= self._time_data[1:]): - raise ValueError("Times must be increasing.") - - if len(self._target) != len(self._time_data): - raise ValueError("Time data and signal data must be the same length.") + self.n_outputs = len(self.signal) + self._time_data = None + self._target = None # Set bounds self.bounds = dict( @@ -62,35 +61,230 @@ def __init__( for i, param in enumerate(self.parameters): param.update(value=self.x0[i]) - # Set the fitting parameters and build the model - self.fit_parameters = {o.name: o.value for o in parameters} + def evaluate(self, x): + """ + Evaluate the model with the given parameters and return the signal. + + Parameters + ---------- + x : np.ndarray + Parameter values to evaluate the model at. + + Raises + ------ + NotImplementedError + This method must be implemented by subclasses. + """ + raise NotImplementedError + + def evaluateS1(self, x): + """ + Evaluate the model with the given parameters and return the signal and its derivatives. + + Parameters + ---------- + x : np.ndarray + Parameter values to evaluate the model at. + + Raises + ------ + NotImplementedError + This method must be implemented by subclasses. + """ + raise NotImplementedError + + def time_data(self): + """ + Returns the time data. + + Returns + ------- + np.ndarray + The time array. + """ + return self._time_data + + def target(self): + """ + Return the target dataset. + + Returns + ------- + np.ndarray + The target dataset array. + """ + return self._target + + +class FittingProblem(BaseProblem): + """ + Problem class for fitting (parameter estimation) problems. + + Extends `BaseProblem` with specifics for fitting a model to a dataset. + + Parameters + ---------- + model : object + The model to fit. + parameters : list + List of parameters for the problem. + dataset : list + List of data objects to fit the model to. + signal : str, optional + The signal to fit (default: "Voltage [V]"). + """ + + def __init__( + self, + model, + parameters, + dataset, + check_model=True, + signal=["Voltage [V]"], + init_soc=None, + x0=None, + ): + super().__init__(parameters, model, check_model, signal, init_soc, x0) + self._dataset = dataset.data + + # Check that the dataset contains time and current + for name in ["Time [s]", "Current function [A]"] + self.signal: + if name not in self._dataset: + raise ValueError(f"expected {name} in list of dataset") + + self._time_data = self._dataset["Time [s]"] + self.n_time_data = len(self._time_data) + if np.any(self._time_data < 0): + raise ValueError("Times can not be negative.") + if np.any(self._time_data[:-1] >= self._time_data[1:]): + raise ValueError("Times must be increasing.") + + target = [self._dataset[signal] for signal in self.signal] + self._target = np.vstack(target).T + if self.n_outputs == 1: + if len(self._target) != self.n_time_data: + raise ValueError("Time data and target data must be the same length.") + else: + if self._target.shape != (self.n_time_data, self.n_outputs): + raise ValueError("Time data and target data must be the same shape.") + + # Add useful parameters to model + if model is not None: + self._model.signal = self.signal + self._model.n_outputs = self.n_outputs + self._model.n_time_data = self.n_time_data + + # Build the model if self._model._built_model is None: self._model.build( dataset=self._dataset, - fit_parameters=self.fit_parameters, + parameters=self.parameters, check_model=self.check_model, init_soc=self.init_soc, ) - def evaluate(self, parameters): + def evaluate(self, x): """ Evaluate the model with the given parameters and return the signal. + + Parameters + ---------- + x : np.ndarray + Parameter values to evaluate the model at. """ - y = np.asarray(self._model.simulate(inputs=parameters, t_eval=self._time_data)) + y = np.asarray(self._model.simulate(inputs=x, t_eval=self._time_data)) return y - def evaluateS1(self, parameters): + def evaluateS1(self, x): """ - Evaluate the model with the given parameters and return the signal and - its derivatives. + Evaluate the model with the given parameters and return the signal and its derivatives. + + Parameters + ---------- + x : np.ndarray + Parameter values to evaluate the model at. + """ + + y, dy = self._model.simulateS1( + inputs=x, + t_eval=self._time_data, + ) + + return (np.asarray(y), np.asarray(dy)) + + +class DesignProblem(BaseProblem): + """ + Problem class for design optimization problems. + + Extends `BaseProblem` with specifics for applying a model to an experimental design. + + Parameters + ---------- + model : object + The model to apply the design to. + parameters : list + List of parameters for the problem. + experiment : object + The experimental setup to apply the model to. + """ + + def __init__( + self, + model, + parameters, + experiment, + check_model=True, + signal=["Voltage [V]"], + init_soc=None, + x0=None, + ): + super().__init__(parameters, model, check_model, signal, init_soc, x0) + self.experiment = experiment + + # Build the model if required + if experiment is not None: + # Leave the build until later to apply the experiment + self._model.parameters = self.parameters + if self.parameters is not None: + self._model.fit_keys = [param.name for param in self.parameters] + + elif self._model._built_model is None: + self._model.build( + experiment=self.experiment, + parameters=self.parameters, + check_model=self.check_model, + init_soc=self.init_soc, + ) + + def evaluate(self, x): + """ + Evaluate the model with the given parameters and return the signal. + + Parameters + ---------- + x : np.ndarray + Parameter values to evaluate the model at. + """ + + y = np.asarray(self._model.simulate(inputs=x, t_eval=self._time_data)) + + return y + + def evaluateS1(self, x): + """ + Evaluate the model with the given parameters and return the signal and its derivatives. + + Parameters + ---------- + x : np.ndarray + Parameter values to evaluate the model at. """ - for i, key in enumerate(self.fit_parameters): - self.fit_parameters[key] = parameters[i] y, dy = self._model.simulateS1( - inputs=self.fit_parameters, + inputs=x, t_eval=self._time_data, ) diff --git a/pybop/costs/__init__.py b/pybop/costs/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/pybop/costs/error_costs.py b/pybop/costs/error_costs.py deleted file mode 100644 index 2c497d45b..000000000 --- a/pybop/costs/error_costs.py +++ /dev/null @@ -1,114 +0,0 @@ -import numpy as np - - -class BaseCost: - """ - Base class for defining cost functions. - This class computes a corresponding goodness-of-fit for a corresponding model prediction and dataset. - Lower cost values indicate a better fit. - """ - - def __init__(self, problem): - self.problem = problem - if problem is not None: - self._target = problem._target - self.x0 = problem.x0 - self.bounds = problem.bounds - self.n_parameters = problem.n_parameters - - def __call__(self, x, grad=None): - """ - Returns the cost function value and computes the cost. - """ - raise NotImplementedError - - -class RootMeanSquaredError(BaseCost): - """ - Defines the root mean square error cost function. - """ - - def __init__(self, problem): - super(RootMeanSquaredError, self).__init__(problem) - - def __call__(self, x, grad=None): - """ - Computes the cost. - """ - try: - prediction = self.problem.evaluate(x) - - if len(prediction) < len(self._target): - return np.float64(np.inf) # simulation stopped early - else: - return np.sqrt(np.mean((prediction - self._target) ** 2)) - - except Exception as e: - raise ValueError(f"Error in cost calculation: {e}") - - -class SumSquaredError(BaseCost): - """ - Defines the sum squared error cost function. - - The initial fail gradient is set equal to one, but this can be - changed at any time with :meth:`set_fail_gradient()`. - """ - - def __init__(self, problem): - super(SumSquaredError, self).__init__(problem) - - # Default fail gradient - self._de = 1.0 - - def __call__(self, x, grad=None): - """ - Computes the cost. - """ - try: - prediction = self.problem.evaluate(x) - - if len(prediction) < len(self._target): - return np.float64(np.inf) # simulation stopped early - else: - return np.sum( - (np.sum(((prediction - self._target) ** 2), axis=0)), - axis=0, - ) - - except Exception as e: - raise ValueError(f"Error in cost calculation: {e}") - - def evaluateS1(self, x): - """ - Compute the cost and corresponding - gradients with respect to the parameters. - """ - try: - y, dy = self.problem.evaluateS1(x) - if len(y) < len(self._target): - e = np.float64(np.inf) - de = self._de * np.ones(self.problem.n_parameters) - else: - dy = dy.reshape( - ( - self.problem.n_time_data, - self.problem.n_outputs, - self.problem.n_parameters, - ) - ) - r = y - self._target - e = np.sum(np.sum(r**2, axis=0), axis=0) - de = 2 * np.sum(np.sum((r.T * dy.T), axis=2), axis=1) - - return e, de - - except Exception as e: - raise ValueError(f"Error in cost calculation: {e}") - - def set_fail_gradient(self, de): - """ - Sets the fail gradient for this optimiser. - """ - de = float(de) - self._de = de diff --git a/pybop/costs/standalone.py b/pybop/costs/standalone.py deleted file mode 100644 index 197dcca5b..000000000 --- a/pybop/costs/standalone.py +++ /dev/null @@ -1,18 +0,0 @@ -import pybop -import numpy as np - - -class StandaloneCost(pybop.BaseCost): - def __init__(self, problem=None): - super().__init__(problem) - - self.x0 = np.array([4.2]) - self.n_parameters = len(self.x0) - - self.bounds = dict( - lower=[-1], - upper=[10], - ) - - def __call__(self, x, grad=None): - return x[0] ** 2 + 42 diff --git a/pybop/datasets/__init__.py b/pybop/datasets/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/pybop/datasets/base_dataset.py b/pybop/datasets/base_dataset.py deleted file mode 100644 index ed194ae48..000000000 --- a/pybop/datasets/base_dataset.py +++ /dev/null @@ -1,20 +0,0 @@ -import pybamm - - -class Dataset: - """ - Class for experimental observations. - """ - - def __init__(self, name, data): - self.name = name - self.data = data - - def __repr__(self): - return f"Dataset: {self.name} \n Data: {self.data}" - - def Interpolant(self): - if self.variable == "time": - self.Interpolant = pybamm.Interpolant(self.x, self.y, pybamm.t) - else: - NotImplementedError("Only time interpolation is supported") diff --git a/pybop/models/base_model.py b/pybop/models/base_model.py index ced38437e..6e679cb28 100644 --- a/pybop/models/base_model.py +++ b/pybop/models/base_model.py @@ -4,32 +4,59 @@ class BaseModel: """ - Base class for pybop models. + A base class for constructing and simulating models using PyBaMM. + + This class serves as a foundation for building specific models in PyBaMM. + It provides methods to set up the model, define parameters, and perform + simulations. The class is designed to be subclassed for creating models + with custom behavior. + """ def __init__(self, name="Base Model"): + """ + Initialize the BaseModel with an optional name. + + Parameters + ---------- + name : str, optional + The name given to the model instance. + """ self.name = name self.pybamm_model = None - self.fit_parameters = None + self.parameters = None self.dataset = None self.signal = None def build( self, dataset=None, - fit_parameters=None, + parameters=None, check_model=True, init_soc=None, ): """ - Build the PyBOP model (if not built already). - For PyBaMM forward models, this method follows a - similar process to pybamm.Simulation.build(). + Construct the PyBaMM model if not already built, and set parameters. + + This method initializes the model components, applies the given parameters, + sets up the mesh and discretization if needed, and prepares the model + for simulations. + + Parameters + ---------- + dataset : pybamm.Dataset, optional + The dataset to be used in the model construction. + parameters : dict, optional + A dictionary containing parameter values to apply to the model. + check_model : bool, optional + If True, the model will be checked for correctness after construction. + init_soc : float, optional + The initial state of charge to be used in simulations. """ - self.fit_parameters = fit_parameters self.dataset = dataset - if self.fit_parameters is not None: - self.fit_keys = list(self.fit_parameters.keys()) + self.parameters = parameters + if self.parameters is not None: + self.fit_keys = [param.name for param in self.parameters] if init_soc is not None: self.set_init_soc(init_soc) @@ -53,7 +80,12 @@ def build( def set_init_soc(self, init_soc): """ - Set the initial state of charge. + Set the initial state of charge for the battery model. + + Parameters + ---------- + init_soc : float + The initial state of charge to be used in the model. """ if self._built_initial_soc != init_soc: # reset @@ -73,21 +105,24 @@ def set_init_soc(self, init_soc): def set_params(self): """ - Set the parameters in the model. + Assign the parameters to the model. + + This method processes the model with the given parameters, sets up + the geometry, and updates the model instance. """ if self.model_with_set_params: return - if self.fit_parameters is not None: - # set input parameters in parameter set from fitting parameters - for i in self.fit_parameters.keys(): + # Mark any simulation inputs in the parameter set + if self.parameters is not None: + for i in self.fit_keys: self._parameter_set[i] = "[input]" - if self.dataset is not None and self.fit_parameters is not None: + if self.dataset is not None and self.parameters is not None: if "Current function [A]" not in self.fit_keys: self.parameter_set["Current function [A]"] = pybamm.Interpolant( - self.dataset["Time [s]"].data, - self.dataset["Current function [A]"].data, + self.dataset["Time [s]"], + self.dataset["Current function [A]"], pybamm.t, ) # Set t_eval @@ -101,63 +136,87 @@ def set_params(self): def simulate(self, inputs, t_eval): """ - Run the forward model and return the result in Numpy array format - aligning with Pints' ForwardModel simulate method. + Execute the forward model simulation and return the result. + + Parameters + ---------- + inputs : dict or array-like + The input parameters for the simulation. If array-like, it will be + converted to a dictionary using the model's fit keys. + t_eval : array-like + An array of time points at which to evaluate the solution. + + Returns + ------- + array-like + The simulation result corresponding to the specified signal. + + Raises + ------ + ValueError + If the model has not been built before simulation. """ if self._built_model is None: raise ValueError("Model must be built before calling simulate") else: if not isinstance(inputs, dict): - inputs_dict = { - key: inputs[i] for i, key in enumerate(self.fit_parameters) - } - return self.solver.solve( - self.built_model, inputs=inputs_dict, t_eval=t_eval - )[self.signal].data - else: - return self.solver.solve( - self.built_model, inputs=inputs, t_eval=t_eval - )[self.signal].data + inputs = {key: inputs[i] for i, key in enumerate(self.fit_keys)} + + sol = self.solver.solve(self.built_model, inputs=inputs, t_eval=t_eval) + + predictions = [sol[signal].data for signal in self.signal] + + return np.vstack(predictions).T def simulateS1(self, inputs, t_eval): """ - Run the forward model and return the function evaulation and it's gradient - aligning with Pints' ForwardModel simulateS1 method. + Perform the forward model simulation with sensitivities. + + Parameters + ---------- + inputs : dict or array-like + The input parameters for the simulation. If array-like, it will be + converted to a dictionary using the model's fit keys. + t_eval : array-like + An array of time points at which to evaluate the solution and its + sensitivities. + + Returns + ------- + tuple + A tuple containing the simulation result and the sensitivities. + + Raises + ------ + ValueError + If the model has not been built before simulation. """ if self._built_model is None: raise ValueError("Model must be built before calling simulate") else: if not isinstance(inputs, dict): - inputs_dict = { - key: inputs[i] for i, key in enumerate(self.fit_parameters) - } - - sol = self.solver.solve( - self.built_model, - inputs=inputs_dict, - t_eval=t_eval, - calculate_sensitivities=True, - ) - else: - sol = self.solver.solve( - self.built_model, - inputs=inputs, - t_eval=t_eval, - calculate_sensitivities=True, - ) + inputs = {key: inputs[i] for i, key in enumerate(self.fit_keys)} - return ( - sol[self.signal].data, - np.asarray( - [ - sol[self.signal].sensitivities[key].toarray() - for key in self.fit_keys - ] - ).T, + sol = self.solver.solve( + self.built_model, + inputs=inputs, + t_eval=t_eval, + calculate_sensitivities=True, ) + predictions = [sol[signal].data for signal in self.signal] + + sensitivities = [ + np.array( + [[sol[signal].sensitivities[key]] for signal in self.signal] + ).reshape(len(sol[self.signal[0]].data), self.n_outputs) + for key in self.fit_keys + ] + + return np.vstack(predictions).T, np.dstack(sensitivities) + def predict( self, inputs=None, @@ -167,11 +226,49 @@ def predict( init_soc=None, ): """ - Create a PyBaMM simulation object, solve it, and return a solution object. + Solve the model using PyBaMM's simulation framework and return the solution. + + This method sets up a PyBaMM simulation by configuring the model, parameters, experiment + (if any), and initial state of charge (if provided). It then solves the simulation and + returns the resulting solution object. + + Parameters + ---------- + inputs : dict or array-like, optional + Input parameters for the simulation. If the input is array-like, it is converted + to a dictionary using the model's fitting keys. Defaults to None, indicating + that the default parameters should be used. + t_eval : array-like, optional + An array of time points at which to evaluate the solution. Defaults to None, + which means the time points need to be specified within experiment or elsewhere. + parameter_set : pybamm.ParameterValues, optional + A PyBaMM ParameterValues object or a dictionary containing the parameter values + to use for the simulation. Defaults to the model's current ParameterValues if None. + experiment : pybamm.Experiment, optional + A PyBaMM Experiment object specifying the experimental conditions under which + the simulation should be run. Defaults to None, indicating no experiment. + init_soc : float, optional + The initial state of charge for the simulation, as a fraction (between 0 and 1). + Defaults to None. + + Returns + ------- + pybamm.Solution + The solution object returned after solving the simulation. + + Raises + ------ + ValueError + If the model has not been configured properly before calling this method or + if PyBaMM models are not supported by the current simulation method. + """ parameter_set = parameter_set or self._parameter_set if inputs is not None: + if not isinstance(inputs, dict): + inputs = {key: inputs[i] for i, key in enumerate(self.fit_keys)} parameter_set.update(inputs) + if self._unprocessed_model is not None: if experiment is None: return pybamm.Simulation( diff --git a/pybop/models/empirical/__init__.py b/pybop/models/empirical/__init__.py new file mode 100644 index 000000000..587906276 --- /dev/null +++ b/pybop/models/empirical/__init__.py @@ -0,0 +1,4 @@ +# +# Import lithium ion based models +# +from .ecm import Thevenin diff --git a/pybop/models/empirical/ecm.py b/pybop/models/empirical/ecm.py new file mode 100644 index 000000000..e6d29c3b0 --- /dev/null +++ b/pybop/models/empirical/ecm.py @@ -0,0 +1,77 @@ +import pybamm +from ..base_model import BaseModel + + +class Thevenin(BaseModel): + """ + The Thevenin class represents an equivalent circuit model based on the Thevenin model in PyBaMM. + + This class encapsulates the PyBaMM equivalent circuit Thevenin model, providing an interface + to define the parameters, geometry, submesh types, variable points, spatial methods, and solver + to be used for simulations. + + Parameters + ---------- + name : str, optional + A name for the model instance. Defaults to "Equivalent Circuit Thevenin Model". + parameter_set : dict or None, optional + A dictionary of parameters to be used for the model. If None, the default parameters from PyBaMM are used. + geometry : dict or None, optional + The geometry definitions for the model. If None, the default geometry from PyBaMM is used. + submesh_types : dict or None, optional + The types of submeshes to use. If None, the default submesh types from PyBaMM are used. + var_pts : dict or None, optional + The number of points for each variable in the model to define the discretization. If None, the default is used. + spatial_methods : dict or None, optional + The spatial methods to be used for discretization. If None, the default spatial methods from PyBaMM are used. + solver : pybamm.Solver or None, optional + The solver to use for simulating the model. If None, the default solver from PyBaMM is used. + options : dict or None, optional + A dictionary of options to pass to the PyBaMM Thevenin model. + **kwargs : + Additional arguments passed to the PyBaMM Thevenin model constructor. + """ + + def __init__( + self, + name="Equivalent Circuit Thevenin Model", + parameter_set=None, + geometry=None, + submesh_types=None, + var_pts=None, + spatial_methods=None, + solver=None, + options=None, + **kwargs, + ): + super().__init__() + self.pybamm_model = pybamm.equivalent_circuit.Thevenin( + options=options, **kwargs + ) + self._unprocessed_model = self.pybamm_model + self.name = name + + if isinstance(parameter_set, dict): + self.default_parameter_values = pybamm.ParameterValues(parameter_set) + self._parameter_set = self.default_parameter_values + else: + self.default_parameter_values = self.pybamm_model.default_parameter_values + self._parameter_set = ( + parameter_set or self.pybamm_model.default_parameter_values + ) + + self._unprocessed_parameter_set = self._parameter_set + + self.geometry = geometry or self.pybamm_model.default_geometry + self.submesh_types = submesh_types or self.pybamm_model.default_submesh_types + self.var_pts = var_pts or self.pybamm_model.default_var_pts + self.spatial_methods = ( + spatial_methods or self.pybamm_model.default_spatial_methods + ) + self.solver = solver or self.pybamm_model.default_solver + + self._model_with_set_params = None + self._built_model = None + self._built_initial_soc = None + self._mesh = None + self._disc = None diff --git a/pybop/models/lithium_ion/__init__.py b/pybop/models/lithium_ion/__init__.py index 69b51653b..d61591b4f 100644 --- a/pybop/models/lithium_ion/__init__.py +++ b/pybop/models/lithium_ion/__init__.py @@ -1,4 +1,4 @@ # # Import lithium ion based models # -from .base_echem import SPM, SPMe +from .echem import SPM, SPMe diff --git a/pybop/models/lithium_ion/base_echem.py b/pybop/models/lithium_ion/base_echem.py deleted file mode 100644 index d22a99e6d..000000000 --- a/pybop/models/lithium_ion/base_echem.py +++ /dev/null @@ -1,88 +0,0 @@ -import pybamm -from ..base_model import BaseModel - - -class SPM(BaseModel): - """ - Composition of the PyBaMM Single Particle Model class. - - """ - - def __init__( - self, - name="Single Particle Model", - parameter_set=None, - geometry=None, - submesh_types=None, - var_pts=None, - spatial_methods=None, - solver=None, - options=None, - ): - super().__init__() - self.pybamm_model = pybamm.lithium_ion.SPM(options=options) - self._unprocessed_model = self.pybamm_model - self.name = name - - self.default_parameter_values = self.pybamm_model.default_parameter_values - self._parameter_set = ( - parameter_set or self.pybamm_model.default_parameter_values - ) - self._unprocessed_parameter_set = self._parameter_set - - self.geometry = geometry or self.pybamm_model.default_geometry - self.submesh_types = submesh_types or self.pybamm_model.default_submesh_types - self.var_pts = var_pts or self.pybamm_model.default_var_pts - self.spatial_methods = ( - spatial_methods or self.pybamm_model.default_spatial_methods - ) - self.solver = solver or self.pybamm_model.default_solver - - self._model_with_set_params = None - self._built_model = None - self._built_initial_soc = None - self._mesh = None - self._disc = None - - -class SPMe(BaseModel): - """ - Composition of the PyBaMM Single Particle Model with Electrolyte class. - - """ - - def __init__( - self, - name="Single Particle Model with Electrolyte", - parameter_set=None, - geometry=None, - submesh_types=None, - var_pts=None, - spatial_methods=None, - solver=None, - options=None, - ): - super().__init__() - self.pybamm_model = pybamm.lithium_ion.SPMe(options=options) - self._unprocessed_model = self.pybamm_model - self.name = name - - self.default_parameter_values = self.pybamm_model.default_parameter_values - self._parameter_set = ( - parameter_set or self.pybamm_model.default_parameter_values - ) - self._unprocessed_parameter_set = self._parameter_set - - self.geometry = geometry or self.pybamm_model.default_geometry - self.submesh_types = submesh_types or self.pybamm_model.default_submesh_types - self.var_pts = var_pts or self.pybamm_model.default_var_pts - self.spatial_methods = ( - spatial_methods or self.pybamm_model.default_spatial_methods - ) - self.solver = solver or self.pybamm_model.default_solver - - self._model_with_set_params = None - self._built_model = None - self._built_initial_soc = None - self._mesh = None - self._disc = None diff --git a/pybop/models/lithium_ion/echem.py b/pybop/models/lithium_ion/echem.py new file mode 100644 index 000000000..35086fe82 --- /dev/null +++ b/pybop/models/lithium_ion/echem.py @@ -0,0 +1,138 @@ +import pybamm +from ..base_model import BaseModel + + +class SPM(BaseModel): + """ + Wraps the Single Particle Model (SPM) for simulating lithium-ion batteries, as implemented in PyBaMM. + + The SPM is a simplified physics-based model that represents a lithium-ion cell using a single + spherical particle to simulate the behavior of the negative and positive electrodes. + + Parameters + ---------- + name : str, optional + The name for the model instance, defaulting to "Single Particle Model". + parameter_set : pybamm.ParameterValues or dict, optional + The parameters for the model. If None, default parameters provided by PyBaMM are used. + geometry : dict, optional + The geometry definitions for the model. If None, default geometry from PyBaMM is used. + submesh_types : dict, optional + The types of submeshes to use. If None, default submesh types from PyBaMM are used. + var_pts : dict, optional + The discretization points for each variable in the model. If None, default points from PyBaMM are used. + spatial_methods : dict, optional + The spatial methods used for discretization. If None, default spatial methods from PyBaMM are used. + solver : pybamm.Solver, optional + The solver to use for simulating the model. If None, the default solver from PyBaMM is used. + options : dict, optional + A dictionary of options to customize the behavior of the PyBaMM model. + """ + + def __init__( + self, + name="Single Particle Model", + parameter_set=None, + geometry=None, + submesh_types=None, + var_pts=None, + spatial_methods=None, + solver=None, + options=None, + ): + super().__init__() + self.pybamm_model = pybamm.lithium_ion.SPM(options=options) + self._unprocessed_model = self.pybamm_model + self.name = name + + # Set parameters, using either the provided ones or the default + self.default_parameter_values = self.pybamm_model.default_parameter_values + self._parameter_set = ( + parameter_set or self.pybamm_model.default_parameter_values + ) + self._unprocessed_parameter_set = self._parameter_set + + # Define model geometry and discretization + self.geometry = geometry or self.pybamm_model.default_geometry + self.submesh_types = submesh_types or self.pybamm_model.default_submesh_types + self.var_pts = var_pts or self.pybamm_model.default_var_pts + self.spatial_methods = ( + spatial_methods or self.pybamm_model.default_spatial_methods + ) + self.solver = solver or self.pybamm_model.default_solver + + # Internal attributes for the built model are initialized but not set + self._model_with_set_params = None + self._built_model = None + self._built_initial_soc = None + self._mesh = None + self._disc = None + + +class SPMe(BaseModel): + """ + Represents the Single Particle Model with Electrolyte (SPMe) for lithium-ion batteries. + + The SPMe extends the basic Single Particle Model (SPM) by incorporating electrolyte dynamics, + making it suitable for simulations where electrolyte effects are non-negligible. This class + provides a framework to define the model parameters, geometry, mesh types, discretization + points, spatial methods, and numerical solvers for simulation within the PyBaMM ecosystem. + + Parameters + ---------- + name: str, optional + A name for the model instance, defaults to "Single Particle Model with Electrolyte". + parameter_set: pybamm.ParameterValues or dict, optional + A dictionary or a ParameterValues object containing the parameters for the model. If None, the default PyBaMM parameters for SPMe are used. + geometry: dict, optional + A dictionary defining the model's geometry. If None, the default PyBaMM geometry for SPMe is used. + submesh_types: dict, optional + A dictionary defining the types of submeshes to use. If None, the default PyBaMM submesh types for SPMe are used. + var_pts: dict, optional + A dictionary specifying the number of points for each variable for discretization. If None, the default PyBaMM variable points for SPMe are used. + spatial_methods: dict, optional + A dictionary specifying the spatial methods for discretization. If None, the default PyBaMM spatial methods for SPMe are used. + solver: pybamm.Solver, optional + The solver to use for simulating the model. If None, the default PyBaMM solver for SPMe is used. + options: dict, optional + A dictionary of options to customize the behavior of the PyBaMM model. + """ + + def __init__( + self, + name="Single Particle Model with Electrolyte", + parameter_set=None, + geometry=None, + submesh_types=None, + var_pts=None, + spatial_methods=None, + solver=None, + options=None, + ): + super().__init__() + self.pybamm_model = pybamm.lithium_ion.SPMe(options=options) + self._unprocessed_model = self.pybamm_model + self.name = name + + # Set parameters, using either the provided ones or the default + self.default_parameter_values = self.pybamm_model.default_parameter_values + self._parameter_set = ( + parameter_set or self.pybamm_model.default_parameter_values + ) + self._unprocessed_parameter_set = self._parameter_set + + # Define model geometry and discretization + self.geometry = geometry or self.pybamm_model.default_geometry + self.submesh_types = submesh_types or self.pybamm_model.default_submesh_types + self.var_pts = var_pts or self.pybamm_model.default_var_pts + self.spatial_methods = ( + spatial_methods or self.pybamm_model.default_spatial_methods + ) + self.solver = solver or self.pybamm_model.default_solver + + # Internal attributes for the built model are initialized but not set + self._model_with_set_params = None + self._built_model = None + self._built_initial_soc = None + self._mesh = None + self._disc = None diff --git a/pybop/optimisers/base_optimiser.py b/pybop/optimisers/base_optimiser.py index 1938c1db2..29cc219a2 100644 --- a/pybop/optimisers/base_optimiser.py +++ b/pybop/optimisers/base_optimiser.py @@ -1,21 +1,44 @@ class BaseOptimiser: """ + A base class for defining optimisation methods. - Base class for the optimisation methods. - + This class serves as a template for creating optimisers. It provides a basic structure for + an optimisation algorithm, including the initial setup and a method stub for performing + the optimisation process. Child classes should override the optimise and _runoptimise + methods with specific algorithms. """ def __init__(self): - self.name = "Base Optimiser" + """ + Initializes the BaseOptimiser. + """ + pass - def optimise(self, cost_function, x0=None, bounds=None): + def optimise(self, cost_function, x0=None, bounds=None, maxiter=None): """ - Optimisiation method to be overloaded by child classes. + Initiates the optimisation process. + + This method should be overridden by child classes with the specific optimisation algorithm. + + Parameters + ---------- + cost_function : callable + The cost function to be minimised by the optimiser. + x0 : ndarray, optional + Initial guess for the parameters. Default is None. + bounds : sequence or Bounds, optional + Bounds on the parameters. Default is None. + maxiter : int, optional + Maximum number of iterations to perform. Default is None. + Returns + ------- + The result of the optimisation process. The specific type of this result will depend on the child implementation. """ self.cost_function = cost_function self.x0 = x0 self.bounds = bounds + self.maxiter = maxiter # Run optimisation result = self._runoptimise(self.cost_function, x0=self.x0, bounds=self.bounds) @@ -24,7 +47,33 @@ def optimise(self, cost_function, x0=None, bounds=None): def _runoptimise(self, cost_function, x0=None, bounds=None): """ - Run optimisation method, to be overloaded by child classes. + Contains the logic for the optimisation algorithm. + This method should be implemented by child classes to perform the actual optimisation. + + Parameters + ---------- + cost_function : callable + The cost function to be minimised by the optimiser. + x0 : ndarray, optional + Initial guess for the parameters. Default is None. + bounds : sequence or Bounds, optional + Bounds on the parameters. Default is None. + + Returns + ------- + This method is expected to return the result of the optimisation, the format of which + will be determined by the child class implementation. """ pass + + def name(self): + """ + Returns the name of the optimiser. + + Returns + ------- + str + The name of the optimiser, which is "BaseOptimiser" for this base class. + """ + return "BaseOptimiser" diff --git a/pybop/optimisers/nlopt_optimize.py b/pybop/optimisers/nlopt_optimize.py index 5c0da8f47..12d7dfba9 100644 --- a/pybop/optimisers/nlopt_optimize.py +++ b/pybop/optimisers/nlopt_optimize.py @@ -1,16 +1,32 @@ import nlopt from .base_optimiser import BaseOptimiser +import numpy as np class NLoptOptimize(BaseOptimiser): """ - Wrapper class for the NLOpt optimiser class. Extends the BaseOptimiser class. + Extends BaseOptimiser to utilize the NLopt library for nonlinear optimization. + + This class serves as an interface to the NLopt optimization algorithms. It allows the user to + define an optimization problem with bounds, initial guesses, and to select an optimization method + provided by NLopt. + + Parameters + ---------- + n_param : int + Number of parameters to optimize. + xtol : float, optional + The relative tolerance for optimization (stopping criteria). If not provided, a default of 1e-5 is used. + method : nlopt.algorithm, optional + The NLopt algorithm to use for optimization. If not provided, LN_BOBYQA is used by default. + maxiter : int, optional + The maximum number of iterations to perform during optimization. If not provided, NLopt's default is used. """ - def __init__(self, n_param, xtol=None, method=None): + def __init__(self, n_param, xtol=None, method=None, maxiter=None): super().__init__() - self.name = "NLoptOptimize" self.n_param = n_param + self._max_iterations = maxiter if method is not None: self.optim = nlopt.opt(method, self.n_param) @@ -24,21 +40,39 @@ def __init__(self, n_param, xtol=None, method=None): def _runoptimise(self, cost_function, x0, bounds): """ - Run the NLOpt optimisation method. + Runs the optimization process using the NLopt library. - Inputs + Parameters ---------- - cost_function: function for optimising - method: optimisation algorithm - x0: initialisation array - bounds: bounds array + cost_function : callable + The objective function to minimize. It should take an array of parameter values and return the scalar cost. + x0 : array_like + The initial guess for the parameters. + bounds : dict + A dictionary containing the 'lower' and 'upper' bounds arrays for the parameters. + + Returns + ------- + tuple + A tuple containing the optimized parameter values and the final cost. """ + # Add callback storing history of parameter values + self.log = [[x0]] + + def cost_wrapper(x, grad): + self.log.append([np.array(x)]) + return cost_function(x, grad) + # Pass settings to the optimiser - self.optim.set_min_objective(cost_function) + self.optim.set_min_objective(cost_wrapper) self.optim.set_lower_bounds(bounds["lower"]) self.optim.set_upper_bounds(bounds["upper"]) + # Set max iterations + if self._max_iterations is not None: + self.optim.set_maxeval(self._max_iterations) + # Run the optimser x = self.optim.optimize(x0) @@ -49,6 +83,22 @@ def _runoptimise(self, cost_function, x0, bounds): def needs_sensitivities(self): """ - Returns True if the optimiser needs sensitivities. + Indicates if the optimiser requires gradient information for the cost function. + + Returns + ------- + bool + False, as the default NLopt algorithms do not require gradient information. """ return False + + def name(self): + """ + Returns the name of this optimiser instance. + + Returns + ------- + str + The name 'NLoptOptimize' representing this NLopt optimization class. + """ + return "NLoptOptimize" diff --git a/pybop/optimisers/pints_optimisers.py b/pybop/optimisers/pints_optimisers.py index 6524cb607..7b70e97f6 100644 --- a/pybop/optimisers/pints_optimisers.py +++ b/pybop/optimisers/pints_optimisers.py @@ -3,20 +3,210 @@ class GradientDescent(pints.GradientDescent): """ - Gradient descent optimiser. Inherits from the PINTS gradient descent class. + Implements a simple gradient descent optimization algorithm. + + This class extends the gradient descent optimiser from the PINTS library, designed + to minimize a scalar function of one or more variables. Note that this optimiser + does not support boundary constraints. + + Parameters + ---------- + x0 : array_like + Initial position from which optimization will start. + sigma0 : float, optional + Initial step size (default is 0.1). + bounds : sequence or ``Bounds``, optional + Ignored by this optimiser, provided for API consistency. + + See Also + -------- + pints.GradientDescent : The PINTS implementation this class is based on. + """ + + def __init__(self, x0, sigma0=0.1, bounds=None): + if bounds is not None: + print("NOTE: Boundaries ignored by Gradient Descent") + + self.boundaries = None # Bounds ignored in pints.GradDesc + super().__init__(x0, sigma0, self.boundaries) + + +class Adam(pints.Adam): + """ + Implements the Adam optimization algorithm. + + This class extends the Adam optimiser from the PINTS library, which combines + ideas from RMSProp and Stochastic Gradient Descent with momentum. Note that + this optimiser does not support boundary constraints. + + Parameters + ---------- + x0 : array_like + Initial position from which optimization will start. + sigma0 : float, optional + Initial step size (default is 0.1). + bounds : sequence or ``Bounds``, optional + Ignored by this optimiser, provided for API consistency. + + See Also + -------- + pints.Adam : The PINTS implementation this class is based on. + """ + + def __init__(self, x0, sigma0=0.1, bounds=None): + if bounds is not None: + print("NOTE: Boundaries ignored by Adam") + + self.boundaries = None # Bounds ignored in pints.Adam + super().__init__(x0, sigma0, self.boundaries) + + +class IRPropMin(pints.IRPropMin): + """ + Implements the iRpropMin optimization algorithm. + + This class inherits from the PINTS IRPropMin class, which is an optimiser that + uses resilient backpropagation with weight-backtracking. It is designed to handle + problems with large plateaus, noisy gradients, and local minima. + + Parameters + ---------- + x0 : array_like + Initial position from which optimization will start. + sigma0 : float, optional + Initial step size (default is 0.1). + bounds : dict, optional + Lower and upper bounds for each optimization parameter. + + See Also + -------- + pints.IRPropMin : The PINTS implementation this class is based on. """ def __init__(self, x0, sigma0=0.1, bounds=None): if bounds is not None: - print("Boundaries ignored by GradientDescent") + self.boundaries = pints.RectangularBoundaries( + bounds["lower"], bounds["upper"] + ) + else: + self.boundaries = None + super().__init__(x0, sigma0, self.boundaries) + + +class PSO(pints.PSO): + """ + Implements a particle swarm optimization (PSO) algorithm. + + This class extends the PSO optimiser from the PINTS library. PSO is a + metaheuristic optimization method inspired by the social behavior of birds + flocking or fish schooling, suitable for global optimization problems. - boundaries = None # Bounds ignored in pints.GradDesc - super().__init__(x0, sigma0, boundaries) + Parameters + ---------- + x0 : array_like + Initial positions of particles, which the optimization will use. + sigma0 : float, optional + Spread of the initial particle positions (default is 0.1). + bounds : dict, optional + Lower and upper bounds for each optimization parameter. + + See Also + -------- + pints.PSO : The PINTS implementation this class is based on. + """ + + def __init__(self, x0, sigma0=0.1, bounds=None): + if bounds is not None: + self.boundaries = pints.RectangularBoundaries( + bounds["lower"], bounds["upper"] + ) + else: + self.boundaries = None + super().__init__(x0, sigma0, self.boundaries) + + +class SNES(pints.SNES): + """ + Implements the stochastic natural evolution strategy (SNES) optimization algorithm. + + Inheriting from the PINTS SNES class, this optimiser is an evolutionary algorithm + that evolves a probability distribution on the parameter space, guiding the search + for the optimum based on the natural gradient of expected fitness. + + Parameters + ---------- + x0 : array_like + Initial position from which optimization will start. + sigma0 : float, optional + Initial step size (default is 0.1). + bounds : dict, optional + Lower and upper bounds for each optimization parameter. + + See Also + -------- + pints.SNES : The PINTS implementation this class is based on. + """ + + def __init__(self, x0, sigma0=0.1, bounds=None): + if bounds is not None: + self.boundaries = pints.RectangularBoundaries( + bounds["lower"], bounds["upper"] + ) + else: + self.boundaries = None + super().__init__(x0, sigma0, self.boundaries) + + +class XNES(pints.XNES): + """ + Implements the Exponential Natural Evolution Strategy (XNES) optimiser from PINTS. + + XNES is an evolutionary algorithm that samples from a multivariate normal distribution, which is updated iteratively to fit the distribution of successful solutions. + + Parameters + ---------- + x0 : array_like + The initial parameter vector to optimize. + sigma0 : float, optional + Initial standard deviation of the sampling distribution, defaults to 0.1. + bounds : dict, optional + A dictionary with 'lower' and 'upper' keys containing arrays for lower and upper bounds on the parameters. If ``None``, no bounds are enforced. + + See Also + -------- + pints.XNES : PINTS implementation of XNES algorithm. + """ + + def __init__(self, x0, sigma0=0.1, bounds=None): + if bounds is not None: + self.boundaries = pints.RectangularBoundaries( + bounds["lower"], bounds["upper"] + ) + else: + self.boundaries = None + super().__init__(x0, sigma0, self.boundaries) class CMAES(pints.CMAES): """ - Class for the PINTS optimisation. Extends the BaseOptimiser class. + Adapter for the Covariance Matrix Adaptation Evolution Strategy (CMA-ES) optimiser in PINTS. + + CMA-ES is an evolutionary algorithm for difficult non-linear non-convex optimization problems. + It adapts the covariance matrix of a multivariate normal distribution to capture the shape of the cost landscape. + + Parameters + ---------- + x0 : array_like + The initial parameter vector to optimize. + sigma0 : float, optional + Initial standard deviation of the sampling distribution, defaults to 0.1. + bounds : dict, optional + A dictionary with 'lower' and 'upper' keys containing arrays for lower and upper bounds on the parameters. + If ``None``, no bounds are enforced. + + See Also + -------- + pints.CMAES : PINTS implementation of CMA-ES algorithm. """ def __init__(self, x0, sigma0=0.1, bounds=None): diff --git a/pybop/optimisers/scipy_minimize.py b/pybop/optimisers/scipy_minimize.py deleted file mode 100644 index 083d93c53..000000000 --- a/pybop/optimisers/scipy_minimize.py +++ /dev/null @@ -1,50 +0,0 @@ -from scipy.optimize import minimize -from .base_optimiser import BaseOptimiser - - -class SciPyMinimize(BaseOptimiser): - """ - Wrapper class for the SciPy optimisation class. Extends the BaseOptimiser class. - """ - - def __init__(self, method=None, bounds=None): - super().__init__() - self.name = "SciPyMinimize" - self.method = method - self.bounds = bounds - - if self.method is None: - self.method = "L-BFGS-B" - - def _runoptimise(self, cost_function, x0, bounds): - """ - Run the SciPy optimisation method. - - Inputs - ---------- - cost_function: function for optimising - method: optimisation algorithm - x0: initialisation array - bounds: bounds array - """ - - if bounds is not None: - # Reformat bounds and run the optimser - bounds = ( - (lower, upper) for lower, upper in zip(bounds["lower"], bounds["upper"]) - ) - output = minimize(cost_function, x0, method=self.method, bounds=bounds) - else: - output = minimize(cost_function, x0, method=self.method) - - # Get performance statistics - x = output.x - final_cost = output.fun - - return x, final_cost - - def needs_sensitivities(self): - """ - Returns True if the optimiser needs sensitivities. - """ - return False diff --git a/pybop/optimisers/scipy_optimisers.py b/pybop/optimisers/scipy_optimisers.py new file mode 100644 index 000000000..5c17ff0ae --- /dev/null +++ b/pybop/optimisers/scipy_optimisers.py @@ -0,0 +1,205 @@ +from scipy.optimize import minimize, differential_evolution +from .base_optimiser import BaseOptimiser + + +class SciPyMinimize(BaseOptimiser): + """ + Adapts SciPy's minimize function for use as an optimization strategy. + + This class provides an interface to various scalar minimization algorithms implemented in SciPy, allowing fine-tuning of the optimization process through method selection and option configuration. + + Parameters + ---------- + method : str, optional + The type of solver to use. If not specified, defaults to 'COBYLA'. + bounds : sequence or ``Bounds``, optional + Bounds for variables as supported by the selected method. + maxiter : int, optional + Maximum number of iterations to perform. + """ + + def __init__(self, method=None, bounds=None, maxiter=None): + super().__init__() + self.method = method + self.bounds = bounds + self.options = {} + self._max_iterations = maxiter + + if self.method is None: + self.method = "COBYLA" # "L-BFGS-B" + + def _runoptimise(self, cost_function, x0, bounds): + """ + Executes the optimization process using SciPy's minimize function. + + Parameters + ---------- + cost_function : callable + The objective function to minimize. + x0 : array_like + Initial guess for the parameters. + bounds : sequence or `Bounds` + Bounds for the variables. + + Returns + ------- + tuple + A tuple (x, final_cost) containing the optimized parameters and the value of `cost_function` at the optimum. + """ + + # Add callback storing history of parameter values + self.log = [[x0]] + + def callback(x): + self.log.append([x]) + + # Reformat bounds + if bounds is not None: + bounds = ( + (lower, upper) for lower, upper in zip(bounds["lower"], bounds["upper"]) + ) + + # Set max iterations + if self._max_iterations is not None: + self.options = {"maxiter": self._max_iterations} + else: + self.options.pop("maxiter", None) + + output = minimize( + cost_function, + x0, + method=self.method, + bounds=bounds, + options=self.options, + callback=callback, + ) + + # Get performance statistics + x = output.x + final_cost = output.fun + + return x, final_cost + + def needs_sensitivities(self): + """ + Determines if the optimization algorithm requires gradient information. + + Returns + ------- + bool + False, indicating that gradient information is not required. + """ + return False + + def name(self): + """ + Provides the name of the optimization strategy. + + Returns + ------- + str + The name 'SciPyMinimize'. + """ + return "SciPyMinimize" + + +class SciPyDifferentialEvolution(BaseOptimiser): + """ + Adapts SciPy's differential_evolution function for global optimization. + + This class provides a global optimization strategy based on differential evolution, useful for problems involving continuous parameters and potentially multiple local minima. + + Parameters + ---------- + bounds : sequence or ``Bounds`` + Bounds for variables. Must be provided as it is essential for differential evolution. + strategy : str, optional + The differential evolution strategy to use. Defaults to 'best1bin'. + maxiter : int, optional + Maximum number of iterations to perform. Defaults to 1000. + popsize : int, optional + The number of individuals in the population. Defaults to 15. + """ + + def __init__(self, bounds=None, strategy="best1bin", maxiter=1000, popsize=15): + super().__init__() + self.bounds = bounds + self.strategy = strategy + self._max_iterations = maxiter + self.popsize = popsize + + def _runoptimise(self, cost_function, x0=None, bounds=None): + """ + Executes the optimization process using SciPy's differential_evolution function. + + Parameters + ---------- + cost_function : callable + The objective function to minimize. + x0 : array_like, optional + Ignored parameter, provided for API consistency. + bounds : sequence or ``Bounds`` + Bounds for the variables, required for differential evolution. + + Returns + ------- + tuple + A tuple (x, final_cost) containing the optimized parameters and the value of ``cost_function`` at the optimum. + """ + + if bounds is None: + raise ValueError("Bounds must be specified for differential_evolution.") + + if x0 is not None: + print( + "Ignoring x0. Initial conditions are not used for differential_evolution." + ) + + # Add callback storing history of parameter values + self.log = [] + + def callback(x, convergence): + self.log.append([x]) + + # Reformat bounds if necessary + if isinstance(bounds, dict): + bounds = [ + (lower, upper) for lower, upper in zip(bounds["lower"], bounds["upper"]) + ] + + output = differential_evolution( + cost_function, + bounds, + strategy=self.strategy, + maxiter=self._max_iterations, + popsize=self.popsize, + callback=callback, + ) + + # Get performance statistics + x = output.x + final_cost = output.fun + + return x, final_cost + + def needs_sensitivities(self): + """ + Determines if the optimization algorithm requires gradient information. + + Returns + ------- + bool + False, indicating that gradient information is not required for differential evolution. + """ + return False + + def name(self): + """ + Provides the name of the optimization strategy. + + Returns + ------- + str + The name 'SciPyDifferentialEvolution'. + """ + return "SciPyDifferentialEvolution" diff --git a/pybop/parameters/base_parameter.py b/pybop/parameters/base_parameter.py deleted file mode 100644 index fa8754831..000000000 --- a/pybop/parameters/base_parameter.py +++ /dev/null @@ -1,46 +0,0 @@ -import numpy as np - - -class Parameter: - """ "" - Class for creating parameters in PyBOP. - """ - - def __init__(self, name, value=None, prior=None, bounds=None): - self.name = name - self.prior = prior - self.value = value - self.bounds = bounds - self.lower_bound = self.bounds[0] - self.upper_bound = self.bounds[1] - self.margin = 1e-4 - - if self.lower_bound >= self.upper_bound: - raise ValueError("Lower bound must be less than upper bound") - - def rvs(self, n_samples): - """ - Returns a random value sample from the prior distribution. - """ - samples = self.prior.rvs(n_samples) - - # Constrain samples to be within bounds - offset = self.margin * (self.upper_bound - self.lower_bound) - samples = np.clip(samples, self.lower_bound + offset, self.upper_bound - offset) - - return samples - - def update(self, value): - self.value = value - - def __repr__(self): - return f"Parameter: {self.name} \n Prior: {self.prior} \n Bounds: {self.bounds} \n Value: {self.value}" - - def set_margin(self, margin): - """ - Sets the margin for the parameter. - """ - if not 0 < margin < 1: - raise ValueError("Margin must be between 0 and 1") - - self.margin = margin diff --git a/pybop/parameters/base_parameter_set.py b/pybop/parameters/base_parameter_set.py deleted file mode 100644 index dd1653d81..000000000 --- a/pybop/parameters/base_parameter_set.py +++ /dev/null @@ -1,13 +0,0 @@ -import pybamm - - -class ParameterSet: - """ - Class for creating parameter sets in PyBOP. - """ - - def __new__(cls, method, name): - if method.casefold() == "pybamm": - return pybamm.ParameterValues(name).copy() - else: - raise ValueError("Only PyBaMM parameter sets are currently implemented") diff --git a/pybop/parameters/parameter.py b/pybop/parameters/parameter.py new file mode 100644 index 000000000..15dffecb7 --- /dev/null +++ b/pybop/parameters/parameter.py @@ -0,0 +1,114 @@ +import numpy as np + + +class Parameter: + """ + Represents a parameter within the PyBOP framework. + + This class encapsulates the definition of a parameter, including its name, prior + distribution, initial value, bounds, and a margin to ensure the parameter stays + within feasible limits during optimization or sampling. + + Parameters + ---------- + name : str + The name of the parameter. + initial_value : float, optional + The initial value to be assigned to the parameter. Defaults to None. + prior : scipy.stats distribution, optional + The prior distribution from which parameter values are drawn. Defaults to None. + bounds : tuple, optional + A tuple defining the lower and upper bounds for the parameter. + Defaults to None. + + Raises + ------ + ValueError + If the lower bound is not strictly less than the upper bound, or if + the margin is set outside the interval (0, 1). + """ + + def __init__(self, name, initial_value=None, prior=None, bounds=None): + """ + Construct the parameter class with a name, initial value, prior, and bounds. + """ + self.name = name + self.prior = prior + self.initial_value = initial_value + self.value = initial_value + self.bounds = bounds + self.lower_bound = self.bounds[0] + self.upper_bound = self.bounds[1] + self.margin = 1e-4 + + if self.lower_bound >= self.upper_bound: + raise ValueError("Lower bound must be less than upper bound") + + def rvs(self, n_samples): + """ + Draw random samples from the parameter's prior distribution. + + The samples are constrained to be within the parameter's bounds, excluding + a predefined margin at the boundaries. + + Parameters + ---------- + n_samples : int + The number of samples to draw. + + Returns + ------- + array-like + An array of samples drawn from the prior distribution within the parameter's bounds. + """ + samples = self.prior.rvs(n_samples) + + # Constrain samples to be within bounds + offset = self.margin * (self.upper_bound - self.lower_bound) + samples = np.clip(samples, self.lower_bound + offset, self.upper_bound - offset) + + return samples + + def update(self, value): + """ + Update the parameter's current value. + + Parameters + ---------- + value : float + The new value to be assigned to the parameter. + """ + self.value = value + + def __repr__(self): + """ + Return a string representation of the Parameter instance. + + Returns + ------- + str + A string including the parameter's name, prior, bounds, and current value. + """ + return f"Parameter: {self.name} \n Prior: {self.prior} \n Bounds: {self.bounds} \n Value: {self.value}" + + def set_margin(self, margin): + """ + Set the margin to a specified positive value less than 1. + + The margin is used to ensure parameter samples are not drawn exactly at the bounds, + which may be problematic in some optimization or sampling algorithms. + + Parameters + ---------- + margin : float + The new margin value to be used, which must be in the interval (0, 1). + + Raises + ------ + ValueError + If the margin is not between 0 and 1. + """ + if not 0 < margin < 1: + raise ValueError("Margin must be between 0 and 1") + + self.margin = margin diff --git a/pybop/parameters/parameter_set.py b/pybop/parameters/parameter_set.py new file mode 100644 index 000000000..946d05baa --- /dev/null +++ b/pybop/parameters/parameter_set.py @@ -0,0 +1,155 @@ +import json +import types +import pybamm +import pybop + + +class ParameterSet: + """ + Handles the import and export of parameter sets for battery models. + + This class provides methods to load parameters from a JSON file and to export them + back to a JSON file. It also includes custom logic to handle special cases, such + as parameter values that require specific initialization. + + Parameters + ---------- + json_path : str, optional + Path to a JSON file containing parameter data. If provided, parameters will be imported from this file during initialization. + params_dict : dict, optional + A dictionary of parameters to initialize the ParameterSet with. If not provided, an empty dictionary is used. + """ + + def __init__(self, json_path=None, params_dict=None): + self.json_path = json_path + self.params = params_dict or {} + self.chemistry = None + + def import_parameters(self, json_path=None): + """ + Imports parameters from a JSON file specified by the `json_path` attribute. + + If a `json_path` is provided at initialization or as an argument, that JSON file + is loaded and the parameters are stored in the `params` attribute. Special cases + are handled appropriately. + + Parameters + ---------- + json_path : str, optional + Path to the JSON file from which to import parameters. If provided, it overrides the instance's `json_path`. + + Returns + ------- + dict + The dictionary containing the imported parameters. + + Raises + ------ + FileNotFoundError + If the specified JSON file cannot be found. + """ + + # Read JSON file + if not self.params and self.json_path: + with open(self.json_path, "r") as file: + self.params = json.load(file) + self._handle_special_cases() + if self.params["chemistry"] is not None: + self.chemistry = self.params["chemistry"] + return self.params + + def _handle_special_cases(self): + """ + Processes special cases for parameter values that require custom handling. + + For example, if the open-circuit voltage is specified as 'default', it will + fetch the default value from the PyBaMM empirical Thevenin model. + """ + if ( + "Open-circuit voltage [V]" in self.params + and self.params["Open-circuit voltage [V]"] == "default" + ): + self.params[ + "Open-circuit voltage [V]" + ] = pybop.empirical.Thevenin().default_parameter_values[ + "Open-circuit voltage [V]" + ] + + def export_parameters(self, output_json_path, fit_params=None): + """ + Exports parameters to a JSON file specified by `output_json_path`. + + The current state of the `params` attribute is written to the file. If `fit_params` + is provided, these parameters are updated before export. Non-serializable values + are handled and noted in the output JSON. + + Parameters + ---------- + output_json_path : str + The file path where the JSON output will be saved. + fit_params : list of fitted parameter objects, optional + Parameters that have been fitted and need to be included in the export. + + Raises + ------ + ValueError + If there are no parameters to export. + """ + if not self.params: + raise ValueError("No parameters to export. Please import parameters first.") + + # Prepare a copy of the params to avoid modifying the original dict + exportable_params = {**{"chemistry": self.chemistry}, **self.params.copy()} + + # Update parameter set + if fit_params is not None: + for i, param in enumerate(fit_params): + exportable_params.update({param.name: param.value}) + + # Replace non-serializable values + for key, value in exportable_params.items(): + if isinstance(value, types.FunctionType) or not self.is_json_serializable( + value + ): + exportable_params[key] = "Unable to write value to JSON file" + + # Write parameters to JSON file + with open(output_json_path, "w") as file: + json.dump(exportable_params, file, indent=4) + + def is_json_serializable(self, value): + """ + Determines if the given `value` can be serialized to JSON format. + + Parameters + ---------- + value : any + The value to check for JSON serializability. + + Returns + ------- + bool + True if the value is JSON serializable, False otherwise. + """ + try: + json.dumps(value) + return True + except (TypeError, OverflowError): + return False + + @classmethod + def pybamm(cls, name): + """ + Retrieves a PyBaMM parameter set by name. + + Parameters + ---------- + name : str + The name of the PyBaMM parameter set to retrieve. + + Returns + ------- + pybamm.ParameterValues + A PyBaMM parameter set corresponding to the provided name. + """ + return pybamm.ParameterValues(name).copy() diff --git a/pybop/parameters/priors.py b/pybop/parameters/priors.py index f98e9b767..482baff4d 100644 --- a/pybop/parameters/priors.py +++ b/pybop/parameters/priors.py @@ -3,7 +3,17 @@ class Gaussian: """ - Gaussian prior class. + Represents a Gaussian (normal) distribution with a given mean and standard deviation. + + This class provides methods to calculate the probability density function (pdf), + the logarithm of the pdf, and to generate random variates (rvs) from the distribution. + + Parameters + ---------- + mean : float + The mean (mu) of the Gaussian distribution. + sigma : float + The standard deviation (sigma) of the Gaussian distribution. """ def __init__(self, mean, sigma): @@ -12,24 +22,81 @@ def __init__(self, mean, sigma): self.sigma = sigma def pdf(self, x): + """ + Calculates the probability density function of the Gaussian distribution at x. + + Parameters + ---------- + x : float + The point at which to evaluate the pdf. + + Returns + ------- + float + The probability density function value at x. + """ return stats.norm.pdf(x, loc=self.mean, scale=self.sigma) def logpdf(self, x): + """ + Calculates the logarithm of the probability density function of the Gaussian distribution at x. + + Parameters + ---------- + x : float + The point at which to evaluate the log pdf. + + Returns + ------- + float + The logarithm of the probability density function value at x. + """ return stats.norm.logpdf(x, loc=self.mean, scale=self.sigma) def rvs(self, size): + """ + Generates random variates from the Gaussian distribution. + + Parameters + ---------- + size : int + The number of random variates to generate. + + Returns + ------- + array_like + An array of random variates from the Gaussian distribution. + + Raises + ------ + ValueError + If the size parameter is negative. + """ if size < 0: raise ValueError("size must be positive") else: return stats.norm.rvs(loc=self.mean, scale=self.sigma, size=size) def __repr__(self): + """ + Returns a string representation of the Gaussian object. + """ return f"{self.name}, mean: {self.mean}, sigma: {self.sigma}" class Uniform: """ - Uniform prior class. + Represents a uniform distribution over a specified interval. + + This class provides methods to calculate the pdf, the log pdf, and to generate + random variates from the distribution. + + Parameters + ---------- + lower : float + The lower bound of the distribution. + upper : float + The upper bound of the distribution. """ def __init__(self, lower, upper): @@ -38,12 +105,56 @@ def __init__(self, lower, upper): self.upper = upper def pdf(self, x): + """ + Calculates the probability density function of the uniform distribution at x. + + Parameters + ---------- + x : float + The point at which to evaluate the pdf. + + Returns + ------- + float + The probability density function value at x. + """ return stats.uniform.pdf(x, loc=self.lower, scale=self.upper - self.lower) def logpdf(self, x): + """ + Calculates the logarithm of the pdf of the uniform distribution at x. + + Parameters + ---------- + x : float + The point at which to evaluate the log pdf. + + Returns + ------- + float + The log of the probability density function value at x. + """ return stats.uniform.logpdf(x, loc=self.lower, scale=self.upper - self.lower) def rvs(self, size): + """ + Generates random variates from the uniform distribution. + + Parameters + ---------- + size : int + The number of random variates to generate. + + Returns + ------- + array_like + An array of random variates from the uniform distribution. + + Raises + ------ + ValueError + If the size parameter is negative. + """ if size < 0: raise ValueError("size must be positive") else: @@ -52,12 +163,23 @@ def rvs(self, size): ) def __repr__(self): + """ + Returns a string representation of the Uniform object. + """ return f"{self.name}, lower: {self.lower}, upper: {self.upper}" class Exponential: """ - Exponential prior class. + Represents an exponential distribution with a specified scale parameter. + + This class provides methods to calculate the pdf, the log pdf, and to generate random + variates from the distribution. + + Parameters + ---------- + scale : float + The scale parameter (lambda) of the exponential distribution. """ def __init__(self, scale): @@ -65,16 +187,63 @@ def __init__(self, scale): self.scale = scale def pdf(self, x): + """ + Calculates the probability density function of the exponential distribution at x. + + Parameters + ---------- + x : float + The point at which to evaluate the pdf. + + Returns + ------- + float + The probability density function value at x. + """ return stats.expon.pdf(x, scale=self.scale) def logpdf(self, x): + """ + Calculates the logarithm of the pdf of the exponential distribution at x. + + Parameters + ---------- + x : float + The point at which to evaluate the log pdf. + + Returns + ------- + float + The log of the probability density function value at x. + """ return stats.expon.logpdf(x, scale=self.scale) def rvs(self, size): + """ + Generates random variates from the exponential distribution. + + Parameters + ---------- + size : int + The number of random variates to generate. + + Returns + ------- + array_like + An array of random variates from the exponential distribution. + + Raises + ------ + ValueError + If the size parameter is negative. + """ if size < 0: raise ValueError("size must be positive") else: return stats.expon.rvs(scale=self.scale, size=size) def __repr__(self): + """ + Returns a string representation of the Uniform object. + """ return f"{self.name}, scale: {self.scale}" diff --git a/pybop/plotting/plot_convergence.py b/pybop/plotting/plot_convergence.py new file mode 100644 index 000000000..81e9ef65c --- /dev/null +++ b/pybop/plotting/plot_convergence.py @@ -0,0 +1,53 @@ +import pybop + + +def plot_convergence( + optim, xaxis_title="Iteration", yaxis_title="Cost", title="Convergence" +): + """ + Plot the convergence of the optimisation algorithm. + + Parameters + ----------- + optim : optimisation object + Optimisation object containing the cost function and optimiser. + xaxis_title : str, optional + Title for the x-axis (default is "Iteration"). + yaxis_title : str, optional + Title for the y-axis (default is "Cost"). + title : str, optional + Title of the plot (default is "Convergence"). + + Returns + --------- + fig : plotly.graph_objs.Figure + The Plotly figure object for the convergence plot. + """ + + # Extract the cost function from the optimisation object + cost_function = optim.cost + + # Compute the minimum cost for each iteration + min_cost_per_iteration = [ + min(cost_function(solution) for solution in log_entry) + for log_entry in optim.log + ] + + # Generate a list of iteration numbers + iteration_numbers = list(range(1, len(min_cost_per_iteration) + 1)) + + # Create the convergence plot using the StandardPlot class + fig = pybop.StandardPlot( + x=iteration_numbers, + y=min_cost_per_iteration, + cost=cost_function, + xaxis_title=xaxis_title, + yaxis_title=yaxis_title, + title=title, + trace_name=optim.optimiser.name(), + )() + + # Display the figure + fig.show() + + return fig diff --git a/pybop/plotting/plot_cost2d.py b/pybop/plotting/plot_cost2d.py new file mode 100644 index 000000000..ee43d9d09 --- /dev/null +++ b/pybop/plotting/plot_cost2d.py @@ -0,0 +1,159 @@ +import numpy as np + + +def plot_cost2d(cost, bounds=None, optim=None, steps=10): + """ + Plot a 2D visualization of a cost landscape using Plotly. + + This function generates a contour plot representing the cost landscape for a provided + callable cost function over a grid of parameter values within the specified bounds. + + Parameters + ---------- + cost : callable + The cost function to be evaluated. Must accept a list of parameters and return a cost value. + bounds : numpy.ndarray, optional + A 2x2 array specifying the [min, max] bounds for each parameter. If None, uses `get_param_bounds`. + optim : object, optional + An optimiser instance which, if provided, overlays its specific trace on the plot. + steps : int, optional + The number of intervals to divide the parameter space into along each dimension (default is 10). + + Returns + ------- + plotly.graph_objs.Figure + The Plotly figure object containing the cost landscape plot. + + Raises + ------ + ValueError + If the cost function does not return a valid cost when called with a parameter list. + """ + + if bounds is None: + # Set up parameter bounds + bounds = get_param_bounds(cost) + else: + bounds = bounds + + # Generate grid + x = np.linspace(bounds[0, 0], bounds[0, 1], steps) + y = np.linspace(bounds[1, 0], bounds[1, 1], steps) + + # Initialize cost matrix + costs = np.zeros((len(y), len(x))) + + # Populate cost matrix + for i, xi in enumerate(x): + for j, yj in enumerate(y): + costs[j, i] = cost([xi, yj]) + + # Create figure + fig = create_figure(x, y, costs, bounds, cost.problem.parameters, optim) + + # Display figure + fig.show() + + return fig + + +def get_param_bounds(cost): + """ + Retrieve parameter bounds from a cost function's associated problem parameters. + + Parameters + ---------- + cost : callable + The cost function with an associated 'problem' attribute containing 'parameters'. + + Returns + ------- + numpy.ndarray + An array of shape (n_parameters, 2) containing the bounds for each parameter. + """ + bounds = np.empty((len(cost.problem.parameters), 2)) + for i, param in enumerate(cost.problem.parameters): + bounds[i] = param.bounds + return bounds + + +def create_figure(x, y, z, bounds, params, optim): + """ + Create a Plotly figure with a 2D contour plot of the cost landscape. + + Parameters + ---------- + x : numpy.ndarray + 1D array of x-coordinates for the meshgrid. + y : numpy.ndarray + 1D array of y-coordinates for the meshgrid. + z : numpy.ndarray + 2D array of cost function values corresponding to the meshgrid. + bounds : numpy.ndarray + A 2x2 array specifying the [min, max] bounds for each parameter. + params : iterable + An iterable of parameter objects with 'name' attributes for axis labeling. + optim : object + An optimiser instance with 'log' and 'x0' attributes for plotting traces. + + Returns + ------- + plotly.graph_objs.Figure + The Plotly figure object with the contour plot and optimization traces. + """ + + # Import plotly only when needed + import plotly.graph_objects as go + + fig = go.Figure(data=[go.Contour(x=x, y=y, z=z)]) + if optim is not None: + optim_trace = np.array([item for sublist in optim.log for item in sublist]) + optim_trace = optim_trace.reshape(-1, 2) + + # Plot initial guess + fig.add_trace( + go.Scatter( + x=[optim.x0[0]], + y=[optim.x0[1]], + mode="markers", + marker_symbol="x", + marker=dict( + color="red", + line_color="midnightblue", + line_width=1, + size=12, + showscale=False, + ), + showlegend=False, + ) + ) + + # Plot optimisation trace + fig.add_trace( + go.Scatter( + x=optim_trace[:, 0], + y=optim_trace[:, 1], + mode="markers", + marker=dict( + color=[i / len(optim_trace) for i in range(len(optim_trace))], + colorscale="YlOrBr", + showscale=False, + ), + showlegend=False, + ) + ) + + # Set figure properties + fig.update_layout( + title="Cost Landscape", + title_x=0.5, + title_y=0.9, + xaxis_title=params[0].name, + yaxis_title=params[1].name, + width=600, + height=600, + xaxis=dict(range=bounds[0]), + yaxis=dict(range=bounds[1]), + ) + + return fig diff --git a/pybop/plotting/plot_parameters.py b/pybop/plotting/plot_parameters.py new file mode 100644 index 000000000..84307a72a --- /dev/null +++ b/pybop/plotting/plot_parameters.py @@ -0,0 +1,158 @@ +import pybop +import math + + +def plot_parameters( + optim, xaxis_titles="Iteration", yaxis_titles=None, title="Convergence" +): + """ + Plot the evolution of parameters during the optimization process using Plotly. + + Parameters + ---------- + optim : object + The optimization object containing the history of parameter values and associated cost. + xaxis_titles : str, optional + Title for the x-axis, defaulting to "Iteration". + yaxis_titles : list of str, optional + Titles for the y-axes, one for each parameter. If None, parameter names are used. + title : str, optional + Title of the plot, defaulting to "Convergence". + + Returns + ------- + plotly.graph_objs.Figure + A Plotly figure object showing the parameter evolution over iterations. + """ + + # Extract parameters from the optimisation object + params = optim.cost.problem.parameters + + # Create the traces from the optimisation log + traces = create_traces(params, optim.log) + + # Create the axis titles + axis_titles = [] + for param in params: + axis_titles.append(("Function Call", param.name)) + + # Create the figure + fig = create_subplots_with_traces(traces, axis_titles=axis_titles) + + # Display the figure + fig.show() + + return fig + + +def create_traces(params, trace_data, x_values=None): + """ + Create traces for plotting parameter evolution. + + Parameters + ---------- + params : list + List of parameter objects, each having a 'name' attribute used for labeling the trace. + trace_data : list of numpy.ndarray + A list of arrays representing the historical values of each parameter. + x_values : list or numpy.ndarray, optional + The x-axis values for plotting. If None, defaults to sequential integers. + + Returns + ------- + list of plotly.graph_objs.Scatter + A list of Scatter trace objects, one for each parameter. + """ + + # Attempt to import plotly when an instance is created + go = pybop.PlotlyManager().go + + traces = [] + + # If x_values are not provided: + if x_values is None: + x_values = list(range(len(trace_data[0]) * len(trace_data))) + + # Determine the number of elements in the smallest arrays + num_elements = len(trace_data[0][0]) + + # Initialize a list of lists to store our columns + columns = [[] for _ in range(num_elements)] + + # Loop through each numpy array in trace_data + for array in trace_data: + # Loop through each item (which is a n-element array) in the numpy array + for item in array: + # Loop through each element in the item and append to the corresponding column + for i in range(num_elements): + columns[i].append(item[i]) + + # Create a trace for each column + for i in range(len(columns)): + wrap_param = pybop.StandardPlot.wrap_text(params[i].name, width=50) + traces.append(go.Scatter(x=x_values, y=columns[i], name=wrap_param)) + + return traces + + +def create_subplots_with_traces( + traces, + plot_size=(1024, 576), + title="Parameter Convergence", + axis_titles=None, + **layout_kwargs, +): + """ + Create a subplot with individual traces for each parameter. + + Parameters + ---------- + traces : list of plotly.graph_objs.Scatter + Traces to be plotted, one trace per subplot. + plot_size : tuple of int, optional + The size of the plot as (width, height), defaulting to (1024, 576). + title : str, optional + The title of the plot, defaulting to "Parameter Convergence". + axis_titles : list of tuple of str, optional + A list of (x_title, y_title) pairs for each subplot. If None, titles are omitted. + **layout_kwargs : dict + Additional keyword arguments to customize the layout. + + Returns + ------- + plotly.graph_objs.Figure + A Plotly figure object with subplots for each trace. + """ + + # Attempt to import plotly when an instance is created + make_subplots = pybop.PlotlyManager().make_subplots + + num_traces = len(traces) + num_cols = int(math.ceil(math.sqrt(num_traces))) + num_rows = int(math.ceil(num_traces / num_cols)) + + fig = make_subplots(rows=num_rows, cols=num_cols, start_cell="bottom-left") + + for idx, trace in enumerate(traces): + row = (idx // num_cols) + 1 + col = (idx % num_cols) + 1 + fig.add_trace(trace, row=row, col=col) + + if axis_titles and idx < len(axis_titles): + x_title, y_title = axis_titles[idx] + fig.update_xaxes(title_text=x_title, row=row, col=col) + fig.update_yaxes(title_text=y_title, row=row, col=col) + + if plot_size: + layout_kwargs["width"], layout_kwargs["height"] = plot_size + + if title: + layout_kwargs["title_text"] = title + + # Set the legend above the subplots + fig.update_layout( + legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1), + **layout_kwargs, + ) + + return fig diff --git a/pybop/plotting/plotly_manager.py b/pybop/plotting/plotly_manager.py new file mode 100644 index 000000000..44f551f53 --- /dev/null +++ b/pybop/plotting/plotly_manager.py @@ -0,0 +1,130 @@ +import subprocess +import webbrowser +import sys + + +class PlotlyManager: + """ + Manages the installation and configuration of Plotly for generating visualizations. + + This class ensures that Plotly is installed and properly configured to display + plots in a web browser. + + Upon instantiation, it checks for Plotly's presence, installs it if missing, + and configures the default renderer and browser settings. + + Attributes + ---------- + go : module + The Plotly graph_objects module for creating figures. + pio : module + The Plotly input/output module for configuring the renderer. + make_subplots : function + The function from Plotly for creating subplot figures. + + Examples + -------- + >>> plotly_manager = PlotlyManager() + """ + + def __init__(self): + """ + Initialize the PlotlyManager, ensuring Plotly is installed and configured. + """ + self.go = None + self.pio = None + self.make_subplots = None + self.ensure_plotly_installed() + self.check_renderer_settings() + self.check_browser_availability() + + def ensure_plotly_installed(self): + """ + Check if Plotly is installed and import necessary modules; prompt for installation if missing. + """ + try: + import plotly.graph_objs as go + import plotly.io as pio + from plotly.subplots import make_subplots + + self.go = go + self.pio = pio + self.make_subplots = make_subplots + except ImportError: + self.prompt_for_plotly_installation() + + def prompt_for_plotly_installation(self): + """ + Prompt the user for Plotly installation and install it upon agreement. + """ + user_input = ( + input( + "Plotly is not installed. To proceed, we need to install plotly. (Y/n)? " + ) + .strip() + .lower() + ) + if user_input == "y": + self.install_plotly() + self.post_install_setup() + else: + print("Installation cancelled by user.") + sys.exit(1) # Exit if user cancels installation + + def install_plotly(self): + """ + Install the Plotly package using pip. Exit if installation fails. + """ + try: + subprocess.check_call([sys.executable, "-m", "pip", "install", "plotly"]) + except subprocess.CalledProcessError as e: + print(f"Error installing plotly: {e}") + sys.exit(1) # Exit if installation fails + + def post_install_setup(self): + """ + Import Plotly modules and set the default renderer after installation. + """ + import plotly.graph_objs as go + import plotly.io as pio + from plotly.subplots import make_subplots + + self.go = go + self.pio = pio + self.make_subplots = make_subplots + if pio.renderers.default == "": + pio.renderers.default = "browser" + print( + 'Set default renderer to "browser" as it was empty after installation.' + ) + + def check_renderer_settings(self): + """ + Check and provide information on setting the Plotly renderer if it's not already set. + """ + if self.pio and self.pio.renderers.default == "": + print( + "The Plotly renderer is an empty string. To set the renderer, use:\n" + " pio.renderers\n" + ' pio.renderers.default = "browser"\n' + "For more information, see: https://plotly.com/python/renderers/#setting-the-default-renderer" + ) + + def check_browser_availability(self): + """ + Confirm a web browser is available for Plotly's 'browser' renderer; provide guidance if not. + """ + if self.pio and self.pio.renderers.default == "browser": + try: + webbrowser.get() + except webbrowser.Error: + raise Exception( + "\n **Browser Not Found** \nFor Windows users, in order to view figures in the browser using Plotly, " + "you need to set the environment variable BROWSER equal to the " + "path to your chosen browser. To do this, please enter a command like " + "the following to add this to your virtual environment activation file:\n\n" + "echo 'export BROWSER=\"/mnt/c/Program Files/Mozilla Firefox/firefox.exe\"' >> your-env/bin/activate" + "\n\nThen reactivate your virtual environment. Alternatively, you can use a " + "different Plotly renderer. For more information see: " + "https://plotly.com/python/renderers/#setting-the-default-renderer" + ) diff --git a/pybop/plotting/quick_plot.py b/pybop/plotting/quick_plot.py index 5acbb2626..6f0cf616c 100644 --- a/pybop/plotting/quick_plot.py +++ b/pybop/plotting/quick_plot.py @@ -1,22 +1,236 @@ -class QuickPlot: +import numpy as np +import textwrap +import pybop + + +class StandardPlot: + """ + A class for creating and displaying Plotly figures for model output comparison. + + Generates interactive plots comparing simulated model output with an optional target dataset and visualizes uncertainty. + + Parameters + ---------- + x : list or np.ndarray + X-axis data points. + y : list or np.ndarray + Primary Y-axis data points for simulated model output. + cost : float + Cost associated with the model output. + y2 : list or np.ndarray, optional + Secondary Y-axis data points for the target dataset (default: None). + title : str, optional + Title of the plot (default: None). + xaxis_title : str, optional + Title for the x-axis (default: None). + yaxis_title : str, optional + Title for the y-axis (default: None). + trace_name : str, optional + Name for the primary trace (default: "Simulated"). + width : int, optional + Width of the figure in pixels (default: 1024). + height : int, optional + Height of the figure in pixels (default: 576). """ - Class to generate plots with standard variables and formatting. + def __init__( + self, + x, + y, + cost, + y2=None, + title=None, + xaxis_title=None, + yaxis_title=None, + trace_name=None, + width=1024, + height=576, + ): + """ + Initialize the StandardPlot object with simulation and optional target data. + + Parameters + ---------- + x : list or np.ndarray + X-axis data points. + y : list or np.ndarray + Primary Y-axis data points for simulated model output. + cost : float + Cost associated with the model output. + y2 : list or np.ndarray, optional + Secondary Y-axis data points for target dataset (default: None). + title : str, optional + Plot title (default: None). + xaxis_title : str, optional + X-axis title (default: None). + yaxis_title : str, optional + Y-axis title (default: None). + trace_name : str, optional + Name for the primary trace (default: "Simulated"). + width : int, optional + Figure width in pixels (default: 1024). + height : int, optional + Figure height in pixels (default: 576). + """ + self.x = x if isinstance(x, list) else x.tolist() + self.y = y + self.y2 = y2 + self.cost = cost + self.width = width + self.height = height + self.title = title + self.xaxis_title = xaxis_title + self.yaxis_title = yaxis_title + self.trace_name = trace_name or "Simulated" + + if self.y2 is not None: + self.sigma = np.std(self.y - self.y2) + self.y_upper = (self.y + self.sigma).tolist() + self.y_lower = (self.y - self.sigma).tolist() + + # Attempt to import plotly when an instance is created + self.go = pybop.PlotlyManager().go + + @staticmethod + def wrap_text(text, width): + """ + Wrap text to a specified width with HTML line breaks. + + Parameters + ---------- + text : str + The text to wrap. + width : int + The width to wrap the text to. + + Returns + ------- + str + The wrapped text. + """ + wrapped_text = textwrap.fill(text, width=width, break_long_words=False) + return wrapped_text.replace("\n", "
") + + def create_layout(self): + """ + Create the layout for the Plotly figure. - Plots - -------------- - Observability - if method == parameterisation + Returns + ------- + plotly.graph_objs.Layout + The layout for the Plotly figure. + """ + return self.go.Layout( + title=self.title, + title_x=0.5, + xaxis=dict(title=self.xaxis_title, titlefont_size=12, tickfont_size=12), + yaxis=dict(title=self.yaxis_title, titlefont_size=12, tickfont_size=12), + legend=dict(x=1, y=1, xanchor="right", yanchor="top", font_size=12), + showlegend=True, + autosize=False, + width=self.width, + height=self.height, + margin=dict(l=10, r=10, b=10, t=75, pad=4), + ) - Comparison of fitting data with optimised forward model + def create_traces(self): + """ + Create traces for the Plotly figure. - elseif method == optimisation + Returns + ------- + list + A list of plotly.graph_objs.Scatter objects to be used as traces. + """ + traces = [] - Pareto front - Alternative solutions - Initial value compared to optimal + wrapped_trace_name = self.wrap_text(self.trace_name, width=40) + simulated_trace = self.go.Scatter( + x=self.x, + y=self.y, + line=dict(width=4), + mode="lines", + name=wrapped_trace_name, + ) + if self.y2 is not None: + target_trace = self.go.Scatter( + x=self.x, y=self.y2, mode="markers", name="Target" + ) + fill_trace = self.go.Scatter( + x=self.x + self.x[::-1], + y=self.y_upper + self.y_lower[::-1], + fill="toself", + fillcolor="rgba(255,229,204,0.8)", + line=dict(color="rgba(255,255,255,0)"), + hoverinfo="skip", + showlegend=False, + ) + traces.extend([fill_trace, target_trace]) + + traces.append(simulated_trace) + + return traces + + def __call__(self): + """ + Generate the Plotly figure. + + Returns + ------- + plotly.graph_objs.Figure + The generated Plotly figure. + """ + layout = self.create_layout() + traces = self.create_traces() + fig = self.go.Figure(data=traces, layout=layout) + return fig + + +def quick_plot(params, cost, title="Scatter Plot", width=1024, height=576): """ + Quickly plot the target dataset against minimized model output. + + Parameters + ---------- + params : array-like + Optimized parameters. + cost : object + Cost object with problem, dataset, and signal attributes. + title : str, optional + Title of the plot (default: "Scatter Plot"). + width : int, optional + Width of the figure in pixels (default: 1024). + height : int, optional + Height of the figure in pixels (default: 576). + + Returns + ------- + plotly.graph_objs.Figure + The Plotly figure object for the scatter plot. + """ + + # Extract the time data and evaluate the model's output and target values + time_data = cost.problem._dataset["Time [s]"].data + model_output = cost.problem.evaluate(params) + target_output = cost.problem.target() + + for i in range(0, cost.problem.n_outputs): + # Create the figure using the StandardPlot class + fig = pybop.StandardPlot( + x=time_data, + y=model_output[:, i], + cost=cost, + y2=target_output[:, i], + xaxis_title="Time [s]", + yaxis_title=cost.problem.signal[i], + title=title, + trace_name="Model", + width=width, + height=height, + )() + + # Display the figure + fig.show() - def __init__(self): - self.name = "Quick Plot" + return fig diff --git a/pybop/version.py b/pybop/version.py index 915a9aedb..f3d58cf85 100644 --- a/pybop/version.py +++ b/pybop/version.py @@ -1 +1 @@ -__version__ = "23.11" +__version__ = "23.12" diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..ab0a003d6 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +# pytest.ini +[pytest] +addopts = --showlocals -v diff --git a/readthedocs.yaml b/readthedocs.yaml new file mode 100644 index 000000000..aaeb9cfcf --- /dev/null +++ b/readthedocs.yaml @@ -0,0 +1,20 @@ +version: 2 + +build: + os: ubuntu-20.04 + tools: + python: "3.11" + +# Build documentation in the "docs/" directory with Sphinx +sphinx: + configuration: docs/conf.py + +formats: + - htmlzip + - pdf + - epub + +python: + install: + - method: pip + path: .[docs] diff --git a/setup.py b/setup.py index 4d6b63a65..d0bf68ae6 100644 --- a/setup.py +++ b/setup.py @@ -25,13 +25,27 @@ long_description_content_type="text/markdown", url="https://github.com/pybop-team/PyBOP", install_requires=[ - "pybamm>=23.1", + "pybamm>=23.5", "numpy>=1.16", "scipy>=1.3", "pandas>=1.0", "nlopt>=2.6", "pints>=0.5", ], + extras_require={ + "plot": ["plotly>=5.0"], + "all": ["pybop[plot]"], + "docs": [ + "sphinx>=6", + "pydata-sphinx-theme", + "sphinx-autobuild", + "sphinx-autoapi", + "sphinx_copybutton", + "sphinx_favicon", + "sphinx_design", + "myst-parser", + ], + }, # https://pypi.org/classifiers/ classifiers=[], python_requires=">=3.8,<=3.12", diff --git a/tests/unit/test_cost.py b/tests/unit/test_cost.py index 0c7e329f3..362499482 100644 --- a/tests/unit/test_cost.py +++ b/tests/unit/test_cost.py @@ -25,16 +25,18 @@ def test_costs(self, cut_off): # Form dataset x0 = np.array([0.52]) solution = self.getdata(model, x0) - dataset = [ - pybop.Dataset("Time [s]", solution["Time [s]"].data), - pybop.Dataset("Current function [A]", solution["Current [A]"].data), - pybop.Dataset("Voltage [V]", solution["Terminal voltage [V]"].data), - ] + dataset = pybop.Dataset( + { + "Time [s]": solution["Time [s]"].data, + "Current function [A]": solution["Current [A]"].data, + "Voltage [V]": solution["Terminal voltage [V]"].data, + } + ) # Construct Problem - signal = "Voltage [V]" + signal = ["Voltage [V]"] model.parameter_set.update({"Lower voltage cut-off [V]": cut_off}) - problem = pybop.Problem(model, parameters, dataset, signal=signal, x0=x0) + problem = pybop.FittingProblem(model, parameters, dataset, signal=signal, x0=x0) # Base Cost base_cost = pybop.BaseCost(problem) diff --git a/tests/unit/test_dataset.py b/tests/unit/test_dataset.py new file mode 100644 index 000000000..b5cfa96dc --- /dev/null +++ b/tests/unit/test_dataset.py @@ -0,0 +1,40 @@ +import pytest +import pybop +import numpy as np + + +class TestDataset: + """ + Class to test dataset construction. + """ + + @pytest.mark.unit + def test_dataset(self): + # Construct and simulate model + model = pybop.lithium_ion.SPM() + model.parameter_set = model.pybamm_model.default_parameter_values + solution = model.predict(t_eval=np.linspace(0, 10, 100)) + + # Form dataset + data_dictionary = { + "Time [s]": solution["Time [s]"].data, + "Current [A]": solution["Current [A]"].data, + "Terminal voltage [V]": solution["Terminal voltage [V]"].data, + } + dataset = pybop.Dataset(data_dictionary) + + # Test repr + print(dataset) + + # Test data structure + assert dataset.data == data_dictionary + + # Test exception for non-dictionary inputs + with pytest.raises(ValueError): + pybop.Dataset(["StringInputShouldNotWork"]) + with pytest.raises(ValueError): + pybop.Dataset(solution["Time [s]"].data) + + # Test conversion of pybamm solution into dictionary + assert dataset.data == pybop.Dataset(solution).data + assert dataset.names == pybop.Dataset(solution).names diff --git a/tests/unit/test_examples.py b/tests/unit/test_examples.py index 6e8fc09e0..ebc3570aa 100644 --- a/tests/unit/test_examples.py +++ b/tests/unit/test_examples.py @@ -9,11 +9,17 @@ class TestExamples: A class to test the example scripts. """ - @pytest.mark.unit - def test_example_scripts(self): + def list_of_examples(): + list = [] path_to_example_scripts = os.path.join( pybop.script_path, "..", "examples", "scripts" ) for example in os.listdir(path_to_example_scripts): if example.endswith(".py"): - runpy.run_path(os.path.join(path_to_example_scripts, example)) + list.append(os.path.join(path_to_example_scripts, example)) + return list + + @pytest.mark.parametrize("example", list_of_examples()) + @pytest.mark.examples + def test_example_scripts(self, example): + runpy.run_path(example) diff --git a/tests/unit/test_models.py b/tests/unit/test_models.py index ce73000a6..6925391de 100644 --- a/tests/unit/test_models.py +++ b/tests/unit/test_models.py @@ -34,7 +34,7 @@ def test_predict_without_pybamm(self): @pytest.mark.unit def test_predict_with_inputs(self): - # Define model + # Define SPM model = pybop.lithium_ion.SPM() t_eval = np.linspace(0, 10, 100) inputs = { @@ -45,6 +45,11 @@ def test_predict_with_inputs(self): res = model.predict(t_eval=t_eval, inputs=inputs) assert len(res["Terminal voltage [V]"].data) == 100 + # Define SPMe + model = pybop.lithium_ion.SPMe() + res = model.predict(t_eval=t_eval, inputs=inputs) + assert len(res["Terminal voltage [V]"].data) == 100 + @pytest.mark.unit def test_build(self): model = pybop.lithium_ion.SPM() diff --git a/tests/unit/test_optimisation.py b/tests/unit/test_optimisation.py index 5bbb4998b..cf82a51ec 100644 --- a/tests/unit/test_optimisation.py +++ b/tests/unit/test_optimisation.py @@ -1,7 +1,7 @@ import pybop import numpy as np import pytest -from pybop.costs.standalone import StandaloneCost +from examples.costs.standalone import StandaloneCost class TestOptimisation: @@ -9,32 +9,19 @@ class TestOptimisation: A class to test the optimisation class. """ - @pytest.mark.unit - def test_standalone(self): - # Build an Optimisation problem with a StandaloneCost - cost = StandaloneCost() - - opt = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize) - - assert len(opt.x0) == opt.n_parameters - - x, final_cost = opt.run() - - np.testing.assert_allclose(x, 0, atol=1e-2) - np.testing.assert_allclose(final_cost, 42, atol=1e-2) - - @pytest.mark.unit - def test_prior_sampling(self): - # Tests prior sampling - model = pybop.lithium_ion.SPM() - - dataset = [ - pybop.Dataset("Time [s]", np.linspace(0, 3600, 100)), - pybop.Dataset("Current function [A]", np.zeros(100)), - pybop.Dataset("Terminal voltage [V]", np.ones(100)), - ] + @pytest.fixture + def dataset(self): + return pybop.Dataset( + { + "Time [s]": np.linspace(0, 360, 10), + "Current function [A]": np.zeros(10), + "Terminal voltage [V]": np.ones(10), + } + ) - param = [ + @pytest.fixture + def parameters(self): + return [ pybop.Parameter( "Negative electrode active material volume fraction", prior=pybop.Gaussian(0.75, 0.2), @@ -42,95 +29,96 @@ def test_prior_sampling(self): ) ] - signal = "Terminal voltage [V]" - problem = pybop.Problem(model, param, dataset, signal=signal) - cost = pybop.RootMeanSquaredError(problem) - - for i in range(50): - opt = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize) - - assert opt.x0 <= 0.77 and opt.x0 >= 0.73 + @pytest.fixture + def problem(self, parameters, dataset): + model = pybop.lithium_ion.SPM() + return pybop.FittingProblem( + model, + parameters, + dataset, + signal=["Terminal voltage [V]"], + ) + @pytest.fixture + def cost(self, problem): + return pybop.SumSquaredError(problem) + + @pytest.mark.parametrize( + "optimiser_class, expected_name", + [ + (pybop.NLoptOptimize, "NLoptOptimize"), + (pybop.SciPyMinimize, "SciPyMinimize"), + (pybop.SciPyDifferentialEvolution, "SciPyDifferentialEvolution"), + (pybop.GradientDescent, "Gradient descent"), + (pybop.Adam, "Adam"), + (pybop.CMAES, "Covariance Matrix Adaptation Evolution Strategy (CMA-ES)"), + (pybop.SNES, "Seperable Natural Evolution Strategy (SNES)"), + (pybop.XNES, "Exponential Natural Evolution Strategy (xNES)"), + (pybop.PSO, "Particle Swarm Optimisation (PSO)"), + (pybop.IRPropMin, "iRprop-"), + ], + ) @pytest.mark.unit - def test_optimiser_construction(self): - # Tests construction of optimisers - - dataset = [ - pybop.Dataset("Time [s]", np.linspace(0, 360, 10)), - pybop.Dataset("Current function [A]", np.zeros(10)), - pybop.Dataset("Terminal voltage [V]", np.ones(10)), - ] - parameters = [ - pybop.Parameter( - "Negative electrode active material volume fraction", - prior=pybop.Gaussian(0.75, 0.2), - bounds=[0.73, 0.77], - ) - ] - - problem = pybop.Problem( - pybop.lithium_ion.SPM(), parameters, dataset, signal="Terminal voltage [V]" - ) - cost = pybop.SumSquaredError(problem) + def test_optimiser_classes(self, cost, optimiser_class, expected_name): + cost.bounds = None + opt = pybop.Optimisation(cost=cost, optimiser=optimiser_class) - # Test construction of optimisers - # NLopt - opt = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize) assert opt.optimiser is not None - assert opt.optimiser.name == "NLoptOptimize" - assert opt.optimiser.n_param == 1 + assert opt.optimiser.name() == expected_name - # Gradient Descent - opt = pybop.Optimisation(cost=cost, optimiser=pybop.GradientDescent) - assert opt.optimiser is not None + if optimiser_class not in [ + pybop.NLoptOptimize, + pybop.SciPyMinimize, + pybop.SciPyDifferentialEvolution, + ]: + assert opt.optimiser.boundaries is None - # None + if optimiser_class == pybop.NLoptOptimize: + assert opt.optimiser.n_param == 1 + + @pytest.mark.unit + def test_default_optimiser_with_bounds(self, cost): opt = pybop.Optimisation(cost=cost) - assert opt.optimiser is not None assert ( opt.optimiser.name() == "Covariance Matrix Adaptation Evolution Strategy (CMA-ES)" ) - # None with no bounds + @pytest.mark.unit + def test_default_optimiser_no_bounds(self, cost): cost.bounds = None opt = pybop.Optimisation(cost=cost) assert opt.optimiser.boundaries is None - # SciPy - opt = pybop.Optimisation(cost=cost, optimiser=pybop.SciPyMinimize) - assert opt.optimiser is not None - assert opt.optimiser.name == "SciPyMinimize" - - # Incorrect class - class randomclass: + @pytest.mark.unit + def test_incorrect_optimiser_class(self, cost): + class RandomClass: pass with pytest.raises(ValueError): - pybop.Optimisation(cost=cost, optimiser=randomclass) + pybop.Optimisation(cost=cost, optimiser=RandomClass) @pytest.mark.unit - def test_halting(self): - # Tests halting criteria - model = pybop.lithium_ion.SPM() + def test_standalone(self): + # Build an Optimisation problem with a StandaloneCost + cost = StandaloneCost() + opt = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize) + x, final_cost = opt.run() - dataset = [ - pybop.Dataset("Time [s]", np.linspace(0, 3600, 100)), - pybop.Dataset("Current function [A]", np.zeros(100)), - pybop.Dataset("Terminal voltage [V]", np.ones(100)), - ] + assert len(opt.x0) == opt.n_parameters + np.testing.assert_allclose(x, 0, atol=1e-2) + np.testing.assert_allclose(final_cost, 42, atol=1e-2) - param = [ - pybop.Parameter( - "Negative electrode active material volume fraction", - prior=pybop.Gaussian(0.75, 0.2), - bounds=[0.73, 0.77], - ) - ] + @pytest.mark.unit + def test_prior_sampling(self, cost): + # Tests prior sampling + for i in range(50): + opt = pybop.Optimisation(cost=cost, optimiser=pybop.NLoptOptimize) - problem = pybop.Problem(model, param, dataset, signal="Terminal voltage [V]") - cost = pybop.SumSquaredError(problem) + assert opt.x0 <= 0.77 and opt.x0 >= 0.73 + @pytest.mark.unit + def test_halting(self, cost): # Test max evalutions optim = pybop.Optimisation(cost=cost, optimiser=pybop.GradientDescent) optim.set_max_evaluations(10) diff --git a/tests/unit/test_parameter_sets.py b/tests/unit/test_parameter_sets.py index 9cc478525..fc9356d2f 100644 --- a/tests/unit/test_parameter_sets.py +++ b/tests/unit/test_parameter_sets.py @@ -12,9 +12,9 @@ class TestParameterSets: def test_parameter_set(self): # Tests parameter set creation with pytest.raises(ValueError): - pybop.ParameterSet("pybamms", "Chen2020") + pybop.ParameterSet.pybamm("sChen2010s") - parameter_test = pybop.ParameterSet("pybamm", "Chen2020") + parameter_test = pybop.ParameterSet.pybamm("Chen2020") np.testing.assert_allclose( parameter_test["Negative electrode active material volume fraction"], 0.75 ) diff --git a/tests/unit/test_parameterisations.py b/tests/unit/test_parameterisations.py index 142e590d0..8f3ffde9e 100644 --- a/tests/unit/test_parameterisations.py +++ b/tests/unit/test_parameterisations.py @@ -9,27 +9,14 @@ class TestModelParameterisation: A class to test the model parameterisation methods. """ - @pytest.mark.parametrize("init_soc", [0.3, 0.7]) - @pytest.mark.unit - def test_spm(self, init_soc): - # Define model - parameter_set = pybop.ParameterSet("pybamm", "Chen2020") - model = pybop.lithium_ion.SPM(parameter_set=parameter_set) - - # Form dataset - x0 = np.array([0.52, 0.63]) - solution = self.getdata(model, x0, init_soc) - - dataset = [ - pybop.Dataset("Time [s]", solution["Time [s]"].data), - pybop.Dataset("Current function [A]", solution["Current [A]"].data), - pybop.Dataset( - "Terminal voltage [V]", solution["Terminal voltage [V]"].data - ), - ] - - # Fitting parameters - parameters = [ + @pytest.fixture + def model(self): + parameter_set = pybop.ParameterSet.pybamm("Chen2020") + return pybop.lithium_ion.SPM(parameter_set=parameter_set) + + @pytest.fixture + def parameters(self): + return [ pybop.Parameter( "Negative electrode active material volume fraction", prior=pybop.Gaussian(0.5, 0.02), @@ -42,9 +29,26 @@ def test_spm(self, init_soc): ), ] + @pytest.fixture + def x0(self): + return np.array([0.52, 0.63]) + + @pytest.mark.parametrize("init_soc", [0.3, 0.7]) + @pytest.mark.unit + def test_spm(self, parameters, model, x0, init_soc): + # Form dataset + solution = self.getdata(model, x0, init_soc) + dataset = pybop.Dataset( + { + "Time [s]": solution["Time [s]"].data, + "Current function [A]": solution["Current [A]"].data, + "Terminal voltage [V]": solution["Terminal voltage [V]"].data, + } + ) + # Define the cost to optimise - signal = "Terminal voltage [V]" - problem = pybop.Problem( + signal = ["Terminal voltage [V]"] + problem = pybop.FittingProblem( model, parameters, dataset, signal=signal, init_soc=init_soc ) cost = pybop.RootMeanSquaredError(problem) @@ -62,113 +66,137 @@ def test_spm(self, init_soc): np.testing.assert_allclose(final_cost, 0, atol=1e-2) np.testing.assert_allclose(x, x0, atol=1e-1) - @pytest.mark.parametrize("init_soc", [0.3, 0.7]) - @pytest.mark.unit - def test_spme_optimisers(self, init_soc): - # Define model - parameter_set = pybop.ParameterSet("pybamm", "Chen2020") - model = pybop.lithium_ion.SPMe(parameter_set=parameter_set) - + @pytest.fixture + def spm_cost(self, parameters, model, x0): # Form dataset - x0 = np.array([0.52, 0.63]) + init_soc = 0.5 solution = self.getdata(model, x0, init_soc) - - dataset = [ - pybop.Dataset("Time [s]", solution["Time [s]"].data), - pybop.Dataset("Current function [A]", solution["Current [A]"].data), - pybop.Dataset( - "Terminal voltage [V]", solution["Terminal voltage [V]"].data - ), - ] - - # Fitting parameters - parameters = [ - pybop.Parameter( - "Negative electrode active material volume fraction", - prior=pybop.Gaussian(0.5, 0.02), - bounds=[0.375, 0.625], - ), - pybop.Parameter( - "Positive electrode active material volume fraction", - prior=pybop.Gaussian(0.65, 0.02), - bounds=[0.525, 0.75], - ), - ] + dataset = pybop.Dataset( + { + "Time [s]": solution["Time [s]"].data, + "Current function [A]": solution["Current [A]"].data, + "Terminal voltage [V]": solution["Terminal voltage [V]"].data, + } + ) # Define the cost to optimise - signal = "Terminal voltage [V]" - problem = pybop.Problem( + signal = ["Terminal voltage [V]"] + problem = pybop.FittingProblem( model, parameters, dataset, signal=signal, init_soc=init_soc ) - cost = pybop.RootMeanSquaredError(problem) + return pybop.SumSquaredError(problem) + + @pytest.mark.parametrize( + "optimiser", + [ + pybop.NLoptOptimize, + pybop.SciPyMinimize, + pybop.SciPyDifferentialEvolution, + pybop.Adam, + pybop.CMAES, + pybop.GradientDescent, + pybop.IRPropMin, + pybop.PSO, + pybop.SNES, + pybop.XNES, + ], + ) + @pytest.mark.unit + def test_spm_optimisers(self, optimiser, spm_cost, x0): + # Test each optimiser + parameterisation = pybop.Optimisation(cost=spm_cost, optimiser=optimiser) + parameterisation.set_max_unchanged_iterations(iterations=15, threshold=5e-4) - # Select optimisers - optimisers = [pybop.NLoptOptimize, pybop.SciPyMinimize, pybop.CMAES] + if optimiser in [pybop.CMAES]: + parameterisation.set_f_guessed_tracking(True) + assert parameterisation._use_f_guessed is True + parameterisation.set_max_iterations(1) + x, final_cost = parameterisation.run() - # Test each optimiser - for optimiser in optimisers: - parameterisation = pybop.Optimisation(cost=cost, optimiser=optimiser) + parameterisation.set_f_guessed_tracking(False) + parameterisation.set_max_iterations(100) - if optimiser == pybop.CMAES: - parameterisation.set_f_guessed_tracking(True) - assert parameterisation._use_f_guessed is True - parameterisation.set_max_iterations(1) - x, final_cost = parameterisation.run() + x, final_cost = parameterisation.run() + assert parameterisation._max_iterations == 100 - parameterisation.set_f_guessed_tracking(False) - parameterisation.set_max_iterations(250) + elif optimiser in [pybop.GradientDescent]: + parameterisation.optimiser.set_learning_rate(0.025) + parameterisation.set_max_iterations(100) + x, final_cost = parameterisation.run() - x, final_cost = parameterisation.run() - assert parameterisation._max_iterations == 250 + else: + parameterisation.set_max_iterations(100) + x, final_cost = parameterisation.run() - else: - x, final_cost = parameterisation.run() + # Assertions + np.testing.assert_allclose(final_cost, 0, atol=1e-2) + np.testing.assert_allclose(x, x0, atol=1e-1) - # Assertions - np.testing.assert_allclose(final_cost, 0, atol=1e-2) - np.testing.assert_allclose(x, x0, atol=1e-1) + @pytest.fixture + def spm_two_signal_cost(self, parameters, model, x0): + # Form dataset + init_soc = 0.5 + solution = self.getdata(model, x0, init_soc) + dataset = pybop.Dataset( + { + "Time [s]": solution["Time [s]"].data, + "Current function [A]": solution["Current [A]"].data, + "Terminal voltage [V]": solution["Terminal voltage [V]"].data, + } + ) + + # Define the cost to optimise + signal = ["Terminal voltage [V]", "Time [s]"] + problem = pybop.FittingProblem( + model, parameters, dataset, signal=signal, init_soc=init_soc + ) + return pybop.SumSquaredError(problem) + + @pytest.mark.parametrize( + "optimiser", + [ + pybop.NLoptOptimize, + pybop.SciPyMinimize, + pybop.Adam, + pybop.CMAES, + ], + ) + @pytest.mark.unit + def test_multiple_signals(self, optimiser, spm_two_signal_cost, x0): + # Test each optimiser + parameterisation = pybop.Optimisation( + cost=spm_two_signal_cost, optimiser=optimiser + ) + parameterisation.set_max_unchanged_iterations(iterations=15, threshold=5e-4) + parameterisation.set_max_iterations(100) + + x, final_cost = parameterisation.run() + + # Assertions + np.testing.assert_allclose(final_cost, 0, atol=2e-2) + np.testing.assert_allclose(x, x0, atol=1e-1) @pytest.mark.parametrize("init_soc", [0.3, 0.7]) @pytest.mark.unit - def test_model_misparameterisation(self, init_soc): + def test_model_misparameterisation(self, parameters, model, x0, init_soc): # Define two different models with different parameter sets # The optimisation should fail as the models are not the same - - parameter_set = pybop.ParameterSet("pybamm", "Chen2020") - model = pybop.lithium_ion.SPM(parameter_set=parameter_set) - - second_parameter_set = pybop.ParameterSet("pybamm", "Ecker2015") + second_parameter_set = pybop.ParameterSet.pybamm("Ecker2015") second_model = pybop.lithium_ion.SPM(parameter_set=second_parameter_set) - # Form observations - x0 = np.array([0.52, 0.63]) + # Form dataset solution = self.getdata(second_model, x0, init_soc) - - dataset = [ - pybop.Dataset("Time [s]", solution["Time [s]"].data), - pybop.Dataset("Current function [A]", solution["Current [A]"].data), - pybop.Dataset( - "Terminal voltage [V]", solution["Terminal voltage [V]"].data - ), - ] - - # Fitting parameters - parameters = [ - pybop.Parameter( - "Negative electrode active material volume fraction", - prior=pybop.Gaussian(0.5, 0.02), - bounds=[0.375, 0.625], - ), - pybop.Parameter( - "Positive electrode active material volume fraction", - prior=pybop.Gaussian(0.65, 0.02), - bounds=[0.525, 0.75], - ), - ] + dataset = pybop.Dataset( + { + "Time [s]": solution["Time [s]"].data, + "Current function [A]": solution["Current [A]"].data, + "Terminal voltage [V]": solution["Terminal voltage [V]"].data, + } + ) # Define the cost to optimise - signal = "Terminal voltage [V]" - problem = pybop.Problem( + signal = ["Terminal voltage [V]"] + problem = pybop.FittingProblem( model, parameters, dataset, signal=signal, init_soc=init_soc ) cost = pybop.RootMeanSquaredError(problem) diff --git a/tests/unit/test_plotting.py b/tests/unit/test_plotting.py new file mode 100644 index 000000000..92a327c61 --- /dev/null +++ b/tests/unit/test_plotting.py @@ -0,0 +1,113 @@ +from importlib.metadata import distributions +from distutils.spawn import find_executable +from pybop import PlotlyManager +import subprocess +import plotly +import pytest + +# Find the Python executable +python_executable = find_executable("python") + + +@pytest.fixture(scope="session") +def plotly_installed(): + """A session-level fixture that ensures Plotly is installed after tests.""" + # Check if Plotly is initially installed + initially_installed = is_package_installed("plotly") + + # If Plotly is not installed initially, install it + if not initially_installed: + subprocess.check_call([python_executable, "-m", "pip", "install", "plotly"]) + + # Yield control back to the tests + yield + + # After tests, if Plotly was not installed initially, uninstall it + if not initially_installed: + subprocess.check_call( + [python_executable, "-m", "pip", "uninstall", "plotly", "-y"] + ) + + +@pytest.fixture(scope="function") +def uninstall_plotly_if_installed(): + """A fixture to uninstall Plotly if it's installed before a test and reinstall it afterwards.""" + # Check if Plotly is installed before the test + was_installed = is_package_installed("plotly") + + # If Plotly is installed, uninstall it + if was_installed: + subprocess.check_call( + [python_executable, "-m", "pip", "uninstall", "plotly", "-y"] + ) + + # Yield control back to the test + yield + + # If Plotly was uninstalled for the test, reinstall it afterwards + if was_installed: + subprocess.check_call([python_executable, "-m", "pip", "install", "plotly"]) + + # Reset the default renderer for tests + plotly.io.renderers.default = None + + +@pytest.mark.unit +def test_initialization_with_plotly_installed(plotly_installed): + """Test initialization when Plotly is installed.""" + assert is_package_installed("plotly") + plotly_manager = PlotlyManager() + + import plotly.graph_objs as go + import plotly.io as pio + from plotly.subplots import make_subplots + + assert plotly_manager.go == go + assert plotly_manager.pio == pio + assert plotly_manager.make_subplots == make_subplots + + +@pytest.mark.unit +def test_prompt_for_plotly_installation(mocker, uninstall_plotly_if_installed): + """Test prompt for Plotly installation when not installed.""" + assert not is_package_installed("plotly") + mocker.patch("builtins.input", return_value="y") + plotly_manager = PlotlyManager() + + import plotly.graph_objs as go + import plotly.io as pio + from plotly.subplots import make_subplots + + assert plotly_manager.go == go + assert plotly_manager.pio == pio + assert plotly_manager.make_subplots == make_subplots + + +@pytest.mark.unit +def test_cancel_installation(mocker, uninstall_plotly_if_installed): + """Test exit if Plotly installation is canceled.""" + assert not is_package_installed("plotly") + mocker.patch("builtins.input", return_value="n") + with pytest.raises(SystemExit) as pytest_wrapped_e: + PlotlyManager().prompt_for_plotly_installation() + + assert pytest_wrapped_e.type == SystemExit + assert pytest_wrapped_e.value.code == 1 + assert not is_package_installed("plotly") + + +@pytest.mark.unit +def test_post_install_setup(plotly_installed): + """Test post-install setup.""" + plotly_manager = PlotlyManager() + plotly_manager.post_install_setup() + + assert plotly_manager.pio.renderers.default == "browser" + + # Reset the default renderer for tests + plotly.io.renderers.default = None + + +def is_package_installed(package_name): + """Check if a package is installed without raising an exception.""" + return any(d.metadata["Name"] == package_name for d in distributions()) diff --git a/tests/unit/test_problem.py b/tests/unit/test_problem.py index aa470d9b4..976388e94 100644 --- a/tests/unit/test_problem.py +++ b/tests/unit/test_problem.py @@ -9,11 +9,13 @@ class TestProblem: A class to test the problem class. """ - @pytest.mark.unit - def test_problem(self): - # Define model - model = pybop.lithium_ion.SPM() - parameters = [ + @pytest.fixture + def model(self): + return pybop.lithium_ion.SPM() + + @pytest.fixture + def parameters(self): + return [ pybop.Parameter( "Negative electrode active material volume fraction", prior=pybop.Gaussian(0.5, 0.02), @@ -25,24 +27,73 @@ def test_problem(self): bounds=[0.525, 0.75], ), ] - signal = "Voltage [V]" - # Form dataset + @pytest.fixture + def experiment(self): + return pybamm.Experiment( + [ + ( + "Discharge at 1C for 5 minutes (1 second period)", + "Rest for 2 minutes (1 second period)", + "Charge at 1C for 5 minutes (1 second period)", + "Rest for 2 minutes (1 second period)", + ), + ] + * 2 + ) + + @pytest.fixture + def dataset(self, model, experiment): + model.parameter_set = model.pybamm_model.default_parameter_values x0 = np.array([0.52, 0.63]) - solution = self.getdata(model, x0) + model.parameter_set.update( + { + "Negative electrode active material volume fraction": x0[0], + "Positive electrode active material volume fraction": x0[1], + } + ) + solution = model.predict(experiment=experiment) + return pybop.Dataset( + { + "Time [s]": solution["Time [s]"].data, + "Current function [A]": solution["Current [A]"].data, + "Voltage [V]": solution["Terminal voltage [V]"].data, + } + ) - dataset = [ - pybop.Dataset("Time [s]", solution["Time [s]"].data), - pybop.Dataset("Current function [A]", solution["Current [A]"].data), - pybop.Dataset("Voltage [V]", solution["Terminal voltage [V]"].data), - ] + @pytest.fixture + def signal(self): + return "Voltage [V]" + + @pytest.mark.unit + def test_base_problem(self, parameters, model): + # Test incorrect number of initial parameter values + with pytest.raises(ValueError): + pybop._problem.BaseProblem(parameters, model=model, x0=np.array([])) + + # Construct Problem + problem = pybop._problem.BaseProblem(parameters, model=model) + + assert problem._model == model + with pytest.raises(NotImplementedError): + problem.evaluate([0.5, 0.5]) + with pytest.raises(NotImplementedError): + problem.evaluateS1([0.5, 0.5]) + + with pytest.raises(ValueError): + pybop._problem.BaseProblem(parameters, model=model, signal=[0.5, 0.5]) + + @pytest.mark.unit + def test_fitting_problem(self, parameters, dataset, model, signal): # Test incorrect number of initial parameter values with pytest.raises(ValueError): - pybop.Problem(model, parameters, dataset, signal=signal, x0=np.array([])) + pybop.FittingProblem( + model, parameters, dataset, signal=signal, x0=np.array([]) + ) # Construct Problem - problem = pybop.Problem(model, parameters, dataset, signal=signal) + problem = pybop.FittingProblem(model, parameters, dataset, signal=signal) assert problem._model == model assert problem._model._built_model is not None @@ -50,25 +101,47 @@ def test_problem(self): # Test model.simulate model.simulate(inputs=[0.5, 0.5], t_eval=np.linspace(0, 10, 100)) - def getdata(self, model, x0): - model.parameter_set = model.pybamm_model.default_parameter_values + # Test problem construction errors + for bad_dataset in [ + pybop.Dataset({"Time [s]": np.array([0])}), + pybop.Dataset( + { + "Time [s]": np.array([-1]), + "Current function [A]": np.array([0]), + "Voltage [V]": np.array([0]), + } + ), + pybop.Dataset( + { + "Time [s]": np.array([1, 0]), + "Current function [A]": np.array([0, 0]), + "Voltage [V]": np.array([0, 0]), + } + ), + pybop.Dataset( + { + "Time [s]": np.array([0]), + "Current function [A]": np.array([0, 0]), + "Voltage [V]": np.array([0, 0]), + } + ), + ]: + with pytest.raises(ValueError): + pybop.FittingProblem(model, parameters, bad_dataset, signal=signal) - model.parameter_set.update( - { - "Negative electrode active material volume fraction": x0[0], - "Positive electrode active material volume fraction": x0[1], - } - ) - experiment = pybamm.Experiment( - [ - ( - "Discharge at 1C for 5 minutes (1 second period)", - "Rest for 2 minutes (1 second period)", - "Charge at 1C for 5 minutes (1 second period)", - "Rest for 2 minutes (1 second period)", - ), - ] - * 2 - ) - sim = model.predict(experiment=experiment) - return sim + @pytest.mark.unit + def test_design_problem(self, parameters, experiment, model): + # Test incorrect number of initial parameter values + with pytest.raises(ValueError): + pybop.DesignProblem(model, parameters, experiment, x0=np.array([])) + + # Construct Problem + problem = pybop.DesignProblem(model, parameters, experiment) + + assert problem._model == model + assert ( + problem._model._built_model is None + ) # building postponed with input experiment + + # Test model.predict + model.predict(inputs=[0.5, 0.5], experiment=experiment)