def test__str__():
    layers = EventLayers(5)
    layers.add(1.0, age=3.0)
    vals = str(layers)
    assert vals.splitlines() == [
        "number_of_layers: 1", "number_of_stacks: 5", "tracking: age"
    ]
示例#2
0
def test__str__():
    layers = EventLayers(5)
    layers.add(1.0, age=3.0)
    vals = str(layers)
    assert vals.splitlines() == [
        "number_of_layers: 1",
        "number_of_stacks: 5",
        "tracking: age",
    ]
示例#3
0
def test_reduce_with_no_args():
    layers = EventLayers(3)

    layers.add(1.5)
    layers.reduce()
    assert_array_equal(layers.dz, [[1.5, 1.5, 1.5]])

    layers.add(2.5)
    layers.reduce()
    assert_array_equal(layers.dz, [[4.0, 4.0, 4.0]])
示例#4
0
def test_setitem_with_scalar():
    layers = EventLayers(5)
    layers.add(1.0, age=3.0)
    layers.add(2.0, age=4.0)

    truth = np.array([[3.0, 3.0, 3.0, 3.0, 3.0], [4.0, 4.0, 4.0, 4.0, 4.0]])
    assert_array_equal(layers["age"], truth)

    layers["age"] = 2.0
    truth = np.array([[2.0, 2.0, 2.0, 2.0, 2.0], [2.0, 2.0, 2.0, 2.0, 2.0]])
    assert_array_equal(layers["age"], truth)
示例#5
0
def test_setitem_with_scalar():
    layers = EventLayers(5)
    layers.add(1., age=3.)
    layers.add(2., age=4.)

    truth = np.array([[3., 3., 3., 3., 3.], [4., 4., 4., 4., 4.]])
    assert_array_equal(layers["age"], truth)

    layers["age"] = 2.
    truth = np.array([[2., 2., 2., 2., 2.], [2., 2., 2., 2., 2.]])
    assert_array_equal(layers["age"], truth)
示例#6
0
def test_set_item_with_2d():
    layers = EventLayers(5)
    layers.add(1.0, age=3.0)
    layers.add(2.0, age=4.0)

    truth = np.array([[3.0, 3.0, 3.0, 3.0, 3.0], [4.0, 4.0, 4.0, 4.0, 4.0]])
    assert_array_equal(layers["age"], truth)

    layers["age"] = [[4.0, 4.0, 4.0, 4.0, 4.0], [7.0, 7.0, 7.0, 7.0, 7.0]]

    truth = np.array([[4.0, 4.0, 4.0, 4.0, 4.0], [7.0, 7.0, 7.0, 7.0, 7.0]])
    assert_array_equal(layers["age"], truth)
示例#7
0
def test_set_item_with_2d():
    layers = EventLayers(5)
    layers.add(1., age=3.)
    layers.add(2., age=4.)

    truth = np.array([[3., 3., 3., 3., 3.], [4., 4., 4., 4., 4.]])
    assert_array_equal(layers["age"], truth)

    layers["age"] = [[4., 4., 4., 4., 4.], [7., 7., 7., 7., 7.]]

    truth = np.array([[4., 4., 4., 4., 4.], [7., 7., 7., 7., 7.]])
    assert_array_equal(layers["age"], truth)
示例#8
0
def test_reduce_with_reducer():
    layers = EventLayers(3)
    layers.add([2, 2, 2], age=1.0)
    layers.add([2, 2, 2], age=3.0)
    layers.add([2, 2, 2], age=4.0)
    layers.reduce(1, 3, age=np.mean)
    assert_array_equal(layers["age"], [[1.0, 1.0, 1.0], [3.5, 3.5, 3.5]])
示例#9
0
def test_reduce_with_attrs():
    layers = EventLayers(3)
    layers.add([1, 1, 1], age=0.0)
    layers.add([1, 2, 5], age=1.0)
    layers.add([2, 2, 2], age=2.0)
    layers.reduce(age=np.sum)
    assert_array_equal(layers["age"], [[3.0, 3.0, 3.0]])
示例#10
0
def test_reduce_with_start():
    layers = EventLayers(3)

    layers.add([3.0, 4.0, 5.0])
    layers.add([1.0, 2.0, 0.5])
    layers.add([1.0, 2.0, 0.5])
    layers.reduce(1, 3)

    assert_array_equal(layers.dz, [[3.0, 4.0, 5.0], [2.0, 4.0, 1.0]])
示例#11
0
def test_reduce_with_stop_less_than_start():
    layers = EventLayers(3)

    layers.add([3.0, 4.0, 5.0])
    layers.add([1.0, 2.0, 0.5])
    layers.add([1.0, 2.0, 0.5])
    layers.add([2.0, 5.0, 6.0])

    with pytest.raises(ValueError):
        layers.reduce(3, 1)
示例#12
0
def test_adding_untracked_layer():
    layers = EventLayers(3)
    layers.add(1., type=3., size="sand")
    layers.add([0., 0., 1.], type=3., size="sand")
    with pytest.raises(ValueError):
        layers.add([1.], type=3., size="sand", spam="eggs")
