Initializing a population#

Initializing with no previous ancestry#

A single deme#

To initialize a fwdpy11.DiploidPopulation with \(N = 100\) diploids and a genome length of \(1000\):

import fwdpy11

pop = fwdpy11.DiploidPopulation(100, 1000.0)

We can access these fields:

print(f"N = {pop.N}, L = {pop.tables.genome_length}")
N = 100, L = 1000.0

The genome length is a property of the fwdpy11.TableCollection that records the population’s ancestry.

Multiple initial demes#

To initialize \(N = 100\) with two demes of sizes 25 and 50, respectively, and the same genome length as above:

pop = fwdpy11.DiploidPopulation([25, 75], 1000.0)

The overall \(N\) is the same:

print(f"N = {pop.N}")
N = 100

The deme labels are reflected in the individual meta data. The meta data are a list of instance of fwdpy11.DiploidMetadata. That class is also a numpy.dtype, allowing us to access the raw data efficiently as a numpy.recarray:

import numpy as np
md = np.array(pop.diploid_metadata, copy=False)
np.unique(md['deme'], return_counts=True)
(array([0, 1], dtype=int32), array([25, 75]))

The individuals are intuitively ordered:

print(np.where(md['deme'] == 0)[0].min(),
      np.where(md['deme'] == 0)[0].max(),
      np.where(md['deme'] == 1)[0].min(),
      np.where(md['deme'] == 1)[0].max())
0 24 25 99

Initializing with ancestry from msprime#

A single deme#

import msprime

N = 100
L = 1000.0

ts = msprime.sim_ancestry(N, population_size = N, sequence_length=L, recombination_rate = 1e-3, random_seed = 42)
pop = fwdpy11.DiploidPopulation.create_from_tskit(ts)
assert pop.N == 100
assert pop.tables.genome_length == L

Now, our tables have some data in them. Edges are stored as a list of fwdpy11.Edge and nodes as a list of fwdpy11.Node. As with meta data, these are numpy.dtypes:

np.array(pop.tables.edges, copy=False)[:10]
array([(0., 1000., 200, 182), (0., 1000., 200, 191),
       (0., 1000., 201,  59), (0., 1000., 201,  71),
       (0., 1000., 202,   1), (0., 1000., 202, 166),
       (0., 1000., 203,  96), (0., 1000., 203, 145),
       (0., 1000., 204, 111), (0., 1000., 204, 199)],
      dtype=[('left', '<f8'), ('right', '<f8'), ('parent', '<i4'), ('child', '<i4')])
np.array(pop.tables.nodes, copy=False)[:10]
array([(0, 0.), (0, 0.), (0, 0.), (0, 0.), (0, 0.), (0, 0.), (0, 0.),
       (0, 0.), (0, 0.), (0, 0.)],
      dtype={'names': ['deme', 'time'], 'formats': ['<i4', '<f8'], 'offsets': [0, 8], 'itemsize': 16})

Multiple demes#

We can initialize from a multi-deme msprime simulation as well. The simplest way to do this is to use demes to specify the model:

import demes

model_yaml = """
description:
  Example from the fwdpy11 manual
time_units: generations
demes:
  - name: deme0
    epochs:
      - start_size: 50
        end_time: 0
  - name: deme1
    epochs:
      - start_size: 150
        end_time: 0
migrations:
  - demes: [deme0, deme1]
    rate: 0.1    
"""

graph = demes.loads(model_yaml)

demography = msprime.Demography.from_demes(graph)
ts = msprime.sim_ancestry(
    samples={0: 50, 1: 150},
    demography=demography,
    sequence_length=100,
    recombination_rate=1e-3)
pop = fwdpy11.DiploidPopulation.create_from_tskit(ts)
assert pop.N == 200
ds = pop.deme_sizes(as_dict=True)
assert ds[0] == 50
assert ds[1] == 150

Importing msprime tree sequences with mutations.#