class Residual

Residual

class Residual(model, data, flow_accumulator_kwds=None, chi_finder_kwds=None, residuals=None)[source]

Create a Residual class based on a model and data Landlab grid.

__init__(model, data, flow_accumulator_kwds=None, chi_finder_kwds=None, residuals=None)[source]
Parameters
  • model (Landlab model grid) –

  • data (Landlab model grid) –

  • flow_accumulator_kwds (dict) – Parameters to pass to the Landlab FlowAccumulator to specify flow direction and accumulation.

  • chi_finder_kwds (dict) – Parameters to pass to the Landlab ChiFinder to specify optional arguments. `

  • residuals (dict) – A dictionary of desired residuals to calculate. See examples for required format.

Examples

>>> import numpy as np
>>> from io import StringIO
>>> from landlab import RasterModelGrid
>>> from umami import Residual
>>> np.random.seed(42)
>>> model = RasterModelGrid((10, 10))
>>> z_model = model.add_zeros("node", "topographic__elevation")
>>> z_model += model.x_of_node + model.y_of_node
>>> data = RasterModelGrid((10, 10))
>>> z_data = data.add_zeros("node", "topographic__elevation")
>>> z_data +=  data.x_of_node + data.y_of_node
>>> z_data[data.core_nodes] += np.random.random(data.core_nodes.shape)
>>> file_like=StringIO('''
... me:
...     _func: aggregate
...     method: mean
...     field: topographic__elevation
... ep10:
...     _func: aggregate
...     method: percentile
...     field: topographic__elevation
...     q: 10
... oid1_mean:
...     _func: watershed_aggregation
...     field: topographic__elevation
...     method: mean
...     outlet_id: 1
... sn1:
...     _func: count_equal
...     field: drainage_area
...     value: 1
... ''')
>>> residual = Residual(model, data)
>>> residual.add_from_file(file_like)
>>> residual.names
['me', 'ep10', 'oid1_mean', 'sn1']
>>> residual.calculate()
>>> np.testing.assert_array_almost_equal(
...     residual.value("me"),
...     -0.467,
...     decimal=3)
>>> np.testing.assert_array_almost_equal(
...     residual.values,
...     np.array([ -0.467,  -0.151,   3.313, -18.   ]),
...     decimal=3)
add_from_dict(params)[source]

Add residuals to an umami.Residual from a dictionary.

Adding residuals through this method does not overwrite already existing residuals. New residuals are appended to the existing residual list.

Parameters

params (dict or OrderedDict) – Keys are residual names and values are a dictionary describing the creation of the residual. It will be convereted to an OrderedDict before residuals are added so as to preserve residual order.

add_from_file(file)[source]

Add residuals to an umami.Residual from a file.

Parameters

file_like (file path or StringIO) – File will be parsed by yaml.safe_load and converted to an OrderedDict.

calculate()[source]

Calculate residual values.

Calculated residual values are stored in the attribute Residual.values.

property category

Category labels from discretized_misfit.

Returns

category – The category labels used with discretized_misfit or None if this calculation is not used.

Return type

ndarray of size (number of nodes,)

classmethod from_dict(params)[source]

Create an umami Residual from a dictionary.

Parameters

params (dict or OrderedDict) – This dict must contain a key grid, the values of which will be passed to the Landlab function create_grid to create the model grid. It will be convereted to an OrderedDict before residuals are added so as to preserve residual order.

Examples

>>> import numpy as np
>>> from io import StringIO
>>> from umami import Residual
>>> np.random.seed(42)
>>> params = {
...     "model": {
...         "RasterModelGrid": [
...             [10, 10],
...             {
...                 "fields": {
...                     "node": {
...                         "topographic__elevation": {
...                             "plane": [
...                                 {"point": [0, 0, 0]},
...                                 {"normal": [-1, -1, 1]},
...                             ]
...                         }
...                     }
...                 }
...             },
...         ]
...     },
...     "data": {
...         "RasterModelGrid": [
...             [10, 10],
...             {
...                 "fields": {
...                     "node": {
...                         "topographic__elevation": {
...                             "plane": [
...                                 {"point": [0, 0, 0]},
...                                 {"normal": [-1, -1, 1]},
...                             ],
...                             "random" : [
...                                 {"where": "CORE_NODE"},
...                                 {"distribution": "standard_normal"},
...                             ]
...                         }
...                     }
...                 }
...             },
...         ]
...     },
...     "residuals": {
...         "me": {
...             "_func": "aggregate",
...             "method": "mean",
...             "field": "topographic__elevation",
...         },
...         "ep10": {
...             "_func": "aggregate",
...             "method": "percentile",
...             "field": "topographic__elevation",
...             "q": 10,
...         },
...         "oid1_mean": {
...             "_func": "watershed_aggregation",
...             "field": "topographic__elevation",
...             "method": "mean",
...             "outlet_id": 1,
...         },
...         "sn1": {
...             "_func": "count_equal",
...             "field": "drainage_area",
...             "value": 1,
...         },
...     },
... }
>>> residual = Residual.from_dict(params)
>>> residual.names
['me', 'ep10', 'oid1_mean', 'sn1']
>>> residual.calculate()
>>> np.testing.assert_array_almost_equal(
...     residual.value("me"),
...     0.158,
...     decimal=3)
>>> np.testing.assert_array_almost_equal(
...     residual.values,
...     np.array([  0.158,   0.67 ,   4.138, -20.   ]),
...     decimal=3)
classmethod from_file(file_like)[source]

Create an umami Residual from a file-like object.

Parameters

file_like (file path or StringIO) – File will be parsed by yaml.safe_load and converted to an OrderedDict.

Returns

Return type

umami.Residual

Examples

>>> import numpy as np
>>> from io import StringIO
>>> from umami import Residual
>>> np.random.seed(42)
>>> file_like=StringIO('''
... model:
...     RasterModelGrid:
...         - [10, 10]
...         - fields:
...               node:
...                   topographic__elevation:
...                       plane:
...                           - point: [0, 0, 0]
...                           - normal: [-1, -1, 1]
... data:
...     RasterModelGrid:
...         - [10, 10]
...         - fields:
...               node:
...                   topographic__elevation:
...                       plane:
...                           - point: [0, 0, 0]
...                           - normal: [-1, -1, 1]
...                       random:
...                          distribution: standard_normal
...                          where: CORE_NODE
... residuals:
...     me:
...         _func: aggregate
...         method: mean
...         field: topographic__elevation
...     ep10:
...         _func: aggregate
...         method: percentile
...         field: topographic__elevation
...         q: 10
...     oid1_mean:
...         _func: watershed_aggregation
...         field: topographic__elevation
...         method: mean
...         outlet_id: 1
...     sn1:
...         _func: count_equal
...         field: drainage_area
...         value: 1
... ''')
>>> residual = Residual.from_file(file_like)
>>> residual.names
['me', 'ep10', 'oid1_mean', 'sn1']
>>> residual.calculate()
>>> np.testing.assert_array_almost_equal(
...     residual.value("me"),
...     0.191,
...     decimal=3)
>>> np.testing.assert_array_almost_equal(
...     residual.values,
...     np.array([  0.191,   0.426,   3.252, -20.   ]),
...     decimal=3)
property names

Names of residuals in residual order.

value(name)[source]

Get a specific residual value.

Parameters

name (str) – Name of desired residual.

property values

Residual values in residual order.

write_residuals_to_file(path, style, decimals=3)[source]

Write residuals to a file.

Parameters
  • path

  • style (str) – yaml, dakota

  • decimals (int) – Number of decimals to round output to.

Examples

>>> import numpy as np
>>> from io import StringIO
>>> from landlab import RasterModelGrid
>>> from umami import Residual
>>> np.random.seed(42)
>>> model = RasterModelGrid((10, 10))
>>> z_model = model.add_zeros("node", "topographic__elevation")
>>> z_model += model.x_of_node + model.y_of_node
>>> data = RasterModelGrid((10, 10))
>>> z_data = data.add_zeros("node", "topographic__elevation")
>>> z_model += data.x_of_node + data.y_of_node
>>> z_data[data.core_nodes] += np.random.random(data.core_nodes.shape)
>>> file_like=StringIO('''
... me:
...     _func: aggregate
...     method: mean
...     field: topographic__elevation
... ep10:
...     _func: aggregate
...     method: percentile
...     field: topographic__elevation
...     q: 10
... oid1_mean:
...     _func: watershed_aggregation
...     field: topographic__elevation
...     method: mean
...     outlet_id: 1
... sn1:
...     _func: count_equal
...     field: drainage_area
...     value: 1
... ''')
>>> residual = Residual(model, data)
>>> residual.add_from_file(file_like)
>>> residual.calculate()

First we ouput in dakota style, in which each metric is listed on its own line with its name as a comment.

>>> out = StringIO()
>>> residual.write_residuals_to_file(out, style="dakota", decimals=3)
>>> file_contents = out.getvalue().splitlines()
>>> for line in file_contents:
...     print(line.strip())
17.533 me
9.909 ep10
9.813 oid1_mean
-41 sn1

Next we output in yaml style, in which each metric is serialized in YAML format.

>>> out = StringIO()
>>> residual.write_residuals_to_file(out, style="yaml", decimals=3)
>>> file_contents = out.getvalue().splitlines()
>>> for line in file_contents:
...     print(line.strip())
me: 17.533
ep10: 9.909
oid1_mean: 9.813
sn1: -41