/// <summary> /// Attempt to convert each object to a TGraph /// </summary> /// <param name="source"></param> /// <returns></returns> public static IEnumerable <ROOTNET.NTGraph> ConvertToTGraph(this IEnumerable <object> source, IScopeContext ctx) { foreach (var o in source) { var directConversion = o as ROOTNET.NTGraph; if (directConversion != null) { yield return(directConversion); } else if (o is ROOTNET.NTH1) { var histo = o as ROOTNET.NTH1; ROOTNET.NTGraph g = histo.ConvertHistoToGraph(ctx); yield return(g); } else { throw new InvalidCastException($"Unable to convert or cast object of type {o.GetType().Name} to a TGraph"); } } }
/// <summary> /// Convert a histogram to a graph, simply. /// </summary> /// <param name="histo"></param> /// <returns></returns> public static ROOTNET.NTGraph ConvertHistoToGraph(this ROOTNET.NTH1 histo, IScopeContext ctx) { var g = new ROOTNET.NTGraph(histo.NbinsX); g.FillColor = 0; // Make sure the background is white // Copy meta-data. Tags.CopyTags(ctx, histo, g); g.Title = histo.Title; g.Name = $"{histo.Name}_g"; g.LineWidth = histo.LineWidth; g.LineColor = histo.LineColor; g.LineStyle = histo.LineStyle; // And points. for (int i = 0; i < histo.NbinsX; i++) { g.SetPoint(i, histo.GetBinCenter(i + 1), histo.GetBinContent(i + 1)); } return(g); }
/// <summary> /// Calculate on the fly the signal and rejection curves for the two plots. /// </summary> /// <param name="xAxisHist"></param> /// <param name="yAxisHist"></param> /// <returns></returns> private static NTGraph CalculateROC(NTH1 xAxisHist, NTH1 yAxisHist, string name, string title) { var tg = new ROOTNET.NTGraph(xAxisHist.NbinsX, xAxisHist.Data(), yAxisHist.Data()); tg.Xaxis.Title = "Fractional Signal Efficiency"; tg.Yaxis.Title = "Fractional Background Rejection"; tg.Title = title; tg.Name = name; return tg; }
/// <summary> /// Return a graph plot /// </summary> /// <param name="g"></param> /// <returns></returns> public static GraphContext draw(ROOTNET.NTGraph g) { return(new GraphContext(g)); }
/// <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); }