I was reading TGraph from problem.root with problem.C, clone the graph and fit them.
the problem is that, whenever i perform a Fit, the TGraph that were written to the output file is not accessible (i opened it with the following code and it keep restarting the kernel), but it is OK when i did not perform a fit (it is not possible !!! i want them to be fitted !!!)
fname = "fitted_problem.root"
file = r.TFile(fname)
file.ls()
c = r.TCanvas("c","c",1200,600)
gr = file.Get("gr_x_1667176620.642.78")
gr.SetMarkerStyle(7)
gr.Draw("AP")
c.Draw()
void read_problem(){
auto f = new TFile("fitted_problem.root");
f->ls();
TGraph *gr = (TGraph *)f->Get("gr_x_1667176620.642.78");
gr->Draw("AP");
}
It gives me:
% .x read_problem.C
root [0]
Processing read_problem.C...
TFile** fitted_problem.root
TFile* fitted_problem.root
KEY: TGraph gr_x_1667176620.642.78;5 x vs time (muonID:1667176620.642.78); time [#mus]; x [mm] [current cycle]
KEY: TGraph gr_x_1667176620.642.78;4 x vs time (muonID:1667176620.642.78); time [#mus]; x [mm] [backup cycle]
KEY: TGraph gr_x_1667176620.642.78;3 x vs time (muonID:1667176620.642.78); time [#mus]; x [mm] [backup cycle]
KEY: TGraph gr_x_1667176620.642.78;2 x vs time (muonID:1667176620.642.78); time [#mus]; x [mm] [backup cycle]
KEY: TGraph gr_x_1667176620.642.78;1 x vs time (muonID:1667176620.642.78); time [#mus]; x [mm] [backup cycle]
KEY: TTree tree;1 a tree
Info in <TCanvas::MakeDefCanvas>: created default TCanvas with name c1
input_line_37:2:187: error: expected expression
Double_t TFormula____id15367673592536998465(Double_t *x,Double_t *p){ return p[0]+(p[1]+p[2]*x[0]+p[3]*x[0]*x[0])*TMath::Cos(p[4]*x[0]+p[5])+(p[6]+p[7]*x[0]+p[8]*x[0]*x[0])*TMath::Cos({[#omega_x[0]]}*x[0]+{[#phi_x[0]]}) ; }
^
input_line_38:2:187: error: expected expression
Double_t TFormula____id15367673592536998465(Double_t *x,Double_t *p){ return p[0]+(p[1]+p[2]*x[0]+p[3]*x[0]*x[0])*TMath::Cos(p[4]*x[0]+p[5])+(p[6]+p[7]*x[0]+p[8]*x[0]*x[0])*TMath::Cos({[#omega_x[0]]}*x[0]+{[#phi_x[0]]}) ; }
^
Error in <prepareMethod>: Can't compile function TFormula____id15367673592536998465 prototype with arguments Double_t*,Double_t*
Error in <TFormula::InputFormulaIntoCling>: Error compiling formula expression in Cling
Error in <TFormula::DoEval>: Formula has error and it is not properly initialized
*** Break *** segmentation violation
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[/usr/lib/system/libsystem_c.dylib] __sF (no debug info)
[/Users/couet/git/couet-root-bin/lib/libHist.so] TF1::DoCreateHistogram(double, double, bool) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libHist.so] TF1::Paint(char const*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libHistPainter.so] TGraphPainter::PaintGraphSimple(TGraph*, char const*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libHistPainter.so] TGraphPainter::PaintHelper(TGraph*, char const*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libGpad.so] TPad::PaintModified() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libGpad.so] TCanvas::Update() (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] TCling::ProcessLine(char const*, TInterpreter::EErrorCode*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libCling.so] TCling::ProcessLineSynch(char const*, TInterpreter::EErrorCode*) (no debug info)
[/Users/couet/git/couet-root-bin/lib/libRint.so] TRint::Run(bool) (no debug info)
[/Users/couet/git/couet-root-bin/bin/root.exe] main (no debug info)
[/usr/lib/dyld] start (no debug info)
Root >
ok. i change that line to : TF1* fit_func = new TF1(Form("fit_func_%s",muonID), "[0] + ([1]+[2]*x + [3]*x*x ) * TMath::Cos([4]*x + [5]) + ([6]+[7]*x + [8]*x*x ) * TMath::Cos([9]*x + [10])",ta, tb);
and it still did not worked …
but after that, i found that the problem arose in the SetParName line… i simply cannot set the names of 11 parameters at the same time … (if i remember it correctly, this function only allows us to set up to 10, but can >10 if the function is compiled from a c++ function)
ps: i was doing in python version, thinking that the same applies when i comes to c++ …
now it is clear that the SetParNames that gave the problem, and i dont have idea on WHY it gave problem in this particular use case (sorry I am still too young after using ROOT for 3 years !!!)
The problem is in using the parameter names #omega_{x} and #phi_{x}# as parameter name. x is a special character of TFormula, used to identify the variable and you cannot use then as {x}. if you would just use #omega_x it will work fine. We can probably improve the TFormula parsing for this, but there is also this easy workaround.
Yes, if you defined the TF1 using a C++ function pointer or a functor, this problem is avoided. However, note that when cloning the function or when writing to disk, you will not be able to save the full function formula, but only the function values. This means that you will not be able to use for fitting teh TF1 object after cloning or reading from a file.
so if i use the cloned function to do fitting, i will end up with unexpected behavior am i right ?
also, can you elaborate more on what you meant by “only the function values” ?
Hi,
If you TF1 is created using a C++ function, (not as a string representing t he formula), when you clone or save the function to disk, only the vector of the function values evaluated in a grid will be saved. You can then plot the function afterwards, but not anymore change its parameters.
In this case you would need to re-create a new TF1 object with the corresponding C++ function.