コード例 #1
0
 def __getattr__(self, method):
     try:
         object.__getattr__(self, method)
     except AttributeError:
         if method.startswith("get"):
             # Deprecated method names
             # -- this will be deprecated in favour of the error below
             new_names = {"get_cl": "get_Cl"}
             if method in new_names:
                 msg = create_banner(
                     "Method '%s' has been re-capitalized to '%s'.\n"
                     "Overriding for now, but please change it: "
                     "this will produce an error in the future." %
                     (method, new_names[method]))
                 for line in msg.split("\n"):
                     self.log.warning(line)
                 return getattr(self, new_names[method])
             # End of deprecation block ------------------------------
             raise LoggedError(
                 self.log,
                 "Getter method for cosmology product %r is not known. "
                 "Maybe you meant any of %r?", method,
                 fuzzy_match(method, dir(self), n=3))
コード例 #2
0
ファイル: input.py プロジェクト: rancesol/cobaya
def update_info(info):
    """
    Creates an updated info starting from the defaults for each module and updating it
    with the input info.
    """
    # Don't modify the original input!
    input_info = deepcopy_where_possible(info)
    # Creates an equivalent info using only the defaults
    updated_info = odict()
    default_params_info = odict()
    default_prior_info = odict()
    modules = get_used_modules(input_info)
    for block in modules:
        updated_info[block] = odict()
        for module in modules[block]:
            # Preprocess "no options" and "external function" in input
            try:
                input_info[block][module] = input_info[block][module] or {}
            except TypeError:
                raise LoggedError(
                    log,
                    "Your input info is not well formatted at the '%s' block. "
                    "It must be a dictionary {'%s':{options}, ...}. ", block,
                    block)
            if not hasattr(input_info[block][module], "get"):
                input_info[block][module] = {
                    _external: input_info[block][module]
                }
            # Get default class options
            updated_info[block][module] = deepcopy(
                getattr(
                    import_module(_package + "." + block, package=_package),
                    "class_options", {}))
            default_module_info = get_default_info(module, block)
            # TODO: check - get_default_info was ignoring this extra arg: input_info[block][module])
            updated_info[block][module].update(
                default_module_info[block][module] or {})
            # Update default options with input info
            # Consistency is checked only up to first level! (i.e. subkeys may not match)
            ignore = set(
                [_external, _p_renames, _input_params, _output_params])
            options_not_recognized = (set(
                input_info[block][module]).difference(ignore).difference(
                    set(updated_info[block][module])))
            if options_not_recognized:
                alternatives = odict()
                available = (set([_external, _p_renames
                                  ]).union(updated_info[block][module]))
                while options_not_recognized:
                    option = options_not_recognized.pop()
                    alternatives[option] = fuzzy_match(option, available, n=3)
                did_you_mean = ", ".join([
                    ("'%s' (did you mean %s?)" %
                     (o, "|".join(["'%s'" % _
                                   for _ in a])) if a else "'%s'" % o)
                    for o, a in alternatives.items()
                ])
                if default_module_info[block][module]:
                    # Internal module
                    raise LoggedError(
                        log, "'%s' does not recognize some options: %s. "
                        "To see the allowed options, check out the documentation of"
                        " this module.", module, did_you_mean)
                else:
                    # External module
                    raise LoggedError(
                        log,
                        "External %s '%s' does not recognize some options: %s. "
                        "Check the documentation for 'external %s'.", block,
                        module, did_you_mean, block)
            updated_info[block][module].update(input_info[block][module])
            # Store default parameters and priors of class, and save to combine later
            if block == _likelihood:
                params_info = default_module_info.get(_params, {})
                updated_info[block][module].update(
                    {_params: list(params_info or [])})
                default_params_info[module] = params_info
                default_prior_info[module] = default_module_info.get(
                    _prior, {})
    # Add priors info, after the necessary checks
    if _prior in input_info or any(default_prior_info.values()):
        updated_info[_prior] = input_info.get(_prior, odict())
    for prior_info in default_prior_info.values():
        for name, prior in prior_info.items():
            if updated_info[_prior].get(name, prior) != prior:
                raise LoggedError(
                    log,
                    "Two different priors cannot have the same name: '%s'.",
                    name)
            updated_info[_prior][name] = prior
    # Add parameters info, after the necessary updates and checks
    defaults_merged = merge_default_params_info(default_params_info)
    updated_info[_params] = merge_params_info(defaults_merged,
                                              input_info.get(_params, {}))
    # Add aliases for theory params (after merging!)
    if _theory in updated_info:
        renames = list(updated_info[_theory].values())[0].get(_p_renames)
        str_to_list = lambda x: ([x] if isinstance(x, string_types) else x)
        renames_flat = [
            set([k] + str_to_list(v)) for k, v in (renames or {}).items()
        ]
        for p in updated_info.get(_params, {}):
            # Probably could be made faster by inverting the renames dicts *just once*
            renames_pairs = [a for a in renames_flat if p in a]
            if renames_pairs:
                this_renames = reduce(lambda x, y: x.union(y),
                                      [a for a in renames_flat if p in a])
                updated_info[_params][p][_p_renames] = list(
                    set(this_renames).union(
                        set(
                            str_to_list(updated_info[_params][p].get(
                                _p_renames, [])))).difference(set([p])))
    # Rest of the options
    for k, v in input_info.items():
        if k not in updated_info:
            updated_info[k] = v
    return updated_info
