Clarification on `FitResult::GetConfidenceIntervals()` for evaluating the uncertainty of a 2D fit at a given point

Dear ROOT experts,

I am doing an analysis in which I create two-dimensional trigger efficiencies and store both the TEfficiency and TH2F from TEfficiency::CreateHistogram() in a ROOT file. I can successfully fit the histogram with a parametric TF2, but now I’d like to be able to evaluate the function at a given point and recover f(X,Y;p0,p1,p2,...) = value +/- error. The fit itself looks like this:

I could write a method which computes the function uncertainty from the covariance matrix, but while researching whether this was implemented already in vanilla ROOT (instead of having to use RooFit), I came across this old forum post, which indicated that the FitResult::GetConfidenceIntervals() method could help. However, for a 2D function I’m somewhat unsure as to how one should interpret the results of this method. I’ve attached a code snippet and give its output below to help illustrate my confusion.

void evalFuncUncertainty() {
    // Open file, get TEfficiency, create TH2 which we'll fit
    TFile* f = new TFile("THtrigger2D_HT750_18.root","READ");
    TEfficiency* eff = (TEfficiency*)f->Get("Pretag");
    TH2F* h = (TH2F*)eff->CreateHistogram();
    // Create function, set decent starting parameters
    TF2* func = new TF2("eff_func","1-[0]/10*exp([1]*y/1000)*exp([2]*x/200)",60,260,800,2600);
    func->SetParameter(0,550);
    func->SetParameter(1,-5);
    func->SetParameter(2,-1);
    // Fit function to histogram, get TFitResultPtr
    TFitResultPtr r = (TFitResultPtr)h->Fit(func,"SER");
    // Evaluate fit results
    printf("The fit uses %d X points and %d Y points\n",func->GetNpx(),func->GetNpy());
    printf("The fit uses %d fit points\n",func->GetNumberFitPoints());
    // Now, check that everything makes sense with the covariance matrix
    printf("The covariance matrix is given by:\n");
    r->GetCovarianceMatrix().Print();
    // Check that covariance matrix is as expected
    float par0Cov = r->CovMatrix(0,0);
    float SqrtPar0Cov = TMath::Sqrt(par0Cov);
    float par0err = func->GetParError(0);
    printf("Covariance & uncertainty checks:\n\tCov[p0,p0] = %f\n\tSqrt(Cov[p0,p0]) = %f\n\tp0 error = %f\n\n",par0Cov,SqrtPar0Cov,par0err);
    // Now try to get uncertainty at a given point straight from the fit
    std::vector<double> CL = r->GetConfidenceIntervals(0.683,true);
    printf("The confidence levels were evaluated at %u points\n", CL.size());
}

The output is as follows:

Processing evalFuncUncertainty.C...
Info in <TCanvas::MakeDefCanvas>:  created default TCanvas with name c1
 FCN=0.752307 FROM MINOS     STATUS=SUCCESSFUL    460 CALLS        1789 TOTAL
                     EDM=6.55355e-07    STRATEGY= 1      ERROR MATRIX ACCURATE

  EXT PARAMETER                                   STEP         FIRST
  NO.   NAME      VALUE            ERROR          SIZE      DERIVATIVE
   1  p0           5.29474e+02   8.94639e+03  -2.10905e-02  -1.85028e-05
   2  p1          -5.85658e+00   1.90164e+01   5.90370e-02   5.97904e-05
   3  p2          -1.03439e+00   3.59615e+00   3.59615e+00  -4.28703e-07
The fit uses 30 X points and 30 Y points
The fit uses 357 fit points
The covariance matrix is given by:

3x3 matrix is as follows

     |      0    |      1    |      2    |
--------------------------------------------
   0 |  8.004e+07  -1.683e+05       -1206
   1 | -1.683e+05       361.6      -6.497
   2 |      -1206      -6.497       12.93

