Species Evolution#

SpeciesEvolver: Component to evolve life in a landscape#

Evolve life in a landscape.

Life evolves alongside landscapes by biotic and abiotic processes under complex dynamics at Earth’s surface. Researchers who wish to explore these dynamics can use this component as a tool for them to build landscape-life evolution models. Landlab components, including SpeciesEvolver are designed to work with a shared model grid. Researchers can build novel models using plug-and-play surface process components to evolve the grid’s landscape alongside the life tracked by SpeciesEvolver. The simulated life evolves following customizable processes.

Component written by Nathan Lyons beginning August 2017.

class SpeciesEvolver(*args, **kwds)[source]#

Bases: Component

Evolve life in a landscape.

This component tracks Taxon objects as they evolve in a landscape. The component calls the evolutionary process methods of tracked Taxon objects. Taxon are intended to be subclassed for unique behavior, attributes, and model approaches, including different implementations of evolutionary processes.

The general workflow to use this component in a model is

  1. Instantiate the component.

  2. Instantiate taxa.

  3. Introduce taxa to SpeciesEvolver using the track_taxon method.

  4. Advance the component instance in time using run_one_step method.

Taxa can be introduced at model onset and later time steps. Multiple types can be tracked by the same SpeciesEvolver instance.

The taxon type, ZoneTaxon is distributed with SpeciesEvolver. The spatial aspect of ZoneTaxon macroevolutionary processes is determined using Zone objects. A ZoneController is used to create and manage zones as well as efficiently create multiple ZoneTaxon objects. See the documentation of ZoneController and ZoneTaxon for more information. SpeciesEvolver knows nothing about zones and their controller, meaning the concept of zones are not required for other taxon types.

Model time and other variables can be viewed with the class attribute, record_data_frame. Time is recorded to track the history of taxa lineages. The unit of time is not considered within the component other than the record, and can be thought of as in years or whatever unit is needed. Time is advanced with the dt parameter of the run_one_step method.

The geographic ranges of the taxa at the current model time are evaluated during the run_one_step method. Each taxon object determines if it persists or becomes extinct, and if it creates child Taxon objects. Metadata of all taxa introduced to the component can be viewed with the attribute, taxa_data_frame.

Taxa are automatically assigned unique taxon identifiers, tid. Identifiers are used to reference and retrieve taxon objects. Identifiers are assigned in the order taxa are introduced to SpeciesEvolver.

Examples

The evolution of a lowland taxa lineage in response to mountain range formation is simulated using ZoneTaxon managed by ZoneController. Mountain range formation is forced without processes for simplicity in this example.

Import modules used in the following examples.

>>> from landlab import RasterModelGrid
>>> from landlab.components import SpeciesEvolver
>>> from landlab.components.species_evolution import ZoneController

Create a model grid with mountain scale resolution. The elevation is equally low throughout the grid at model onset.

>>> mg = RasterModelGrid((3, 7), 1000)
>>> z = mg.add_ones("topographic__elevation", at="node")
>>> z.reshape(mg.shape)
array([[ 1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.,  1.,  1.,  1.]])

Instantiate the component with the grid as the first parameter.

>>> se = SpeciesEvolver(mg)

ZoneController requires a function that returns a mask of the total extent of taxa habitat. The mask is a boolean array where True values represent nodes that satisfy habitat conditions. Zone objects are not created here. The mask only maps the extent where taxa can exist. This function returns True where elevation is below 100, which is where the simulated lowland taxa of this model can inhabit.

>>> def zone_func(grid):
...     return grid.at_node["topographic__elevation"] < 100
...

Instantiate ZoneController with the grid and zone function. The initial zones are created at controller instantiation. In this example, one zone is created because all nodes of the zone mask are adjacent to each other.

>>> zc = ZoneController(mg, zone_func)
>>> len(zc.zones) == 1
True

Additional examples of controller usage are provided in ZoneController documentation.

The mask of the zone is True where the conditions of the zone function are met. All nodes of the grid are included because the elevation of each node is below 100. The zones attribute of ZoneController returns a list of the zones that currently exist in the model. Below we return the mask of the single zone by indexing this list.

