Exemplo n.º 1
0
def _set_magnitude_phase(magn_phase_tuple):
    try:
        magnitude, phase = magn_phase_tuple
    except:
        raise ValueError(
            'Pass an iterable with two items (magnitude and phase)!')
    if not isscalar(magnitude) or not isscalar(phase):
        raise TypeError('Only scalar values for magnitude and phase accepted!')
    if magnitude < 0.0 and phase != 0.0:
        raise ValueError(
            'Only accepting negative values with a zero phase (real coupling)!'
        )
    return magnitude, phase
Exemplo n.º 2
0
 def eps_prime(self, value):
     if isinstance(value, complex) or not isscalar(value):
         raise TypeError("eps_prime must be a real number!")
     self._eps_prime = value
Exemplo n.º 3
0
 def eps_tautau(self, value):
     if isinstance(value, complex) or not isscalar(value):
         raise TypeError("eps_tautau must be a real number!")
     self._eps_matrix[2, 2] = value + 1.j * self._eps_matrix[2, 2].imag
Exemplo n.º 4
0
def load_reco_param(source):
    """Load reco parameterisation (energy-dependent) from file or dictionary.

    Parameters
    ----------
    source : string or mapping
        Source of the parameterization. If string, treat as file path or
        resource location and load from the file; this must yield a mapping. If
        `source` is a mapping, it is used directly. See notes below on format.

    Returns
    -------
    reco_params : OrderedDict
        Keys are stringified flavintgroups and values are dicts of strings
        representing the different reco dimensions and lists of distribution
        properties. These latter have a 'fraction', a 'dist' and a 'kwargs' key.
        The former two hold callables, while the latter holds a dict of
        key-callable pairs ('loc', 'scale'), which can be evaluated at the desired
        energies and passed into the respective `scipy.stats` distribution.
        The distributions for a given dimension will be superimposed according
        to their relative weights to form the reco kernels (via integration)
        when called with energy values (parameterisations are functions of
        energy only!).

    Notes
    -----
    The mapping passed via `source` or loaded therefrom must have the format:
        {
            <flavintgroup_string>:
                {
                    <dimension_string>:[
                        {
                            "dist": dist_id,
                            "fraction": val,
                            "kwargs": {
                                "loc": val,
                                "scale": val,
                                ...
                            }
                        },
                    ...
                    ]
                },
            <flavintgroup_string>:
                ...
        }

    `flavintgroup_string`s must be parsable by
    pisa.utils.flavInt.NuFlavIntGroup. Note that the `transform_groups` defined
    in a pipeline config file using this must match the groupings defined
    above.

    `dimension_string`s denote the observables/dimensions whose reco error
    distribution is parameterised (`"energy"` or `"coszen"`).

    `dist_id` needs to be a string identifying a probability distribution/statistical
    function provided by `scipy.stats`. No implicit assumptions about the
    distribution will be made if the `"dist"` key is missing.

    `"fraction"` holds the relative weight of the distribution. For a given
    dimension, the sum of all fractions present must be 1.

    Valid kwargs for distributions must at least include `"loc"` and `"scale"` -
    these will be passed into the respective `scipy.stats` function.

    `val`s can be one of the following:
        - Callable with one argument
        - String such that `eval(val)` yields a callable with one argument
    """
    if not (source is None or isinstance(source, (basestring, Mapping))):
        raise TypeError('`source` must be string, mapping, or None')

    if isinstance(source, basestring):
        orig_dict = from_file(source)

    elif isinstance(source, Mapping):
        orig_dict = source

    else:
        raise TypeError('Cannot load reco parameterizations from a %s' %
                        type(source))

    valid_dimensions = ('coszen', 'energy')
    required_keys = ('dist', 'fraction', 'kwargs')

    # Build dict of parameterizations (each a callable) per flavintgroup
    reco_params = OrderedDict()
    for flavint_key, dim_dict in orig_dict.iteritems():
        flavintgroup = NuFlavIntGroup(flavint_key)
        reco_params[flavintgroup] = {}
        for dimension in dim_dict.iterkeys():
            dim_dist_list = []

            if not isinstance(dimension, basestring):
                raise TypeError("The dimension needs to be given as a string!"
                                " Allowed: %s." % valid_dimensions)

            if dimension not in valid_dimensions:
                raise ValueError("Dimension '%s' not recognised!" % dimension)

            for dist_dict in dim_dict[dimension]:
                dist_spec_dict = {}

                # allow reading in even if kwargs not present - computation of
                # transform will fail because "loc" and "scale" hard-coded
                # requirement
                for required in required_keys:
                    if required not in dist_dict:
                        raise ValueError("Found distribution property dict "
                                         "without required '%s' key for "
                                         "%s - %s!" %
                                         (required, flavintgroup, dimension))

                for k in dist_dict.iterkeys():
                    if k not in required_keys:
                        logging.warn("Unrecognised key in distribution"
                                     " property dict: '%s'" % k)

                dist_spec = dist_dict['dist']

                if not isinstance(dist_spec, basestring):
                    raise TypeError(" The resolution function needs to be"
                                    " given as a string!")

                if not dist_spec:
                    raise ValueError("Empty string found for resolution"
                                     " function!")

                try:
                    dist = getattr(stats, dist_spec.lower())
                except AttributeError:
                    try:
                        import scipy
                        sp_ver_str = scipy.__version__
                    except:
                        sp_ver_str = "N/A"
                    raise AttributeError("'%s' is not a valid distribution"
                                         " from scipy.stats (your scipy"
                                         " version: '%s')." %
                                         (dist_spec.lower(), sp_ver_str))
                logging.debug("Found %s - %s resolution function: '%s'" %
                              (flavintgroup, dimension, dist.name))

                dist_spec_dict['dist'] = dist

                frac = dist_dict['fraction']

                if isinstance(frac, basestring):
                    frac_func = eval(frac)

                elif callable(frac):
                    frac_func = frac

                else:
                    raise TypeError(
                        "Expected 'fraction' to be either a string"
                        " that can be interpreted by eval or a callable."
                        " Got '%s'." % type(frac))

                dist_spec_dict['fraction'] = frac_func

                kwargs = dist_dict['kwargs']

                if not isinstance(kwargs, dict):
                    raise TypeError(
                        "'kwargs' must hold a dictionary. Got '%s' instead." %
                        type(kwargs))

                dist_spec_dict['kwargs'] = kwargs
                for kwarg, kwarg_spec in kwargs.iteritems():

                    if isinstance(kwarg_spec, basestring):
                        kwarg_eval = eval(kwarg_spec)

                    elif callable(kwarg_spec) or isscalar(kwarg_spec):
                        kwarg_eval = kwarg_spec

                    else:
                        raise TypeError(
                            "Expected kwarg '%s' spec to be either a string"
                            " that can be interpreted by eval, a callable or"
                            " a scalar. Got '%s'." % type(kwarg_spec))

                    dist_spec_dict['kwargs'][kwarg] = kwarg_eval

                dim_dist_list.append(dist_spec_dict)

            reco_params[flavintgroup][dimension] = dim_dist_list

    return reco_params
