def clkk_gen(Omega_m, A_se9, zs=1.0): A_s = A_se9 * 1e-9 omch2 = (OmegaM - OmegaB) * h**2 LambdaCDM = Class() LambdaCDM.set({ 'omega_b': ombh2, 'omega_cdm': omch2, 'h': h, 'A_s': A_s, 'n_s': n_s }) LambdaCDM.set({ 'output': 'mPk,sCl', 'P_k_max_1/Mpc': 10.0, 'l_switch_limber': 100, 'selection': 'dirac', 'selection_mean': zs, 'l_max_lss': lmax, 'non linear': 'halofit' }) # run class LambdaCDM.compute() si8 = LambdaCDM.sigma8() cls = LambdaCDM.density_cl(lmax) ell = cls['ell'][2:] clphiphi = cls['ll'][0][2:] clkk = 1.0 / 4 * (ell + 2.0) * (ell + 1.0) * (ell) * (ell - 1.0) * clphiphi return si8, ell, clkk
class TestClass(unittest.TestCase): """ Testing Class and its wrapper classy on different cosmologies To run it, do ~] nosetest test_class.py It will run many times Class, on different cosmological scenarios, and everytime testing for different output possibilities (none asked, only mPk, etc..) """ @classmethod def setUpClass(cls): cls.faulty_figs_path = os.path.join( os.path.sep.join( os.path.realpath(__file__).split(os.path.sep)[:-1]), 'faulty_figs') if os.path.isdir(cls.faulty_figs_path): shutil.rmtree(cls.faulty_figs_path) os.mkdir(cls.faulty_figs_path) @classmethod def tearDownClass(cls): pass def setUp(self): """ set up data used in the tests. setUp is called before each test function execution. """ self.cosmo = Class() self.cosmo_newt = Class() if CLASS_VERBOSE: self.verbose = { 'input_verbose': 1, 'background_verbose': 1, 'thermodynamics_verbose': 1, 'perturbations_verbose': 1, 'transfer_verbose': 1, 'primordial_verbose': 1, 'harmonic_verbose': 1, 'fourier_verbose': 1, 'lensing_verbose': 1, 'distortions_verbose': 1, 'output_verbose': 1, } else: self.verbose = {} self.scenario = {} def tearDown(self): self.cosmo.struct_cleanup() self.cosmo.empty() self.cosmo = 0 self.cosmo_newt.struct_cleanup() self.cosmo_newt.empty() self.cosmo_newt = 0 del self.scenario def poormansname(self, somedict): string = "_".join( [k + '=' + str(v) for k, v in list(somedict.items())]) string = string.replace('/', '%') string = string.replace(',', '') string = string.replace(' ', '') return string @parameterized.expand(TUPLE_ARRAY, doc_func=custom_name_func, custom_name_func=custom_name_func) @attr('dump_ini_files') def test_Valgrind(self, inputdict): """Dump files""" self.scenario.update(inputdict) self.name = self._testMethodName if self.has_incompatible_input(): return path = os.path.join(self.faulty_figs_path, self.name) self.store_ini_file(path) self.scenario.update({'gauge': 'Newtonian'}) self.store_ini_file(path + 'N') @parameterized.expand(TUPLE_ARRAY, doc_func=custom_name_func, custom_name_func=custom_name_func) @attr('test_scenario') def test_scenario(self, inputdict): """Test scenario""" self.scenario.update(inputdict) self.name = self._testMethodName self.cosmo.set( dict(itertools.chain(self.verbose.items(), self.scenario.items()))) cl_dict = { 'tCl': ['tt'], 'lCl': ['pp'], 'pCl': ['ee', 'bb'], 'nCl': ['dd'], 'sCl': ['ll'], } # 'lensing' is always set to yes. Therefore, trying to compute 'tCl' or # 'pCl' will fail except if we also ask for 'lCl'. if self.has_incompatible_input(): self.assertRaises(CosmoSevereError, self.cosmo.compute) return else: self.cosmo.compute() self.assertTrue(self.cosmo.state, "Class failed to go through all __init__ methods") # Depending if 'output' in self.scenario.keys(): # Positive tests of raw cls output = self.scenario['output'] for elem in output.split(): if elem in cl_dict.keys(): for cl_type in cl_dict[elem]: is_density_cl = (elem == 'nCl' or elem == 'sCl') if is_density_cl: cl = self.cosmo.density_cl(100) else: cl = self.cosmo.raw_cl(100) self.assertIsNotNone(cl, "raw_cl returned nothing") cl_length = np.shape( cl[cl_type][0])[0] if is_density_cl else np.shape( cl[cl_type])[0] self.assertEqual(cl_length, 101, "raw_cl returned wrong size") if elem == 'mPk': pk = self.cosmo.pk(0.1, 0) self.assertIsNotNone(pk, "pk returned nothing") # Negative tests of output functions if not any( [elem in list(cl_dict.keys()) for elem in output.split()]): # testing absence of any Cl self.assertRaises(CosmoSevereError, self.cosmo.raw_cl, 100) if 'mPk' not in output.split(): # testing absence of mPk self.assertRaises(CosmoSevereError, self.cosmo.pk, 0.1, 0) if COMPARE_OUTPUT_REF or COMPARE_OUTPUT_GAUGE: # Now compute same scenario in Newtonian gauge self.cosmo_newt.set( dict(list(self.verbose.items()) + list(self.scenario.items()))) self.cosmo_newt.set({'gauge': 'newtonian'}) self.cosmo_newt.compute() if COMPARE_OUTPUT_GAUGE: # Compare synchronous and Newtonian gauge self.assertTrue( self.cosmo_newt.state, "Class failed to go through all __init__ methods in Newtonian gauge" ) self.compare_output(self.cosmo, "Synchronous", self.cosmo_newt, 'Newtonian', COMPARE_CL_RELATIVE_ERROR_GAUGE, COMPARE_PK_RELATIVE_ERROR_GAUGE) if COMPARE_OUTPUT_REF: # Compute reference models in both gauges and compare cosmo_ref = classyref.Class() cosmo_ref.set(self.cosmo.pars) cosmo_ref.compute() status = self.compare_output(cosmo_ref, "Reference", self.cosmo, 'Synchronous', COMPARE_CL_RELATIVE_ERROR, COMPARE_PK_RELATIVE_ERROR) assert status, 'Reference comparison failed in Synchronous gauge!' cosmo_ref = classyref.Class() cosmo_ref.set(self.cosmo_newt.pars) cosmo_ref.compute() self.compare_output(cosmo_ref, "Reference", self.cosmo_newt, 'Newtonian', COMPARE_CL_RELATIVE_ERROR, COMPARE_PK_RELATIVE_ERROR) assert status, 'Reference comparison failed in Newtonian gauge!' def has_incompatible_input(self): should_fail = False # If we have tensor modes, we must have one tensor observable, # either tCl or pCl. if has_tensor(self.scenario): if 'output' not in list(self.scenario.keys()): should_fail = True else: output = self.scenario['output'].split() if 'tCl' not in output and 'pCl' not in output: should_fail = True # If we have specified lensing, we must have lCl in output, # otherwise lensing will not be read (which is an error). if 'lensing' in list(self.scenario.keys()): if 'output' not in list(self.scenario.keys()): should_fail = True else: output = self.scenario['output'].split() if 'lCl' not in output: should_fail = True elif 'tCl' not in output and 'pCl' not in output: should_fail = True # If we have specified a tensor method, we must have tensors. if 'tensor method' in list(self.scenario.keys()): if not has_tensor(self.scenario): should_fail = True # If we have specified non linear, we must have some form of # perturbations output. if 'non linear' in list(self.scenario.keys()): if 'output' not in list(self.scenario.keys()): should_fail = True # If we ask for Cl's of lensing potential, number counts or cosmic shear, we must have scalar modes. # The same applies to density and velocity transfer functions and the matter power spectrum: if 'output' in self.scenario and 'modes' in self.scenario and self.scenario[ 'modes'].find('s') == -1: requested_output_types = set(self.scenario['output'].split()) for scalar_output_type in [ 'lCl', 'nCl', 'dCl', 'sCl', 'mPk', 'dTk', 'mTk', 'vTk' ]: if scalar_output_type in requested_output_types: should_fail = True break # If we specify initial conditions (for scalar modes), we must have # perturbations and scalar modes. if 'ic' in list(self.scenario.keys()): if 'modes' in list(self.scenario.keys() ) and self.scenario['modes'].find('s') == -1: should_fail = True if 'output' not in list(self.scenario.keys()): should_fail = True # If we use inflation module, we must have scalar modes, # tensor modes, no vector modes and we should only have adiabatic IC: if 'P_k_ini type' in list(self.scenario.keys( )) and self.scenario['P_k_ini type'].find('inflation') != -1: if 'modes' not in list(self.scenario.keys()): should_fail = True else: if self.scenario['modes'].find('s') == -1: should_fail = True if self.scenario['modes'].find('v') != -1: should_fail = True if self.scenario['modes'].find('t') == -1: should_fail = True if 'ic' in list(self.scenario.keys() ) and self.scenario['ic'].find('i') != -1: should_fail = True return should_fail def compare_output(self, reference, reference_name, candidate, candidate_name, rtol_cl, rtol_pk): status_pass = True for elem in ['raw_cl', 'lensed_cl']: # Try to get the elem, but if they were not computed, a # CosmoComputeError should be raised. In this case, ignore the # whole block. try: to_test = getattr(candidate, elem)() except CosmoSevereError: continue ref = getattr(reference, elem)() for key, value in list(ref.items()): if key != 'ell': # For all self spectra, try to compare allclose if key[0] == key[1]: # If it is a 'dd' or 'll', it is a dictionary. if isinstance(value, dict): for subkey in list(value.keys()): try: np.testing.assert_allclose( value[subkey], to_test[key][subkey], rtol=rtol_cl, atol=COMPARE_CL_ABSOLUTE_ERROR) except AssertionError: self.cl_faulty_plot( elem + "_" + key, value[subkey][2:], reference_name, to_test[key][subkey][2:], candidate_name, rtol_cl) except TypeError: self.cl_faulty_plot( elem + "_" + key, value[subkey][2:], reference_name, to_test[key][subkey][2:], candidate_name, rtol_cl) else: try: np.testing.assert_allclose( value, to_test[key], rtol=rtol_cl, atol=COMPARE_CL_ABSOLUTE_ERROR) except (AssertionError, TypeError) as e: self.cl_faulty_plot(elem + "_" + key, value[2:], reference_name, to_test[key][2:], candidate_name, rtol_cl) status_pass = False # For cross-spectra, as there can be zero-crossing, we # instead compare the difference. else: # First, we multiply each array by the biggest value norm = max( np.abs(value).max(), np.abs(to_test[key]).max()) value *= norm to_test[key] *= norm try: np.testing.assert_array_almost_equal(value, to_test[key], decimal=3) except AssertionError: self.cl_faulty_plot(elem + "_" + key, value[2:], reference_name, to_test[key][2:], candidate_name, rtol_cl) status_pass = False if 'output' in list(self.scenario.keys()): if self.scenario['output'].find('mPk') != -1: # testing equality of Pk k = np.logspace(-2, log10(self.scenario['P_k_max_1/Mpc']), 50) reference_pk = np.array([reference.pk(elem, 0) for elem in k]) candidate_pk = np.array([candidate.pk(elem, 0) for elem in k]) try: np.testing.assert_allclose(reference_pk, candidate_pk, rtol=rtol_pk, atol=COMPARE_PK_ABSOLUTE_ERROR) except AssertionError: self.pk_faulty_plot(k, reference_pk, reference_name, candidate_pk, candidate_name, rtol_pk) status_pass = False return status_pass def store_ini_file(self, path): parameters = dict( list(self.verbose.items()) + list(self.scenario.items())) with open(path + '.ini', 'w') as param_file: param_file.write('# ' + str(parameters) + '\n') if len(parameters) == 0: # CLASS complains if the .ini file does not do anything. param_file.write('write warnings = yes\n') for key, value in list(parameters.items()): param_file.write(key + " = " + str(value) + '\n') def cl_faulty_plot(self, cl_type, reference, reference_name, candidate, candidate_name, rtol): path = os.path.join(self.faulty_figs_path, self.name) fig, axes = plt.subplots(2, 1, sharex=True) ell = np.arange(max(np.shape(candidate))) + 2 factor = ell * (ell + 1) / (2 * np.pi) if cl_type[-2:] != 'pp' else ell**5 axes[0].plot(ell, factor * reference, label=reference_name) axes[0].plot(ell, factor * candidate, label=candidate_name) axes[1].semilogy(ell, 100 * abs(candidate / reference - 1), label=cl_type) axes[1].axhline(y=100 * rtol, color='k', ls='--') axes[-1].set_xlabel(r'$\ell$') if cl_type[-2:] == 'pp': axes[0].set_ylabel(r'$\ell^5 C_\ell^\mathrm{{{_cl_type}}}$'.format( _cl_type=cl_type[-2:].upper())) else: axes[0].set_ylabel( r'$\ell(\ell + 1)/(2\pi)C_\ell^\mathrm{{{_cl_type}}}$'.format( _cl_type=cl_type[-2:].upper())) axes[1].set_ylabel('Relative error [%]') for ax in axes: ax.legend(loc='upper right') fig.tight_layout() fname = '{}_{}_{}_vs_{}.pdf'.format(path, cl_type, reference_name, candidate_name) fig.savefig(fname, bbox_inches='tight') plt.close(fig) # Store parameters (contained in self.scenario) to text file self.store_ini_file(path) def pk_faulty_plot(self, k, reference, reference_name, candidate, candidate_name, rtol): path = os.path.join(self.faulty_figs_path, self.name) fig, axes = plt.subplots(2, 1, sharex=True) axes[0].loglog(k, k**1.5 * reference, label=reference_name) axes[0].loglog(k, k**1.5 * candidate, label=candidate_name) axes[0].legend(loc='upper right') axes[1].loglog(k, 100 * np.abs(candidate / reference - 1)) axes[1].axhline(y=100 * rtol, color='k', ls='--') axes[-1].set_xlabel(r'$k\quad [\mathrm{Mpc}^{-1}]$') axes[0].set_ylabel(r'$k^\frac{3}{2}P(k)$') axes[1].set_ylabel(r'Relative error [%]') fig.tight_layout() fname = path + '_pk_{}_vs_{}.pdf'.format(reference_name, candidate_name) fig.savefig(fname, bbox_inches='tight') plt.close(fig) # Store parameters (contained in self.scenario) to text file self.store_ini_file(path)
fig, axs = plt.subplots(1, 2, figsize=(14, 5)) finer_z_grid = np.linspace(0, 2, num=2000) for i, nz in enumerate(redshiftdistributions): ic = str(i+1) nz_grid = nz.eval(z_grid) finer_nz_grid = nz.eval(finer_z_grid) axs[i].plot(finer_z_grid, finer_nz_grid, label='Gaussian Mixture') axs[i].plot(z_grid, nz_grid, label='Histogram-ized', ls='steps') plt.show() # Now run Class! cosmo = Class() # Scenario 1 cosmo.set(dict(mainparams.items()+scenario1.items())) cosmo.compute() cl1 = cosmo.density_cl(mainparams['l_max_lss']) cosmo.struct_cleanup() cosmo.empty() # Scenario 2 cosmo.set(dict(mainparams.items()+scenario2.items())) cosmo.compute() cl2 = cosmo.density_cl(mainparams['l_max_lss']) cosmo.struct_cleanup() cosmo.empty() # The Cls should be very close if the histogram is binned finely nbins = len(redshiftdistributions) print 'Comparing accuracy of N(z) representation: multigaussian vs histograms' for i in range(nbins*(nbins+1)/2): err = cl1['dd'][i] / cl2['dd'][i] print 'Accuracy of density Cls ', i+1
class Model(): def __init__(self, cosmo=None): """ Initialize the Model class. By default Model uses its own Class instance. cosmo = external Class instance. Default is None """ if cosmo: self.cosmo = cosmo else: self.cosmo = Class() self.computed = {} self.texnames = {} def __set_scale(self, axes, xscale, yscale): """ Set scales for axes in axes array. axes = axes array (e.g. f, ax = plt.subplots(2,2)) xscale = linear array of xscale. yscale = linear array of yscale. Scales are set once axes is flatten. Each plot is counted from left to right an from top to bottom. """ for i, ax in enumerate(axes.flat): ax.set_xscale(xscale[i]) ax.set_yscale(yscale[i]) def __set_label(self, axes, xlabel, ylabel): """ Set labels for axes in axes array. axes = axes array (e.g. f, ax = plt.subplots(2,2)) xlabel = linear array of xlabels. ylabel = linear array of ylabels. Labels are set once axes is flatten. Each plot is counted from left to right an from top to bottom. """ for i, ax in enumerate(axes.flat): ax.set_xlabel(xlabel[i]) ax.set_ylabel(ylabel[i]) def __store_cl(self, cl_dic): """ Store cl's as (l*(l+1)/2pi)*cl, which is much more useful. """ ell = cl_dic['ell'][2:] for cl, list_val in cl_dic.iteritems(): list_val = list_val[2:] if (list_val == ell).all(): cl_dic[cl] = list_val continue list_val = (ell * (ell + 1) / (2 * np.pi)) * list_val cl_dic[cl] = list_val # Remove first two null items (l=0,1) return cl_dic def add_derived(self, varied_name, keys, value): """ Add a derived parameter for varied_name dictionary. varied_name = varied variable's name. keys = list of keys in descending level. value = value to store for new dictionary key. """ dic = self.computed[varied_name] for key in keys: if key not in dic: dic[key] = {} dic = dic[key] dic.update(value) def compute_models(self, params, varied_name, index_variable, values, back=[], thermo=[], prim=[], pert=[], trans=[], pk=[0.0001, 0.1, 100], extra=[], update=True, cosmo_msg=False, texname=""): """ Fill dic with the hi_class output structures for the model with given params, modifying the varied_name value with values. params = parameters to be set in Class. They must be in agreement with what is asked for. varied_name = the name of the variable you are modifying. It will be used as key in dic assigned to its background structures. index_variable = variable's index in parameters_smg array. values = varied variable values you want to compute the cosmology for. back = list of variables to store from background. If 'all', store the whole dictionary. thermo = list of variables to store from thermodynamics. If 'all', store the whole dictionary. prim = list of variables to store from primordial. If 'all', store the whole dictionary. pert = list of variables to store from perturbations. If 'all', store the whole dictionary. trans = list of variables to store from transfer. If 'all', store the whole dictionary. get_transfer accept two optional arguments: z=0 and output_format='class' (avaible options are 'class' or 'camb'). If different values are desired, first item of trans must be {'z': value, 'output_format': value}. pk = list with the minimum and maximum k values to store the present matter power spectrum and the number of points [k_min, k_max, number_points]. Default [10^-4, 10^1, 100]. extra = list of any of the method or objects defined in cosmo, e.g. w0_smg(). It will store {'method': cosmo.w0_smg()} update = if True update old computed[key] dictionary elsewise create a new one. Default: True. cosmo_msg = if True, print cosmo.compute() messages. Default: False. """ key = varied_name if texname: self.set_texnames({varied_name: texname}) elif key not in self.texnames: # texname will not be set at this stage. No check required self.set_texnames({varied_name: varied_name}) if (not update) or (key not in self.computed.keys()): self.computed[key] = od() for val in values: # key = "{}={}".format(varied_name, val) params["parameters_smg"] = inip.vary_params(params["parameters_smg"], [[index_variable, val]]) # It might be after the try to not store empty dictionaries. # Nevertheless, I find more useful having them to keep track of # those failed and, perhaps, to implement a method to obtain them # with Omega_smg_debug. d = self.computed[key][val] = {} self.cosmo.empty() self.cosmo.set(params) try: self.cosmo.compute() except Exception, e: print "Error: skipping {}={}".format(key, val) if cosmo_msg: print e continue d['tunned'] = self.cosmo.get_current_derived_parameters(['tuning_parameter'])['tuning_parameter'] for lst in [[back, 'back', self.cosmo.get_background], [thermo, 'thermo', self.cosmo.get_thermodynamics], [prim, 'prim', self.cosmo.get_thermodynamics]]: if lst[0]: output = lst[2]() if lst[0][0] == 'all': d[lst[1]] = output else: d[lst[1]] = {} for item in back: if type(item) is list: d[lst[1]].update({item[0]: output[item[0]][item[1]]}) else: d[lst[1]].update({item: output[item]}) if pert: # Perturbation is tricky because it can accept two optional # argument for get_perturbations and this method returns a # dictionary {'kind_of_pert': [{variable: list_values}]}, where # each item in the list is for a k (chosen in params). if type(pert[0]) is dict: output = self.cosmo.get_perturbations(pert[0]['z'], pert[0]['output_format']) if pert[1] == 'all': d['pert'] = output else: output = self.cosmo.get_perturbations() if pert[0] == 'all': d['pert'] = output if (type(pert[0]) is not dict) and (pert[0] != 'all'): d['pert'] = {} for subkey, lst in output.iteritems(): d['pert'].update({subkey: []}) for n, kdic in enumerate(lst): # Each item is for a k d['pert'][subkey].append({}) for item in pert: if type(item) is list: d['pert'][subkey][n].update({item[0]: kdic[item[0]][item[1]]}) else: d['pert'][subkey][n].update({item: kdic[item]}) for i in extra: exec('d[i] = self.cosmo.{}'.format(i)) try: d['cl'] = self.__store_cl(self.cosmo.raw_cl()) except CosmoSevereError: pass try: d['lcl'] = self.__store_cl(self.cosmo.lensed_cl()) except CosmoSevereError: pass try: d['dcl'] = self.cosmo.density_cl() except CosmoSevereError: pass if ("output" in self.cosmo.pars) and ('mPk' in self.cosmo.pars['output']): k_array = np.linspace(*pk) pk_array = np.array([self.cosmo.pk(k, 0) for k in k_array]) d['pk'] = {'k': k_array, 'pk': pk_array} self.cosmo.struct_cleanup()