Covariance & uncertainty checks:
        Cov[p0,p0] = 80037840.000000
        Sqrt(Cov[p0,p0]) = 8946.386719
        p0 error = 8946.386719

The confidence levels were evaluated at 357 points

The 2D fit is using its default 30x30 points in the fit, but TF2::GetNumberFitPoints() returns only 357 points. These 357 points are clearly the ones at which the confidence levels are being evaluated, but several things are unclear to me:

  1. How would one determine to which (x,y) points in the TH2 the points whose confidence intervals were evaluated in the fitted function correspond?
  2. Why are all 30x30=900 points in the fit not evaluated? My thought was perhaps empty bins in the histogram are not evaluated, but there were not enough empty bins in the histogram to explain the 543 non-evaluated points.
  3. The 2D TEfficiency has asymmetric errors. Are these errors propagated to the TH2 created via TEfficiency::CreateHistogram() and should I therefore call FitResult::GetConfidenceIntervals() with the argument norm=false?

Apologies for the long post, but I hope my questions are clear. Thank you very much in advance for any insights and explanations.

ROOT Version: 6.24/04


I think @moneta can help with this

Hi,

The points at which the confidence interval is evaluated are those used in the fit. These are then centres of the histograms excluding the empty ones, since you are doing a simple fit of a TH2 histogram.
If you want to inspect those points, you can use the function FitResult::FittedBinData and from the BinData class you can retrieve the bin x and y values and the histogram weight.

If you want to evaluate at some specific points, lets say for point1 = {10,10} and point2={20,20}, you need to use this signature of FitResult::GetConfidenceInterval:

double ci[2];
double points = {10,10 ,    // x,y first point
                           20,20 };  //x,y second point
int stride1 = 2;   
int stride2 = 1;
r->GetConfidenceIntervals(2, stride1, stride2, points, ci, 0.683, true);
std::cout << "The confidence level for x = 10 , y = 10 is " << ci[0] << std::endl;
std::cout << "The confidence level for x = 20 , y = 20 is " << ci[1] << std::endl;

For your last question, the asymmetric errors are not propagated to the TH2.
The correct way is to fit directly the TEfficiency object doing a likelihood fit, which takes into account the binomial distribution in each bin.
Otherwise you could convert to a TGraphAsymmErrors and then fit that object.

If you have a good estimation of the errors you should use the flag norm=false, which is the default.
And do not use norm=true when doing the likelihood fit.

Best regards

Lorenzo

Dear Lorenzo,

Thank you very much for the comprehensive response, it’s much clearer to me what the fitter is doing and how one would use the alternate constructor for FitResult::GetConfidenceInterval.

I also see that trying to fit the TH2 will not produce the correct results. However, in trying to implement your suggestion of fitting the TEfficiency or TGraphAsymmErrors instead I’ve run into several issues with each method - perhaps you would be able to provide further clarification.

Method 1: Fitting the TEfficiency directly
It appears that the TEfficiency’s internal TBinomialEfficiencyFitter::Fit() method accepts only TF1s. Attempting to fit the TEfficiency with a TF2 results in a segfault (understandably). Is there an existing method for directly fitting a TEfficiency with a 2D function?

Method 2: Converting TEfficiency → TGraphAsymmErrors and then fitting
I did some brief testing in pyROOT and discovered that this method will also not work because I am not using a dim=1 TEfficiency object:

The reason this method fails is that, upon the first call to TEfficiency::Paint() the TEfficiency calls TEfficiency::CreateGraph(), which is not compatible with anything other than dim=1 TEfficiencies:

TGraphAsymmErrors * TEfficiency::CreateGraph(Option_t * opt) const
{
   if (GetDimension() != 1) {
      Error("CreatePaintingGraph","Call this function only for dimension == 1");
      return 0;
   }

   Int_t npoints = fTotalHistogram->GetNbinsX();
   TGraphAsymmErrors * graph = new TGraphAsymmErrors(npoints);
   graph->SetName("eff_graph");
   FillGraph(graph,opt);
 
   return graph;
}