示例#13
0
    def __init__(self,
                 grid,
                 thicknesses,
                 ids,
                 attrs,
                 layer_type="MaterialLayers"):
        """Create a new instance of Lithology.

        Parameters
        ----------
        grid : Landlab ModelGrid
        thicknesses : ndarray of shape `(n_layers, )` or `(n_layers, n_nodes)`
            Values of layer thicknesses from surface to depth. Layers do not
            have to have constant thickness. Layer thickness can be zero,
            though the entirety of Lithology must have non-zero thickness.
        ids : ndarray of shape `(n_layers, )` or `(n_layers, n_nodes)`
            Values of rock type IDs cooresponding to each layer specified in
            **thicknesses**. A single layer may have multiple rock types if
            specified by the user.
        attrs : dict
            Rock type property dictionary. See class docstring for example of
            required format.
        layer_type : str, optional
            Type of Landlab layers object used to store the layers. If
            MaterialLayers (default) is specified, then erosion removes material
            and does not create a layer of thickness zero. If EventLayers is
            used, then erosion removes material and creates layers of thickness
            zero. Thus, EventLayers may be appropriate if the user is interested
            in chronostratigraphy.

        Examples
        --------
        >>> from landlab import RasterModelGrid
        >>> from landlab.components import Lithology
        >>> mg = RasterModelGrid(3, 3)
        >>> z = mg.add_zeros('node', 'topographic__elevation')

        Create a Lithology with uniform thicknesses that alternates between
        layers of type 1 and type 2 rock.

        >>> thicknesses = [1, 2, 4, 1]
        >>> ids = [1, 2, 1, 2]
        >>> attrs = {'K_sp': {1: 0.001,
        ...                   2: 0.0001}}
        >>> lith = Lithology(mg, thicknesses, ids, attrs)

        After creating a Lithology, the model grid will have an at-node grid
        field set to the surface values of 'K_sp'.

        >>> mg.at_node['K_sp']
        array([ 0.001,  0.001,  0.001,  0.001,  0.001,  0.001,  0.001,  0.001,
                0.001])

        The surface values are also properties of the Lithology.

        >>> lith['K_sp']
        array([ 0.001,  0.001,  0.001,  0.001,  0.001,  0.001,  0.001,  0.001,
                0.001])

        We can access information about the Lithology like the total thickness
        or layer thicknesses.

        >>> lith.thickness
        array([ 8.,  8.,  8.,  8.,  8.,  8.,  8.,  8.,  8.])
        >>> lith.dz
        array([[ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.],
               [ 4.,  4.,  4.,  4.,  4.,  4.,  4.,  4.,  4.],
               [ 2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.,  2.],
               [ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.]])

        This might look confusing -- that the layers are in reverse order, but
        it is OK. The last layers in the Lithology are those that are closest
        to the surface.

        The layers don't all have to have the same thickness as in the prior
        example. If the layers have non-uniform thickness, then they must be
        specified in an array of shape `(n_layer, n_nodes)`. In this case, the
        layer IDs must be specified in either an array of `(n_layer)` or
        `(n_layer, n_nodes)`.

        Here we make a layer that gets thicker as a function of the x value of
        the model grid.

        >>> layer_pattern = (0.5 * mg.x_of_node) + 1.0
        >>> thicknesses = [1*layer_pattern, 2*layer_pattern, 4*layer_pattern]
        >>> ids = [1, 2, 1]
        >>> lith = Lithology(mg, thicknesses, ids, attrs)
        >>> lith.thickness
        array([  7. ,  10.5,  14. ,   7. ,  10.5,  14. ,   7. ,  10.5,  14. ])
        >>> lith.dz
        array([[ 4. ,  6. ,  8. ,  4. ,  6. ,  8. ,  4. ,  6. ,  8. ],
               [ 2. ,  3. ,  4. ,  2. ,  3. ,  4. ,  2. ,  3. ,  4. ],
               [ 1. ,  1.5,  2. ,  1. ,  1.5,  2. ,  1. ,  1.5,  2. ]])
        """
        # save reference to the grid and the last time steps's elevation.
        self._grid = grid

        try:
            self.last_elevation = self._grid['node'][
                'topographic__elevation'][:].copy()
        except KeyError:
            msg = ('Lithology requires that topographic__elevation already '
                   'exists as an at-node field.')
            raise ValueError(msg)

        # save inital information about thicknesses, layers, attributes, and ids.
        self._init_thicknesses = np.asarray(thicknesses)
        self._attrs = attrs
        self._number_of_init_layers = self._init_thicknesses.shape[0]
        self._properties = list(attrs.keys())
        self._rock_id_name = 'rock_type__id'
        # assert that thicknesses and ids are correct and consistent shapes

        # if thickness is a 2d array.
        if self._init_thicknesses.ndim == 2:
            # assert that the 2nd dimension is the same as the number of nodes.
            if self._init_thicknesses.shape[1] != self._grid.number_of_nodes:
                msg = ('Thicknesses provided to Lithology are ',
                       'inconsistent with the ModelGrid.')
                raise ValueError(msg)

            # if IDs is a 2d array assert that it is the same size as thicknesses
            if np.asarray(ids).ndim == 2:
                if self._init_thicknesses.shape != np.asarray(ids).shape:
                    msg = ('Thicknesses and IDs provided to Lithology are ',
                           'inconsistent with each other.')
                    raise ValueError(msg)
                # if tests pass set value of IDs.
                self._layer_ids = np.asarray(ids)

            # if IDS is a 1d array
            elif np.asarray(ids).ndim == 1:
                if np.asarray(ids).size != self._number_of_init_layers:
                    msg = ('Number of IDs provided to Lithology is ',
                           'inconsistent with number of layers provided in '
                           'thicknesses.')
                    raise ValueError(msg)
                # if tests pass, broadcast ids to correct shape.
                self._layer_ids = np.broadcast_to(
                    np.atleast_2d(np.asarray(ids)).T,
                    self._init_thicknesses.shape)

            else:
                msg = ('IDs must be of shape `(n_layers, )` or `(n_layers, '
                       'n_nodes)`. Passed array has more than 2 dimensions.')
                raise ValueError(msg)

        elif self._init_thicknesses.ndim == 1:
            if self._init_thicknesses.shape != np.asarray(ids).shape:
                msg = ('Thicknesses and IDs provided to Lithology are ',
                       'inconsistent with each other.')
                raise ValueError(msg)
            self._layer_ids = np.asarray(ids)
        else:
            msg = (
                'Thicknesses must be of shape `(n_layers, )` or `(n_layers, '
                'n_nodes)`. Passed array has more than 2 dimensions.')
            raise ValueError(msg)

        # assert that attrs are pointing to fields (or create them)
        for at in self._properties:
            if at not in grid.at_node:
                self._grid.add_empty('node', at)

        # add a field for the rock type id
        if self._rock_id_name not in self._grid.at_node:
            self._grid.add_empty('node', self._rock_id_name)

        # verify that all IDs have attributes.
        self._check_property_dictionary()

        # create a EventLayers instance
        if layer_type == 'EventLayers':
            self._layers = EventLayers(grid.number_of_nodes,
                                       self._number_of_init_layers)
        elif layer_type == 'MaterialLayers':
            self._layers = MaterialLayers(grid.number_of_nodes,
                                          self._number_of_init_layers)
        else:
            raise ValueError(('Lithology passed an invalid option for '
                              'layer type.'))

        # From bottom to top, add layers to the Lithology with attributes.
        for i in range(self._number_of_init_layers - 1, -1, -1):
            try:
                self.add_layer(self._init_thicknesses[i, :],
                               self._layer_ids[i, :])
            except IndexError:
                self.add_layer(self._init_thicknesses[i], self._layer_ids[i])
