Home | News | Documentation | Download

Create a TF1 from a TH1F

Hi ROOTers,
I am trying to define a function that mirrors an histogram, returning for each value x the bin content associated to the interval in which x fells.
I defined the following variable

double converted_1Dhisto(double* vx, TH1F* vh_input)
{

  double x = vx[0];
  TH1F h_input = vh_input[0];

  if (x < h_input.GetBinLowEdge(1) || x > h_input.GetBinLowEdge(h_input.GetNbinsX())+ h_input.GetBinWidth(1))
    return 0.;

  return h_input.GetBinContent(h_input.FindBin(x));
}

but then I don’t know how to define the TF1. All the constructor described on the documentations show TF1 with parameters that are all double.
How can I give a TH1F as input to a TF1?
Or alternatively, is there another way to do what I am trying to do?

_ROOT Version: 6.18/00
_Platform: Linux 3.10.0-1127.13.1.el7.x86_64

May be create a C function which will return the content of the histogram corresponding to the x value.

Yes, that’s what I want to do.
But how can I give an histogram in input to a function?

That’s the opposite: you make a C function used by TF1 (see the link I sent) and that function access the histogram.

Ok. But in this example the parameters of the C function are Double_t, so one sets them with the SetParameters command after defining the TF1.
How do I set a parameter that is not a Double_t?

X is the value you will use to retrieve the bin content… you may access the histogram as a global variable. The calling sequence of the function is fixed.

Hi,

The simple way is to create a TF1 from a lambda function, see https://root.cern.ch/doc/master/classTF1.html#F5.
Here is an example

TH1D * h_input  = new TH1D("h_input","dummy input histogram", 100, -5, 5.); 
h_input->FillRandom("gaus")
// create lambda function that captures a reference to the input histogram
auto converted_1Dhisto  = [&](double* vx, double *) {
   double x = vx[0];
   int bin  = h_input->FindBin(x);
   if (bin <= 0 || bin > h_input->GetNbinsX() ) return 0.;
    return h_input->GetBinContent(bin);
};
auto f1 = new TF1("f1", converted_1Dhisto, h_input->GetXaxis()->GetXmin(), h_input->GetXaxis()->GetXmax(), 0); 
f1->Draw(); 

Lorenzo

1 Like

Hi, thanks for the help.
Unluckily the lambda function does not work for a generic histogram but needs to define each time.
I tried a similar aproach shown at the same web page, defining an own class where I read the histogram and convert it to a function. Here below the code

class convert_1Dhisto {
 public:
  TH1F* h_input;
  void set_histo (TH1F* h_in) {                                                                              
    h_input = (TH1F*)h_in;                                                                                                     
    return;
  }
  double Evaluate (double *vx, double *p) {
    double x = vx[0];
    if (x < h_input->GetBinLowEdge(1) || x > h_input->GetBinLowEdge(h_input->GetNbinsX())+ h_input->GetBinWidth(1))
      return 0.;

    return h_input->GetBinContent(h_input->FindBin(x));
  }
};

Now I can load the macro with this definition without errors, but when trying to use it on the command line I get a strange errors. Here is what I do and the error output:

