def dual_analysis(labels, pop, migration_fun, migration_outofbounds_fun, startparams, migration_fun_name): """ Analyse a population using a given migration function, with both the composite and classical models. """ ## 1a. the composite demographic model. # Get the information about the tracts out of the population object, and # split the population into 2 groups, in order to perform an analysis as a # composite demographic model. bins, group_data = pop.get_global_tractlengths(npts=50, split_count=2) # The actual groups that we're splitting the population into. groups = pop.split_by_props(2) # Compute the counts of individuals in each group and the average ancestry # proportions across individuals. The counts of individuals in each groups # should differ by no more than one. ninds, group_ancestry_averages = zip(*map( lambda p: ( len(p.indivs), p.get_mean_ancestry_proportions(ancestry_labels)), groups)) # Rearrange the data for each group into a list ordered in the same way as # the population labels. group_data = [ [g[ancestry_label] for ancestry_label in ancestry_labels] for g in group_data] ## Optimize the model parameters using COBYLA #composite_model_parameters = tracts.optimize_cob_multifracs( # startparams, bins, pop.Ls, group_data, ninds, migration_fun, # group_ancestry_averages, outofbounds_fun=migration_outofbounds_fun, # cutoff=cutoff, epsilon=1e-12) # Optimize the model parameters using brute composite_model_parameters, _ = tracts.optimize_brute_multifracs( bins, pop.Ls, group_data, ninds, migration_fun, group_ancestry_averages, startparams, outofbounds_fun=migration_outofbounds_fun, cutoff=cutoff) # Construct the composite demographic model composite_model = tracts.composite_demographic_model( migration_fun, composite_model_parameters, group_ancestry_averages) ## 1b. the fracs2 model. nind = len(pop.indivs) _, data = pop.get_global_tractlengths(npts=50, split_count=1) data = [data[ancestry_label] for ancestry_label in ancestry_labels] ancestry_averages = pop.get_mean_ancestry_proportions(ancestry_labels) fracs2_model_parameters, _ = tracts.optimize_brute_fracs2( bins, pop.Ls, data, nind, migration_fun, ancestry_averages, startparams, outofbounds_fun=migration_outofbounds_fun, cutoff=cutoff) fracs2_model = tracts.demographic_model( migration_fun(fracs2_model_parameters, ancestry_averages)) return { 'classical': { 'params': fracs2_model_parameters, 'model': fracs2_model, 'averages': ancestry_averages, 'theories': dict( ( name, fp.Theory( bins, nind * np.array( fracs2_model.expectperbin( pop.Ls, i, bins)), migration_fun_name + ' classical', name) ) for i, name in enumerate(labels)), }, 'composite': { 'params': composite_model_parameters, 'model': composite_model, 'ninds': ninds, 'averages': group_ancestry_averages, 'groups': group_data, 'theories': dict( ( name, fp.Theory( bins, composite_model.expectperbin( pop.Ls, i, bins, ninds), migration_fun_name + ' composite', name) ) for i, name in enumerate(labels)), }, 'misc': { 'startparams': startparams, 'bins': bins, 'data': data, 'fun': migration_fun, }, }
for frac, flat_tract in izip(bypopfrac, flattracts): frac.append(flat_tract / flat_tracts_sum) props = map(numpy.mean, bypopfrac) Ls = pop.Ls nind = pop.nind cutoff = 2 def randomize(arr, scale=2): # takes an array and multiplies every element by a factor between 0 and # 2, uniformly. caps at 1. return map(lambda i: min(i, 1), scale * numpy.random.random(arr.shape) * arr) xopt = tracts.optimize_brute_fracs2( bins, Ls, data, nind, func, props, slices, outofbounds_fun=bound, cutoff=cutoff) print xopt optmod = tracts.demographic_model(func(xopt[0], props)) optpars = xopt[0] liks = xopt[1] maxlik = optmod.loglik(bins, Ls, data, pop.nind, cutoff=cutoff) expects = [] for popnum in range(len(data)): expects.append(optmod.expectperbin(Ls, popnum, bins)) expects = nind * numpy.array(expects) outf = outdir + "boot%d_%2.2f" % (bootnum, maxlik,) fbins = open(outf + "_bins", 'w')