コード例 #3
0
def update_info(info):
    """
    Creates an updated info starting from the defaults for each component and updating it
    with the input info.
    """
    component_base_classes = get_base_classes()
    # Don't modify the original input, and convert all Mapping to consistent dict
    input_info = deepcopy_where_possible(info)
    # Creates an equivalent info using only the defaults
    updated_info = {}
    default_params_info = {}
    default_prior_info = {}
    components = get_used_components(input_info)
    from cobaya.component import CobayaComponent
    for block in components:
        updated = {}
        updated_info[block] = updated
        input_block = input_info[block]
        for component in components[block]:
            # Preprocess "no options" and "external function" in input
            try:
                input_block[component] = input_block[component] or {}
            except TypeError:
                raise LoggedError(
                    log,
                    "Your input info is not well formatted at the '%s' block. "
                    "It must be a dictionary {'%s_i':{options}, ...}. ", block,
                    block)
            if isinstance(component, CobayaComponent) or \
                    isinstance(input_block[component], CobayaComponent):
                raise LoggedError(
                    log, "Input for %s:%s should specify a class not "
                    "an instance", block, component)
                # TODO: allow instance passing?
                #       could allow this, but would have to sort out deepcopy
                # if input_block[component]:
                #   raise LoggedError(log, "Instances should be passed a dictionary "
                #                           "entry of the form 'instance: None'")
                # change_key(input_block, component, component.get_name(),
                #           {_external: component})
                # updated[component.get_name()] = input_block[component.get_name()].copy()
                # continue
            if inspect.isclass(input_block[component]) or \
                    not isinstance(input_block[component], dict):
                input_block[component] = {_external: input_block[component]}
            ext = input_block[component].get(_external)
            if ext:
                if inspect.isclass(ext):
                    default_class_info = get_default_info(
                        ext, block, input_options=input_block[component])
                else:
                    default_class_info = deepcopy_where_possible(
                        component_base_classes[block].get_defaults())
            else:
                component_path = input_block[component].get(
                    _component_path, None)
                default_class_info = get_default_info(
                    component,
                    block,
                    class_name=input_block[component].get(_class_name),
                    component_path=component_path,
                    input_options=input_block[component])
            updated[component] = default_class_info or {}
            # Update default options with input info
            # Consistency is checked only up to first level! (i.e. subkeys may not match)
            # Reserved attributes not necessarily already in default info:
            reserved = {
                _external, _class_name, _provides, _requires, partag.renames,
                _input_params, _output_params, _component_path, _aliases
            }
            options_not_recognized = (set(
                input_block[component]).difference(reserved).difference(
                    set(updated[component])))
            if options_not_recognized:
                alternatives = {}
                available = ({
                    _external, _class_name, _requires, partag.renames
                }.union(updated_info[block][component]))
                while options_not_recognized:
                    option = options_not_recognized.pop()
                    alternatives[option] = fuzzy_match(option, available, n=3)
                did_you_mean = ", ".join([
                    ("'%s' (did you mean %s?)" %
                     (o, "|".join(["'%s'" % _
                                   for _ in a])) if a else "'%s'" % o)
                    for o, a in alternatives.items()
                ])
                raise LoggedError(
                    log, "%s '%s' does not recognize some options: %s. "
                    "Check the documentation for '%s'.", block, component,
                    did_you_mean, block)
            updated[component].update(input_block[component])
            # save params and priors of class to combine later
            default_params_info[component] = default_class_info.get(
                _params, {})
            default_prior_info[component] = default_class_info.get(_prior, {})
    # Add priors info, after the necessary checks
    if _prior in input_info or any(default_prior_info.values()):
        updated_info[_prior] = input_info.get(_prior, {})
    for prior_info in default_prior_info.values():
        for name, prior in prior_info.items():
            if updated_info[_prior].get(name, prior) != prior:
                raise LoggedError(
                    log,
                    "Two different priors cannot have the same name: '%s'.",
                    name)
            updated_info[_prior][name] = prior
    # Add parameters info, after the necessary updates and checks
    defaults_merged = merge_default_params_info(default_params_info)
    updated_info[_params] = merge_params_info(
        [defaults_merged, input_info.get(_params, {})], default_derived=False)
    # Add aggregated chi2 params
    if kinds.likelihood in info:
        all_types = set(
            chain(*[
                str_to_list(like_info.get("type", []) or [])
                for like_info in updated_info[kinds.likelihood].values()
            ]))
        for t in all_types:
            updated_info[_params][_get_chi2_name(t)] = {
                partag.latex: _get_chi2_label(t),
                partag.derived: True
            }
    # Add automatically-defined parameters
    if _auto_params in updated_info:
        make_auto_params(updated_info.pop(_auto_params), updated_info[_params])
    # Add aliases for theory params (after merging!)
    for kind in [
            k for k in [kinds.theory, kinds.likelihood] if k in updated_info
    ]:
        for item in updated_info[kind].values():
            renames = item.get(partag.renames)
            if renames:
                if not isinstance(renames, Mapping):
                    raise LoggedError(
                        log,
                        "'renames' should be a dictionary of name mappings "
                        "(or you meant to use 'aliases')")
                renames_flat = [
                    set([k] + str_to_list(v)) for k, v in renames.items()
                ]
                for p in updated_info[_params]:
                    # Probably could be made faster by inverting the renames dicts *once*
                    renames_pairs = [a for a in renames_flat if p in a]
                    if renames_pairs:
                        this_renames = reduce(
                            lambda x, y: x.union(y),
                            [a for a in renames_flat if p in a])
                        updated_info[_params][p][partag.renames] = \
                            list(set(this_renames).union(set(str_to_list(
                                updated_info[_params][p].get(partag.renames, []))))
                                 .difference({p}))
    # Rest of the options
    for k, v in input_info.items():
        if k not in updated_info:
            updated_info[k] = v
    return updated_info
