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

add script and workflow to update parameter_sets.py #1371

Merged
merged 12 commits into from
Feb 11, 2021
41 changes: 41 additions & 0 deletions .github/workflows/update_parameter_sets_doc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Update parameter_sets.py docstring

on:
push:
paths:
- 'pybamm/parameters/parameter_sets.py'
- 'pybamm/parameters/CITATIONS.txt'

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.8]

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install wheel
pip install --editable .
pip install pybtex
- name: Update docstring
run: python pybamm/parameters/update_parameter_sets_doc.py
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
delete-branch: true
branch-suffix: short-commit-hash
commit-message: update parameter_sets
title: Update parameter_sets.py docstring
body: |
Update docstring of parameter_sets.py

Auto-generated pull request
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

## Optimizations

- Add script and workflow to automatically update parameter_sets.py docstrings ([#1371](https://github.com/pybamm-team/PyBaMM/pull/1371))
- Add URLs checker in workflows ([#1347](https://github.com/pybamm-team/PyBaMM/pull/1347))
- The `Solution` class now only creates the concatenated `y` when the user asks for it. This is an optimization step as the concatenation can be slow, especially with larger experiments ([#1331](https://github.com/pybamm-team/PyBaMM/pull/1331))
- If solver method `solve()` is passed a list of inputs as the `inputs` keyword argument, the resolution of the model for each input set is spread across several Python processes, usually running in parallel on different processors. The default number of processes is the number of processors available. `solve()` takes a new keyword argument `nproc` which can be used to set this number a manually.
Expand Down
119 changes: 119 additions & 0 deletions pybamm/parameters/update_parameter_sets_doc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"""
Automatically update the docstring of parameter_sets.py
"""

from collections import defaultdict
import os
import re

import pybtex

import pybamm
from pybamm.parameters import parameter_sets


DOC_INTRO = """
Parameter sets from papers. The 'citation' entry provides a reference to the appropriate
paper in the file "pybamm/CITATIONS.txt". To see which parameter sets have been used in
your simulation, add the line "pybamm.print_citations()" to your script."""


def get_ps_dict():
"""
Returns {chemistry:(author_year, [citations])} from all dictionaries in
parameter_sets.py
"""
parameter_set_dict = defaultdict(list)
for ps_name, ps_dict in parameter_sets.__dict__.items():
if not isinstance(ps_dict, dict):
continue
elif "citation" not in ps_dict or "chemistry" not in ps_dict:
continue

chemistry = ps_dict["chemistry"]
citation = ps_dict["citation"]

# Enclose citation in a list if not already enclosed
if not isinstance(citation, list):
citation = [citation]

parameter_set_dict[chemistry].append((ps_name, citation))
return parameter_set_dict


def generate_ps_doc(parameter_set_dict):
"""
Generates docstring of parameter_sets.py from the given dictionary
"""
output_list = [DOC_INTRO]
citations_file = os.path.join(pybamm.root_dir(), "pybamm", "CITATIONS.txt")

for ps_chemistry in sorted(parameter_set_dict.keys()):
output_list.append("")
ps_citations = parameter_set_dict[ps_chemistry]
chem_name = ps_chemistry.capitalize() + " " + "parameter sets"
output_list.append(chem_name)
dashes = "-" * len(ps_chemistry) + "-" * 15
output_list.append(dashes)

for ps_name, ps_citation in sorted(ps_citations):
citations = pybtex.format_from_file(
citations_file,
style="plain",
output_backend="plaintext",
citations=ps_citation,
nocite=True,
)
# Remove citation labels "[3]"
citations = re.split(r"(?:^|\n)\[\d+\]\s", citations)
# Remove empty strings
citations = filter(bool, citations)
fmt_citations = []
for citation in citations:
# Break line at the first space before 80 characters
citation_parts = re.findall(r"(.{1,80})(?:\s|$)", citation)
# first_line = citation.split('\n')

indent_citation_parts = []
for idx, citation_part in enumerate(citation_parts):
if idx == 0:
citation_part = "- " + citation_part
else:
citation_part = " " + citation_part
indent_citation_parts.append(" " * 6 + citation_part)

# Join to create a single citation paragraph
citation = "\n".join(indent_citation_parts)
fmt_citations.append(citation)
fmt_citations = "\n".join(fmt_citations)
ps_doc = f" * {ps_name:} :\n{fmt_citations}"
output_list.append(ps_doc)

output = "\n".join(output_list)
output += "\n"
return output


def update_doc(generated_doc):
"""
Opens parameter_sets.py, replaces the docstring and then writes it
"""
with open(
os.path.join(pybamm.root_dir(), "pybamm", "parameters", "parameter_sets.py"),
"r+",
) as ps_fp:
ps_output = ps_fp.read()
ps_output = ps_output.replace(parameter_sets.__doc__, generated_doc)
ps_fp.truncate(0)
ps_fp.seek(0)
ps_fp.write(ps_output)


def main():
parameter_set_dict = get_ps_dict()
generated_doc = generate_ps_doc(parameter_set_dict)
update_doc(generated_doc)


if __name__ == "__main__":
main()
66 changes: 66 additions & 0 deletions tests/unit/test_parameters/test_update_parameter_sets_doc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
Tests for the update_parameter_sets_doc.py
"""
from pybamm.parameters.update_parameter_sets_doc import get_ps_dict, generate_ps_doc
import pybamm
import unittest


DOC = """
Parameter sets from papers. The 'citation' entry provides a reference to the appropriate
paper in the file "pybamm/CITATIONS.txt". To see which parameter sets have been used in
your simulation, add the line "pybamm.print_citations()" to your script.

Lead-acid parameter sets
------------------------
* Sulzer2019 :
- Valentin Sulzer, S. Jon Chapman, Colin P. Please, David A. Howey, and Charles W.
Monroe. Faster Lead-Acid Battery Simulations from Porous-Electrode Theory: Part
I. Physical Model. Journal of The Electrochemical Society, 166(12):A2363–A2371,
2019. doi:10.1149/2.0301910jes.

Lithium-ion parameter sets
--------------------------
* Prada2013 :
- Chang-Hui Chen, Ferran Brosa Planella, Kieran O'Regan, Dominika Gastol, W.
Dhammika Widanage, and Emma Kendrick. Development of Experimental Techniques for
Parameterization of Multi-scale Lithium-ion Battery Models. Journal of The
Electrochemical Society, 167(8):080534, 2020. doi:10.1149/1945-7111/ab9050.
- Michael J. Lain, James Brandon, and Emma Kendrick. Design strategies for high
power vs. high energy lithium ion cells. Batteries, 5(4):64, 2019.
doi:10.3390/batteries5040064.
- Eric Prada, D. Di Domenico, Y. Creff, J. Bernard, Valérie Sauvant-Moynot, and
François Huet. A simplified electrochemical and thermal aging model of
LiFePO4-graphite Li-ion batteries: power and capacity fade simulations. Journal
of The Electrochemical Society, 160(4):A616, 2013. doi:10.1149/2.053304jes.
"""

AUTHOR_YEAR_DICT = {
"lithium-ion": [
("Prada2013", ["Chen2020", "Lain2019", "Prada2013"]),
],
"lead-acid": [("Sulzer2019", ["Sulzer2019physical"])],
}


class TestUpdateParameterSetsDoc(unittest.TestCase):
def test_get_ps_dict(self):
output = get_ps_dict()
for key, values in AUTHOR_YEAR_DICT.items():
output_values = output.get(key, [])
for value in values:
self.assertIn(value, output_values)

def test_generate_ps_doc(self):
output = generate_ps_doc(AUTHOR_YEAR_DICT)
self.assertEqual(output, DOC)


if __name__ == "__main__":
print("Add -v for more debug output")
import sys

if "-v" in sys.argv:
debug = True
pybamm.settings.debug_mode = True
unittest.main()