Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds plotting methods #115

Merged
merged 21 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ecf995d
Add plot_cost2d with example addition
BradyPlanden Nov 21, 2023
2b06d18
Updt noxfile, setup.py for plotly dependency
BradyPlanden Nov 21, 2023
68d5a4d
Updt remaining noxfile sessions for [plot]
BradyPlanden Nov 21, 2023
c2e32f0
Add quick_plot()
BradyPlanden Nov 23, 2023
c2575e8
Add optimiser trace to plot_cost2d, restore plotly theme to quick_plot
BradyPlanden Nov 23, 2023
5f28480
Add convergence_plot(), refactor plotting methods into StandardPlot()…
BradyPlanden Nov 23, 2023
f1e5f4e
Merge branch 'develop' into 114-plotting-classes
BradyPlanden Nov 23, 2023
bef09c9
Revert to plotly import on init, Updt. changelog
BradyPlanden Nov 23, 2023
e0cd5b5
Add optimiser.name() to optimisers, updt. plotting across examples, c…
BradyPlanden Nov 23, 2023
42325aa
Add plot_parameters() method, bugfix pytest flags, updt. examples
BradyPlanden Nov 24, 2023
51e07e7
Adds and displays timing to testing suite
BradyPlanden Nov 29, 2023
329c36f
Updt. cost_2d() with optional bounds arg + example, updt. contributin…
BradyPlanden Nov 29, 2023
605e20b
Add browser check
NicolaCourtier Nov 30, 2023
05a36fa
style: pre-commit fixes
pre-commit-ci[bot] Nov 30, 2023
7ffaa37
Fix typo
NicolaCourtier Nov 30, 2023
6edfa6e
Update plotly browser catch, Add logic to install plotly if not alrea…
BradyPlanden Nov 30, 2023
d02bb95
Adds user prompt for plotly install, uncomments plotly install code
BradyPlanden Nov 30, 2023
d9c429e
Add Plotly install help for WSL users
NicolaCourtier Nov 30, 2023
6955044
Add PlotManager class for plotly installation, add tests for plotly i…
BradyPlanden Dec 1, 2023
27a88aa
Updt. noxfile for pytest-mock requirement
BradyPlanden Dec 1, 2023
1e505ee
Add pytest-mock to nofile coverage
BradyPlanden Dec 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# [Unreleased](https://github.com/pybop-team/PyBOP)

## Features
- [#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
- [#116](https://github.com/pybop-team/PyBOP/issues/116) - Adds PSO, SNES, XNES, ADAM, and IPropMin optimisers to PintsOptimisers() class

## Bug Fixes

# [v23.11](https://github.com/pybop-team/PyBOP/releases/tag/v23.11)
- Initial release
- Adds Pints, NLOpt, and SciPy optimisers
Expand Down
17 changes: 15 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
# Contributing to PyBOP

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.

## 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:
Expand Down Expand Up @@ -123,7 +136,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
Expand Down
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,7 @@ To alternatively install PyBOP from a local directory, use the following templat
pip install -e "path/to/pybop"
```

To check whether PyBOP has been installed correctly, run one of the examples in the following section or the full set of unit tests:

```bash
pytest --unit -v
```
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:
Expand Down
34 changes: 21 additions & 13 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pytest
import matplotlib
import plotly
BradyPlanden marked this conversation as resolved.
Show resolved Hide resolved

plotly.io.renderers.default = None
matplotlib.use("Template")


Expand All @@ -13,24 +15,30 @@ def pytest_addoption(parser):
)


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):
def skip_marker(marker_name, reason):
skip = pytest.mark.skip(reason=reason)
if config.getoption("--unit") and not config.getoption("--examples"):
skip_examples = pytest.mark.skip(
reason="need --examples option to run examples tests"
)
for item in items:
if marker_name in item.keywords:
item.add_marker(skip)

if config.getoption("--unit"):
skip_marker("examples", "need --examples option to run")
return
if "examples" in item.keywords:
item.add_marker(skip_examples)

if config.getoption("--examples"):
skip_marker("unit", "need --unit option to run")
return

skip_marker("unit", "need --unit option to run")
if config.getoption("--examples") and not config.getoption("--unit"):
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)
32 changes: 19 additions & 13 deletions examples/scripts/spm_CMAES.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pybop
import numpy as np
import matplotlib.pyplot as plt

# Define model
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPM(parameter_set=parameter_set)

Expand All @@ -19,13 +19,15 @@
),
]

# Generate data
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)
)

# Form dataset for optimisation
dataset = [
pybop.Dataset("Time [s]", t_eval),
pybop.Dataset("Current function [A]", values["Current [A]"].data),
Expand All @@ -38,18 +40,22 @@
optim = pybop.Optimisation(cost, optimiser=pybop.CMAES)
optim.set_max_iterations(100)

# Run the optimisation
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()
# 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)
28 changes: 15 additions & 13 deletions examples/scripts/spm_IRPropMin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pybop
import numpy as np
import matplotlib.pyplot as plt

# Define model
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPM(parameter_set=parameter_set)

Expand Down Expand Up @@ -41,15 +41,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, 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()
# 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)
28 changes: 15 additions & 13 deletions examples/scripts/spm_SNES.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pybop
import numpy as np
import matplotlib.pyplot as plt

# Define model
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPM(parameter_set=parameter_set)

Expand Down Expand Up @@ -41,15 +41,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, 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()
# 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)
28 changes: 15 additions & 13 deletions examples/scripts/spm_XNES.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pybop
import numpy as np
import matplotlib.pyplot as plt

# Define model
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
model = pybop.lithium_ion.SPM(parameter_set=parameter_set)

Expand Down Expand Up @@ -41,15 +41,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, 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()
# 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)
27 changes: 14 additions & 13 deletions examples/scripts/spm_adam.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pybop
import numpy as np
import matplotlib.pyplot as plt

# Parameter set and model definition
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
Expand Down Expand Up @@ -45,15 +44,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)
27 changes: 14 additions & 13 deletions examples/scripts/spm_descent.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pybop
import numpy as np
import matplotlib.pyplot as plt

# Parameter set and model definition
parameter_set = pybop.ParameterSet("pybamm", "Chen2020")
Expand Down Expand Up @@ -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)
Loading