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

Virtual subpopulations not recognized when evolving age-structured population with overlapping generations #55

Closed gabelow closed 6 years ago

gabelow commented 6 years ago

Dear Bo,

I'd like to thank you in advance for taking up your time with my request for help. I am pretty new to simuPOP and have been struggling to solve an error that I think seems to be rooted in how virtual subpopulations or age information fields are being handled in my script.

Briefly, I am attempting to simulate successive generations for captive-bred individuals using empirical genotypes (SNPs) sequenced from 17 such individuals in an age-structured framework with overlapping generations. Using my script, I am so far able to:

1) load the sequenced genotypes into simuPOP via the utils.importPopulation function

2) assign all relevant information fields with

pop.setInfoFields(['ind_id','father_id','mother_id','father_idx','mother_idx','age']) 

3) create and verify that virtual subpopulations by age strata are created correctly with

pop.setVirtualSplitter(sim.InfoSplitter(field='age', cutoff=[1,20]))
def printPop(pop): 
    for sp in range(pop.numSubPop()): 
        for vsp in range(pop.numVirtualSubPop()): 
            print("Population {subpop}: {vspname1} ({vspsize}) --> [{subpop}, {vsp}]".format(subpop = sp, 
            vspname1 = pop.subPopName([sp, vsp]), 
            vspsize = pop.subPopSize([sp, vsp]), 
            vsp = vsp 
            )) 
printPop(pop)

However, when I run the rest of the script thereafter, I run into the following error:

[17]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-4-232bc1af6f31> in demoModel(gen, pop)
      9     '''A demographic model that keep a constant supply of new individuals'''
     10     # number of individuals that will die
---> 11     sim.stat(rfltpop, popSize=True, subPops=[(0,2)])
     12     # individuals that will be kept, plus some new guys.
     13     return rfltpop.popSize() - rfltpop.dvars().popSize + N / 75

~/anaconda2/envs/py365/lib/python3.6/site-packages/simuPOP/__init__.py in stat(pop, *args, **kwargs)
   1201     Resulting statistics could be accessed from the local namespace of ``pop``
   1202     using functions ``pop.vars()`` or ``pop.dvars()``'''
-> 1203     Stat(*args, **kwargs).apply(pop)
   1204 
   1205 def tagID(pop, reset=False, *args, **kwargs):

IndexError: population.cpp: 1015 No virtual subpopulation is defined, or subpop index (2) out of range of 0  ~ 18446744073709551615

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-232bc1af6f31> in <module>()
     45              sim.PyEval(r'"%s\n" % subPopSize')
     46             ],
---> 47     gen = 1) 

~/anaconda2/envs/py365/lib/python3.6/site-packages/simuPOP/__init__.py in evolve_pop(self, initOps, preOps, matingScheme, postOps, finalOps, gen, dryrun)
    404     simu = Simulator(self)
    405     # evolve
--> 406     gen = simu.evolve(initOps, preOps, matingScheme, postOps, finalOps, gen)
    407     # get the evolved population
    408     self.swap(simu.population(0))

ValueError: Function call failed.

I've found that the script runs correctly as long as I use an integer in place of demoModel for subPopSize, so I strongly believe the fault lies in how the virtual subpopulations are being recognised. Unfortunately, I can't seem to find a solution to this. When demoModel(0,0) is evaluated separately, it always gives an integer as expected.

I have attached my script and the input dataset for your use. I hope that you will be willing to help me and look forward to your reply.

Best wishes, Gabriel Low

empirical_simuPOP.txt empirical_dataset.txt

BoPeng commented 6 years ago

Hi, Gabriel,

I tried to run your script, with the demoModel and the one you commented out, and did not observe any problem. From your error message,

<ipython-input-4-232bc1af6f31> in demoModel(gen, pop)
      9     '''A demographic model that keep a constant supply of new individuals'''
     10     # number of individuals that will die
---> 11     sim.stat(rfltpop, popSize=True, subPops=[(0,2)])

I can see that you are applying the Stat operator on rfltpop, not pop. I am not sure how rfltpop is created but as documented here, virtual subpopulations are not preserved during save/load so you will have to re-define VSPs for rfltpop if you are to calculated subpopulation size for [(0,2)].

gabelow commented 6 years ago

Hi Bo,

Thank you for having a look at the script. I apologize for the confusion but rfltpop is actually the same object as pop - I was trying to clean up my personal notation before posting my question but I forgot to clean up the quoted errors as well.

So the error message associated with the code I last attached should read:

[17]
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-4-232bc1af6f31> in demoModel(gen, pop)
      9     '''A demographic model that keep a constant supply of new individuals'''
     10     # number of individuals that will die
---> 11     sim.stat(pop, popSize=True, subPops=[(0,2)])
     12     # individuals that will be kept, plus some new guys.
     13     return pop.popSize() - pop.dvars().popSize + N / 75

~/anaconda2/envs/py365/lib/python3.6/site-packages/simuPOP/__init__.py in stat(pop, *args, **kwargs)
   1201     Resulting statistics could be accessed from the local namespace of ``pop``
   1202     using functions ``pop.vars()`` or ``pop.dvars()``'''
-> 1203     Stat(*args, **kwargs).apply(pop)
   1204 
   1205 def tagID(pop, reset=False, *args, **kwargs):

IndexError: population.cpp: 1015 No virtual subpopulation is defined, or subpop index (2) out of range of 0  ~ 18446744073709551615

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-232bc1af6f31> in <module>()
     45              sim.PyEval(r'"%s\n" % subPopSize')
     46             ],
---> 47     gen = 1) 

~/anaconda2/envs/py365/lib/python3.6/site-packages/simuPOP/__init__.py in evolve_pop(self, initOps, preOps, matingScheme, postOps, finalOps, gen, dryrun)
    404     simu = Simulator(self)
    405     # evolve
--> 406     gen = simu.evolve(initOps, preOps, matingScheme, postOps, finalOps, gen)
    407     # get the evolved population
    408     self.swap(simu.population(0))

ValueError: Function call failed.

I wonder if this makes more sense now? I have been continuing to troubleshoot the error today but can't seem to get away from it.

Thanks again!

Gabriel

gabelow commented 6 years ago

Hi Bo!

After you mentioned that you were able to rerun the code without any issues, I finally realised that the problem could be lying with my personal notation for the script. After changing all relevant instances of 'rfltpop' to simply 'pop' in my script, it appears to be running correctly on my side now.

Sorry for taking up your time, but somehow it seems like you've helped me a lot with this! Thank you very much!

Best regards, Gabriel