Apologies again for the long response, but would you have any other ideas for fitting this 2-dimensional TEfficiency properly? Any suggestion would be greatly appreciated, I’ll happily do the implementation. One other thought I had was to take 1D projections of the two 2D input histograms to the TEfficiency, then produce 1D TEfficiencies from the slices and fit those… However, since I want to parameterize the two-dimensional efficiency I’m not entirely sure how best to “join” the 1D fits afterwards.

Thanks again for your time!

Best,
Amitav

Hi,

The TEfficiency::Fit for the 2D case it should work, it is maybe not tested for 2D and there is a bug. I will investigate and fix it.

For the TGraphAsymmErrors you should use (from 6.28) the new TGraph2DAsymmErrors class, but also here I suspect is not working properly, because it has not been tested. I will try to fix these two cases tomorrow. If you share your input Efficiency class in a root file, I can test directly in your case

Best regards

Lorenzo

Dear Lorenzo,

Thank you for the quick response and for looking into these bugs. It would be great if the 2D TEfficiency fit could be performed. Attached below is the TEfficiency object I’m using, called Pretag.

THtrigger2D_HT750_18.root (25.8 KB)

Best,
Amitav

Hi,
Thank you for the file.
You should be able to use TEfficiency::Fit passing a TF2, since a TF2 is a derived class of TF1.
If I try this code (e…g. fitting with a constant function), it works for me:

>>> f = ROOT.TFile.Open("THtrigger2D_HT750_18.root")
>>> h = f.Get("Pretag")
>>> f2 = ROOT.TF2("f2","[0]")
>>> f2.SetParameter(0,1)
>>> result = h.Fit(f2,"S")
Info in <TBinomialEfficiencyFitter::result>:  chi2 1008.868336 ndf 0 
>>> result.Print()

****************************************
Minimizer is Minuit / Migrad
MinFCN                    =      504.434
NDf                       =            0
Edm                       =  7.78874e-13
NCalls                    =           37
p0                        =     0.944731   +/-   0.00188174  

If you are having a set fault fitting your function, please let me know

Lorenzo

Hi,

Unfortunately, the same code results in a segfault for me. I’ve copied your code above into a file named segfault.py, and I’ve copied my original code (non-constant TF2) into a C script segfault.C. Both cases segfault due to an invalid free() call…

segfault.py (167 Bytes)

