Skip to content
Draft
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
1 change: 1 addition & 0 deletions demes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@

from .demes import Epoch, Migration, Pulse, Deme, Graph, Split, Branch, Merge, Admix
from .load_dump import load_asdict, loads_asdict, load, loads, dump, dumps
import demes.models
74 changes: 74 additions & 0 deletions demes/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import numpy as np

from . import demes


def island(size, migration_rate):
"""
Returns a :class:`.Graph` object representing a collection of
demes with specified sizes with symmetric migration between
each pair of demes at the specified rate.

:param array_like size: the ``start_size`` value for each
of :class:`.Deme` in the returned model. The length
of the array corresponds to the number of demes.
:param float migration_rate: The migration rate between each pair of
demes.
:return: A Graph object representing this model.
:rtype: .Graph
"""
graph = demes.Graph(description="Island model", time_units="generations")
for j, start_size in enumerate(size):
graph.deme(
id=f"pop_{j}", epochs=[demes.Epoch(start_size=start_size, end_time=0)]
)
graph.symmetric_migration(
demes=[deme.id for deme in graph.demes], rate=migration_rate
)
return graph


def stepping_stone(size, migration_rate, boundaries=False):
"""
Returns a :class:`.Graph` object representing a collection of
demes with the specified population sizes and in which adjacent
demes exchange migrants at the specified rate.

.. note:: The current implementation only supports a one-dimensional
stepping stone model, but higher dimensions could also be supported.
Please open an issue on GitHub if this feature would be useful to you.

:param array_like size: the size of each deme in the returned model.
The length of the array corresponds to the number of demes.
:param float migration_rate: The migration rate between adjacent pairs
of demes.
:param bool boundaries: If True the stepping stone model has boundary
conditions imposed so that demes at either end of the chain do
not exchange migrants. If False (the default), the set of
populations is "circular" and migration takes place between the
terminal demes.
:return: A Graph object representing this model.
:rtype: .Graph
"""
size = np.array(size, dtype=np.float64)
if len(size.shape) > 1:
raise ValueError(
"Only 1D stepping stone models currently supported. Please open "
"an issue on GitHub if you would like 2D (or more) models"
)
K = size.shape[0]
graph = demes.Graph(description="1D stepping model", time_units="generations")
for j, start_size in enumerate(size):
graph.deme(
id=f"pop_{j}", epochs=[demes.Epoch(start_size=start_size, end_time=0)]
)

for j in range(K - 1):
graph.symmetric_migration(
demes=[graph.demes[j].id, graph.demes[j + 1].id], rate=migration_rate
)
if K > 1 and not boundaries:
graph.symmetric_migration(
demes=[graph.demes[0].id, graph.demes[-1].id], rate=migration_rate
)
return graph