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
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
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
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
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