#! /usr/bin/env python
r"""Registry of landlab components being used.
The landlab registry keeps track of landlab components that have
be instantiated by a user. A user can then get a list of all
the components in use and then print a list of citations for
all of the components they have used.
Examples
--------
>>> from landlab import registry
>>> registry.registered
('landlab',)
>>> print(registry.format_citations())
# Citations
## landlab
@article{hobley2017creative,
title={Creative computing with Landlab: an open-source toolkit
for building, coupling, and exploring two-dimensional
numerical models of Earth-surface dynamics},
author={Hobley, Daniel EJ and Adams, Jordan M and Nudurupati,
Sai Siddhartha and Hutton, Eric WH and Gasparini, Nicole M and
Istanbulluoglu, Erkan and Tucker, Gregory E},
journal={Earth Surface Dynamics},
volume={5},
number={1},
pages={21},
year={2017},
publisher={Copernicus GmbH}
}
@article{barnhart2020short,
author = {Barnhart, K. R. and Hutton, E. W. H. and Tucker, G. E.
and Gasparini, N. M. and Istanbulluoglu, E. and Hobley,
D. E. J. and Lyons, N. J. and Mouchene, M. and Nudurupati,
S. S. and Adams, J. M. and Bandaragoda, C.},
title = {Short communication: Landlab v2.0: A software package
for Earth surface dynamics},
journal = {Earth Surface Dynamics Discussions},
volume = {2020},
year = {2020},
pages = {1--25},
url = {https://www.earth-surf-dynam-discuss.net/esurf-2020-12/},
doi = {10.5194/esurf-2020-12}
}
When a component contains citation information, and the component has been
instantiated (not just imported) the component citation is also included.
>>> from landlab import RasterModelGrid
>>> from landlab.components import Flexure
>>> grid = RasterModelGrid((4, 5))
>>> _ = grid.add_zeros("lithosphere__overlying_pressure_increment", at="node")
>>> _ = grid.add_zeros("lithosphere_surface__elevation_increment", at="node")
>>> flexure = Flexure(grid)
>>> print(registry.format_citations())
# Citations
## landlab
@article{hobley2017creative,
title={Creative computing with Landlab: an open-source toolkit
for building, coupling, and exploring two-dimensional
numerical models of Earth-surface dynamics},
author={Hobley, Daniel EJ and Adams, Jordan M and Nudurupati,
Sai Siddhartha and Hutton, Eric WH and Gasparini, Nicole M and
Istanbulluoglu, Erkan and Tucker, Gregory E},
journal={Earth Surface Dynamics},
volume={5},
number={1},
pages={21},
year={2017},
publisher={Copernicus GmbH}
}
@article{barnhart2020short,
author = {Barnhart, K. R. and Hutton, E. W. H. and Tucker, G. E.
and Gasparini, N. M. and Istanbulluoglu, E. and Hobley,
D. E. J. and Lyons, N. J. and Mouchene, M. and Nudurupati,
S. S. and Adams, J. M. and Bandaragoda, C.},
title = {Short communication: Landlab v2.0: A software package
for Earth surface dynamics},
journal = {Earth Surface Dynamics Discussions},
volume = {2020},
year = {2020},
pages = {1--25},
url = {https://www.earth-surf-dynam-discuss.net/esurf-2020-12/},
doi = {10.5194/esurf-2020-12}
}
<BLANKLINE>
## Flexure
@article{hutton2008sedflux,
title={Sedflux 2.0: An advanced process-response model that
generates three-dimensional stratigraphy},
author={Hutton, Eric WH and Syvitski, James PM},
journal={Computers \& Geosciences},
volume={34},
number={10},
pages={1319--1337},
year={2008},
publisher={Pergamon}
}
Finally, the component's citation information is accessible through an
attribute called ``cite_as``:
>>> print(Flexure.cite_as)
@article{hutton2008sedflux,
title={Sedflux 2.0: An advanced process-response model that
generates three-dimensional stratigraphy},
author={Hutton, Eric WH and Syvitski, James PM},
journal={Computers \& Geosciences},
volume={34},
number={10},
pages={1319--1337},
year={2008},
publisher={Pergamon}
}
"""
import os
from . import _info
from .core.messages import indent_and_wrap
[docs]
class ComponentRegistry:
"""A registry for instantiated landlab components."""
[docs]
def __init__(self, objs=None):
self._registered = []
if objs is not None:
try:
[self.add(obj) for obj in objs]
except TypeError:
self.add(objs)
[docs]
def add(self, cls):
"""Add a class to the registry.
Parameters
----------
cls : Component
A landlab component to register as used.
"""
if cls not in self._registered:
self._registered.append(cls)
@property
def registered(self):
"""All registered classes.
Returns
-------
tuple
The components in the registry.
Examples
--------
>>> from landlab._registry import ComponentRegistry
>>> registry = ComponentRegistry()
>>> registry.registered
()
>>> class FooBar(object):
... pass
...
>>> registry.add(FooBar)
>>> registry.registered
('FooBar',)
"""
return tuple(ComponentRegistry.get_name(obj) for obj in self._registered)
[docs]
@staticmethod
def get_name(obj):
"""Get the display name for an object.
Examples
--------
>>> from landlab._registry import ComponentRegistry
>>> class MontyPython(object):
... name = "Eric Idle"
...
>>> ComponentRegistry.get_name(MontyPython)
'Eric Idle'
>>> class MontyPython(object):
... _name = "Graham Chapman"
...
>>> ComponentRegistry.get_name(MontyPython)
'Graham Chapman'
>>> class MontyPython(object):
... pass
...
>>> ComponentRegistry.get_name(MontyPython)
'MontyPython'
"""
name = "Unknown"
for attr in ("name", "_name", "__name__"):
try:
name = getattr(obj, attr)
except AttributeError:
pass
else:
break
return name
[docs]
@staticmethod
def get_citations(obj):
"""Get a list of citations from an object."""
citations = "None"
for attr in ("cite_as", "_cite_as"):
try:
citations = getattr(obj, attr)
except AttributeError:
pass
else:
break
if isinstance(citations, str):
citations = [citations]
return citations
[docs]
def format_citations(self):
"""Format citations for all registered components.
Returns
-------
str
The formatted citations.
Examples
--------
>>> from landlab._registry import ComponentRegistry
>>> registry = ComponentRegistry()
>>> class HolyGrailFinder(object):
... _name = "Monty Python"
... _cite_as = [
... '''@book{python2000holy,
... title={the Holy Grail},
... author={Python, Monty and Chapman, Graham and Cleese, John and Gilliam, Terry and Jones, Terry and Idle, Eric and Palin, Michael},
... year={2000},
... publisher={EMI Records}
... }''',
... '''@book{chapman1989complete,
... title={The Complete Monty Python's Flying Circus: All the Words. Volume one},
... author={Chapman, Graham and Python, Monty},
... volume={1},
... year={1989},
... publisher={Pantheon}
... }''',
... ]
...
>>> class Evolution(object):
... _cite_as = '''
... @book{darwin1859origin,
... title={On the origin of species},
... author={Darwin, Charles},
... year={1859},
... publisher={Lulu. com}
... }'''
...
>>> registry.add(HolyGrailFinder)
>>> registry.add(Evolution)
>>> print(registry.format_citations())
# Citations
## Monty Python
@book{python2000holy,
title={the Holy Grail},
author={Python, Monty and Chapman, Graham and Cleese, John and
Gilliam, Terry and Jones, Terry and Idle, Eric and Palin,
Michael},
year={2000},
publisher={EMI Records}
}
@book{chapman1989complete,
title={The Complete Monty Python's Flying Circus: All the Words.
Volume one},
author={Chapman, Graham and Python, Monty},
volume={1},
year={1989},
publisher={Pantheon}
}
<BLANKLINE>
## Evolution
@book{darwin1859origin,
title={On the origin of species},
author={Darwin, Charles},
year={1859},
publisher={Lulu. com}
}
""" # noqa: B950
header = ["# Citations"]
body = []
for cls in self._registered:
body.append(self.format_citation(cls))
return os.linesep.join(header + [(2 * os.linesep).join(body)])
def __repr__(self):
return f"ComponentRegistry({repr(self.registered)})"
registry = ComponentRegistry(_info)