Exemplo n.º 5
0
def get_prior_bounds(obj, param=None, stddev=1.0):
    """Obtain confidence intervals for given number of
    standard deviations from parameter prior.

    Parameters
    ----------
    obj : Prior, string, or Mapping
        if str, interpret as path from which to load a dict
        if dict, can be:
            template settings dict; must supply parameter name via `param`
            params dict; must supply parameter name via `param`
            prior dict

    param : Param
        Name of parameter for which to get bounds;
        necessary if `obj` is either template settings or params

    stddev : float or Iterable of floats
        number of stddevs


    Returns
    -------
    bounds : OrderedDict
        A dictionary mapping the passed `stddev` values to the corresponding
        bounds

    """
    if isscalar(stddev):
        stddev = [stddev]
    elif isinstance(stddev, Iterable):
        stddev = list(stddev)

    bounds = OrderedDict()
    for s in stddev:
        bounds[s] = []

    if isinstance(obj, Prior):
        prior = obj
    else:
        if isinstance(obj, str):
            obj = from_file(obj)
        if 'params' in obj:
            obj = obj['params']
        if param is not None and param in obj:
            obj = obj[param]
        if 'prior' in obj:
            obj = obj['prior']

        prior = Prior(**obj)

    logging.debug('Getting confidence region from prior: %s', prior)
    x0 = prior.valid_range[0]
    x1 = prior.valid_range[1]
    x = ureg.Quantity(np.linspace(x0, x1, 10000), prior.units)
    chi2 = prior.chi2(x)
    for (i, xval) in enumerate(x[:-1]):
        for s in stddev:
            chi2_level = s**2
            if chi2[i] > chi2_level and chi2[i + 1] < chi2_level:
                bounds[s].append(xval)
            elif chi2[i] < chi2_level and chi2[i + 1] > chi2_level:
                bounds[s].append(x[i + 1])
    return bounds