/// <summary> /// Create an ABCD explorer along these two axes /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> public ABCDCutExplorer(IPlotSpec <T> v1, IPlotSpec <T> v2) { _v1 = v1; _v2 = v2; _2DPlot = _v1.CombinePlotAxes(_v2); }
/// <summary> /// Initialize everything we can do before. /// </summary> static EventTypePlotters() { // Sum logR JetEventTypeSumCalRPlot = JetRawSumCalRPlot .FromType <double, EventType>(info => NormalizeCalRatio.Invoke(info.Item1.Jet.logRatio) + NormalizeCalRatio.Invoke(info.Item2.Jet.logRatio)); // Sum Track pT of the two JetEventTypeSum2JTrackPt = JetRawSum2JTrackPt .FromType <double, EventType>(info => info.Item1.AllTracks.Select(t => t.pT).Sum() + info.Item2.AllTracks.Select(t => t.pT).Sum()); // Sum of the DR's for both trakcs. JetEventDRToTrackSum = JetRawDRToTrackSum .FromType <double, EventType>(info => CalcDR2GeVTrack.Invoke(info.Item1.AllTracks, info.Item1.Jet) + CalcDR2GeVTrack.Invoke(info.Item2.AllTracks, info.Item2.Jet)); }
/// <summary> /// Get the dependencies right /// </summary> static PlotSpecifications() { JetPtPlot = JetPtPlotRaw.FromType<double, recoTreeJets>(j => j.pT); JetETPlot = JetEtaPlotRaw.FromType<double, recoTreeJets>(j => j.ET); JetWidthPlot = JetWidthPlotRaw.FromType<double, recoTreeJets>(j => j.width); JetEtaPlot = JetEtaPlotRaw.FromType<double, recoTreeJets>(j => j.eta); JetLxyPlot = JetLxyPlotRaw.FromType<double, recoTreeJets>(j => j.LLP.IsGoodIndex() ? j.LLP.Lxy / 1000.0 : 0.0); JetCalRPlot = JetCalRPlotRaw.FromType<double, recoTreeJets>(j => j.logRatio); JetCalRPlotFine = JetCalRPlotFineRaw.FromType<double, recoTreeJets>(j => j.logRatio); NTrackPlot = NTrackPlotRaw.FromType<double, IEnumerable<recoTreeTracks>>(tks => tks.Count()); LLPPtPlot = LLPPtPlotRaw.FromType<double, recoTreeLLPs>(j => j.pT / 1000.0); JetPtPlotJetStream = JetPtPlot.FromType<recoTreeJets, JetStream>(j => j.JetInfo.Jet, weight: j => j.Weight); JetETPlotJetStream = JetETPlot.FromType<recoTreeJets, JetStream>(j => j.JetInfo.Jet, weight: j => j.Weight); JetEtaPlotJetStream = JetEtaPlot.FromType<recoTreeJets, JetStream>(j => j.JetInfo.Jet, weight: j=> j.Weight); JetLxyPlotJetStream = JetLxyPlot.FromType<recoTreeJets, JetStream>(j => j.JetInfo.Jet, weight: j => j.Weight); JetCalRPlotJetStream = JetCalRPlot.FromType<recoTreeJets, JetStream>(j => j.JetInfo.Jet, weight: j => j.Weight); JetCalRPlotFineJetStream = JetCalRPlotFine.FromType<recoTreeJets, JetStream>(j => j.JetInfo.Jet, weight: j => j.Weight); JetStreamSumPt = JetExtraSumPt.FromType<JetInfoExtra, JetStream>(j => j.JetInfo, weight: j => j.Weight); JetStreamMaxPt = JetExtraMaxPt.FromType<JetInfoExtra, JetStream>(j => j.JetInfo, weight: j => j.Weight); SumTrackPtPlot = SumTrackPtPlotRaw.FromType<double, JetInfoExtra>(j => j.AllTracks.Sum(t => t.pT)); MaxTrackPtPlot = MaxTrackPtPlotRaw.FromType<double, JetInfoExtra>(j => CalcMaxPt.Invoke(j.AllTracks)); DeltaROfCloseTrackPlotExtra = DeltaROfCloseTrackPlotRaw.FromType<double, JetInfoExtra>(j => CalcDR2GeVTrack.Invoke(j.AllTracks, j.Jet)); JetExtraPtPlot = JetPtPlot.FromType<recoTreeJets, JetInfoExtra>(jinfo => jinfo.Jet); JetWidthPlotExtra = JetWidthPlot.FromType<recoTreeJets, JetInfoExtra>(jinfo => jinfo.Jet); JetExtraEtaPlot = JetEtaPlot.FromType<recoTreeJets, JetInfoExtra>(jinfo => jinfo.Jet); JetExtraCalRPlot = JetCalRPlot.FromType<recoTreeJets, JetInfoExtra>(jinfo => jinfo.Jet); NTrackExtraPlot = NTrackPlot.FromType<IEnumerable<recoTreeTracks>, JetInfoExtra>(jinfo => jinfo.Tracks); TrackPtExtraPlot = TrackPtPlot.FromManyOfType((JetInfoExtra j) => j.Tracks); JetExtraCalRVsPtPlot = JetCalRVsPtPlot.FromType<recoTreeJets, JetInfoExtra>(jinfo => jinfo.Jet); PileUpWeight = PileUpWeightRaw.FromType<double, recoTree>(evt => evt.pileupEventWeight); }
/// <summary> /// Calculate a set of plots over this list of events /// </summary> /// <param name="signal"></param> /// <param name="background"></param> /// <param name="jetSelectorFunc"></param> /// <param name="dir"></param> private static Tuple<IFutureValue<NTH1>, IFutureValue<NTH1>> CalcSignalToBackground(IQueryable<JetInfoExtra> signal, IQueryable<JetInfoExtra> background, IPlotSpec<JetInfoExtra> plotter, FutureTDirectory dir, string name) { GC.Collect(3, GCCollectionMode.Forced, true); // Some generic plots signal .FuturePlot(JetExtraPtPlot, $"{name}_sig") .Save(dir); background .FuturePlot(JetExtraPtPlot, $"{name}_back") .Save(dir); signal .FuturePlot(JetExtraEtaPlot, $"{name}_sig") .Save(dir); background .FuturePlot(JetExtraEtaPlot, $"{name}_back") .Save(dir); // get the histograms for the signal and background var sPlot = signal .FuturePlot(plotter, "eff_sig") .Rename($"{name}_sig") .Save(dir) .Normalize() .AsCumulative(startWithZeroEff: false) .Rename($"{name}_sigrtback_sig") .Save(dir); var bPlot = background .FuturePlot(plotter, "eff_back") .Rename($"{name}_back") .Save(dir) .Normalize() .AsCumulative() .Rename($"{name}_sigrtback_back") .Save(dir); var bPlotSqrt = bPlot .Sqrt(); // As a bonus, calc the effeciency graf. Get the x and y for that. // TODO: there doesn't seem to be a get accessor for Content on NTH1 - is that really right? //var r = from s in sPlot // let sContent = Enumerable.Range(1, s.NbinsX).Select(idx => s.GetBinContent(idx)).ToArray() // from b in bPlot // select new ROOTNET.NTGraph(s.NBinsX, sContent, sContent); var effCurve = from s in sPlot from b in bPlot select CalculateROC(s, b, $"{name}_roc",$"ROC for {name}"); effCurve .Save(dir); // Calc the S/sqrt(B) and return it. sPlot .DividedBy(bPlotSqrt) .Rename($"{name}_sigrtback") .Save(dir); return Tuple.Create(sPlot, bPlot); }
/// <summary> /// Generate a series of plots /// </summary> /// <param name="signal"></param> /// <param name="background"></param> /// <param name="plotter"></param> /// <param name="dir"></param> /// <param name="nameStub"></param> private static Tuple<IFutureValue<NTH1>, IFutureValue<NTH1>> CalcSignalToBackgroundSeries(IQueryable<JetInfoExtra> signal, IQueryable<JetInfoExtra> background, IPlotSpec<JetInfoExtra> plotter, FutureTDirectory dir, string nameStub) { // Do them all. CalcSignalToBackground(signal, background, plotter, dir, nameStub); // Do LLP that have LLPs // TODO: understand how the LLP association is made, and make sure it is good enough. CalcSignalToBackground(signal.Where(sj => sj.Jet.LLP.IsGoodIndex()), background, plotter, dir, $"{nameStub}LLPJ"); // Has an LLP in the calorimeter. // TODO: understand how the LLP association is made, and make sure it is good enough. // TODO: Understand what isCRJet is defined to be. return CalcSignalToBackground(signal.Where(sj => sj.Jet.LLP.IsGoodIndex() && Constants.InCalorimeter.Invoke(sj.Jet.LLP.Lxy/1000)), background, plotter, dir, $"{nameStub}LLPJCal"); }
/// <summary> /// Try to uncorrelate the variables /// </summary> /// <param name="coVar"></param> /// <param name="jetEventTypeSumCalRPlot"></param> /// <param name="jetEventTypeSum2JTrackPt"></param> /// <returns></returns> private static Tuple <IPlotSpec <EventType>, IPlotSpec <EventType> > UncorrelateVariables(Matrix <double> coVar, IPlotSpec <EventType> v1, IPlotSpec <EventType> v2) { // Calculate the coefficients, and then the expressions var c = coVar.Cholesky(); var coeff = c.Factor.Inverse(); Expression <Func <EventType, double> > v1UCcalc = et => coeff[0, 0] * v1.ValueExpressionX.Invoke(et) + coeff[0, 1] * v2.ValueExpressionX.Invoke(et); Expression <Func <EventType, double> > v2UCcalc = et => coeff[1, 0] * v1.ValueExpressionX.Invoke(et) + coeff[1, 1] * v2.ValueExpressionX.Invoke(et); // Next, we have to build up new plotter guys! var plotter1 = MakePlotterSpec <EventType>(100, -10.0, 10.0, v1UCcalc, "UnCor1{0}", "Uncorrelated Variable 1"); var plotter2 = MakePlotterSpec <EventType>(100, -10.0, 10.0, v2UCcalc, "UnCor2{0}", "Uncorrelated Variable 2"); return(Tuple.Create(plotter1, plotter2)); }
/// <summary> /// Generate plots for the signal /// </summary> /// <param name="queryable"></param> /// <param name="sampleD"></param> /// <param name="mvaValue"></param> private static void PlotMVAResult(IQueryable<JetStream> source, FutureTDirectory dir, Expression<Func<TrainingTree, double>> mvaValue) { // Plot the weights. This can be used to plot signal vs background, ROC curves, etc. var weights = source .Select(j => TrainingUtils.TrainingTreeConverter.Invoke(j)) .Select(j => Tuple.Create(mvaValue.Invoke(j), j.Weight)) .FuturePlot(TrainingEventWeightFine.NameFormat, TrainingEventWeightFine.TitleFormat, TrainingEventWeightFine, "All") .Save(dir); // Next, let plot lots of kinematic plots so we can see what they look like. var plotsFromJS = new IPlotSpec<JetStream>[] { JetPtPlotJetStream, JetETPlotJetStream, JetEtaPlotJetStream, JetLxyPlotJetStream, JetCalRPlotJetStream, JetStreamSumPt, JetStreamMaxPt, JetCalRPlotFineJetStream, }; var plots = plotsFromJS .Select(myp => myp.FromType<JetStream, Tuple<JetStream, double>>(jinfo => jinfo.Item1, weight: jinfo => jinfo.Item2 * jinfo.Item1.Weight)); // We want weighted and unweighted plots here. We first have to normalize the weighting to be from 0 to 1. // If there is only a single weight in the sample (which is just weird) then correctly make sure we are set to deal // with things. var firstNonZeroBinValue = weights.Value.FindNonZeroBinValue(); var lastNonZeroBinValue = weights.Value.FindNonZeroBinValue(HistogramUtils.BinSearchOrder.HighestBin); if (firstNonZeroBinValue == lastNonZeroBinValue) { Console.WriteLine($" Sample has events with all one weight ({firstNonZeroBinValue})."); } var scaleing = lastNonZeroBinValue == firstNonZeroBinValue ? 1.0 : 1.0 / (lastNonZeroBinValue - firstNonZeroBinValue); firstNonZeroBinValue = lastNonZeroBinValue == firstNonZeroBinValue ? firstNonZeroBinValue - 1.0 : firstNonZeroBinValue; var mvaWeithedJetStream = source .Select(j => Tuple.Create(j, j.Weight * (mvaValue.Invoke(TrainingUtils.TrainingTreeConverter.Invoke(j)) - firstNonZeroBinValue)*scaleing)); var weithedJetStream = source .Select(j => Tuple.Create(j, j.Weight)); // And run through each plot foreach (var p in plots) { mvaWeithedJetStream .FuturePlot(p, "MVA") .Save(dir); weithedJetStream .FuturePlot(p, "") .Save(dir); } }