Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
202 changes: 101 additions & 101 deletions doc/examples/landscape-evolution-model.ipynb

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions doc/run_model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The following imports are necessary for the examples below.

.. ipython:: python

import numpy as np
import xsimlab as xs
import matplotlib.pyplot as plt

Expand Down Expand Up @@ -47,12 +48,12 @@ create a new setup in a very declarative way:

in_ds = xs.create_setup(
model=model2,
clocks={'time': {'start': 0, 'end': 1, 'step': 0.01},
'otime': {'data': [0, 0.5, 1]}},
clocks={'time': np.linspace(0., 1., 101),
'otime': [0, 0.5, 1]},
master_clock='time',
input_vars={'grid': {'length': 1.5, 'spacing': 0.01},
'advect': {'v': 1.},
'init': {'loc': 0.3, 'scale': 0.1}},
'init': {'loc': 0.3, 'scale': 0.1},
'advect': {'v': 1.}},
output_vars={None: {'grid': 'x'},
'otime': {'profile': 'u'}}
)
Expand Down Expand Up @@ -187,8 +188,7 @@ for the ``otime`` coordinate (which serves to take snapshots of

.. ipython:: python

clocks = {'time': {'data': in_ds.time},
'otime': {'data': [0, 0.25, 0.5]}}
clocks = {'otime': [0, 0.25, 0.5]}
with model2:
out_ds3 = (in_ds.xsimlab.update_clocks(clocks=clocks,
master_clock='time')
Expand Down
12 changes: 12 additions & 0 deletions doc/whats_new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ changes are effective now!
updating a setup using ``create_setup`` or
``Dataset.xsimlab.update_vars``. this is a regression that will be
fixed in the next releases.
- Argument values for generating clock data in ``create_setup`` and
``Dataset.xsimlab.update_clocks`` have changed and are now more
consistent with how coordinates are set in xarray. Additionally,
``auto_adjust`` has been removed (an error is raised instead when
clock coordinate labels are not synchronized).

- Scalar values from a input ``xarray.Dataset`` are now converted into
scalars (instead of a 0-d numpy array) when setting input model
Expand Down Expand Up @@ -117,6 +122,9 @@ Enhancements
but return all variable names in the model.
- ``input_vars`` and ``output_vars`` arguments of ``create_setup`` and
``Dataset.xsimlab.update_vars`` now accepts different formats.
- It is now possible to update only some clocks with
``Dataset.xsimlab.update_clocks`` (previously all existing clock
coordinates were dropped first).

Regressions (will be fixed in future releases)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -128,6 +136,10 @@ Regressions (will be fixed in future releases)
own name. This may be useful, e.g., for sensitivity analysis, but as
the latter is not implemented yet this feature has been removed and
will be added back in a next release.
- High-level API for generating clock coordinate data (i.e.,
``start``, ``end``, ``step`` and ``auto_adjust`` arguments) is not
supported anymore. This could be added back in a future release in a
cleaner form.

v0.1.1 (20 November 2017)
-------------------------
Expand Down
140 changes: 51 additions & 89 deletions xsimlab/tests/test_xr_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,88 +99,18 @@ def test_master_clock_dim(self):
ds = xr.Dataset()
assert ds.xsimlab.master_clock_dim is None

def test_set_master_clock_dim(self):
ds = xr.Dataset(coords={'clock': [1, 2], 'clock2': [3, 4]})

ds.xsimlab._set_master_clock_dim('clock')
assert self._master_clock_key in ds.clock.attrs

ds.xsimlab._set_master_clock_dim('clock2')
assert self._master_clock_key not in ds.clock.attrs
assert self._master_clock_key in ds.clock2.attrs

with pytest.raises(KeyError):
ds.xsimlab._set_master_clock_dim('invalid_clock')

def test_set_master_clock(self):
data = [0, 2, 4, 6, 8]

valid_kwargs = [
{'data': data},
# data provided -> ignore other arguments even if invalid
{'data': data, 'end': 0, 'nsteps': -1, 'step': 3},
{'nsteps': 4, 'end': 8, 'step': 2},
{'nsteps': 4, 'end': 8},
{'nsteps': 4, 'step': 2},
{'step': 2, 'end': 8}
]
for kwargs in valid_kwargs:
ds = xr.Dataset()
ds.xsimlab._set_master_clock('clock', **kwargs)
np.testing.assert_array_equal(ds.clock.values, data)

invalid_kwargs = [
{'nsteps': 4, 'end': 8, 'step': 3},
{'start': 1, 'nsteps': 4, 'end': 8, 'step': 2},
{'nsteps': 4}
]
for kwargs in invalid_kwargs:
with pytest.raises(ValueError) as excinfo:
ds = xr.Dataset()
ds.xsimlab._set_master_clock('clock', **kwargs)
assert "Invalid combination" in str(excinfo.value)
# def test_set_master_clock_dim(self):
# ds = xr.Dataset(coords={'clock': [1, 2], 'clock2': [3, 4]})

ds = xr.Dataset()
ds.xsimlab._set_master_clock('clock', data=data,
units='years since 1-1-1 0:0:0',
calendar='365_day')
assert self._master_clock_key in ds.clock.attrs
assert ds.clock.attrs['units'] == 'years since 1-1-1 0:0:0'
assert ds.clock.attrs['calendar'] == '365_day'

with pytest.raises(ValueError) as excinfo:
ds.xsimlab._set_master_clock('clock', data=data)
assert "already exists" in str(excinfo.value)

ds = xr.Dataset()
da = xr.DataArray(data, dims='other_dim')
with pytest.raises(ValueError) as excinfo:
ds.xsimlab._set_master_clock('clock', data=da)
assert "expected dimension" in str(excinfo.value)
# ds.xsimlab._set_master_clock_dim('clock')
# assert self._master_clock_key in ds.clock.attrs

def test_set_snapshot_clock(self):
with pytest.raises(ValueError) as excinfo:
ds = xr.Dataset()
ds.xsimlab._set_snapshot_clock('snap_clock', data=[1, 2])
assert "no master clock" in str(excinfo.value)
# ds.xsimlab._set_master_clock_dim('clock2')
# assert self._master_clock_key not in ds.clock.attrs
# assert self._master_clock_key in ds.clock2.attrs

ds = xr.Dataset()
ds.xsimlab._set_master_clock('clock', data=[0, 2, 4, 6, 8],
units='years since 1-1-1 0:0:0',
calendar='365_day')

ds.xsimlab._set_snapshot_clock('snap_clock', end=8, step=4)
np.testing.assert_array_equal(ds['snap_clock'], [0, 4, 8])
assert self._clock_key in ds['snap_clock'].attrs
assert 'units' in ds['snap_clock'].attrs
assert 'calendar' in ds['snap_clock'].attrs

ds.xsimlab._set_snapshot_clock('snap_clock', data=[0, 3, 8])
np.testing.assert_array_equal(ds['snap_clock'], [0, 4, 8])

with pytest.raises(KeyError):
ds.xsimlab._set_snapshot_clock('snap_clock', data=[0, 3, 8],
auto_adjust=False)
# with pytest.raises(KeyError):
# ds.xsimlab._set_master_clock_dim('invalid_clock')

def test_set_input_vars(self, model, in_dataset):
in_vars = {('init_profile', 'n_points'): 5,
Expand All @@ -206,46 +136,78 @@ def test_update_clocks(self, model):
ds = xr.Dataset()
with pytest.raises(ValueError) as excinfo:
ds.xsimlab.update_clocks(model=model, clocks={})
assert "cannot determine which clock" in str(excinfo.value)
assert "Cannot determine which clock" in str(excinfo.value)

ds = xr.Dataset()
with pytest.raises(ValueError) as excinfo:
ds.xsimlab.update_clocks(
model=model,
clocks={'clock': {'data': [0, 1, 2]},
'out': {'data': [0, 2]}}
clocks={'clock': [0, 1, 2],
'out': [0, 2]}
)
assert "cannot determine which clock" in str(excinfo.value)
assert "Cannot determine which clock" in str(excinfo.value)

ds = xr.Dataset()
with pytest.raises(KeyError) as excinfo:
ds.xsimlab.update_clocks(
model=model,
clocks={'clock': {'data': [0, 1, 2]}},
clocks={'clock': [0, 1, 2]},
master_clock='non_existing_clock_dim'
)
assert "master clock dimension name" in str(excinfo.value)
assert "Master clock dimension name" in str(excinfo.value)

ds = xr.Dataset()
with pytest.raises(ValueError) as excinfo:
ds.xsimlab.update_clocks(
model=model,
clocks={'clock': ('x', [0, 1, 2])},
)
assert "Invalid dimension" in str(excinfo.value)

ds = xr.Dataset()
with pytest.raises(ValueError) as excinfo:
ds.xsimlab.update_clocks(
model=model,
clocks={'clock': [0, 1, 2],
'out': [0, 0.5, 2]},
master_clock='clock'
)
assert "not synchronized" in str(excinfo.value)

ds = xr.Dataset()
ds = ds.xsimlab.update_clocks(
model=model,
clocks={'clock': {'data': [0, 1, 2]}}
clocks={'clock': [0, 1, 2]}
)
assert ds.xsimlab.master_clock_dim == 'clock'

ds.clock.attrs[self._output_vars_key] = 'profile__u'

ds = ds.xsimlab.update_clocks(
model=model,
clocks={'clock': {'data': [0, 1, 2]}},
clocks={'clock': [0, 1, 2]},
master_clock={'dim': 'clock',
'units': 'days since 1-1-1 0:0:0',
'calendar': '365_days'}
)
np.testing.assert_array_equal(ds.clock.values, [0, 1, 2])
assert 'units' in ds.clock.attrs
assert 'calendar' in ds.clock.attrs
assert ds.clock.attrs[self._output_vars_key] == 'profile__u'

new_ds = ds.xsimlab.update_clocks(
model=model,
clocks={'clock2': [0, 0.5, 1, 1.5, 2]},
master_clock='clock2'
)
assert new_ds.xsimlab.master_clock_dim == 'clock2'

new_ds = ds.xsimlab.update_clocks(
model=model,
clocks={'out2': [0, 2]}
)
assert new_ds.xsimlab.master_clock_dim == 'clock'

def test_update_vars(self, model, in_dataset):
ds = in_dataset.xsimlab.update_vars(
model=model,
Expand Down Expand Up @@ -337,8 +299,8 @@ def test_create_setup(model, in_dataset):
'add__offset': ('clock', [1, 2, 3, 4, 5])
},
clocks={
'clock': {'data': [0, 2, 4, 6, 8]},
'out': {'data': [0, 4, 8]},
'clock': [0, 2, 4, 6, 8],
'out': [0, 4, 8],
},
master_clock='clock',
output_vars={
Expand Down
Loading