コード例 #4
0
def update_info(info: _Dict, add_aggr_chi2=True) -> _Dict:
    """
    Creates an updated info starting from the defaults for each component and updating it
    with the input info.
    """
    component_base_classes = get_base_classes()
    # Don't modify the original input, and convert all Mapping to consistent dict
    input_info = deepcopy_where_possible(info)
    # Creates an equivalent info using only the defaults
    updated_info: _Dict = {}
    default_params_info = {}
    default_prior_info = {}
    used_kind_members = get_used_components(input_info)
    from cobaya.component import CobayaComponent
    for block in used_kind_members:
        updated: InfoDict = {}
        updated_info[block] = updated
        input_block = input_info[block]
        name: str
        for name in used_kind_members[block]:
            # Preprocess "no options" and "external function" in input
            try:
                input_block[name] = input_block[name] or {}
            except TypeError:
                raise LoggedError(
                    log,
                    "Your input info is not well formatted at the '%s' block. "
                    "It must be a dictionary {'%s_i':{options}, ...}. ", block,
                    block)
            if isinstance(name, CobayaComponent) or isinstance(name, type):
                raise LoggedError(
                    log, "Instances and classes should be passed a "
                    "dictionary entry of the form 'name: instance'")
            if isinstance(input_block[name], CobayaComponent):
                log.warning("Support for input instances is experimental")
            if isinstance(input_block[name], type) or \
                    not isinstance(input_block[name], dict):
                input_block[name] = {"external": input_block[name]}
            ext = input_block[name].get("external")
            annotations = {}
            if ext:
                if isinstance(ext, type):
                    default_class_info, annotations = \
                        get_default_info(ext, block, input_options=input_block[name],
                                         return_undefined_annotations=True)
                else:
                    default_class_info = deepcopy_where_possible(
                        component_base_classes[block].get_defaults())
            else:
                component_path = input_block[name].get("python_path")
                default_class_info, annotations = get_default_info(
                    name,
                    block,
                    class_name=input_block[name].get("class"),
                    component_path=component_path,
                    input_options=input_block[name],
                    return_undefined_annotations=True)
            updated[name] = default_class_info or {}
            # Update default options with input info
            # Consistency is checked only up to first level! (i.e. subkeys may not match)
            # Reserved attributes not necessarily already in default info:
            reserved = {
                "external", "class", "provides", "requires", "renames",
                "input_params", "output_params", "python_path", "aliases"
            }
            options_not_recognized = set(input_block[name]).difference(
                chain(reserved, updated[name], annotations))
            if options_not_recognized:
                alternatives = {}
                available = {"external", "class", "requires",
                             "renames"}.union(updated_info[block][name])
                while options_not_recognized:
                    option = options_not_recognized.pop()
                    alternatives[option] = fuzzy_match(option, available, n=3)
                did_you_mean = ", ".join([
                    ("'%s' (did you mean %s?)" %
                     (o, "|".join(["'%s'" % _
                                   for _ in a])) if a else "'%s'" % o)
                    for o, a in alternatives.items()
                ])
                raise LoggedError(
                    log, "%s '%s' does not recognize some options: %s. "
                    "Check the documentation for '%s'.", block, name,
                    did_you_mean, block)
            updated[name].update(input_block[name])
            # save params and priors of class to combine later
            default_params_info[name] = default_class_info.get("params", {})
            default_prior_info[name] = default_class_info.get("prior", {})
    # Add priors info, after the necessary checks
    if "prior" in input_info or any(default_prior_info.values()):
        updated_info["prior"] = input_info.get("prior", {})
    for prior_info in default_prior_info.values():
        for name, prior in prior_info.items():
            if updated_info["prior"].get(name, prior) != prior:
                raise LoggedError(
                    log,
                    "Two different priors cannot have the same name: '%s'.",
                    name)
            updated_info["prior"][name] = prior
    # Add parameters info, after the necessary updates and checks
    defaults_merged = merge_default_params_info(default_params_info)
    param_info: ExpandedParamsDict = merge_params_info(
        [defaults_merged, input_info.get("params", {})], default_derived=False)
    updated_info["params"] = param_info  # type: ignore
    # Add aggregated chi2 params
    if info.get("likelihood") and add_aggr_chi2:
        all_types = set(
            chain(*[
                str_to_list(like_info.get("type", []) or [])
                for like_info in updated_info["likelihood"].values()
                if like_info is not None
            ]))
        add_aggregated_chi2_params(param_info, all_types)
    # Add automatically-defined parameters
    if "auto_params" in updated_info:
        make_auto_params(updated_info.pop("auto_params"), param_info)
    # Add aliases for theory params (after merging!)
    for name in ("theory", "likelihood"):
        if isinstance(updated_info.get(name), dict):
            for item in updated_info[name].values():
                renames = item.get("renames")
                if renames:
                    if not isinstance(renames, Mapping):
                        raise LoggedError(
                            log, "'renames' should be a dictionary of "
                            "name mappings "
                            "(or you meant to use 'aliases')")
                    renames_flat = [
                        set([k] + str_to_list(v)) for k, v in renames.items()
                    ]
                    for p in param_info:
                        # Probably could be made faster by inverting
                        # the renames dicts *once*
                        renames_pairs = [a for a in renames_flat if p in a]
                        if renames_pairs:
                            this_renames = reduce(
                                lambda x, y: x.union(y),
                                [a for a in renames_flat if p in a])
                            param_info[p]["renames"] = \
                                list(set(chain(this_renames, str_to_list(
                                    param_info[p].get("renames", []))))
                                     .difference({p}))
    # Rest of the options
    for k, v in input_info.items():
        if k not in updated_info:
            updated_info[k] = v
    return updated_info