Beispiel #1
0
    def __init_spline(self, knots, coeffs, deg, units=None):
        knots = interpret_quantity(knots, expect_sequence=True)
        self._state_attrs.extend(['knots', 'coeffs', 'deg'])
        self.kind = 'spline'
        if isunitless(knots):
            knots = ureg.Quantity(knots, units)
        elif units is not None:
            units = ureg.Unit(units)
            assert knots.dimensionality == units.dimensionality
            knots = knots.to(units)

        self.units = str(knots.units)

        self.knots = knots
        self.coeffs = coeffs
        self.deg = deg
        def llh(x):
            x = self.__strip(self.__convert(x))
            return splev(x, tck=(self.__strip(self.knots), coeffs, deg), ext=2)
        self.llh = llh
        self.max_at = fminbound(
            func=self.__attach_units_to_args(self.chi2),
            x1=np.min(self.__strip(self.knots)),
            x2=np.max(self.__strip(self.knots)),
        )
        if self.units is not None:
            self.max_at = self.max_at * ureg(self.units)
        self.max_at_str = self.__stringify(self.max_at)
        self.valid_range = (np.min(self.knots) * ureg(self.units),
                            np.max(self.knots) * ureg(self.units))
        self._str = lambda s: 'spline prior: deg=%d, valid in [%s, %s]%s; max at %s%s' \
                %(self.deg, self.__stringify(np.min(self.knots)),
                  self.__stringify(np.max(self.knots)), self.units_str,
                  self.max_at_str, self.units_str)
Beispiel #2
0
def parse_fit_config(fit_cfg):
    """Perform sanity checks on and parse fit configuration file.

    Parameters
    ----------
    fit_cfg : str
        path to a fit configuration file

    Returns
    -------
    fit_cfg : PISAConfigParser
        parsed fit configuration
    sys_list : list of str
        parsed names of systematic parameters
    units_list : list of str
        units corresponding to each discrete systematic
    combine_regex : list of str
        each string is a regular expression for combining pipeline outputs; see
        :func:`pisa.core.map.MapSet.combine_regex` for details.

    """
    fit_cfg = from_file(fit_cfg)
    no_ws_section_map = {s.strip(): s for s in fit_cfg.sections()}

    if GENERAL_SECTION_NAME not in no_ws_section_map.values():
        raise KeyError('Fit config is missing the "%s" section!' %
                       GENERAL_SECTION_NAME)

    general_section = fit_cfg[GENERAL_SECTION_NAME]
    if SYS_LIST_OPTION not in general_section:
        raise KeyError(
            "Fit config has to specify systematic parameters as"
            ' "%s" option in "%s" section (comma-separated list of names).' %
            (SYS_LIST_OPTION, GENERAL_SECTION_NAME))

    sys_list = [s.strip() for s in general_section[SYS_LIST_OPTION].split(",")]

    if UNITS_OPTION in general_section:
        units_list = []
        units_specs = (general_section[UNITS_OPTION].replace(
            UNITS_SPECIFIER, "").split(","))
        for units_spec in units_specs:
            # Make sure units are interpret-able by Pint
            try:
                ureg.Unit(units_spec)
            except:
                logging.error(
                    'Unit "%s" specified by "%s" option in "general" section is not'
                    "interpret-able by Pint",
                    units_spec,
                    UNITS_OPTION,
                )
                raise
            units_list.append(units_spec)
    else:
        units_list = ["dimensionless" for s in sys_list]
        logging.warn(
            "No %s option found in %s section; assuming systematic parameters are"
            " dimensionless",
            UNITS_OPTION,
            GENERAL_SECTION_NAME,
        )

    if len(units_list) != len(sys_list):
        raise ValueError(
            '{} units specified by "{}" option but {} systematics specified by "{}"'
            "option; must be same number of each.".format(
                len(units_list), UNITS_OPTION, len(sys_list), SYS_LIST_OPTION))

    logging.info(
        "Found systematic parameters %s",
        ["{} ({})".format(s, u) for s, u in zip(sys_list, units_list)],
    )

    combine_regex = general_section.get(COMBINE_REGEX_OPTION, None)
    if combine_regex:
        try:
            combine_regex = literal_eval(combine_regex)
        except (SyntaxError, ValueError):
            logging.warn(
                'Deprecated syntax for "combine_re" (make into a Python-evaluatable'
                "sequence of strings instead) :: combine_regex = %s",
                combine_regex,
            )
            combine_regex = [r.strip() for r in combine_regex.split(",")]

    if APPLY_ALL_SECTION_NAME in no_ws_section_map:
        apply_all_section = fit_cfg[no_ws_section_map[APPLY_ALL_SECTION_NAME]]
        for no_ws_sname, sname in no_ws_section_map.items():
            if not (no_ws_sname.startswith(NOMINAL_SET_PFX)
                    or no_ws_sname.startswith(SYS_SET_PFX)):
                continue
            sys_set_section = fit_cfg[sname]
            for option, val in apply_all_section.items():
                sys_set_section[option] = val

    return fit_cfg, sys_list, units_list, combine_regex