>>> zc.zones[0].mask
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True], dtype=bool)

Populate a taxon to the zone.

>>> taxon = zc.populate_zones_uniformly(1)
>>> se.track_taxa(taxon)

The attribute, taxa_data_frame indicates only the one taxon exists because we populated each zone with one taxon, and only the one zone exists.

>>> se.taxa_data_frame
pid  type    t_first  t_final      tid
0    <NA>  ZoneTaxon        0     <NA>

The identifier of the taxon, tid is 0. The identifier of the taxon’s parent, pid, is ‘<NA>’ because it does not have a parent taxon given that it was manually introduced using the track_taxa method. The taxon was introduced at time, t_first and time, t_final is ‘<NA>’ because the taxon remains extant. See the documentation of this attribute for further explanation of data frame columns.

Force a change in the zone mask to demonstrate component functionality. Here we begin a new time step where topography is uplifted by 200 that forms a ridge trending north-south in the center of the grid.

>>> z[[3, 10, 17]] = 200
>>> z.reshape(mg.shape)
array([[   1.,    1.,    1.,  200.,    1.,    1.,    1.],
       [   1.,    1.,    1.,  200.,    1.,    1.,    1.],
       [   1.,    1.,    1.,  200.,    1.,    1.,    1.]])

The current elevation, the elevation following uplift, is represented here.

- - - ^ - - -       elevation:  - 1
- - - ^ - - -                   ^ 200
- - - ^ - - -

The updated zone mask is below.

. . . x . . .       key:    . node in zone mask
. . . x . . .               x node outside of zone mask
. . . x . . .

Run a step of both the ZoneController and SpeciesEvolver. Both are run to keep time in sync between the ZoneController``and ``SpeciesEvolver instances. >>> delta_time = 1000 >>> zc.run_one_step(delta_time) >>> se.run_one_step(delta_time)

Two zones exist following this time step.

>>> len(zc.zones) == 2
True

An additional zone was created because the zone mask was not continuous.

. . . ^ * * *       key:    . a zone
. . . ^ * * *               * another zone
. . . ^ * * *               ^ mountain range

The split of the initial zone triggered speciation of taxon 1 by taxon 0.

>>> se.taxa_data_frame
pid  type    t_first  t_final      tid
0    <NA>  ZoneTaxon        0     <NA>
1       0  ZoneTaxon     1000     <NA>

The phylogenetic tree of the simulated taxa is represented below. The number at the line tips are the taxa identifiers.

0 ──────┬── 0
        │
        └── 1
  _________
  0    1000
    time

The split of the initial zone into two zones at time 1000 triggered taxon 0 to speciate. Taxon 0 occupies a zone on one side of the mountain range, and the child, taxon 1 occupies a zone on the other side. This outcome is the result of the evolutionary processes programmed within ZoneTaxon as well as the parameters used in this example (default values were used as optional parameters were not set). Different behavior can be achieved by subclassing ZoneTaxon or Taxon.

References

Required Software Citation(s) Specific to this Component

Lyons, N.J., Albert, J.S., Gasparini, N.M. (2020). SpeciesEvolver: A Landlab component to evolve life in simulated landscapes. Journal of Open Source Software 5(46), 2066, https://doi.org/10.21105/joss.02066

Additional References

Albert, J.S., Schoolmaster Jr, D.R., Tagliacollo, V., Duke-Sylvester, S.M. (2016). Barrier displacement on a neutral landscape: Toward a theory of continental biogeography. Systematic Biology 66(2), 167–182.

Lyons, N.J., Val, P., Albert, J.S., Willenbring, J.K., Gasparini, N.M., in review. Topographic controls on divide migration, stream capture, and diversification in riverine life. Earth Surface Dynamics.

Instantiate SpeciesEvolver.

Parameters:
  • grid (ModelGrid) – A Landlab ModelGrid.

  • initial_time (float, int, optional) – The initial time. The unit of time is not considered within the component, with the exception that time is logged in the record. The default value of this parameter is 0.

