How to combine two C++ user defined function in one function with some calculation of both?

Ref: https://root.cern.ch/doc/master/classTF1.html
// Macro myfunc.C

Double_t myfunction(Double_t *x, Double_t *par)

{

Float_t xx =x[0];

Double_t f = TMath::Abs(par[0]*sin(par[1]*xx)/xx);

return f;

}

void myfunc()

{

auto f1 = new TF1(“myfunc”,myfunction,0,10,2);

f1SetParameters(2,1);

f1SetParNames(“constant”,“coefficient”);

f1Draw();

}

void myfit()

{

auto h1 = new TH1F(“h1”,“test”,100,0,10);

h1FillRandom(“myfunc”,20000);

TF1 *f1 = (TF1 *)gROOT->GetFunction(“myfunc”);

f1SetParameters(800,1);

h1Fit(“myfunc”);

}

Can I add myfunction2 and then create “auto f1= new TF1(“myfunc”, myfunc + myfunc2, 0, 10, 2)” ?

Example exists in this version below , but not in c++ user defined functions?

{

auto fcos = new TF1 (“fcos”, “[0]*cos(x)”, 0., 10.);

fcos->SetParNames( “cos”);

fcos->SetParameter( 0, 1.1);

auto fsin = new TF1 (“fsin”, “[0]*sin(x)”, 0., 10.);

fsin->SetParNames( “sin”);

fsin->SetParameter( 0, 2.1);

auto fsincos = new TF1 (“fsc”, “fcos+fsin”);

auto fs2 = new TF1 (“fs2”, “fsc+fsc”);

}

Hi,

Thanks for the post.
I think I understand that you would like to build a TF1 wrapping the sum of two arbitrary C++ functions (please correct me if I am wrong).
If that’s what you want, it’s certainly possible, and very easy if the two functions are known to the interpreter. Below an example:

TF1 f("f", "cosh(x)+sinh(x)",-1,1);
f.Draw()

Results in

I hope this helps.

Best,
D

I mean combination of 2 user defined functions with variable and parameters?

@Danilo

I asked if this is possible: Can I add myfunction2 and then create “auto f1= new TF1(“myfunc”, myfunc + myfunc2, 0, 10, 2)” ?

I think I found an example.

Hi,

Thanks for the clarification. The answer is yes. Minimal snipped to show the functionality:

TF1 a("f1", "cos(x)", 0., 10.);
TF1 b("f2", "x+1", 0., 10.);
TF1 c("f3", "f1(x)+f2(x)", 0., 10.);
c.Draw();

I hope this gets you started.

Cheers,
D

Thanks. I see my mistake now. Instead of calling the function by name without quotation mark, we need to call it like “f1(x) + f2(x)” .

Let me play around for a bit.

When I type like yours, I got empty canvas. However, I got it right if I type like below. Why is that?

TCanvas c1 = new TCanvas(“c1”, “Combined Functions”, 800, 600);
c1->cd();
TF1
f1 = new TF1(“f1”, “cos(x)”, 0., 10.);
TF1* f2 = new TF1(“f2”, “x+1”, 0., 10.);
TF1* f3 = new TF1(“f3”, “f1(x)+f2(x)”, 0., 10.);
f3->Draw();

Because if a, b, and c are allocated on the stack, they will be destroyed as soon as these TF1’s go out of scope.

Why this code doesn’t scale?

#include <TF1.h>
#include <TCanvas.h>
#include <TMath.h>

// Define the standalone function
double myFunction(double* x, double* params) {
return params[0] * TMath::Sin(x[0]);
}

void CombineFunctions4(){ //copyAndScaleFunction() {
// Create the original TF1 object with the standalone function
TF1* originalFunction = new TF1(“originalFunction”, myFunction, 0, 10, 1);
originalFunction->SetParameter(0, 1.); // Set the initial parameter

// Copy the TF1 object
TF1* copiedFunction = (TF1*)originalFunction->Clone("copiedFunction");

// Scale the copied function by a factor of 10
copiedFunction->SetParameter(0, 10. * copiedFunction->GetParameter(0));

// Print the original and scaled functions
originalFunction->Print();
copiedFunction->Print();

// Draw the functions
TCanvas* canvas = new TCanvas("canvas", "Function Copy and Scale Example", 800, 600);
originalFunction->SetLineColor(kRed);
originalFunction->Draw();
copiedFunction->SetLineColor(kBlue);
copiedFunction->Draw("SAME");

}