Beispiel #3
0
    def __init__(
        self,
        fit_results_file,
        data=None,
        params=None,
        input_names=None,
        output_names=None,
        debug_mode=None,
        error_method=None,
        input_specs=None,
        calc_specs=None,
        output_specs=None,
        links=None,
    ):
        # -- Read fit_results_file and extract necessary info -- #

        fit_results = from_file(fit_results_file)

        # handle backwards compatibility for old style fit results files
        if "hyperplanes" in fit_results:
            using_old_fit_file = False
        elif "sys_list" in fit_results:
            using_old_fit_file = True
        else:
            raise ValueError("Unrecognised format for input fit file")

        # get list of systematic parameter names fitted; need to conserve order here!
        if using_old_fit_file:
            fit_param_names = fit_results["sys_list"]
        else:
            fit_param_names = fit_results["param_names"]

        if "param_units" in fit_results:
            fit_param_units = fit_results["param_units"]
        else:
            fit_param_units = ["dimensionless" for _ in fit_param_names]
        fit_param_units = [ureg.Unit(u) for u in fit_param_units]

        # Perfer to have the actual binning, so we can compare bin edges to
        # "reasonable" precision to make sure the hyperplane fits are applicable to the
        # current binning.
        #
        # If there is no binning in the hyperplane fit results file, look for a hash
        # value; barring that, just ensure that the dimensionality & number of bins
        # match.
        binning_spec = fit_results.get("binning", None)
        if binning_spec is not None:
            fit_binning = MultiDimBinning(**binning_spec)
        else:
            fit_binning = None

        if fit_binning is not None:
            fit_binning_hash = fit_binning.hash
        else:
            fit_binning_hash = fit_results.get("binning_hash", None)

        if fit_binning_hash is None:
            logging.warn("Cannot determine the hash of the binning employed"
                         " for the hyperplane fits. Correct application of"
                         " fits is not guaranteed!")

        # -- Expected input / output names -- #

        input_names = ()
        output_names = ()

        # -- Which keys are added or altered for the outputs during `apply` -- #

        input_calc_keys = ()
        output_calc_keys = ("hyperplane_scalefactors", )

        if error_method == "sumw2":
            output_apply_keys = ("weights", "errors")
            input_apply_keys = output_apply_keys
        else:
            output_apply_keys = ("weights", )
            input_apply_keys = output_apply_keys

        # -- Initialize base class -- #

        super(pi_hyperplanes, self).__init__(
            data=data,
            params=params,
            expected_params=fit_param_names,
            input_names=input_names,
            output_names=output_names,
            debug_mode=debug_mode,
            error_method=error_method,
            input_specs=input_specs,
            calc_specs=calc_specs,
            output_specs=output_specs,
            input_calc_keys=input_calc_keys,
            output_calc_keys=output_calc_keys,
            input_apply_keys=input_apply_keys,
            output_apply_keys=output_apply_keys,
        )

        # -- Only allowed/implemented modes -- #

        assert self.input_mode is not None
        assert self.calc_mode == "binned"
        assert self.output_mode is not None

        self.links = ast.literal_eval(links)

        # -- Add attrs to `self` specific to `pi_hyperplanes` -- #

        self.fit_results_file = fit_results_file
        """str : path to hyperplane fit results file"""

        self.using_old_fit_file = using_old_fit_file
        """bool : whether the hyperplane fit file is in the "old" format"""

        self.fit_results = fit_results
        """OrderedDict : parsed hyperplane fit file"""

        self.fit_param_names = fit_param_names
        """list : param names used in hyperplane fit, in order they appear in file"""

        self.fit_param_units = fit_param_units
        """list : param untis used in hyperplane fit, in order they appear in file"""

        self.fit_binning = fit_binning
        """MultiDimBinning : binning used for hyperplane fits; one hyperplane per bin"""

        self.fit_binning_hash = fit_binning_hash
        """str : hash of the binning used for hyperplane fits"""
