def test_bbn_yhe(packages_path): packages_path = process_packages_path(packages_path) load_module("camb", path=os.path.join(packages_path, "code", "CAMB")) from camb.bbn import BBN_table_interpolator BBN.bbn = BBN_table_interpolator(bbn_table) BBN2.bbn = BBN.bbn info['params']['check'] = {'derived': True} for inf in (info, info2): inf['packages_path'] = packages_path for order in [1, -1]: for explicit_derived in [None, None, {'derived': True}]: print(inf, order, explicit_derived) model = get_model(inf) loglike, derived = model.loglikes({}) vals = set([BBN.bbn.Y_He(camb_params['ombh2'])] + derived) assert len(vals) == 1, \ "wrong Yhe value: %s" % vals inf['params']["YHe"] = explicit_derived inf['params'].pop('YHe') inf['theory'] = { p: v for p, v in reversed(list(inf['theory'].items())) }
def is_installed_clik(path, allow_global=False): log = logging.getLogger("clik") if path is not None and path.lower() == "global": path = None clik_path = None if path and path.lower() != "global": try: clik_path = os.path.join( get_clik_source_folder(path), 'lib/python/site-packages') except FileNotFoundError: log.error("The given folder does not exist: '%s'", clik_path or path) return False if path and not allow_global: log.info("Importing *local* clik from %s ", path) elif not path: log.info("Importing *global* clik.") else: log.info("Importing *auto-installed* clik (but defaulting to *global*).") try: return load_module("clik", path=clik_path) except ImportError: if path is not None and path.lower() != "global": log.error("Couldn't find the clik python interface at '%s'. " "Are you sure it has been installed and compiled there?", path) else: log.error("Could not import global clik installation. " "Specify a Cobaya or clik installation path, " "or install the clik Python interface globally.") except Exception as excpt: log.error("Error when trying to import clik from %s [%s]. Error message: [%s].", path, clik_path, str(excpt)) return False
def test_bbn_likelihood(packages_path): packages_path = process_packages_path(packages_path) load_module("camb", path=os.path.join(packages_path, "code", "CAMB")) from camb.bbn import BBN_table_interpolator BBN_likelihood.bbn = BBN_table_interpolator(bbn_table) info_error['packages_path'] = packages_path model = get_model(info_error) assert np.allclose(model.loglikes({'YHe': 0.246})[0], [0.246, -0.84340], rtol=1e-4), \ "Failed BBN likelihood with %s" % info_error # second case, BBN likelihood has to be calculated before CAMB BBN_with_theory_errors.bbn = BBN_likelihood.bbn info_error2['packages_path'] = packages_path model = get_model(info_error2) assert np.allclose(model.loglikes({'BBN_delta': 1.0})[0], [0.24594834, -0.5], rtol=1e-4)
def get_camb(packages_path): try: return load_module("camb", path=os.path.join( process_packages_path(packages_path), "code", "CAMB")) except ModuleNotFoundError: raise NotInstalledError(None)
def is_installed(cls, **kwargs): log = get_logger(cls.__name__) if not kwargs.get("code", True): return True check = kwargs.get("check", True) func = log.info if check else log.error path: Optional[str] = kwargs["path"] if path is not None and path.lower() == "global": path = None if path and not kwargs.get("allow_global"): if is_main_process(): log.info("Importing *local* PolyChord from '%s'.", path) if not os.path.exists(path): if is_main_process(): func("The given folder does not exist: '%s'", path) return False poly_build_path = cls.get_import_path(path) if not poly_build_path: return False elif not path: if is_main_process(): log.info("Importing *global* PolyChord.") poly_build_path = None else: if is_main_process(): log.info( "Importing *auto-installed* PolyChord (but defaulting to *global*)." ) poly_build_path = cls.get_import_path(path) cls._poly_build_path = poly_build_path try: # TODO: add min_version when polychord module version available return load_module('pypolychord', path=poly_build_path, min_version=None) except ModuleNotFoundError: if path is not None and path.lower() != "global": log.error( "Couldn't find the PolyChord python interface at '%s'. " "Are you sure it has been installed there?", path) elif not check: log.error( "Could not import global PolyChord installation. " "Specify a Cobaya or PolyChord installation path, " "or install the PolyChord Python interface globally with " "'cd /path/to/polychord/ ; python setup.py install'") return False except ImportError as e: log.error( "Couldn't load the PolyChord python interface in %s:\n" "%s", poly_build_path or "global", e) return False except VersionCheckError as e: log.error(str(e)) return False
def initialize(self): """Importing CLASS from the correct path, if given, and if not, globally.""" # If path not given, try using general path to external packages if not self.path and self.packages_path: self.path = self.get_path(self.packages_path) if self.path: self.log.info("Importing *local* classy from " + self.path) classy_build_path = os.path.join(self.path, "python", "build") py_version = "%d.%d" % (sys.version_info.major, sys.version_info.minor) try: post = next(d for d in os.listdir(classy_build_path) if (d.startswith("lib.") and py_version in d)) classy_build_path = os.path.join(classy_build_path, post) if not os.path.exists(classy_build_path): # If path was given as an install path, try to load global one anyway if self.packages_path: self.log.info( "Importing *global* CLASS (because not compiled?)." ) else: raise StopIteration except StopIteration: raise LoggedError( self.log, "Either CLASS is not in the given folder, " "'%s', or you have not compiled it.", self.path) else: classy_build_path = None self.log.info("Importing *global* CLASS.") try: self.classy_module = load_module( 'classy', path=classy_build_path, min_version=self._classy_repo_version) from classy import Class, CosmoSevereError, CosmoComputationError except ImportError: raise LoggedError( self.log, "Couldn't find the CLASS python interface. " "Make sure that you have compiled it, and that you either\n" " (a) specify a path (you didn't) or\n" " (b) install the Python interface globally with\n" " '/path/to/class/python/python setup.py install --user'") except VersionCheckError as e: raise LoggedError(self.log, str(e)) self.classy = Class() # Propagate errors up global CosmoComputationError, CosmoSevereError super().initialize() # Add general CLASS stuff self.extra_args["output"] = self.extra_args.get("output", "") if "sBBN file" in self.extra_args: self.extra_args["sBBN file"] = ( self.extra_args["sBBN file"].format(classy=self.path)) # Derived parameters that may not have been requested, but will be necessary later self.derived_extra = []
def is_installed(cls, **kwargs): if not kwargs.get("code", True): return True log = get_logger(cls.__name__) import platform check = kwargs.get("check", True) func = log.info if check else log.error path = kwargs["path"] if path is not None and path.lower() == "global": path = None if isinstance(path, str) and not kwargs.get("allow_global"): log.info("Importing *local* CAMB from " + path) if not os.path.exists(path): func("The given folder does not exist: '%s'", path) return False if not os.path.exists(os.path.join(path, "setup.py")): func( "Either CAMB is not in the given folder, '%s', or you are using" " a very old version without the Python interface.", path) return False if not os.path.isfile( os.path.realpath( os.path.join( path, "camb", "cambdll.dll" if (platform.system() == "Windows") else "camblib.so"))): log.error( "CAMB installation at '%s' appears not to be compiled.", path) return False elif not path: log.info("Importing *global* CAMB.") path = None else: log.info( "Importing *auto-installed* CAMB (but defaulting to *global*)." ) try: return load_module("camb", path=path, min_version=cls._min_camb_version) except ImportError: if path is not None and path.lower() != "global": func( "Couldn't find the CAMB python interface at '%s'. " "Are you sure it has been installed there?", path) elif not check: log.error("Could not import global CAMB installation. " "Specify a Cobaya or CAMB installation path, " "or install the 'camb' Python package globally.") return False except VersionCheckError as e: log.error(str(e)) return False
def is_installed(cls, **kwargs): if not kwargs.get("code", True): return True log = get_logger(cls.__name__) check = kwargs.get("check", True) func = log.info if check else log.error path = kwargs["path"] if path is not None and path.lower() == "global": path = None if path and not kwargs.get("allow_global"): log.info("Importing *local* CLASS from '%s'.", path) assert path is not None if not os.path.exists(path): func("The given folder does not exist: '%s'", path) return False classy_build_path = cls.get_import_path(path) if not classy_build_path: return False elif not path: log.info("Importing *global* CLASS.") classy_build_path = None else: log.info( "Importing *auto-installed* CLASS (but defaulting to *global*)." ) classy_build_path = cls.get_import_path(path) try: return load_module('classy', path=classy_build_path, min_version=cls._classy_repo_version) except ImportError: if path is not None and path.lower() != "global": func( "Couldn't find the CLASS python interface at '%s'. " "Are you sure it has been installed there?", path) elif not check: log.error( "Could not import global CLASS installation. " "Specify a Cobaya or CLASS installation path, " "or install the CLASS Python interface globally with " "'cd /path/to/class/python/ ; python setup.py install'") return False except VersionCheckError as e: log.error(str(e)) return False
def initialize(self): """Importing CAMB from the correct path, if given.""" if not self.path and self.packages_path: self.path = self.get_path(self.packages_path) camb_path = None if self.path and not os.path.exists(self.path): # Fail if this was a directly specified path, # or ignore and try to global-import if it came from a packages_path if self.packages_path: self.log.info("*local* CAMB not found at " + self.path) self.log.info("Importing *global* CAMB.") else: raise LoggedError(self.log, "*local* CAMB not found at " + self.path) elif self.path: self.log.info("Importing *local* CAMB from " + self.path) if not os.path.exists(self.path): raise LoggedError( self.log, "The given folder does not exist: '%s'", self.path) camb_path = self.path if not os.path.exists(os.path.join(self.path, "setup.py")): raise LoggedError( self.log, "Either CAMB is not in the given folder, '%s', or you are using a " "very old version without the Python interface.", self.path) else: self.log.info("Importing *global* CAMB.") try: self.camb = load_module("camb", path=camb_path, min_version=self._min_camb_version) except ImportError: raise LoggedError( self.log, "Couldn't find the CAMB python interface.\n" "Make sure that you have compiled it, and that you either\n" " (a) specify a path (you didn't) or\n" " (b) install the Python interface globally with\n" " 'python -m pip install -e /path/to/camb [--user]'") except VersionCheckError as e: raise LoggedError(self.log, str(e)) super().initialize() self.extra_attrs = {"Want_CMB": False, "Want_cl_2D_array": False, 'WantCls': False} # Derived parameters that may not have been requested, but will be necessary later self.derived_extra = [] # Some default settings self.needs_perts = False self.limber = False self.non_linear_sources = False self.non_linear_pk = False self._base_params = None self._needs_lensing_cross = False self._sigmaR_z_indices = {} if self.external_primordial_pk: self.extra_args['initial_power_model'] \ = self.camb.initialpower.SplinedInitialPower self.initial_power_args, self.power_params = {}, [] else: power_spectrum = self.camb.CAMBparams.make_class_named( self.extra_args.get('initial_power_model', self.camb.initialpower.InitialPowerLaw), self.camb.initialpower.InitialPower) self.initial_power_args, self.power_params = \ self._extract_params(power_spectrum.set_params) nonlin = self.camb.CAMBparams.make_class_named( self.extra_args.get('non_linear_model', self.camb.nonlinear.Halofit), self.camb.nonlinear.NonLinearModel) self.nonlin_args, self.nonlin_params = self._extract_params(nonlin.set_params) self.requires = str_to_list(getattr(self, _requires, [])) self._transfer_requires = [p for p in self.requires if p not in self.get_can_support_params()] self.requires = [p for p in self.requires if p not in self._transfer_requires]
def initialize(self): """Imports the PolyChord sampler and prepares its arguments.""" # Allow global import if no direct path specification allow_global = not self.path if not self.path and self.packages_path: self.path = self.get_path(self.packages_path) self.pc: Any = self.is_installed(path=self.path, allow_global=allow_global, check=False) if not self.pc: raise NotInstalledError( self.log, "Could not find PolyChord. Check error message above. " "To install it, run 'cobaya-install polychord --%s " "[packages_path]'", packages_path_arg) # Prepare arguments and settings self.n_sampled = len(self.model.parameterization.sampled_params()) self.n_derived = len(self.model.parameterization.derived_params()) self.n_priors = len(self.model.prior) self.n_likes = len(self.model.likelihood) self.nDims = self.model.prior.d() self.nDerived = (self.n_derived + self.n_priors + self.n_likes) if self.logzero is None: self.logzero = np.nan_to_num(-np.inf) if self.max_ndead == np.inf: self.max_ndead = -1 self._quants_d_units = ["nlive", "max_ndead"] for p in self._quants_d_units: if getattr(self, p) is not None: setattr( self, p, NumberWithUnits(getattr(self, p), "d", scale=self.nDims, dtype=int).value) self._quants_nlive_units = ["nprior"] for p in self._quants_nlive_units: if getattr(self, p) is not None: setattr( self, p, NumberWithUnits(getattr(self, p), "nlive", scale=self.nlive, dtype=int).value) # Fill the automatic ones if getattr(self, "feedback", None) is None: values = { logging.CRITICAL: 0, logging.ERROR: 0, logging.WARNING: 0, logging.INFO: 1, logging.DEBUG: 2 } self.feedback = values[self.log.getEffectiveLevel()] # Prepare output folders and prefixes if self.output: self.file_root = self.output.prefix self.read_resume = self.output.is_resuming() else: output_prefix = share_mpi( hex(int(self._rng.random() * 16**6))[2:] if is_main_process() else None) self.file_root = output_prefix # dummy output -- no resume! self.read_resume = False self.base_dir = self.get_base_dir(self.output) self.raw_clusters_dir = os.path.join(self.base_dir, self._clusters_dir) self.output.create_folder(self.base_dir) if self.do_clustering: self.clusters_folder = self.get_clusters_dir(self.output) self.output.create_folder(self.clusters_folder) self.mpi_info("Storing raw PolyChord output in '%s'.", self.base_dir) # Exploiting the speed hierarchy if self.blocking: blocks, oversampling_factors = self.model.check_blocking( self.blocking) else: if self.measure_speeds: self.model.measure_and_set_speeds(n=self.measure_speeds, random_state=self._rng) blocks, oversampling_factors = self.model.get_param_blocking_for_sampler( oversample_power=self.oversample_power) self.mpi_info("Parameter blocks and their oversampling factors:") max_width = len(str(max(oversampling_factors))) for f, b in zip(oversampling_factors, blocks): self.mpi_info("* %" + "%d" % max_width + "d : %r", f, b) # Save blocking in updated info, in case we want to resume self._updated_info["blocking"] = list(zip(oversampling_factors, blocks)) blocks_flat = list(chain(*blocks)) self.ordering = [ blocks_flat.index(p) for p in self.model.parameterization.sampled_params() ] self.grade_dims = [len(block) for block in blocks] # Steps per block # NB: num_repeats is ignored by PolyChord when int "grade_frac" given, # so needs to be applied by hand. # In num_repeats, `d` is interpreted as dimension of each block self.grade_frac = [ int(o * read_dnumber(self.num_repeats, dim_block)) for o, dim_block in zip(oversampling_factors, self.grade_dims) ] # Assign settings pc_args = [ "nlive", "num_repeats", "nprior", "do_clustering", "precision_criterion", "max_ndead", "boost_posterior", "feedback", "logzero", "posteriors", "equals", "compression_factor", "cluster_posteriors", "write_resume", "read_resume", "write_stats", "write_live", "write_dead", "base_dir", "grade_frac", "grade_dims", "feedback", "read_resume", "base_dir", "file_root", "grade_frac", "grade_dims" ] # As stated above, num_repeats is ignored, so let's not pass it pc_args.pop(pc_args.index("num_repeats")) settings: Any = load_module('pypolychord.settings', path=self._poly_build_path, min_version=None) self.pc_settings = settings.PolyChordSettings( self.nDims, self.nDerived, seed=(self.seed if self.seed is not None else -1), **{ p: getattr(self, p) for p in pc_args if getattr(self, p) is not None }) # prior conversion from the hypercube bounds = self.model.prior.bounds( confidence_for_unbounded=self.confidence_for_unbounded) # Check if priors are bounded (nan's to inf) inf = np.where(np.isinf(bounds)) if len(inf[0]): params_names = list(self.model.parameterization.sampled_params()) params = [params_names[i] for i in sorted(set(inf[0]))] raise LoggedError( self.log, "PolyChord needs bounded priors, but the parameter(s) '" "', '".join(params) + "' is(are) unbounded.") locs = bounds[:, 0] scales = bounds[:, 1] - bounds[:, 0] # This function re-scales the parameters AND puts them in the right order self.pc_prior = lambda x: (locs + np.array(x)[self.ordering] * scales ).tolist() # We will need the volume of the prior domain, since PolyChord divides by it self.logvolume = np.log(np.prod(scales)) # Prepare callback function if self.callback_function is not None: self.callback_function_callable = (get_external_function( self.callback_function)) self.last_point_callback = 0 # Prepare runtime live and dead points collections self.live = SampleCollection(self.model, None, name="live") self.dead = SampleCollection(self.model, self.output, name="dead") # Done! if is_main_process(): self.log.debug("Calling PolyChord with arguments:") for p, v in inspect.getmembers(self.pc_settings, lambda a: not (callable(a))): if not p.startswith("_"): self.log.debug(" %s: %s", p, v) self.mpi_info("Initialized!")
def get_camb(packages_path): return load_module("camb", path=os.path.join(process_packages_path(packages_path), "code", "CAMB"))