def get_physical_bounds(dim): """Get physical bounds for a dimension. Works on the "base" dimension (e.g. true-energy and reco-energy both are treated as just "energy"). Ignores any artificially limits imposed by a user. Parameters ---------- dim : string Returns ------- lower_bound, upper_bound : pint.Quantity Raises ------ ValueError If `dim` cannot resolve to either 'energy' or 'coszen'. """ base_dim = basename(dim) if base_dim == 'energy': return 0 * ureg.GeV, np.inf * ureg.GeV if base_dim == 'coszen': return -1 * ureg.dimensionless, 1 * ureg.dimensionless raise ValueError('Unknown `dim` = %s' % dim)
def get_physical_bounds(dim): """Returns the boundaries of the physical region for the various dimensions""" dim = basename(dim) if dim == "coszen": trunc_low = -1. trunc_high = 1. elif dim == "energy": trunc_low = 0. trunc_high = None elif dim == "azimuth": trunc_low = 0. trunc_high = 2 * np.pi else: raise ValueError("No physical bounds for dimension '%s' available." % dim) return trunc_low, trunc_high
def populate_reco_observables(mc_events, param_source, random_state=None): """Modify `mc_events` with the reconstructed variables derived from the true variables that must already be present. Note that modification is in-place. Parameters ---------- mc_events : pisa.core.events.Events param_source : string Resource location from which to load parameterizations random_state Passed as argument to `pisa.utils.random_numbers.get_random_state`. See docs for that function for acceptable values. """ random_state = get_random_state(random_state) logging.info(' Applying resolution functions') reco_params = load_reco_param(param_source) for flavint in mc_events.flavints: logging.debug('Processing %s.', flavint) all_dist_info = None for flavintgroup, info in reco_params.iteritems(): if flavint in flavintgroup: all_dist_info = info if all_dist_info is None: raise ValueError('Did not find reco parameterizations for' ' %s' % flavint) true_energies = mc_events[flavint]['true_energy'] num_events = len(true_energies) for true_dimension in mc_events[flavint].keys(): if 'true' not in true_dimension: continue base_dim = basename(true_dimension) true_vals = mc_events[flavint][true_dimension] dist_info = all_dist_info[base_dim] if len(dist_info) != 1: raise NotImplementedError('Multiple distributions not' ' yet supported.') dist_info = dist_info[0] dist_class = dist_info['dist'] dist_kwargs = {} for key, func in dist_info['kwargs'].iteritems(): dist_kwargs[key] = func(true_energies) #dist_frac = dist_info['fraction'] reco_dist = dist_class(**dist_kwargs) logging.debug( 'Drawing %d samples from res func. %s (only within' ' physical boundaries for )', num_events, dist_class) physical_min, physical_max = get_physical_bounds(base_dim, ) error_min = physical_min.magnitude - true_vals error_max = physical_max.magnitude - true_vals error_samples = sample_truncated_dist(reco_dist, size=len(true_vals), trunc_low=error_min, trunc_high=error_max, random_state=random_state) reco_vals = true_vals + error_samples if base_dim == 'energy': min_reco_val = min(reco_vals) logging.trace('min reco energy = %s', min_reco_val) assert min_reco_val >= 0, format(min_reco_val, '%.15e') elif base_dim == 'coszen': min_reco_val = min(reco_vals) logging.trace('min reco coszen = %s', min_reco_val) assert min_reco_val >= -1, format(min_reco_val, '%.15e') max_reco_val = max(reco_vals) logging.trace('max reco coszen = %s', max_reco_val) assert max_reco_val <= +1, format(max_reco_val, '%.15e') mc_events[flavint]['reco_' + base_dim] = reco_vals return mc_events