/// <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);
        }
Beispiel #2
0
 private static void GetFilePathFromObjects(NTObject[] obj, out NTH1 hPath, out NTH1 hSize)
 {
     hPath = null;
     hSize = null;
     foreach (var h in obj.Where(o => o != null))
     {
         if (h.Name.EndsWith("_size"))
         {
             hSize = h as NTH1;
         }
         else
         {
             hPath = h as NTH1;
         }
     }
 }
        /// <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>
        /// Extract the file name from the NTObjects we are getting fed.
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="hPath"></param>
        /// <param name="hSize"></param>
        private static void GetFilePathFromObjects(NTObject[] obj, out NTH1 hPath, out NTH1 hSize)
        {
            hPath = null;
            hSize = null;
            foreach (var h in obj)
            {
                if (h.Name.EndsWith("_size"))
                {
                    hSize = h as NTH1;
                }
                else
                {
                    hPath = h as NTH1;
                }
            }

            if (hPath == null || hSize == null)
            {
                throw new InvalidOperationException("Internal error - cache is missing either the path for a CSV file or its size");
            }
        }
        /// <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);
        }
Beispiel #6
0
 public DrawingObject(ROOTNET.Interface.NTH1 p)
 {
     _p = p;
 }
Beispiel #7
0
        /// <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;
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #9
0
 /// <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);
 }
Beispiel #10
0
        /// <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);
        }
Beispiel #11
0
 /// <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;
 }