__init__(grid, initial_time=0)[source]#

Instantiate SpeciesEvolver.

Parameters:
  • grid (ModelGrid) – A Landlab ModelGrid.

  • initial_time (float, int, optional) – The initial time. The unit of time is not considered within the component, with the exception that time is logged in the record. The default value of this parameter is 0.

get_extant_taxon_objects(tids=nan, ancestor=nan, time=nan)[source]#

Get extant taxon objects filtered by parameters.

This method returns all taxon objects tracked by the component when no optional parameters are included. The objects returned can be limited using one or more parameters.

Parameters:
  • tids (list of int, optional) – The taxa with these identifiers will be returned. A list is returned even if only one object is contained within the list. By default, when tids is not specified, extant taxa with any identifier can be returned.

  • ancestor (int, optional) – Limit the taxa returned to those descending from the taxon designated as the ancestor. The ancestor is designated using its tid. By default, taxa with any or no ancestors are returned.

  • time (float, int, optional) – Limit the taxa returned to those that were extant at the time designated by this parameter as well as extant at the current model time. By default, extant taxa at all of the times listed in the component record can be returned.

Returns:

taxa – The Taxon objects that pass through the filter. The list is sorted by tid. An empty list is returned if no taxa pass through the filter.

Return type:

a list of Taxon

Examples

ZoneTaxon are used to demonstrate this method.

Import modules used in the following examples.

>>> from landlab import RasterModelGrid
>>> from landlab.components import SpeciesEvolver
>>> from landlab.components.species_evolution import ZoneController

Create a model grid.

>>> mg = RasterModelGrid((3, 7), 1000)
>>> z = mg.add_ones("topographic__elevation", at="node")

Instantiate SpeciesEvolver and a ZoneController. Instantiate the latter with a function that masks the low elevation zone extent. Only one zone is created.

>>> se = SpeciesEvolver(mg)
>>> def zone_func(grid):
...     return grid.at_node["topographic__elevation"] < 100
...
>>> zc = ZoneController(mg, zone_func)
>>> len(zc.zones) == 1
True

Introduce two taxa to the zone.

>>> taxa = zc.populate_zones_uniformly(2)
>>> se.track_taxa(taxa)

Force north-south mountain ranges over two time steps that drives taxa evolution.

>>> z[mg.x_of_node == 2000] = 200
>>> zc.run_one_step(1000)
>>> se.run_one_step(1000)
>>> z[mg.x_of_node == 4000] = 200
>>> zc.run_one_step(1000)
>>> se.run_one_step(1000)

Display taxa metadata.

>>> se.taxa_data_frame
pid  type  t_first    t_final      tid
0    <NA>  ZoneTaxon        0     <NA>
1    <NA>  ZoneTaxon        0     <NA>
2       0  ZoneTaxon     1000     <NA>
3       1  ZoneTaxon     1000     <NA>
4       0  ZoneTaxon     2000     <NA>
5       1  ZoneTaxon     2000     <NA>

Objects of all extant taxon are returned when no parameters are inputted.

>>> se.get_extant_taxon_objects()
[<ZoneTaxon, tid=0>,
 <ZoneTaxon, tid=1>,
 <ZoneTaxon, tid=2>,
 <ZoneTaxon, tid=3>,
 <ZoneTaxon, tid=4>,
 <ZoneTaxon, tid=5>]

The returned objects of extant species can be limited using parameters. Here, get the taxon objects with identifiers, 4 and 5.

>>> se.get_extant_taxon_objects(tids=[4, 5])
[<ZoneTaxon, tid=4>, <ZoneTaxon, tid=5>]

Extant taxon objects descending from a taxon can be obtained using the ancestor property. Here, get the taxa that descended from taxon 0.

>>> se.get_extant_taxon_objects(ancestor=0)
[<ZoneTaxon, tid=2>, <ZoneTaxon, tid=4>]

Taxa can be limited to those that were extant time.

>>> se.get_extant_taxon_objects(time=1000)
[<ZoneTaxon, tid=0>,
 <ZoneTaxon, tid=1>,
 <ZoneTaxon, tid=2>,
 <ZoneTaxon, tid=3>]

