/// <summary> /// Returna plot that has as its content its value divided by its error, and zero errors. /// </summary> /// <param name="ctx"></param> /// <param name="source"></param> /// <returns></returns> public static NTH1 asSigma(IScopeContext ctx, NTH1 plot) { var result = plot.Clone() as NTH1; Tags.CopyTags(ctx, plot, result); result.Reset(); // Besure to do the overflow bins as well. for (int i_bin_x = 0; i_bin_x < result.NbinsX + 2; i_bin_x++) { for (int i_bin_y = 0; i_bin_y < result.NbinsY + 2; i_bin_y++) { for (int i_bin_z = 0; i_bin_z < result.NbinsZ + 2; i_bin_z++) { var v = plot.GetBinContent(i_bin_x, i_bin_y, i_bin_z); var e = plot.GetBinError(i_bin_x, i_bin_y, i_bin_z); var sig = e == 0 ? 0.0 : v / e; result.SetBinContent(i_bin_x, i_bin_y, i_bin_z, sig); } } } return(result); }
/// <summary> /// Create a plot out of a single ratio point. /// </summary> /// <param name="template"></param> /// <param name="xpos"></param> /// <param name="numerator"></param> /// <param name="denominator"></param> /// <returns></returns> public static NTH1 ratioPointAsPlot(NTH1 template, double xpos, double numerator, double denominator) { // Make a clone, and zero it out. var hNum = template.Clone() as NTH1; hNum.Reset(); var hDen = hNum.Clone() as NTH1; // Now, do the division var index = hNum.FindBin(xpos); hNum.SetBinContent(index, numerator); hNum.SetBinError(index, Math.Sqrt(numerator)); hDen.SetBinContent(index, denominator); hDen.SetBinError(index, Math.Sqrt(denominator)); hNum.Divide(hDen); return(hNum); }
/// <summary> /// Generate an integral plot out of the current plot. /// </summary> /// <param name="ctx"></param> /// <param name="plot"></param> /// <returns></returns> public static ROOTNET.Interface.NTH1 asIntegral(IScopeContext ctx, NTH1 plot, bool sumForward = true) { // Clone it. var result = plot.Clone() as ROOTNET.Interface.NTH1;; Tags.CopyTags(ctx, plot, result); // get the numbers out var numbers = Enumerable.Range(0, result.NbinsX + 1) .Select(ibin => result.GetBinContent(ibin)); // Now, sum them up. var total = numbers.Sum(); // And transform them. double runningTotal = sumForward ? 0 : total; Func <double, double> calRunningTotal; if (sumForward) { calRunningTotal = p => runningTotal += p; } else { calRunningTotal = p => runningTotal -= p; } numbers = numbers .Select(n => calRunningTotal(n)) .ToArray(); // The runningTotal has side effects, so we better put a stop. // Stuff them back in result. foreach (var n in Enumerable.Range(0, result.NbinsX + 1).Zip(numbers, (ibin, v) => Tuple.Create(ibin, v))) { result.SetBinContent(n.Item1, n.Item2); } return(result); }
/// <summary> /// Internally do the divide, hidden in the monad. /// </summary> /// <param name="hn"></param> /// <param name="hd"></param> /// <returns></returns> private static NTH1 InternalDivide(NTH1 hn, NTH1 hd) { var result = hn.Clone(string.Format("{0}_div_{1}", hn.Name, hd.Name)) as NTH1; if (!result.Divide(hd)) { throw new HistogramOperationErrorException($"Failure to divide {hn.Name} by {hd.Name}"); } return result; }