示例#14
0
def test__str__():
    layers = EventLayers(5)
    layers.add(1., age=3.)
    vals = str(layers)
    assert vals == "number_of_layers: 1\nnumber_of_stacks: 5\ntracking: age"
示例#15
0
def test__repr__():
    layers = EventLayers(5)
    layers.add(1., age=3.)
    vals = repr(layers)
    assert vals == "EventLayers(5)"
示例#16
0
def test_reduce_with_start_too_big():
    layers = EventLayers(3)
    layers.add(1)
    layers.reduce(2, 4)
    assert_array_equal(layers.dz, [[1, 1, 1]])
示例#17
0
def test_reduce_with_no_layers():
    layers = EventLayers(3)
    layers.reduce()
    assert_array_equal(layers.dz, np.empty((0, 3)))
示例#18
0
def test_reduce_with_unknown_property():
    layers = EventLayers(3)
    for layer in range(4):
        layers.add(layer)
    with pytest.raises(TypeError):
        layers.reduce(1, 3, age=np.mean)
示例#19
0
def test_reduce_with_missing_property():
    layers = EventLayers(3)
    for layer in range(4):
        layers.add(layer, age=layer)
    with pytest.raises(TypeError):
        layers.reduce(1, 3)
示例#20
0
def test_reduce_args(args):
    layers = EventLayers(3)
    for layer in range(4):
        layers.add(layer)
    layers.reduce(4)
    assert_array_equal(layers.dz, [[6, 6, 6]])
示例#21
0
def test_reduce_partial_block():
    layers = EventLayers(3)
    for layer in range(6):
        layers.add(layer)
    layers.reduce(1, 6, 4)
    assert_array_equal(layers.dz, [[0, 0, 0], [10, 10, 10], [5, 5, 5]])
示例#22
0
def test_reduce_with_one_layer():
    layers = EventLayers(3)
    layers.add(1.0)
    layers.reduce()
    assert_array_equal(layers.dz, [[1, 1, 1]])