def _evaluate(self, *args): """ uncertainties = f(args) """ bin_vals = { argname: args[self._dim_args[argname]] for argname in self._dim_order } eval_vals = { argname: args[self._eval_args[argname]] for argname in self._eval_vars } #lookup the bins that we care about dim1_name = self._dim_order[0] dim1_indices = np.clip( np.searchsorted( self._bins[dim1_name], bin_vals[dim1_name], side='right') - 1, 0, self._bins[dim1_name].size - 2) #get clamp values and clip the inputs outs = np.ones(shape=(args[0].size, 2), dtype=np.float) for i in np.unique(dim1_indices): mask = np.where(dim1_indices == i) vals = np.clip(eval_vals[self._eval_vars[0]][mask], self._eval_knots[0], self._eval_knots[-1]) outs[:, 0][mask] += self._eval_ups[i](vals) outs[:, 1][mask] -= self._eval_downs[i](vals) return outs
def __init__(self, formula, bins_and_orders, clamps_and_vars, parms_and_orders): """ The constructor takes the output of the "convert_jec(jr)_txt_file" text file converter, which returns a formula, bins, and parameter values. """ super(jme_standard_function, self).__init__() self._dim_order = bins_and_orders[1] self._bins = bins_and_orders[0] self._eval_vars = clamps_and_vars[2] self._eval_clamp_mins = clamps_and_vars[0] self._eval_clamp_maxs = clamps_and_vars[1] self._parm_order = parms_and_orders[1] self._parms = parms_and_orders[0] self._formula_str = formula self._formula = wrap_formula(formula, self._parm_order + self._eval_vars) for binname in self._dim_order[1:]: binsaslists = self._bins[binname].tolist() self._bins[binname] = [np.array(bins) for bins in binsaslists] #get the jit to compile if we've got more than one bin dim if len(self._dim_order) > 1: masked_bin_eval(np.array([0, 0]), self._bins[self._dim_order[1]], np.array([0.0, 0.0])) #compile the formula argsize = len(self._parm_order) + len(self._eval_vars) some_ones = [50 * np.ones(argsize) for i in range(argsize)] _ = self._formula(*tuple(some_ones)) self._signature = deepcopy(self._dim_order) for eval in self._eval_vars: if eval not in self._signature: self._signature.append(eval) self._dim_args = { self._dim_order[i]: i for i in range(len(self._dim_order)) } self._eval_args = {} for i, argname in enumerate(self._eval_vars): self._eval_args[argname] = i + len(self._dim_order) if argname in self._dim_args.keys(): self._eval_args[argname] = self._dim_args[argname]
def _build_standard_jme_lookup(name, layout, pars, nBinnedVars, nBinColumns, nEvalVars, formula, nParms, columns, dtypes, interpolatedFunc=False): #the first bin is always usual for JECs #the next bins may vary in number, so they're jagged arrays... yay bins = {} offset_col = 0 offset_name = 1 bin_order = [] for i in range(nBinnedVars): binMins = None binMaxs = None if i == 0: binMins = np.unique(pars[columns[0]]) binMaxs = np.unique(pars[columns[1]]) bins[layout[i + offset_name]] = np.union1d(binMins, binMaxs) else: counts = np.zeros(0, dtype=np.int) allBins = np.zeros(0, dtype=np.double) for binMin in bins[bin_order[0]][:-1]: binMins = np.unique(pars[np.where( pars[columns[0]] == binMin)][columns[i + offset_col]]) binMaxs = np.unique(pars[np.where( pars[columns[0]] == binMin)][columns[i + offset_col + 1]]) theBins = np.union1d(binMins, binMaxs) allBins = np.append(allBins, theBins) counts = np.append(counts, theBins.size) bins[layout[i + offset_name]] = awkward.JaggedArray.fromcounts( counts, allBins) bin_order.append(layout[i + offset_name]) offset_col += 1 #skip nvars to the variable columns #the columns here define clamps for the variables defined in columns[] # ----> clamps can be different from bins # ----> if there is more than one binning variable this array is jagged # ----> just make it jagged all the time binshapes = tuple([bins[thebin].size - 1 for thebin in bin_order]) clamp_mins = {} clamp_maxs = {} var_order = [] offset_col = 2 * nBinnedVars + 1 offset_name = nBinnedVars + 2 jagged_counts = np.ones(bins[bin_order[0]].size - 1, dtype=np.int) if len(bin_order) > 1: jagged_counts = np.maximum( bins[bin_order[1]].counts - 1, 0) #need counts-1 since we only care about Nbins for i in range(nEvalVars): var_order.append(layout[i + offset_name]) if not interpolatedFunc: clamp_mins[layout[i + offset_name]] = awkward.JaggedArray.fromcounts( jagged_counts, np.atleast_1d(pars[columns[i + offset_col]])) clamp_maxs[layout[i + offset_name]] = awkward.JaggedArray.fromcounts( jagged_counts, np.atleast_1d(pars[columns[i + offset_col + 1]])) offset_col += 1 #now get the parameters, which we will look up with the clamped values parms = [] parm_order = [] offset_col = 2 * nBinnedVars + 1 + (interpolatedFunc == False) * 2 * nEvalVars for i in range(nParms): parms.append( awkward.JaggedArray.fromcounts(jagged_counts, pars[columns[i + offset_col]])) parm_order.append('p%i' % (i)) wrapped_up = {} wrapped_up[(name, 'jme_standard_function')] = (formula, (bins, bin_order), (clamp_mins, clamp_maxs, var_order), (parms, parm_order)) return wrapped_up