Beispiel #4
0
    def __init__(
        self,
        fit_results_file,
        data=None,
        params=None,
        input_names=None,
        output_names=None,
        debug_mode=None,
        error_method=None,
        input_specs=None,
        calc_specs=None,
        output_specs=None,
        links=None,
    ):
        # -- Read fit_results_file and extract necessary info -- #

        if fit_results_file.endswith('.csv'):
            # in this case those are datarelease files
            form = 'datarelease'
            import pandas as pd
            fit_results = {}
            fit_results['nue_cc+nuebar_cc'] = pd.read_csv(
                fit_results_file.replace('*', 'nue_cc'))
            fit_results['numu_cc+numubar_cc'] = pd.read_csv(
                fit_results_file.replace('*', 'numu_cc'))
            fit_results['nutau_cc+nutaubar_cc'] = pd.read_csv(
                fit_results_file.replace('*', 'nutau_cc'))
            fit_results['nu_nc+nubar_nc'] = pd.read_csv(
                fit_results_file.replace('*', 'all_nc'))

            fit_param_names = [
                a for a in fit_results['nu_nc+nubar_nc'].columns
                if a not in ['pid', 'reco_energy', 'reco_coszen', 'offset']
            ]
            fit_binning = calc_specs

        else:

            fit_results = from_file(fit_results_file)

            # handle backwards compatibility for old style fit results files
            if "hyperplanes" in fit_results:
                form = 'linear'
            elif "sys_list" in fit_results:
                form = 'legacy'
            else:
                raise ValueError("Unrecognised format for input fit file")

            # get list of systematic parameter names fitted; need to conserve order here!
            if form == 'legacy':
                fit_param_names = fit_results["sys_list"]
            else:
                fit_param_names = fit_results["param_names"]

            # Perfer to have the actual binning, so we can compare bin edges to
            # "reasonable" precision to make sure the hyperplane fits are applicable to the
            # current binning.
            #
            # If there is no binning in the hyperplane fit results file, look for a hash
            # value; barring that, just ensure that the dimensionality & number of bins
            # match.
            binning_spec = fit_results.get("binning", None)
            if binning_spec is not None:
                fit_binning = MultiDimBinning(**binning_spec)
            else:
                fit_binning = None

        if "param_units" in fit_results:
            fit_param_units = fit_results["param_units"]
        else:
            fit_param_units = ["dimensionless" for _ in fit_param_names]
        fit_param_units = [ureg.Unit(u) for u in fit_param_units]

        if fit_binning is not None:
            fit_binning_hash = fit_binning.hash
        else:
            fit_binning_hash = fit_results.get("binning_hash", None)

        if fit_binning_hash is None:
            logging.warning("Cannot determine the hash of the binning employed"
                            " for the hyperplane fits. Correct application of"
                            " fits is not guaranteed!")

        # -- Expected input / output names -- #

        input_names = ()
        output_names = ()

        # -- Which keys are added or altered for the outputs during `apply` -- #

        input_calc_keys = ()
        output_calc_keys = ("hyperplane_scalefactors", )

        if error_method == "sumw2":
            output_apply_keys = ("weights", "errors")
            input_apply_keys = output_apply_keys
        else:
            output_apply_keys = ("weights", )
            input_apply_keys = output_apply_keys

        # -- Initialize base class -- #

        super().__init__(
            data=data,
            params=params,
            expected_params=fit_param_names,
            input_names=input_names,
            output_names=output_names,
            debug_mode=debug_mode,
            error_method=error_method,
            input_specs=input_specs,
            calc_specs=calc_specs,
            output_specs=output_specs,
            input_calc_keys=input_calc_keys,
            output_calc_keys=output_calc_keys,
            input_apply_keys=input_apply_keys,
            output_apply_keys=output_apply_keys,
        )

        # -- Only allowed/implemented modes -- #

        assert self.input_mode is not None
        assert self.calc_mode == "binned"
        assert self.output_mode is not None

        self.links = ast.literal_eval(links)

        # -- Add attrs to `self` specific to `pi_hyperplanes` -- #

        self.fit_results_file = fit_results_file
        """str : path to hyperplane fit results file"""

        self.fit_results = fit_results
        """OrderedDict : parsed hyperplane fit file"""

        self.fit_param_names = fit_param_names
        """list : param names used in hyperplane fit, in order they appear in file"""

        self.fit_param_units = fit_param_units
        """list : param untis used in hyperplane fit, in order they appear in file"""

        self.fit_binning = fit_binning
        """MultiDimBinning : binning used for hyperplane fits; one hyperplane per bin"""

        self.fit_binning_hash = fit_binning_hash
        """str : hash of the binning used for hyperplane fits"""

        self.form = form
        """str : format of input file"""