The returned taxa can be further limited by including multiple method properties.

>>> se.get_extant_taxon_objects(ancestor=0, time=1000)
[<ZoneTaxon, tid=2>]

An empty list is returned when no extant taxa match parameter criteria.

>>> se.get_extant_taxon_objects(tids=[11])
[]
property record_data_frame#

A Pandas DataFrame of SpeciesEvolver variables over time.

Each row is data of a model time step. The time of the step is recorded in the time column. taxa is the count of taxa extant at a time. Additional columns can be added and updated by SpeciesEvolver objects during the component run_one_step method. See documention of Taxon objects for an explanation of these columns.

The DataFrame is created from a dictionary associated with a SpeciesEvolver Record object. nan values in Pandas DataFrame force the column to become float values even when data are integers. The original value type is retained in the Record object.

run_one_step(dt)[source]#

Update the taxa for a single time step.

This method advances the model time in the component record, calls the evolve method of taxa extant at the current time, and updates the variables in the record and taxa dataframes.

Parameters:

dt (float) – The model time step duration. Time in the record is advanced by the value of this parameter.

property taxa_data_frame#

A Pandas DataFrame of taxa metadata.

Each row is the metadata of a taxon. The column, tid is the taxon identifier assigned when SpeciesEvolver begins tracking the taxon. The column, pid is the tid of the parent of the taxon. A pid of <NA> indicates no parent taxon. type is the type of Taxon object. t_first is the initial model time the taxon was added to SpeciesEvolver. t_final is the model time the taxon was recognized as extinct. A t_final of <NA> indicates the taxon is extant.

Additional columns may be added by some taxon types. See the documentation of these taxa for column description.

The DataFrame is created from a data structure within the component.

track_taxa(taxa)[source]#

Add taxa to be tracked over time by SpeciesEvolver.

The taxon/taxa are introduced at the latest time in the record and also tracked during following model times. Each taxon is assigned an identifier and then can be viewed in taxa_data_frame.

Parameters:

taxa (Taxon or list of Taxon) – The taxa to introduce.

Examples

ZoneTaxon are used to demonstrate this method.

Import modules used in the following examples.

>>> from landlab import RasterModelGrid
>>> from landlab.components import SpeciesEvolver
>>> from landlab.components.species_evolution import ZoneController

Create a model grid with flat topography.

>>> mg = RasterModelGrid((3, 7), 1000)
>>> z = mg.add_ones("topographic__elevation", at="node")

Instantiate SpeciesEvolver and a ZoneController. Instantiate the latter with a function that masks the low elevation zone extent. Only one zone is created.

>>> se = SpeciesEvolver(mg)
>>> def zone_func(grid):
...     return grid.at_node["topographic__elevation"] < 100
...
>>> zc = ZoneController(mg, zone_func)
>>> len(zc.zones) == 1
True

Track the taxon of the one zone.

>>> taxon = zc.populate_zones_uniformly(1)
>>> se.track_taxa(taxon)

The one taxon is now tracked by SpeciesEvolver as indicated by the taxa DataFrame.

>>> se.taxa_data_frame
pid  type    t_first  t_final      tid
0    <NA>  ZoneTaxon        0     <NA>

ZoneController: Control zones and populates them with taxa#

ZoneController of SpeciesEvolver.

class ZoneController(grid, zone_function, minimum_area=0, neighborhood_structure='D8', initial_time=0, **kwargs)[source]#

Bases: object

Controls zones and populates them with taxa.

This object manages ‘zones’ that are used to evaluate the spatial aspect of taxa. A zone represents a portion of a model grid. It is made up of spatially continuous grid nodes.

This controller creates zones using the initialization parameter, zone_function. This function identifies all of the grid nodes where zones are to be created. A zone is created for each cluster of spatially continuous nodes. Zones are updated also using this function when the run_one_step method of this controller is called.

