Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-10-30 08:34:03

0001 #ifndef LFHCAL_FIT_CURVE_DRAWING_H
0002 #define LFHCAL_FIT_CURVE_DRAWING_H
0003 
0004 #include <algorithm>
0005 #include <cmath>
0006 #include <stdexcept>
0007 #include <string>
0008 #include <TF1.h>
0009 #include <TGraph.h>
0010 #include <TError.h>
0011 
0012 namespace lfhcal {
0013 
0014 // Sample the LIVE fitted evaluator. Never Clone()/stream a callback TF1 here:
0015 // a reloaded callback may only evaluate ROOT's saved interpolation table.
0016 // The four Langau parameters are width, MP, area, Gaussian sigma.
0017 inline TGraph SampleMipFit(const TF1& fit, double visibleLow, double visibleHigh) {
0018   const double lo = visibleLow;
0019   const double hi = visibleHigh;
0020   TGraph graph;
0021   graph.SetName((std::string(fit.GetName()) + "_evaluated_curve").c_str());
0022   graph.SetLineColor(fit.GetLineColor());
0023   graph.SetLineStyle(fit.GetLineStyle());
0024   graph.SetLineWidth(fit.GetLineWidth());
0025   if (!(hi > lo)) return graph;
0026   if (fit.GetNpar() < 4 || !std::isfinite(fit.GetParameter(0)) ||
0027       !std::isfinite(fit.GetParameter(3)) || fit.GetParameter(0) <= 0. ||
0028       fit.GetParameter(3) <= 0.)
0029     throw std::runtime_error("invalid Langau widths in fit drawing");
0030   // Resolve both the Landau features and the legacy-100 quadrature ripple.
0031   // Its spacing is 0.1*sigma; when width is small these oscillations are real
0032   // features of the objective, so ROOT's default Npx is not a safe guide.
0033   double step = std::min((hi-lo)/1000., fit.GetParameter(0)/16.);
0034   // The optional seven-parameter fit also contains a narrow pedestal.
0035   if (fit.GetNpar() == 7 && std::isfinite(fit.GetParameter(6)) &&
0036       fit.GetParameter(6) > 0.)
0037     step = std::min(step, fit.GetParameter(6)/16.);
0038   if (fit.GetParameter(0) < .2*fit.GetParameter(3))
0039     step = std::min(step, fit.GetParameter(3)/320.);
0040   const double intervals = std::ceil((hi-lo)/step);
0041   // Bound rendering cost, never silently coarsen a narrow fitted function.
0042   // This existing budget can reject valid narrow-width fits; see FIT_CURVE_DRAWING.md.
0043   if (!std::isfinite(intervals) || intervals > 200000.)
0044     throw std::runtime_error("fit drawing exceeds 200000-interval rendering budget");
0045   const int n = static_cast<int>(intervals);
0046   graph.Set(n+1);
0047   for (int i=0; i<=n; ++i) {
0048     const double x = lo + (hi-lo)*i/n;
0049     const double y = fit.Eval(x);
0050     if (!std::isfinite(y)) throw std::runtime_error("nonfinite fit drawing value");
0051     graph.SetPoint(i,x,y);
0052   }
0053   return graph;
0054 }
0055 
0056 // The evaluated copy belongs to the current pad and is deleted on Clear().
0057 // DrawClone would instead use the selected pad and does not give it ownership.
0058 // The fitted TF1, its evaluation settings and its original range stay intact.
0059 inline TGraph* DrawMipFit(const TF1& fit, double lo, double hi) {
0060   try {
0061     auto* drawn = new TGraph(SampleMipFit(fit,lo,hi));
0062     if (drawn->GetN() == 0) { delete drawn; return nullptr; }
0063     drawn->SetBit(TObject::kCanDelete);
0064     drawn->Draw("L SAME");
0065     return drawn;
0066   } catch (const std::exception& e) {
0067     Warning("DrawMipFit", "%s: %s", fit.GetName(), e.what());
0068     return nullptr;
0069   }
0070 }
0071 
0072 } // namespace lfhcal
0073 #endif