def masked_bin_eval(dim1_indices, dimN_bins, dimN_vals): dimN_indices = np.empty_like(dim1_indices) for i in np.unique(dim1_indices): idx = np.where(dim1_indices == i) dimN_indices[idx] = np.clip( np.searchsorted(dimN_bins[i], dimN_vals[idx], side='right') - 1, 0, len(dimN_bins[i]) - 2) return dimN_indices
def parseGeneratorHistory(gp_pdgId_in,gp_parent_in): inChain = activePdgIds #index manipulation offsets = gp_pdgId_in.offsets parents = gp_pdgId_in.parents pstarts = offsets[parents].astype('i4') gp_pdgId = gp_pdgId_in.content gp_ancestor = gp_parent_in.content + pstarts gp_ancestor_valid = (gp_parent_in.content >= 0) #create parentage bitmaps gp_pdgId_mapped = np.zeros(shape=gp_pdgId.shape, dtype='u4') for pdgId, bit in inChain.items(): if abs(pdgId) == 24: gp_pdgId_mapped[gp_pdgId==pdgId] = bit else: gp_pdgId_mapped[np.abs(gp_pdgId)==pdgId] = bit gp_proc = np.zeros(shape=gp_pdgId.shape, dtype='u4') pdg_tmp = np.empty_like(gp_pdgId_mapped) parent_tmp = np.empty_like(gp_ancestor) niter = 0 while np.any(gp_ancestor_valid) and niter < 50: np.take(gp_pdgId_mapped, gp_ancestor, out=pdg_tmp, mode='clip') np.take(gp_parent_in.content, gp_ancestor, out=parent_tmp, mode='clip') np.bitwise_or(gp_proc, pdg_tmp, where=gp_ancestor_valid, out=gp_proc) np.bitwise_and(gp_ancestor_valid, parent_tmp>=0, where=gp_ancestor_valid, out=gp_ancestor_valid) np.add(parent_tmp, pstarts, out=gp_ancestor) niter += 1 #print 'Parsed ancestor tree in %d iterations'%niter if niter == 50 and np.any(gp_ancestor_valid): raise Exception('reached 50 iterations, gen particles not trustable') return awkward.JaggedArray.fromoffsets(offsets, gp_proc)
def poisson_interval(sumw, sumw2, coverage=_coverage1sd): """ sumw: sum of weights sumw2: sum weights**2 coverage: coverage, default to 68% The so-called 'Garwood' interval c.f. https://www.ine.pt/revstat/pdf/rs120203.pdf or http://ms.mcmaster.ca/peter/s743/poissonalpha.html For weighted data, approximate the observed count by sumw**2/sumw2 This choice effectively scales the unweighted poisson interval by the average weight Maybe not the best... see https://arxiv.org/pdf/1309.1287.pdf for a proper treatment When a bin is zero, find the scale of the nearest nonzero bin If all bins zero, raise warning and set interval to sumw """ scale = np.empty_like(sumw) scale[sumw != 0] = sumw2[sumw != 0] / sumw[sumw != 0] if np.sum(sumw == 0) > 0: missing = np.where(sumw == 0) available = np.nonzero(sumw) if len(available[0]) == 0: warnings.warn( "All sumw are zero! Cannot compute meaningful error bars", RuntimeWarning) return np.vstack([sumw, sumw]) nearest = sum([ np.subtract.outer(d, d0)**2 for d, d0 in zip(available, missing) ]).argmin(axis=0) argnearest = tuple(dim[nearest] for dim in available) scale[missing] = scale[argnearest] counts = sumw / scale lo = scale * scipy.stats.chi2.ppf((1 - coverage) / 2, 2 * counts) / 2. hi = scale * scipy.stats.chi2.ppf( (1 + coverage) / 2, 2 * (counts + 1)) / 2. interval = np.array([lo, hi]) interval[interval == np.nan] = 0. # chi2.ppf produces nan for counts=0 return interval