Skip to content

Commit

Permalink
Raise error if an epoch from a demes model is less than 1 time step.
Browse files Browse the repository at this point in the history
* add test of demes models with very short durations
* add failing tests of models where rounding should cause a problem
  • Loading branch information
molpopgen committed May 24, 2022
1 parent 854cf3d commit 67bb9a4
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 2 deletions.
5 changes: 5 additions & 0 deletions doc/misc/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Testing

* Added many more tests related to models defined using `demes`
PR {pr}`891`.
PR {pr}`931`.
Issue {issue}`890`.
{user}`apragsdale`,
{user}`molpopgen`.
Expand All @@ -57,6 +58,10 @@ Back end changes
PR {pr}`906`.
* Added infrastructure to separate out back end from Python-specific C++ code.
PR {pr}`936`.
* Assert that epochs from `demes` models are at least 1 generation long.
PR {pr}`931`
* Added infrastructure to separate out back end from Python-specific C++ code.
PR {pr}`936`.

Dependencies

Expand Down
6 changes: 5 additions & 1 deletion fwdpy11/_functions/import_demes.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,10 @@ def _process_epoch(

start_size = int(np.rint(e.start_size))
end_size = int(np.rint(e.end_size))
time_span = int(np.rint(e.time_span))

if time_span < 1:
raise ValueError("epoch durations must be >= 1 time step")

# Handle size change functions
events.set_deme_sizes.append(
Expand All @@ -529,7 +533,7 @@ def _process_epoch(
raise ValueError(
f"Size change function must be exponential. We got {e.size_function}"
)
G = exponential_growth_rate(start_size, end_size, int(np.rint(e.time_span)))
G = exponential_growth_rate(start_size, end_size, time_span)
events.set_growth_rates.append(
SetExponentialGrowth(when=when, deme=idmap[deme_id], G=G)
)
Expand Down
5 changes: 4 additions & 1 deletion fwdpy11/discrete_demography.py
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,10 @@ def from_demes_graph(
if start > 0:
start = start + 1
end = model_times.convert_time(e.end_time) + 1
assert end > start, f"{e}, {start}, {end}"
if not end > start:
raise ValueError(
f"epoch end time must be > start, got end: {end}, start: {start}"
)
# NOTE: 1.0 is a HACK for growth rate and is WRONG
itree[start:end] = _EpochData(
idmap[d.name], None, int(e.start_size), 1.0
Expand Down
48 changes: 48 additions & 0 deletions tests/test_demes2fwdpy11.py
Original file line number Diff line number Diff line change
Expand Up @@ -1857,3 +1857,51 @@ def test_non_integer_initial_epoch_size():
for i in sorted(demog.metadata["initial_sizes"].keys())
]
_ = fwdpy11.DiploidPopulation(initial_sizes, 1)


def test_very_short_epoch():
b = demes.Builder()
b.add_deme("A", epochs=[{"start_size": 100}])
b.add_deme(
"B",
ancestors=["A"],
start_time=10,
epochs=[
{"start_size": 100, "end_time": 1e-3},
{"start_size": 200, "end_time": 0.0},
],
)
g = b.resolve()

with pytest.raises(ValueError):
_ = fwdpy11.discrete_demography.from_demes(g)


def test_epoch_rounding_01():
yaml = """
time_units: generations
demes:
- name: bad
epochs:
- {end_time: 1.75, start_size: 1}
- {end_time: 1.25, start_size: 2}
- {end_time: 0.5, start_size: 3}
- {end_time: 0, start_size: 4}
"""
graph = demes.loads(yaml)
with pytest.raises(ValueError):
_ = fwdpy11.discrete_demography.from_demes(graph, burnin=0)

def test_epoch_rounding_02():
yaml = """
time_units: generations
demes:
- name: bad
epochs:
- {end_time: 1.5, start_size: 1}
- {end_time: 0.5, start_size: 2}
- {end_time: 0, start_size: 3}
"""
graph = demes.loads(yaml)
with pytest.raises(ValueError):
_ = fwdpy11.discrete_demography.from_demes(graph, burnin=0)

0 comments on commit 67bb9a4

Please sign in to comment.