The structure of an example model grid is diagrammed below to demonstrate how zones are created. The grid contains six columns and six rows. In this example, the function returns True where node values are greater than 0. Nodes marked with an * are nodes that will belong to a zone because the mask is True at these nodes. All other nodes are marked with a ·. A zone is created for each cluster of continuous nodes where the mask is True.

values         mask returned
evaluated      by zone function
0 0 0 0 0 0    · · · · · ·
0 0 0 5 4 2    · · · * * *
0 6 0 4 6 0    · * · * * ·
0 2 0 0 0 0    · * · · · ·
0 0 4 0 4 0    · · * · * ·
0 0 0 0 0 0    · · · · · ·

The above example is continued in the following four diagrams that demonstrate how individual zones are identified. Each zone is marked with a x, o, +, or @. Clusters can be identified using D8 where diagonal neighbors are included or D4 where diagonal neighbors are excluded. A minimum zone area can be enforced with the minimum_area initialization parameter.

D8             D4             D8             D4
min area = 0   min area = 0   min area = 2   min area = 2
· · · · · ·    · · · · · ·    · · · · · ·    · · · · · ·
· · · + + +    · · · + + +    · · · + + +    · · · + + +
· x · + + ·    · x · + + ·    · x · + + ·    · x · + + ·
· x · · · ·    · x · · · ·    · x · · · ·    · x · · · ·
· · x · o ·    · · @ · o ·    · · x · · ·    · · · · · ·
· · · · · ·    · · · · · ·    · · · · · ·    · · · · · ·

The grid perimeter affects zone creation. Zones can include perimeter nodes (the nodes along grid edges), although because perimeter nodes are not associated with cells that have area, perimeter nodes do not contribute to the area summation of clusters. The area summation only takes into account the cells associated with core nodes.

Creation of zones along boundaries is illustrated below. A zone extent mask different from the above example was produced by the hypothetical zone function in this example. Again * indicates where a zone can exist. Distinct zones include the symbols, $ and # in addition to the symbols defined above. Individual zone masks and the count of zones are affected by the use of D8 or D4 along with the minimum area parameter, especially when zone clusters are along the grid parameter.

zone function  D8             D4             D8             D4
returned mask  min area = 0   min area = 0   min_area = 2   min_area = 2
* · · * * ·    + · · x x ·    + · · x x ·    + · · · · ·    · · · · · ·
· * · · * ·    · + · · x ·    · # · · x ·    · + · · · ·    · # · · · ·
· * · · · ·    · + · · · ·    · # · · · ·    · + · · · ·    · # · · · ·
* · · · * *    + · · · o o    $ · · · o o    + · · · o o    · · · · o o
· · · · * ·    · · · · o ·    · · · · o ·    · · · · o ·    · · · · o ·
· * * · · ·    · @ @ · · ·    · @ @ · · ·    · · · · · ·    · · · · · ·

By default, ZoneTaxon are used with this controller, and the following paragraphs make that assumption. See the documentation of the populate methods to learn how to use other types. Speciation of ZoneTaxon objects occurs when the taxon exists in more than one zone once the allopatric wait time has been exceeded in that zone. See ZoneTaxon documentation for more about allopatric wait time.

A different example grid demonstrates here the temporal connectivity of zones. The grid represents the time, T0 with the nodes of a zone marked with x. The following examples will use D8 neighborhoods and a minimum zone area of 0.

T0
· · · · · ·
· · · · · ·
· x x x x ·
· x x x x ·
· · · · · ·
· · · · · ·

Below are variations of the grid at a later time, T1 in four variations where each contains one zone. In T1a, T1b, and T1c the zone stayed the same, moved, and changed size, respectively. Taxa migrate with the zone when at least one zone node overlaps between the two time steps. However, in T1d, no nodes overlaps, therefore taxa do not disperse from the zone in T0 to the zone in T1d.

T1a            T1b            T1c            T1d
· · · · · ·    · · · · · ·    · · · · · ·    · · · · · ·
· + + + + ·    · · · · · ·    · · + + · ·    · · · · · ·
· + + + + ·    · + + + + ·    · + + + + ·    · · · · · ·
· · · · · ·    · + + + + ·    · · · · + ·    · + + + + ·
· · · · · ·    · · · · · ·    · · · · · ·    · + + + + ·
· · · · · ·    · · · · · ·    · · · · · ·    · · · · · ·

