BoPeng / simuPOP

A general-purpose forward-time population genetics simulation environment.
http://bopeng.github.io/simuPOP/
GNU General Public License v2.0
29 stars 12 forks source link

InstantChangeModel #92

Closed BoPeng closed 2 years ago

BoPeng commented 2 years ago

I have been using the InstantChangeModel to examine the genetic consequences of population bottlenecks and had some questions that do not appear to be covered in the documentation. First, I would like to know if the genotypes of individuals is transferred across a demographic transition. Second, how is this done? If the population declines, are the remaining individuals a random sample of the original population (genotypes)? If it expands, are individual genotypes randomly selected to fill in the expansion?

If this is not the best method to look at the genetic effects of a bottleneck, then would random sampling to create a new subpopulation be more appropriate?

BoPeng commented 2 years ago

I would like to know if the genotypes of individuals is transferred across a demographic transition.

Yes

If the population declines, are the remaining individuals a random sample of the original population (genotypes)? If it expands, are individual genotypes randomly selected to fill in the expansion?

It is done through the passing the genotypes to offspring generations. For example, for population decline, there are fewer offspring than parents so most parents cannot pass their genotypes to offspring. For population increase, most parents will have more than one offspring.

To actually observe the impact of demography on genetic diversity, you would need to have a "good" distribution of parental genotypes (some people use coalescent simulations to generate one, some use of long burnin process to generate an "equilibrium" population). Then the demographic change would break the balance and cause, for example, change of effective population size.

If this is not the best method to look at the genetic effects of a bottleneck, then would random sampling to create a new subpopulation be more appropriate?

In some sense 'random sampling to create a new subpopulation" is the same as generating an offspring population from parental population, the latter can be a lot more sophisticated if you introduce recombination, mutation, selection etc to the evolutionary process.

cruzan-lab commented 2 years ago

Thank you for the response. As a follow-up question I would like to know how to change parameters to correspond to demographic changes in the InstantChangeModel. For example, I want to calculate s based on the population size to maintain constant Ns. Can I extract N from the model so I can calculate s in Python? Alternatively, would it be easier to use MapSelector in matingScheme to determine the fitness of each genotype based on N?

BoPeng commented 2 years ago

The documentation of InstantChangeModel (here) lists the parameters that can be changed. Yes, you can report N during evolution using the PyEval operator after you calculate population size using

sim.Stat(popSize=True)

see here for an example.

If you would like to apply selection, you can do it with MapSelector, preferrably as a pre-mating operator (selection on parents) as shown in this example.

Finally, you can output s and N to calculate Ns, you can also calculate Ns in simuPOP using the methods provided (see here).

cruzan-lab commented 2 years ago

Hi Bo,

The examples are helpful, but do not provide the exact syntax I am looking for.

I'm having trouble getting it to recognize the popSize parameter.

        matingScheme = sim.RandomMating(ops=[             sim.PyEval("h = 0.5"),             sim.Stat(popSize = True, vars='popSize'),             sim.MendelianGenoTransmitter(),             sim.MapSelector(loci=0, fitness={(0,0):(1-(2/popSize), (0,1):(1-(h*(2/popSize)), (1,1):fit11}),

Mitch

On 8/3/2022 2:24 PM, Bo wrote:

The documentation of |InstantChangeModel| (here http://bopeng.github.io/simuPOP/refManual_ch4_sec3.html#class-instantchangemodel) lists the parameters that can be changed. Yes, you can report |N| during evolution using the |PyEval| operator http://bopeng.github.io/simuPOP/userGuide_ch5_sec3.html#evaluate-and-output-python-expressions-operator-pyeval after you calculate population size using

|sim.Stat(popSize=True) |

see here http://bopeng.github.io/simuPOP/userGuide_ch5_sec11.html#counting-individuals-by-sex-and-affection-status for an example.

If you would like to apply selection, you can do it with |MapSelector|, preferrably as a pre-mating operator (selection on parents) as shown in this example http://bopeng.github.io/simuPOP/userGuide_ch5_sec9.html#map-selector-operator-mapselector.

Finally, you can output |s| and |N| to calculate |Ns|, you can also calculate |Ns| in simuPOP using the methods provided (see here http://bopeng.github.io/simuPOP/userGuide_ch5_sec11.html#effective-population-size).

— Reply to this email directly, view it on GitHub https://github.com/BoPeng/simuPOP/issues/92#issuecomment-1204499261, or unsubscribe https://github.com/notifications/unsubscribe-auth/AGCF2N5MPZOYM3HDBAVDKQ3VXLPRDANCNFSM55NFLWYQ. You are receiving this because you commented.Message ID: @.***>

--

Mitch Cruzan (He/Him) Professor of Biology Portland State University PO Box 751 Portland, OR 97207 USA Web:https://cruzanlab.weebly.com/ https://cruzanlab.weebly.com/

  Evolutionary Biology - A Plant Perspective

/Mitchell B. Cruzan// Available through all good bookshops, or direct from Oxford University Press https://global.oup.com/academic/product/evolutionary-biology-9780190882679?cc=us&lang=en&#/


BoPeng commented 2 years ago
         matingScheme = sim.RandomMating(ops=[
             sim.PyEval("h = 0.5"),
             sim.Stat(popSize = True, vars='popSize'),
             sim.MendelianGenoTransmitter(),
             sim.MapSelector(loci=0, fitness={(0,0):(1-(2/popSize),
(0,1):(1-(h*(2/popSize)), (1,1):fit11}),

is an interesting case, so you are modeling a case when the fitness depends on population size.

You code does not work because

  1. Stat(popSize) should be called as preOps before mating happens.
  2. The variable popSize is available "inside" the populations, only available to "expressions" evaluated by for example PyOutput. The MapSelector in your case is expecting a variable defined in the Python namespace.

It is a little bit advanced but you essentially need to create and apply a MapSelector at each generation, using the MapSelector().apply(pop) idiom inside a PyOperator. I cranked a quick example, which can hopefully help you.

import simuPOP as sim

pop = sim.Population(size=1000, loci=1, infoFields=['fitness'])

def select(pop):
    h = 0.5
    popSize = pop.dvars().popSize
    fitness = {
            (0, 0): 1 - (2 / popSize),
            (0, 1): 1 - (h * (2 / popSize)),
            (1, 1): 0.5
        }
    print(f'{popSize} {fitness}')
    sim.MapSelector(
        loci=0,
        fitness=fitness).apply(pop)
    return True

pop.evolve(
    initOps=[sim.InitSex()],
    preOps=[sim.Stat(popSize=True, vars='popSize'),
            sim.PyOperator(select)],
    matingScheme=sim.RandomMating(),
    gen=10)