root [0] .L functions.cc
root [1] f = new TFile("../histograms/angularNew_B2D0rho_Kp_r.root"); hInput = (TH1F*)f->Get("h_sig_dE");
root [2] convert_1Dhisto * conv_histo;
root [3] conv_histo->set_histo(hInput)
#0  0x00007f7f2554746c in waitpid () from /lib64/libc.so.6
#1  0x00007f7f254c4f62 in do_system () from /lib64/libc.so.6
#2  0x00007f7f26643f73 in TUnixSystem::Exec (shellcmd=<optimized out>, this=0x9fb3f0) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/unix/src/TUnixSystem.cxx:2106
#3  TUnixSystem::StackTrace (this=0x9fb3f0) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/unix/src/TUnixSystem.cxx:2400
#4  0x00007f7f215643d5 in cling::MultiplexInterpreterCallbacks::PrintStackTrace() () from /cvmfs/belle.cern.ch/el7/externals/v01-08-00/Linux_x86_64/common/root/lib/libCling.so
#5  0x00007f7f21563e2b in cling_runtime_internal_throwIfInvalidPointer () from /cvmfs/belle.cern.ch/el7/externals/v01-08-00/Linux_x86_64/common/root/lib/libCling.so
#6  0x00007f7f2683b05c in ?? ()
#7  0x0000000000a5fd30 in ?? ()
#8  0x00007ffeac20c7a0 in ?? ()
#9  0x00007f7f2683b000 in ?? ()
#10 0x00007f7f215c9479 in cling::IncrementalExecutor::executeWrapper(llvm::StringRef, cling::Value*) const () from /cvmfs/belle.cern.ch/el7/externals/v01-08-00/Linux_x86_64/common/root/lib/libCling.so
#11 0x00007f7f21565c83 in cling::Interpreter::RunFunction(clang::FunctionDecl const*, cling::Value*) () from /cvmfs/belle.cern.ch/el7/externals/v01-08-00/Linux_x86_64/common/root/lib/libCling.so
#12 0x00007f7f2156b7ea in cling::Interpreter::EvaluateInternal(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::CompilationOptions, cling::Value*, cling::Transaction**, unsigned long) () from /cvmfs/belle.cern.ch/el7/externals/v01-08-00/Linux_x86_64/common/root/lib/libCling.so
#13 0x00007f7f2156bdd1 in cling::Interpreter::process(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, cling::Value*, cling::Transaction**, bool) () from /cvmfs/belle.cern.ch/el7/externals/v01-08-00/Linux_x86_64/common/root/lib/libCling.so
#14 0x00007f7f2161c0ad in cling::MetaProcessor::process(llvm::StringRef, cling::Interpreter::CompilationResult&, cling::Value*, bool) () from /cvmfs/belle.cern.ch/el7/externals/v01-08-00/Linux_x86_64/common/root/lib/libCling.so
#15 0x00007f7f214f1dec in HandleInterpreterException (metaProcessor=0x10ad030, input_line=0x18b7420 "#line 1 \"ROOT_prompt_3\"\nconv_histo->set_histo(hInput)", compRes=
0x7ffeac20c674: cling::Interpreter::kSuccess, result=0x7ffeac20c7a0) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/metacling/src/TCling.cxx:2123
#16 0x00007f7f215015e5 in TCling::ProcessLine (this=0xa5c2c0, line=<optimized out>, error=0x7ffeac20cb6c) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/build/Linux_x86_64/common/root/include/TString.h:239
#17 0x00007f7f26513b0c in TApplication::ProcessLine (this=0xa48210, line=<optimized out>, sync=<optimized out>, err=0x7ffeac20cb6c) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/base/src/TApplication.cxx:1026
#18 0x00007f7f269768d2 in TRint::ProcessLineNr (this=0xa48210, filestem=<optimized out>, line=0x1ced220 "conv_histo->set_histo(hInput)", error=0x7ffeac20cb6c) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/build/Linux_x86_64/common/root/include/TString.h:295
#19 0x00007f7f26976c43 in TRint::HandleTermInput (this=0xa48210) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/build/Linux_x86_64/common/root/include/TString.h:239
#20 0x00007f7f26645b4c in TUnixSystem::CheckDescriptors (this=this
entry=0x9fb3f0) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/unix/src/TUnixSystem.cxx:1309
#21 0x00007f7f26647518 in TUnixSystem::DispatchOneEvent (this=0x9fb3f0, pendingOnly=<optimized out>) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/unix/src/TUnixSystem.cxx:1064
#22 0x00007f7f26575d51 in TSystem::InnerLoop (this=0x9fb3f0) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/base/src/TSystem.cxx:362
#23 TSystem::Run (this=0x9fb3f0) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/base/src/TSystem.cxx:362
#24 0x00007f7f26510cbf in TApplication::Run (this=this
entry=0xa48210, retrn=retrn
entry=false) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/base/src/TApplication.cxx:1178
#25 0x00007f7f26978136 in TRint::Run (this=this
entry=0xa48210, retrn=retrn
entry=false) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/core/rint/src/TRint.cxx:460
#26 0x000000000040112a in main (argc=<optimized out>, argv=0x7ffeac20efa8) at /cvmfs/belle.cern.ch/el7/externals/v01-08-00/src/root/main/src/rmain.cxx:30
Error in <HandleInterpreterException>: Trying to dereference null pointer or trying to call routine taking non-null arguments.
Execution of your code was aborted.
ROOT_prompt_3:1:1: warning: null passed to a callee that requires a non-null argument [-Wnonnull]
conv_histo->set_histo(hInput)
^~~~~~~~~~

Hi,
Yes, creating a class is better and make the solution generic, but you need to create the class.
Do something like :

convert_1Dhisto * conv_histo = new convert_1Dhisto(); 
conv_histo->set_histo(hInput);
auto f1 = new TF1("f1", conv_histo, &convert_1DHisto::Evaluate, hInput->GetXaxis()->GetXmin(), hInput->GetXaxis()->GetXmax(), 0); 

Lorenzo