@Danilo

I have a user defined c++ function with parameters.

double f2(double *x,double *par){
return x[0]*par[0]*par[1]*30. ;
}

TF1* f1 = new TF1(“f1”, f2, 0. , 1000. , 2);
f1->SetNpx(50000.);
f1->FixParameter(0,3. );
f1->FixParameter(1,4. );
double Scaling = 10. ;

TF1*f3 = new TF1("f3", "Scaling* f1(x)", 0. , 1000. );
f3->SetNpx(50000.);

f1-Draw();
f3->Draw(“same”);

HOW TO FIX THIS CODE?

This can’t work. Try the following instead:

double Scaling = 10. ;
TF1* f3 = new TF1("f3", "[0]* f1(x)", 0. , 1000. );
f3->SetParameter(0, Scaling);

@yus
What about the number of parameters carried from f1?
f1 is defined with 2 parameters, but we haven’t stated any parameter for f3 at all.

That I don’t know for sure. Maybe f3 defined this way already “knows” that both parameters of f1 were already fixed…

@Danilo
With same logic :
If STP_PDTA is a user defined c++ function like :

double STP_PDTA(double *x,double *par){

}

what is wrong with this bit of the code below:

f_STP_Proton = new TF1("f_STP_Proton", STP_PDTA , min_Limit, max_Limit,6); //set up parameters
//***** set up parameters*****************************************************************
double Scaling = 10.;

f_STP_Proton->SetNpx(50000.);
f_STP_Proton->FixParameter(0,RME_proton );
f_STP_Proton->FixParameter(1,z_proton ); // z=1 for , e, positron, p, d, t, z=2 for alpha
f_STP_Proton->FixParameter(2,RME_e );
f_STP_Proton->FixParameter(3,N_medium );
f_STP_Proton->FixParameter(4,Z_medium );
f_STP_Proton->FixParameter(5,MEP_medium );

f_STP_Proton->Draw("");
TF1* f2 = new TF1("f2", "[0]*f_STP_Proton(x)" , min_Limit, max_Limit,1); //HOW TO FIX HERE, THE NEW SCALED FUNCTION????????????
f2->SetParameter(0,Scaling);
f2->SetLineColor(kBlack);
f2->Draw("same");

Hi,

What is exactly the problem?

Cheers,
D

Hi,
My codes are usually long codes with headers, function definitions and macros are all in separate files, so I don’t wanna post it all to create a mess here.

The problem is : Error in TFormula::Eval: Formula is invalid and not ready to execute

To simply it , I post here a part of it after I juggled with it many times with failure.
I don’t post the STP_PDTA function with 6 parameters to avoid the mass. It’s working anyways.

double STP_PDTA(double *x,double *par){ …}

double min_Limit= 10. ;
double max_Limit= 1.e2 ;

f_STP_Proton = new TF1("f_STP_Proton", STP_PDTA , min_Limit, max_Limit,6); //set up parameters
//***** set up parameters*****************************************************************
double Scaling = 10.;

f_STP_Proton->SetNpx(50000.);
f_STP_Proton->FixParameter(0,RME_proton );
f_STP_Proton->FixParameter(1,z_proton ); // z=1 for , e, positron, p, d, t, z=2 for alpha
f_STP_Proton->FixParameter(2,RME_e );
f_STP_Proton->FixParameter(3,N_medium );
f_STP_Proton->FixParameter(4,Z_medium );
f_STP_Proton->FixParameter(5,MEP_medium );

f_STP_Proton->Draw("");
TF1* f2 = new TF1("f2", "[0]*f_STP_Proton(x)" , min_Limit, max_Limit,1);
f2->SetNpx(50000.);
f2->SetParameter(0,Scaling);
f2->SetLineColor(kBlack);
f2->Draw("same");

I assume the constructor for f2 function is not designed this way. All I want is to scale the “double STP_PDTA(double *x,double *par){ …}”. function I created with parameters.