Another T1 variation, now demonstrating two zones, + and x. Multiple zones overlapping a zone in the prior time step can be interpreted as a zone that fragmented, which may affect resident taxa. The number of zone fragmentations can be viewed in the record_data_frame attribute. In the T1e example, the fragmentation count for time 1 would be 2 because 2 zones that fragmented from a prior zone were recognized at this time.

T1e
· · · · · ·
· · · · + ·
· x · · + ·
· x x · · ·
· x x · · ·
· · · · · ·

The controller had to decide which of the two clusters of continuous nodes in T1 should be designated as the same zone in T0. This decision must be made in general when multiple clusters overlap the same zone in the prior time step. The zone in the current time step that overlaps the prior time step zone the most becomes the same zone in the earlier time step. In this example, the cluster to the right overlapped four nodes and the left cluster overlapped only one node, therefore the right cluster became the star zone. This is merely for creating new zones objects.

The grid diagrammed below continues from T1e. The continuous nodes overlapped two zones in T1e. When multiple zones overlap, one zone is assumed to be the prior zone and the others are considered captured zones. The number of zone captures can be viewed in the record_data_frame attribute.

T2
· · · · · ·
· · · · · ·
· x x x x ·
· x x x · ·
· · · · · ·
· · · · · ·

The controller had to again decide which of the two clusters of continuous nodes in T1e should be designated as the same zone in T2. This decision must be made in general when multiple clusters in the prior time step overlap a zone in the current time step. The zone in the prior time step that overlaps the current time step zone the most becomes the zone in the earlier time step. In this example, the cluster to the left overlapped two nodes and the right cluster overlapped only one node, therefore the new zone keeps the designation of the left cluster. However, this is merely for creating new zone objects.

ZoneController is currently designed for use with only the grid type, RasterModelGrid.

Examples

Import modules used in the following examples.

>>> from landlab import RasterModelGrid
>>> from landlab.components.species_evolution import ZoneController

The first example uses the default parameters of ZoneController.

Create a model grid and an elevation field for this grid.

>>> mg = RasterModelGrid((3, 7))
>>> z = mg.add_zeros("topographic__elevation", at="node")

Set elevation to 1 for some nodes.

>>> z[[9, 10, 11, 12]] = 1

Define a zone function that returns a boolean array where True values indicate the nodes where zones can be created.

>>> def zone_func(grid):
...     z = grid.at_node["topographic__elevation"]
...     return z == 1
...

Instantiate ZoneController. Only one zone exists because the nodes that were set to one are adjacent to each other in the grid.

>>> zc = ZoneController(mg, zone_func)
>>> zc.record_data_frame[["time", "zones"]]
   time  zones
0     0      1

Populate each zone with a taxon.

>>> taxon = zc.populate_zones_uniformly(1)
>>> len(taxon)
1

A change in elevation is forced to demonstrate a zone fragmentation, and then the zones are updated by advancing the record time by 1000.

>>> z[10] = 0
>>> zc.run_one_step(1000)

Two zones now exist because the zone in time 0 fragmented into two zones.

>>> zc.record_data_frame[["time", "zones", "fragmentations"]]
   time  zones  fragmentations
0     0      1             NaN
1  1000      2             2.0

A change in elevation is forced again, this time to demonstrate zone capture where multiple zones are overlapped by a zone in the later time step. Statistics of the capture can be attained with record_data_frame.

>>> z[10] = 1
>>> zc.run_one_step(1000)
>>> zc.record_data_frame[
...     ["time", "zones", "captures", "area_captured_sum", "area_captured_max"]
... ]
   time  zones  captures  area_captured_sum  area_captured_max
0     0      1       NaN                NaN                NaN
1  1000      2       0.0                0.0                0.0
2  2000      1       1.0                2.0                2.0

The follow example demonstrates non-default ZoneController parameters.

>>> mg = RasterModelGrid((3, 7))
>>> z = mg.add_zeros("topographic__elevation", at="node")

