Skip to content

Commit

Permalink
Improve readme/doc with a minimal, game of life example (#61)
Browse files Browse the repository at this point in the history
* minor changes in FAQ

* add "in a nutshell" section in README and About page (Game of Life)

* show output dataset in readme

* add what's new entry
  • Loading branch information
benbovy committed Sep 26, 2019
1 parent 4769f2f commit 689e200
Show file tree
Hide file tree
Showing 6 changed files with 237 additions and 46 deletions.
107 changes: 105 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ xarray-simlab: xarray extension for computer model simulations
xarray-simlab is a Python library that provides both a generic
framework for building computational models in a modular fashion and a
xarray_ extension for setting and running simulations using the
xarray's ``Dataset`` structure. It is designed for interactive and
exploratory modeling.
xarray's ``Dataset`` structure. It is designed for fast, interactive
and exploratory modeling.

.. _xarray: http://xarray.pydata.org
.. |Build Status| image:: https://travis-ci.org/benbovy/xarray-simlab.svg?branch=master
Expand All @@ -23,6 +23,109 @@ exploratory modeling.
:target: https://zenodo.org/badge/latestdoi/93938479
:alt: Citation

In a nutshell
-------------

The Conway's Game of Life example shown below is adapted from this
`blog post <https://jakevdp.github.io/blog/2013/08/07/conways-game-of-life/>`_
by Jake VanderPlas.

1. Create new model components by writing compact Python classes,
i.e., very much like dataclasses_:

.. code-block:: python
import numpy as np
import xsimlab as xs
@xs.process
class GameOfLife:
world = xs.variable(dims=('x', 'y'), intent='inout')
def run_step(self):
nbrs_count = sum(
np.roll(np.roll(self.world, i, 0), j, 1)
for i in (-1, 0, 1) for j in (-1, 0, 1)
if (i != 0 or j != 0)
)
self._world_next = (nbrs_count == 3) | (self.world & (nbrs_count == 2))
def finalize_step(self):
self.world[:] = self._world_next
@xs.process
class Glider:
pos = xs.variable(dims='point_xy', description='glider position')
world = xs.foreign(GameOfLife, 'world', intent='out')
def initialize(self):
x, y = self.pos
kernel = [[1, 0, 0],
[0, 1, 1],
[1, 1, 0]]
self.world = np.zeros((10, 10), dtype=bool)
self.world[x:x+3, y:y+3] = kernel
2. Create a new model just by providing a dictionary of model components:

.. code-block:: python
model = xs.Model({'gol': GameOfLife,
'init': Glider})
3. Create an input ``xarray.Dataset``, run the model and get an output
``Dataset``:

.. code-block:: python
input_dataset = xs.create_setup(
model=model,
clocks={'step': np.arange(9)},
input_vars={'init__pos': ('point_xy', [4, 5])},
output_vars={'step': 'gol__world'}
)
output_dataset = input_dataset.xsimlab.run(model=model)
.. code-block:: python
>>> output_dataset
<xarray.Dataset>
Dimensions: (point: 2, step: 9, x: 10, y: 10)
Coordinates:
* step (step) int64 0 1 2 3 4 5 6 7 8
Dimensions without coordinates: point, x, y
Data variables:
init__pos (point) int64 4 5
gol__world (step, x, y) bool False False False False ... False False False
4. Perform model setup, pre-processing, run, post-processing and
visualization in a functional style, using method chaining:

.. code-block:: python
import matplotlib.pyplot as plt
with model:
(input_dataset
.xsimlab.update_vars(
input_vars={'init__pos': ('point_xy', [2, 2])}
)
.xsimlab.run()
.gol__world.plot.imshow(
col='step', col_wrap=3, figsize=(5, 5),
xticks=[], yticks=[],
add_colorbar=False, cmap=plt.cm.binary)
)
.. image:: doc/_static/gol.png
:width: 400px

.. _dataclasses: https://docs.python.org/3/library/dataclasses.html

Documentation
-------------

Expand Down
Binary file added doc/_static/gol.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
156 changes: 121 additions & 35 deletions doc/about.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,132 @@
About xarray-simlab
===================

xarray-simlab provides a framework for easily building custom computational
models from a set of modular components (i.e., Python classes), called
xarray-simlab provides a framework to easily build custom
computational models from a collection of modular components, called
processes.

The framework handles issues that scientists who are developing models
should not care too much about, like the model interface and the
overall workflow management. Both are automatically determined from
the succint, declarative-like interfaces of the model processes.
It also provides an extension to `xarray <https://xarray.pydata.org>`_
(i.e., labeled arrays and datasets), that connects it to a wide range
of libraries of the SciPy / PyData stack for processing, analysis,
visualization, etc.

Notably via its xarray extension, xarray-simlab has already deep
integration with the SciPy / PyData stack. Next versions will
hopefully handle other technical issues like command line integration,
interactive visualization and/or running many simulations in parallel,
e.g., in the context of sensitivity analyses or inversion procedures.
In a nutshell
-------------

The Conway's Game of Life example shown below is adapted from this
`blog post <https://jakevdp.github.io/blog/2013/08/07/conways-game-of-life/>`_
by Jake VanderPlas.

1. Create new model components by writing compact Python classes,
i.e., very much like dataclasses_ (note: more features and Python <
3.7 support are also available through the `attrs
<https://www.attrs.org>`_ library):

.. ipython::

In [1]: import numpy as np
...: import xsimlab as xs
...:
...:
...: @xs.process
...: class GameOfLife:
...: world = xs.variable(dims=('x', 'y'), intent='inout')
...:
...: def run_step(self):
...: nbrs_count = sum(
...: np.roll(np.roll(self.world, i, 0), j, 1)
...: for i in (-1, 0, 1) for j in (-1, 0, 1)
...: if (i != 0 or j != 0)
...: )
...: self._world_next = (nbrs_count == 3) | (self.world & (nbrs_count == 2))
...:
...: def finalize_step(self):
...: self.world[:] = self._world_next
...:
...:
...: @xs.process
...: class Glider:
...: pos = xs.variable(dims='point_xy', description='glider position')
...: world = xs.foreign(GameOfLife, 'world', intent='out')
...:
...: def initialize(self):
...: x, y = self.pos
...:
...: kernel = [[1, 0, 0],
...: [0, 1, 1],
...: [1, 1, 0]]
...:
...: self.world = np.zeros((10, 10), dtype=bool)
...: self.world[x:x+3, y:y+3] = kernel

2. Create a new model just by providing a dictionary of model components:

.. ipython::

In [2]: model = xs.Model({'gol': GameOfLife,
...: 'init': Glider})

3. Create an input :py:class:`xarray.Dataset`, run the model and get an
output Dataset:

.. ipython::

In [3]: input_dataset = xs.create_setup(
...: model=model,
...: clocks={'step': np.arange(9)},
...: input_vars={'init__pos': ('point_xy', [4, 5])},
...: output_vars={'step': 'gol__world'}
...: )
...:
...: output_dataset = input_dataset.xsimlab.run(model=model)
...:
...: output_dataset

4. Perform model setup, pre-processing, run, post-processing and
visualization in a functional style, using method chaining:

.. ipython::

@savefig gol.png width=4in
In [5]: import matplotlib.pyplot as plt
...:
...: with model:
...: (input_dataset
...: .xsimlab.update_vars(
...: input_vars={'init__pos': ('point_xy', [2, 2])}
...: )
...: .xsimlab.run()
...: .gol__world.plot.imshow(
...: col='step', col_wrap=3, figsize=(5, 5),
...: xticks=[], yticks=[],
...: add_colorbar=False, cmap=plt.cm.binary)
...: )

.. _dataclasses: https://docs.python.org/3/library/dataclasses.html

Motivation
----------

xarray-simlab is being developped with the idea of reducing the gap between the
environments used for building and running computational models and the ones
used for processing and analyzing simulation results. If the latter environments
become more powerful and interactive, progress has still to be done for the
former ones.

xarray-simlab also encourages building new models from re-usable sets of
components in order to avoid reinventing the wheel. In many cases we want to
customize existing models (e.g., adding a new feature or slightly modifying
the behavior) instead of building new models from scratch. This modular
framework allows to do that with minimal effort. By implementing models using
a large number of small components that can be easily plugged in/out, we
eliminate the need of hard-coding changes that we want to apply to a model,
which often leads to over-complicated code and interface.

The design of this tool is thus mainly focused on both fast model development
and easy, interactive model exploration. Ultimately, this would optimize the
iterative back-and-forth process between ideas that we have on how to model a
particular phenomenon and insights that we get from the exploration of model
behavior.
xarray-simlab is a tool for *fast model development* and *easy,
interactive model exploration*. It aims at empowering scientists to do
better research in less time, collaborate efficiently and make new
discoveries.

**Fast model development**: xarray-simlab allows building new models
from re-usable sets of components, with minimal effort. Models are
created dynamically and instantly just by plugging in/out components,
always keeping the model structure and interface tidy even in
situations where the model development workflow is highly experimental
or organic.

**Interactive model exploration**: xarray-simlab is being developed
with the idea of reducing the gap between the environments used for
building and running computational models and the ones used for
processing, analyzing and visualizing simulation results. Users may
fully leverage powerful environments like jupyter_ at all stages of
their modeling workflow.

.. _jupyter: https://jupyter.org/

Sources of inspiration
----------------------
Expand All @@ -49,8 +137,8 @@ xarray-simlab leverages the great number of packages that are part of the
Python scientific ecosystem. More specifically, the packages below have been
great sources of inspiration for this project.

- xarray_: xarray-simlab actually provides an xarray extension for setting and
running models.
- xarray_: xarray-simlab actually provides an xarray extension for
setting up and running models.
- attrs_: a package that allows writing Python classes without
boilerplate. xarray-simlab uses and extends attrs for writing
processes as succinct Python classes.
Expand All @@ -73,8 +161,6 @@ great sources of inspiration for this project.
processes. In this project we actually borrow some code from dask
for resolving process dependencies and for model visualization.

.. _attrs: https://github.com/python-attrs/attrs
.. _xarray: https://github.com/pydata/xarray
.. _dask: https://github.com/dask/dask
.. _luigi: https://github.com/spotify/luigi
.. _django: https://github.com/django/django
Expand Down
14 changes: 7 additions & 7 deletions doc/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ Does xarray-simlab provide built-in models?
No, xarray-simlab provides only the framework for creating,
customizing and running computational models. It is intended to be a
general-purpose tool. Domain specific models should be implemented in
3rd party packages. For example, `xarray-topo`_ provides xarray-simlab
3rd party packages. For example, `fastscape`_ provides xarray-simlab
models and model components for simulating landscape evolution.

.. _`xarray-topo`: https://gitext.gfz-potsdam.de/sec55-public/xarray-topo
.. _`fastscape`: https://github.com/fastscape-lem/fastscape

Can xarray-simlab be used with existing model implementations?
--------------------------------------------------------------
Expand Down Expand Up @@ -113,11 +113,11 @@ Will xarray-simlab support Python 2.7.x?
----------------------------------------

No, unless there are very good reasons to do so. The main packages of
the Python scientific ecosystem support Python 3.4 or later, and it
seems that Python 2.x will not be maintained anymore past 2020 (see
`PEP 373`_). Although some tools easily allow supporting both Python 2
and 3 versions in a single code base, it still makes the code harder
to maintain.
the Python scientific ecosystem support Python 3.x, and it seems that
Python 2.x will not be maintained anymore past 2020 (see `PEP
373`_). Although some tools easily allow supporting both Python 2 and
3 versions in a single code base, it still makes the code harder to
maintain.

.. _`PEP 373`: https://www.python.org/dev/peps/pep-0373/

Expand Down
4 changes: 2 additions & 2 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ xarray-simlab: xarray extension for computer model simulations
**xarray-simlab** is a Python library that provides both a generic
framework for building computational models in a modular fashion and a
`xarray`_ extension for setting and running simulations using the
:py:class:`xarray.Dataset` structure. It is designed for interactive
and exploratory modeling.
:py:class:`xarray.Dataset` structure. It is designed for fast,
interactive and exploratory modeling.

.. _xarray: http://xarray.pydata.org

Expand Down
2 changes: 2 additions & 0 deletions doc/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Enhancements
more meaningful error message is shown when it fails (:issue:`57`).
- Added ``runtime`` decorator to pass simulation runtime information
to the (runtime) methods defined in process classes (:issue:`59`).
- Better documentation with a minimal, yet illustrative example based
on Game of Life (:issue:`61`).

Bug fixes
~~~~~~~~~
Expand Down

0 comments on commit 689e200

Please sign in to comment.