/// <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> /// Return the x-axis value for a particular efficiency. /// </summary> /// <param name="r"></param> /// <param name="bv"></param> /// <returns></returns> private static double CalcEffValue(NTH1 r, double bv, bool greater = true) { var firstValue = Range(0, r.NbinsX) .Where(bin => greater ? r.GetBinContent(bin) > bv : r.GetBinContent(bin) < bv) .FirstOrDefault(); return r.Xaxis.GetBinCenter(firstValue); }
/// <summary> /// Given a cut value (x axis value), return the value of the histo at that point. /// </summary> /// <param name="hist"></param> /// <param name="xAxisValue"></param> /// <returns></returns> private static double LookupEffAtCut(NTH1 hist, double xAxisValue) { var bin = hist.Xaxis.FindBin(xAxisValue); return hist.GetBinContent(bin); }
/// <summary> /// Generate 2D turn on graphs from input signal and background plots. /// </summary> /// <param name="ctx"></param> /// <param name="plot"></param> /// <param name="xCutGreaterThan"></param> /// <param name="yCutGreaterThan"></param> /// <returns>A graph with the signal eff along the x axis, and the background eff along the y axis</returns> public static ROOTNET.Interface.NTGraph asROC(IScopeContext ctx, NTH1 signal, NTH1 background, bool xCutGreaterThan = true, bool yCutGreaterThan = true) { // The two plots must be identical. if (signal.NbinsX != background.NbinsX) { throw new ArgumentException($"AsROC requires the same binning on the input plots (signal has {signal.NbinsX} and background has {background.NbinsX})."); } // Now, develop pairs of values so we can track the background and signal efficiency. var numberPairs = Enumerable.Range(0, signal.NbinsX + 1) .Select(ibin => Tuple.Create(signal.GetBinContent(ibin), background.GetBinContent(ibin))); // Now, turn them into efficiencies if we need to. var signalTotal = numberPairs.Select(p => p.Item1).Sum(); var backgroundTotal = numberPairs.Select(p => p.Item2).Sum(); double runningTotalSignal = xCutGreaterThan ? 0 : signalTotal; double runningTotalBackground = yCutGreaterThan ? 0 : backgroundTotal; Func <double, double> calcRunningSignal, calcRunningBackground; if (xCutGreaterThan) { calcRunningSignal = p => runningTotalSignal += p; } else { calcRunningSignal = p => runningTotalSignal -= p; } if (yCutGreaterThan) { calcRunningBackground = p => runningTotalBackground += p; } else { calcRunningBackground = p => runningTotalBackground -= p; } numberPairs = numberPairs .Select(p => Tuple.Create(calcRunningSignal(p.Item1), calcRunningBackground(p.Item2))) .Select(p => Tuple.Create(p.Item1 / signalTotal, p.Item2 / backgroundTotal)) .ToArray(); // Side effects, make sure this gets run only once! // Remove the non-unique pairs, since this is going to be a scatter plot. numberPairs = numberPairs .Distinct(new TupleCompare()); // Next, draw them in a graph. var pts = numberPairs.ToArray(); var graf = new ROOTNET.NTGraph(pts.Length, pts.Select(p => p.Item1).ToArray(), pts.Select(p => p.Item2).ToArray()); graf.FillColor = 0; // Make sure the background is white // Track tags for the signal (assuming the background is "common"), and track everything else. Tags.CopyTags(ctx, signal, graf); graf.SetTitle($"{signal.Title} ROC"); graf.Xaxis.Title = $"Efficiency (signal)"; graf.Yaxis.Title = $"Efficiency (background)"; graf.Histogram.Maximum = 1.0; graf.Histogram.Minimum = 0.0; return(graf); }