Similar to the prior example, define a zone function that returns a boolean array where True values indicate the nodes where zones can be created.

>>> def zone_func(grid):
...     z = grid.at_node["topographic__elevation"]
...     return z == 1
...

Set elevation to 1 for nodes so that two clusters of nodes within the zone mask exist.

>>> z[[9, 10, 12]] = 1

Instantiate ZoneController with options.

>>> zc = ZoneController(mg, zone_func, minimum_area=2, initial_time=100)

Only one zone exist, despite two clusters of nodes meeting the zone definition, because the minimum_area was set to 2. Also, the first time in the record was set by the initial_time parameter.

>>> zc.record_data_frame[["time", "zones"]]
   time  zones
0   100      1

Initialize the controller.

Parameters:
  • grid (RasterModelGrid) – A Landlab RasterModelGrid.

  • zone_function (function) – A function that return a mask of the total zone extent. The first input parameter of this function must be grid.

  • minimum_area (float, optional) – The minimum area of the zones that will be created.

  • neighborhood_structure ({'D8', 'D4'}, optional) – The structure describes how zones are identified. The default, ‘D8’ evaluates the eight neighboring nodes. The diagonal neighboring nodes are excluded when ‘D4’ is selected.

  • initial_time (float, int, optional) – The initial time. The unit of time is unspecified within the controller. The default is 0.

  • kwargs – Keyword arguments for zone_function. Do not include grid in kwargs because grid, the first parameter of this method, is automatically added to kwargs.

__init__(grid, zone_function, minimum_area=0, neighborhood_structure='D8', initial_time=0, **kwargs)[source]#

Initialize the controller.

Parameters:
  • grid (RasterModelGrid) – A Landlab RasterModelGrid.

  • zone_function (function) – A function that return a mask of the total zone extent. The first input parameter of this function must be grid.

  • minimum_area (float, optional) – The minimum area of the zones that will be created.

  • neighborhood_structure ({'D8', 'D4'}, optional) – The structure describes how zones are identified. The default, ‘D8’ evaluates the eight neighboring nodes. The diagonal neighboring nodes are excluded when ‘D4’ is selected.

  • initial_time (float, int, optional) – The initial time. The unit of time is unspecified within the controller. The default is 0.

  • kwargs – Keyword arguments for zone_function. Do not include grid in kwargs because grid, the first parameter of this method, is automatically added to kwargs.

populate_zones_uniformly(count, taxon_type=<class 'landlab.components.species_evolution.zone_taxon.ZoneTaxon'>, **kwargs)[source]#

Populate each zone with the same type and count of taxa.

Parameters:
  • count (int) – The count of taxon to populate to each zone.

  • taxon_type (type of Taxon) – A Taxon type that takes a Zone as its first parameter.

  • kwargs (dictionary) – Keyword arguments of taxon_type.

property record_data_frame#

A DataFrame of ZoneController variables over time.

Each row is data of a model time step. The step time is recorded in the time column. The columns, zones, fragmentations, and captures are the count of these variables at a given time. area_captured_sum is the summation of captures over a time. area_captured_max is the maximum area captured of a single capture during a time.

run_one_step(dt)[source]#

Update the zones for a single timestep.

This method advances time in the record and determines the connectivity of zones between the current and prior time steps.

Parameters:

dt (float) – The model time step duration.

property zones#

The zones of the ZoneController.

ZoneTaxon: A zone-based taxon#

ZoneTaxon object of SpeciesEvolver.

class ZoneTaxon(zones, parent=None, time_to_allopatric_speciation=0, persists_post_speciation=True)[source]#

Bases: Taxon

A taxon based in zones.

A ZoneTaxon is composed of members of a lower taxonomic level that each exists within a Zone object. Taxonomic rank is not considered by this class despite the use of the term, ‘speciation’, which is used herein to generally describe creation of a child taxon object.

All zones of the taxon can be obtained with the attribute, zones that are the objects that manage the geographic aspect of taxon member populations. The total geographic extent of all populations is depicted by the range_mask attribute. The zones of a ZoneTaxon instance are created and updated using a ZoneController. At model time steps, the connectivity of zones over time is obtained using attributes of the Zone object.

