Skip to content

Commit

Permalink
Merge pull request #2862 from agriyakhetarpal/issue-1182-tag-citations
Browse files Browse the repository at this point in the history
Issue 1182 verbose outputs and tagging PyBaMM citations
  • Loading branch information
rtimms authored Apr 13, 2023
2 parents 2c32902 + a460035 commit 7c69f1d
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

# Features

- Added verbose logging to `pybamm.print_citations()` and citation tags for the `pybamm.Citations` class so that users can now see where the citations were registered when running simulations ([#2862](https://github.com/pybamm-team/PyBaMM/pull/2862))
- PyBaMM is now natively supported on Apple silicon chips (`M1/M2`) ([#2435](https://github.com/pybamm-team/PyBaMM/pull/2435))
- PyBaMM is now supported on Python `3.10` and `3.11` ([#2435](https://github.com/pybamm-team/PyBaMM/pull/2435))
- Updated to casadi 3.6, which required some changes to the casadi integrator. ([#2859](https://github.com/pybamm-team/PyBaMM/pull/2859))
Expand Down
91 changes: 85 additions & 6 deletions pybamm/citations.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import os
import warnings
import pybtex
from inspect import stack
from pybtex.database import parse_file, parse_string, Entry
from pybtex.scanner import PybtexError

Expand Down Expand Up @@ -35,6 +36,9 @@ def __init__(self):
# Dict mapping citations keys to BibTex entries
self._all_citations: dict[str, str] = dict()

# Dict mapping citation tags for use when registering citations
self._citation_tags = dict()

# store citation error
self._citation_err_msg = None

Expand All @@ -48,10 +52,21 @@ def _reset(self):
"""Reset citations to default only (only for testing purposes)"""
# Initialize empty papers to cite
self._papers_to_cite = set()
# Initialize empty citation tags
self._citation_tags = dict()
# Register the PyBaMM paper and the numpy paper
self.register("Sulzer2021")
self.register("Harris2020")

def _caller_name():
"""
Returns the qualified name of classes that call :meth:`register` internally.
This is used for tagging citations but only for verbose output
"""
# Attributed to https://stackoverflow.com/a/17065634
caller_name = stack()[2][0].f_locals["self"].__class__.__qualname__
return caller_name

def read_citations(self):
"""Reads the citations in `pybamm.CITATIONS.txt`. Other works can be cited
by passing a BibTeX citation to :meth:`register`.
Expand All @@ -78,6 +93,14 @@ def _add_citation(self, key, entry):
# Add to database
self._all_citations[key] = new_citation

def _add_citation_tag(self, key, entry):
"""Adds a tag for a citation key which represents the name of the class that
called :meth:`register`"""

# Add a citation tag to the citation_tags ordered dictionary with
# the key being the citation itself and the value being the name of the class
self._citation_tags[key] = entry

@property
def _cited(self):
"""Return a list of the BibTeX entries that have been cited"""
Expand All @@ -101,6 +124,14 @@ def register(self, key):
# Check if citation is a known key
if key in self._all_citations:
self._papers_to_cite.add(key)
# Add citation tags for the key
# This is used for verbose output
try:
caller = Citations._caller_name()
self._add_citation_tag(key, entry=caller)
# Don't add citation tags if the citation is registered manually
except KeyError: # pragma: no cover
pass
return

# Try to parse the citation using pybtex
Expand All @@ -119,14 +150,54 @@ def register(self, key):
# Unable to parse / unknown key
raise KeyError(f"Not a bibtex citation or known citation: {key}")

def print(self, filename=None, output_format="text"):
"""Print all citations that were used for running simulations.
def tag_citations(self): # pragma: no cover
"""Prints the citations tags for the citations that have been registered
(non-manually). This is used for verbose output when printing citations
such that it can be seen which citations were registered by PyBaMM classes.
To use, either call :meth:`tag_citations` after calling :meth:`register`
for all citations, or enable verbose output with :meth:`print_citations`
or :meth:`print`.
.. note::
If a citation is registered manually, it will not be tagged.
Examples
--------
.. code-block:: python
:linenos:
pybamm.citations.register("Doyle1993")
pybamm.citations.print() or pybamm.print_citations()
will print the following:
.. code-block::
Citations registered:
Sulzer2021 was cited due to the use of
pybamm.models.full_battery_models.lithium_ion.dfn
"""
if self._citation_tags:
print("\n Citations registered: \n")
for key, entry in self._citation_tags.items():
print(f"{key} was cited due to the use of {entry}")

def print(self, filename=None, output_format="text", verbose=False):
"""Print all citations that were used for running simulations. The verbose
option is provided to print the citation tags for the citations that have
been registered non-manually. This is available only upon printing
to the terminal.
Parameters
----------
filename : str, optional
Filename to which to print citations. If None, citations are printed to the
terminal.
Filename to which to print citations. If None, citations are printed
to the terminal.
verbose: bool, optional
If True, prints the citation tags for the citations that have been
registered
"""
if output_format == "text":
citations = pybtex.format_from_strings(
Expand All @@ -142,12 +213,14 @@ def print(self, filename=None, output_format="text"):

if filename is None:
print(citations)
if verbose:
self.tag_citations() # pragma: no cover
else:
with open(filename, "w") as f:
f.write(citations)


def print_citations(filename=None, output_format="text"):
def print_citations(filename=None, output_format="text", verbose=False):
"""See :meth:`Citations.print`"""
if citations._citation_err_msg is not None:
raise ImportError(
Expand All @@ -159,7 +232,13 @@ def print_citations(filename=None, output_format="text"):
f"{citations._citation_err_msg}"
)
else:
pybamm.citations.print(filename, output_format)
if verbose: # pragma: no cover
warnings.warn(
"Verbose output is not available for printing to files, only to the terminal" # noqa: E501
)
pybamm.citations.print(filename, output_format, verbose=True)
else:
pybamm.citations.print(filename, output_format)


citations = Citations()
Loading

0 comments on commit 7c69f1d

Please sign in to comment.