(timber-env) [ammitra@cmslpc151 TopHBoostedAllHad]$ python segfault.py
Info in <TBinomialEfficiencyFitter::result>:  chi2 1008.868336 ndf 0
*** Error in `python': double free or corruption (out): 0x00000000070523a0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x81329)[0x7fc97471b329]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libCore.so(_ZN7TArrayD3SetEiPKd+0x45)[0x7fc9739eead5]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so(_ZN3TF1C2ERKS_+0x254)[0x7fc95f505a24]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so(_ZN11TEfficiency3FitEP3TF1PKc+0xc7)[0x7fc95f4fcc77]
[0x7fc96e696134]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libPyROOT.so(_Z8FastCalllPvS_S_+0x3d9)[0x7fc9745ec3b9]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libPyROOT.so(_ZN5Cppyy5CallOElPvS0_l+0x80)[0x7fc9745ed6d0]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libPyROOT.so(_ZN6PyROOT25TCppObjectByValueExecutor7ExecuteElPvPNS_12TCallContextE+0x3e)[0x7fc9745f083e]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libPyROOT.so(_ZN6PyROOT13TMethodHolder8CallSafeEPvlPNS_12TCallContextE+0x72)[0x7fc9746179f2]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libPyROOT.so(_ZN6PyROOT13TMethodHolder7ExecuteEPvlPNS_12TCallContextE+0x25)[0x7fc974616d15]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libPyROOT.so(_ZN6PyROOT13TMethodHolder4CallERPNS_11ObjectProxyEP7_objectS5_PNS_12TCallContextE+0xe8)[0x7fc9746163d8]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libPyROOT.so(+0x70cd1)[0x7fc9745f6cd1]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libpython2.7.so.1.0(PyObject_Call+0x53)[0x7fc9753db333]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libpython2.7.so.1.0(PyEval_EvalFrameEx+0x408c)[0x7fc975485adc]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libpython2.7.so.1.0(PyEval_EvalCodeEx+0x712)[0x7fc97548b712]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libpython2.7.so.1.0(PyEval_EvalCode+0x19)[0x7fc97548b9a9]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libpython2.7.so.1.0(PyRun_FileExFlags+0x88)[0x7fc9754b0448]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libpython2.7.so.1.0(PyRun_SimpleFileExFlags+0xe3)[0x7fc9754b13c3]
/cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libpython2.7.so.1.0(Py_Main+0x56e)[0x7fc9754c486e]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7fc9746bc555]
python[0x40108e]
======= Memory map: ========
00400000-00401000 r--p 00000000 00:30 283468918376                       /uscms_data/d3/ammitra/TopPhi_analysis/CMSSW_11_1_4/src/timber-env/bin/python
00401000-00402000 r-xp 00001000 00:30 283468918376                       /uscms_data/d3/ammitra/TopPhi_analysis/CMSSW_11_1_4/src/timber-env/bin/python
00402000-00403000 r--p 00002000 00:30 283468918376                       /uscms_data/d3/ammitra/TopPhi_analysis/CMSSW_11_1_4/src/timber-env/bin/python
00403000-00404000 r--p 00002000 00:30 283468918376                       /uscms_data/d3/ammitra/TopPhi_analysis/CMSSW_11_1_4/src/timber-env/bin/python
00404000-00405000 rw-p 00003000 00:30 283468918376                       /uscms_data/d3/ammitra/TopPhi_analysis/CMSSW_11_1_4/src/timber-env/bin/python
01a91000-070d2000 rw-p 00000000 00:00 0                                  [heap]
7fc950000000-7fc950021000 rw-p 00000000 00:00 0
7fc950021000-7fc954000000 ---p 00000000 00:00 0
7fc958000000-7fc958044000 rw-p 00000000 00:00 0
7fc958044000-7fc95c000000 ---p 00000000 00:00 0
7fc95ef25000-7fc95ef31000 r--p 00000000 00:35 123061888                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/external/freetype/2.10.0-bcolbf2/lib/libfreetype.so.6.17.0
7fc95ef31000-7fc95efa0000 r-xp 0000c000 00:35 123061888                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/external/freetype/2.10.0-bcolbf2/lib/libfreetype.so.6.17.0
7fc95efa0000-7fc95efc9000 r--p 0007b000 00:35 123061888                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/external/freetype/2.10.0-bcolbf2/lib/libfreetype.so.6.17.0
7fc95efc9000-7fc95efca000 ---p 000a4000 00:35 123061888                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/external/freetype/2.10.0-bcolbf2/lib/libfreetype.so.6.17.0
7fc95efca000-7fc95efd1000 r--p 000a4000 00:35 123061888                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/external/freetype/2.10.0-bcolbf2/lib/libfreetype.so.6.17.0
7fc95efd1000-7fc95efd2000 rw-p 000ab000 00:35 123061888                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/external/freetype/2.10.0-bcolbf2/lib/libfreetype.so.6.17.0
7fc95efd2000-7fc95f03e000 r--p 00000000 00:35 122142499                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libGraf.so
7fc95f03e000-7fc95f0f0000 r-xp 0006c000 00:35 122142499                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libGraf.so
7fc95f0f0000-7fc95f11f000 r--p 0011e000 00:35 122142499                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libGraf.so
7fc95f11f000-7fc95f12d000 r--p 0014c000 00:35 122142499                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libGraf.so
7fc95f12d000-7fc95f131000 rw-p 0015a000 00:35 122142499                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libGraf.so
7fc95f131000-7fc95f13f000 rw-p 00000000 00:00 0
7fc95f13f000-7fc95f15b000 r--p 00000000 00:35 122142738                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libMinuit.so
7fc95f15b000-7fc95f197000 r-xp 0001c000 00:35 122142738                  /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libMinuit.soAborted

and
segfault.C (598 Bytes)

(timber-env) [ammitra@cmslpc151 TopHBoostedAllHad]$ root -l segfault.C
root [0]
Processing segfault.C...
Info in <TBinomialEfficiencyFitter::result>:  chi2 13607999999999993693082719029821440.000000 ndf 0

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================
#0  0x00007ff2d043860c in waitpid () from /lib64/libc.so.6
#1  0x00007ff2d03b5f62 in do_system () from /lib64/libc.so.6
#2  0x00007ff2d0f403c3 in TUnixSystem::StackTrace() () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libCore.so
#3  0x00007ff2d0f42c14 in TUnixSystem::DispatchSignals(ESignals) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libCore.so
#4  <signal handler called>
#5  0x00007ff2d03f8b7c in free () from /lib64/libc.so.6
#6  0x00007ff2d0e91ad5 in TArrayD::Set(int, double const*) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libCore.so
#7  0x00007ff2bdc46a24 in TF1::TF1(TF1 const&) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so
#8  0x00007ff2bdc3dc77 in TEfficiency::Fit(TF1*, char const*) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so
#9  0x00007ff2d1126325 in ?? ()
#10 0x0000000000000000 in ?? ()
===========================================================


The lines below might hint at the cause of the crash.
You may get help by asking at the ROOT forum http://root.cern.ch/forum
Only if you are really convinced it is a bug in ROOT then please submit a
report at http://root.cern.ch/bugs Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#5  0x00007ff2d03f8b7c in free () from /lib64/libc.so.6
#6  0x00007ff2d0e91ad5 in TArrayD::Set(int, double const*) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libCore.so
#7  0x00007ff2bdc46a24 in TF1::TF1(TF1 const&) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so
#8  0x00007ff2bdc3dc77 in TEfficiency::Fit(TF1*, char const*) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so
#9  0x00007ff2d1126325 in ?? ()
#10 0x0000000000000000 in ?? ()
===========================================================

This was tested on the LPC cluster at Fermilab using
ROOT Version: 6.20/07 Built for linuxx8664gcc

and on my local computer using
ROOT Version: 6.24/04 Built for linuxx8664gcc

Best,
Amitav

Edit: here’s a more detailed stack trace of the segfault from segfault.py, in case it helps. It’s essentially identical to that of the segfault from segfault.C:

(timber-env) [ammitra@cmslpc151 TopHBoostedAllHad]$ python segfault.py
Info in <TBinomialEfficiencyFitter::result>:  chi2 1008.868336 ndf 0

 *** Break *** segmentation violation



===========================================================
There was a crash.
This is the entire stack trace of all threads:
===========================================================

Thread 2 (Thread 0x7f9aa48c9700 (LWP 17775)):
#0  0x00007f9ab9901b3b in do_futex_wait.constprop () from /lib64/libpthread.so.0
#1  0x00007f9ab9901bcf in __new_sem_wait_slow.constprop.0 () from /lib64/libpthread.so.0
#2  0x00007f9ab9901c6b in sem_wait

GLIBC_2.2.5 () from /lib64/libpthread.so.0
#3  0x00007f9ab9c454b8 in PyThread_acquire_lock (lock=lock
entry=0x44aeb30, waitflag=waitflag
entry=1) at Python/thread_pthread.h:324
#4  0x00007f9ab9c03e86 in PyEval_RestoreThread (tstate=tstate
entry=0x5b5af60) at Python/ceval.c:359
#5  0x00007f9ab2e40d36 in floatsleep (secs=<optimized out>) at /data/cmsbld/jenkins/workspace/auto-builds/CMSSW_11_1_0_pre7-slc7_amd64_gcc820/build/CMSSW_11_1_0_pre7-build/BUILD/slc7_amd64_gcc820/external/python/2.7.15-bcolbf2/python-2.7.15/Modules/timemodule.c:1057
#6  time_sleep (self=<optimized out>, args=<optimized out>) at /data/cmsbld/jenkins/workspace/auto-builds/CMSSW_11_1_0_pre7-slc7_amd64_gcc820/build/CMSSW_11_1_0_pre7-build/BUILD/slc7_amd64_gcc820/external/python/2.7.15-bcolbf2/python-2.7.15/Modules/timemodule.c:206
#7  0x00007f9ab9c0ce18 in call_function (oparg=<optimized out>, pp_stack=0x7f9aa48c85d8) at Python/ceval.c:4372
#8  PyEval_EvalFrameEx (f=f
entry=0x7f9aa4c025f0, throwflag=throwflag
entry=0) at Python/ceval.c:3009
#9  0x00007f9ab9c0e712 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=locals
entry=0x0, args=args
entry=0x7f9aa4bfa6a8, argcount=<optimized out>, kws=kws
entry=0x7f9ab9ec8068, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:3604
#10 0x00007f9ab9b87d06 in function_call (func=0x7f9aa4c58e60, arg=0x7f9aa4bfa690, kw=0x7f9aa4bfb5c8) at Objects/funcobject.c:523
#11 0x00007f9ab9b5e333 in PyObject_Call (func=func
entry=0x7f9aa4c58e60, arg=arg
entry=0x7f9aa4bfa690, kw=kw
entry=0x7f9aa4bfb5c8) at Objects/abstract.c:2547
#12 0x00007f9ab9c05aac in ext_do_call (nk=<optimized out>, na=<optimized out>, flags=<optimized out>, pp_stack=0x7f9aa48c8850, func=0x7f9aa4c58e60) at Python/ceval.c:4686
#13 PyEval_EvalFrameEx (f=f
entry=0x7f9aa4be3b00, throwflag=throwflag
entry=0) at Python/ceval.c:3048
#14 0x00007f9ab9c0be41 in fast_function (nk=<optimized out>, na=<optimized out>, n=1, pp_stack=0x7f9aa48c8958, func=0x7f9aa4bf31b8) at Python/ceval.c:4457
#15 call_function (oparg=<optimized out>, pp_stack=0x7f9aa48c8958) at Python/ceval.c:4392
#16 PyEval_EvalFrameEx (f=f
entry=0x7f9aa0000910, throwflag=throwflag
entry=0) at Python/ceval.c:3009
#17 0x00007f9ab9c0be41 in fast_function (nk=<optimized out>, na=<optimized out>, n=1, pp_stack=0x7f9aa48c8a68, func=0x7f9aa4bf3320) at Python/ceval.c:4457
#18 call_function (oparg=<optimized out>, pp_stack=0x7f9aa48c8a68) at Python/ceval.c:4392
#19 PyEval_EvalFrameEx (f=f
entry=0x7f9aa4c063d0, throwflag=throwflag
entry=0) at Python/ceval.c:3009
#20 0x00007f9ab9c0e712 in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=locals
entry=0x0, args=args
entry=0x7f9aa4bfa668, argcount=<optimized out>, kws=kws
entry=0x0, kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:3604
#21 0x00007f9ab9b87c4c in function_call (func=0x7f9aa4bf3230, arg=0x7f9aa4bfa650, kw=0x0) at Objects/funcobject.c:523
#22 0x00007f9ab9b5e333 in PyObject_Call (func=func
entry=0x7f9aa4bf3230, arg=arg
entry=0x7f9aa4bfa650, kw=kw
entry=0x0) at Objects/abstract.c:2547
#23 0x00007f9ab9b6c25c in instancemethod_call (func=0x7f9aa4bf3230, arg=0x7f9aa4bfa650, kw=0x0) at Objects/classobject.c:2600
#24 0x00007f9ab9b5e333 in PyObject_Call (func=func
entry=0x7f9ab8df1500, arg=arg
entry=0x7f9ab9ec8050, kw=0x0) at Objects/abstract.c:2547
#25 0x00007f9ab9c04513 in PyEval_CallObjectWithKeywords (func=0x7f9ab8df1500, arg=0x7f9ab9ec8050, kw=<optimized out>) at Python/ceval.c:4241
#26 0x00007f9ab9c49e02 in t_bootstrap (boot_raw=0x5b59430) at ./Modules/threadmodule.c:620
#27 0x00007f9ab98fbea5 in start_thread () from /lib64/libpthread.so.0
#28 0x00007f9ab8f1bb0d in clone () from /lib64/libc.so.6

Thread 1 (Thread 0x7f9ab9f08740 (LWP 17751)):
#0  0x00007f9ab8ee2659 in waitpid () from /lib64/libc.so.6
#1  0x00007f9ab8e5ff62 in do_system () from /lib64/libc.so.6
#2  0x00007f9ab8e60311 in system () from /lib64/libc.so.6
#3  0x00007f9ab82203c3 in TUnixSystem::StackTrace() () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libCore.so
#4  0x00007f9ab8222c14 in TUnixSystem::DispatchSignals(ESignals) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libCore.so
#5  <signal handler called>
#6  0x00007f9ab8ea2b7c in free () from /lib64/libc.so.6
#7  0x00007f9ab8171ad5 in TArrayD::Set(int, double const*) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libCore.so
#8  0x00007f9a9fbbfa24 in TF1::TF1(TF1 const&) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so
#9  0x00007f9a9fbb6c77 in TEfficiency::Fit(TF1*, char const*) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so
#10 0x00007f9ab2e1b134 in ?? ()
#11 0x0000000000000000 in ?? ()
===========================================================


The lines below might hint at the cause of the crash.
You may get help by asking at the ROOT forum http://root.cern.ch/forum
Only if you are really convinced it is a bug in ROOT then please submit a
report at http://root.cern.ch/bugs Please post the ENTIRE stack trace
from above as an attachment in addition to anything else
that might help us fixing this issue.
===========================================================
#6  0x00007f9ab8ea2b7c in free () from /lib64/libc.so.6
#7  0x00007f9ab8171ad5 in TArrayD::Set(int, double const*) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/cms/cmssw/CMSSW_11_1_4/external/slc7_amd64_gcc820/lib/libCore.so
#8  0x00007f9a9fbbfa24 in TF1::TF1(TF1 const&) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so
#9  0x00007f9a9fbb6c77 in TEfficiency::Fit(TF1*, char const*) () from /cvmfs/cms.cern.ch/slc7_amd64_gcc820/lcg/root/6.20.06-bcolbf/lib/libHist.so
#10 0x00007f9ab2e1b134 in ?? ()
#11 0x0000000000000000 in ?? ()
===========================================================


Traceback (most recent call last):
  File "segfault.py", line 7, in <module>
    result = h.Fit(f2,"S")
SystemError: TFitResultPtr TEfficiency::Fit(TF1* f1, const char* opt = "") =>
    problem in C++; program state has been reset

I see, I think there is a problem with old versions causing the crash.
If you can upgrade to the latest ROOT 6.28 you should be able to have a working fit

Lorenzo

I can confirm that version > 6.28 are not having the crash thanks to this PR, Properly use `Copy(TObject &)` methods in `hist` classes by linev · Pull Request #10942 · root-project/root · GitHub.
The problem is caused by a wrong copy operation of the fitted function after fitting in TEfficiency::Fit.

Ah, that makes sense. Thank you very much for looking into this for me - I appreciate it. With this understood now, I will move my fitting step to ROOT version > 6.28 and proceed with your earlier suggestion for evaluating the 2D function at specific points.

All the best,
Amitav

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.