The evolution of this taxon type is carried out in two stages during a model time step. In the first stage, the zones of the taxon are updated as the result of zone connectivity between the prior and current step in the method, _update_zones. This method is the primary implementation of taxon dispersal and it is called in a stage prior to other evolutionary processes so that all taxa are positioned in their landscape locations prior to the other processes.

In the second stage, processes are carried out in methods that are readily expanded or overridden when needed. The primary methods of second stage macroevolution are _evaluate_dispersal, _evaluate_speciation, and _evaluate_extinction. The evaluate dispersal method is intended to modify dispersal conducted in the first stage and it has no effect unless it is expanded or overridden to have an effect. Processes other than those listed above can be called by expanding or overridding the _evolve method.

The taxon is allopatric when it is associated with/exists within multiple zones (signifying multiple member populations). A timer is started when a taxon becomes allopatric. Allopatric speciation occurs once the timer reaches or exceeds the time_to_allopatric_speciation initialization parameter. If the initialization parameter, persists_post_speciation is True (default), a child taxon is created in each zone except one zone (the largest by area) that becomes the sole zone of the taxon. If persists_post_speciation is set to False, a child taxon is created in each and every zone, and the parent no longer occupies any zones, and therefore the parent taxon is no longer extant.

Extinction occurs when the taxon is no longer associated with any zones. This occurs when zones in the prior time step do not overlap zones in the current time step, signifying the geographic range of the taxon is no more. A taxon can become no longer extant also when the taxon speciates and persists_post_speciation is False signifying that the parent taxon has evolved into multiple taxon distinct from the original taxon.

The following columns will be added to the record_data_frame of the SpeciesEvolver instance that tracks objects of this Taxon: ‘speciations’ and ‘extinctions’, which are the counts of these variables at time steps. Another column, ‘pseudoextinctions’ will be included when persists_post_speciation is False. This variable is the count of occurrences when a parent taxon became non-extant due to speciation and not because of an absence of zones.

Initialize a taxon.

Parameters:
  • zones (list of Zones) – The initial SpeciesEvolver Zones where the taxon is located.

  • parent (Taxon, optional) – A SpeciesEvolver taxon that is the parent taxon. The default value, ‘None’ indicates no parent.

  • time_to_allopatric_speciation (float, int, optional) – The delay in model time to speciate following taxon geographic fragmentation, indicated by multiple objects in the attribute, zones. Speciation occurs at the time step when the delay is reached or exceeded. The default value of 0 indicates speciation occurs at the same time step as geographic fragmentation.

  • persists_post_speciation (boolean, optional) – When ‘True’, the default, taxon persists despite speciation. When ‘False’ and following speciation, the taxon is no longer extant.

__init__(zones, parent=None, time_to_allopatric_speciation=0, persists_post_speciation=True)[source]#

Initialize a taxon.

Parameters:
  • zones (list of Zones) – The initial SpeciesEvolver Zones where the taxon is located.

  • parent (Taxon, optional) – A SpeciesEvolver taxon that is the parent taxon. The default value, ‘None’ indicates no parent.

  • time_to_allopatric_speciation (float, int, optional) – The delay in model time to speciate following taxon geographic fragmentation, indicated by multiple objects in the attribute, zones. Speciation occurs at the time step when the delay is reached or exceeded. The default value of 0 indicates speciation occurs at the same time step as geographic fragmentation.

  • persists_post_speciation (boolean, optional) – When ‘True’, the default, taxon persists despite speciation. When ‘False’ and following speciation, the taxon is no longer extant.

property extant#

The living state of the taxon.

The taxon lives at the current model time if True. The taxon is extinct as of the current model time if False.

property range_mask#

A mask representing the geographic extent of the taxon.

The mask is an array with a length of grid number of nodes. The taxon exists at nodes where mask elements are True. The mask of a ZoneTaxon object is the union of all of its zone masks.

property zones#

The zones of the taxon.