popsim-consortium / demes-python

Tools for describing and manipulating demographic models.
https://popsim-consortium.github.io/demes-docs/
ISC License
18 stars 6 forks source link

Start time for a single demographic scenario #494

Closed rmehta1987 closed 1 year ago

rmehta1987 commented 1 year ago

Hi,

I was wondering if it was possible to have a start time for a single demographic scenario i.e:

description: A single population model with epochs of exponential growth and decay.
doi:
  - https://doi.org/10.1038/ng.3015
time_units: generations
demes:
  - name: generic
    epochs:
    - {start_time: 0, start_size: 7156}
    - {start_time: 25,599.98 , start_size: 71560} # 25,599.98 (= 34133.31 - 8533.33 + 0)
    - {start_time: 31,999.98, start_size: 7156} # (= 8533.33 - 2133.33 + 25,599.98)
    - {start_time: 33,599.98, start_size: 7156}
    - {start_time: 33,999.98, start_size: 71560}
    - {start_time: 34,099.98, start_size: 7156}
    - {start_time: 34133.31, start_size: 71560}

If not would it be worth adding to the API ?

molpopgen commented 1 year ago

Unless I am misunderstanding something, I believe you want all of those start times to be end times?

molpopgen commented 1 year ago

Here is a version of your model that leads to a valid graph:

import demes

model = """
description: A single population model with epochs of exponential growth and decay.
doi:
  - https://doi.org/10.1038/ng.3015
time_units: generations
demes:
  - name: generic
    epochs:
    - {end_time: 34133.31, start_size: 71560}
    - {end_time: 34099.98, end_size: 7156}
    - {end_time: 33999.98, end_size: 71560}
    - {end_time: 33599.98, end_size: 7156}
    - {end_time: 31999.98, end_size: 7156}
    - {end_time: 25599.98, end_size: 71560}
    - {end_time: 0, end_size: 7156}
"""

g = demes.loads(model)

A start time is in the past. And epochs must be written in order of past to present. The final start time must be "infinity", meaning "the start size of this epoch is this value indefinitely until the common ancestor is reached". (Or until the burn in time of something like a forward simulation first started.)

rmehta1987 commented 1 year ago

I understand the msprime is a coalescent simulator so it processes generations going back in time, but for forward simulations I would like to invert the generations. So the initialize population size following the zig-zag population model example is 7156 and then there is an inflection point at 25,999 generations moving the population size of 71560 and so on.

molpopgen commented 1 year ago

For forward simulations, you need to reinterpret the model forwards in time, meaning you read in the graph and then convert time as needed. Examples of this include fwdpy11, which converts the backwards-time graph to the forward time objects and a rust crate that provides a forward-time representation of such graphs that may be used in forward simulations. (Currently, fwdpy11 is being refactored to use that rust crate.)

molpopgen commented 1 year ago

There is also a C API for the rust crate. I may write a Python interface but haven't had the time/need yet.

molpopgen commented 1 year ago

This appendix gives a recipe.

rmehta1987 commented 1 year ago

Okay thanks for the responses! I did not know it was a separate package. I thought it would be useful to have in the demes API just for exporting to YAML files.

molpopgen commented 1 year ago

Just to clarify: it is not a separate package but rather something that I wrote because other projects need it. We could have something akin to it in the current demes-python API, but it wouldn't change the YAML file. The YAML that you wrote above will never be a valid demes input (barring an unforeseen reason to introduce a version 2 of the spec).

If you do want to use demes-forward and need pointers, please ask.

molpopgen commented 1 year ago

Going to close this one as there is nothing actionable:

Feel free to reopen if necessary.