simulation=populationDemographicModel=>{
let currentHeight=0;
const helper = function(population){
const activePopulation = population.filter(n=>n.height<=currentHeight);
const toBeSampled = population.filter(n=>n.height>currentHeight)
const nextSample = toBeSampled.length>0?toBeSampled[d3_array.minIndex(toBeSampled,d=>d.height)]:null;
if(population.length===1){
const tree= new Figtree.Tree(population[0],{lengthsKnown:false,heightsKnown:true});
tree.nodeList.forEach(n=>n.height=populationDemographicModel.getT(n.height));
return tree;
}
if(activePopulation.length===1 && nextSample){
currentHeight=nextSample.height;
return helper(population)
}
const k = activePopulation.length;
const Ne = populationDemographicModel.N0;
const tau = sampleExponetial(k*(k-1)/(2*Ne));
if(nextSample && currentHeight+tau>nextSample.height){
currentHeight=nextSample.height;
return helper(population);
}else{
const luckyDucks = sampleLineages(activePopulation);
currentHeight+=tau;
const parent = coalesce(currentHeight,luckyDucks);
const updatedPopulation = population.filter(n=>!luckyDucks.includes(n)).concat(parent);
return helper(updatedPopulation);
}
}
return helper;
}