User defined functions fit over multi range

Dear Root Talk,

I am trying to fit an exponential over two ranges following the User’s Guide. The only difference is I don’t use the built in “expo” (which does work for this case). Instead I defined my own, yet I get an error message when trying to run the macro:

Error in : can not find any function at the address 0x337fbe0. This function requested for Fit1
Error in : can not find any function at the address 0x337fbe0. This function requested for Fit2
Error in : Bad numerical expression : “fitup(0)”

The relevant code would be:

Double_t par[6];

TF1 *fitup = new TF1("fitup", "[0]*exp(-1*20e-9*x/[1])+[2]");
fitup->SetParameters(155, 2e-6, 1);

TF1 *g1 = new TF1("Fit1", fitup,20,28, 3);
TF1 *g2 = new TF1("Fit2", fitup,35,300, 3);

total = new TF1("mstotal","fitup(0)+fitup(3)",20,306);

histup->Fit(g1,"R");
histup->Fit(g2,"R+");

g1->GetParameters(&par[0]);
g2->GetParameters(&par[3]);

total->SetParameters(par);
 
histup->Fit(total,"R+");

Any thoughts on what I am doing wrong…

Thanks[/code]

Change your code as shown in the tutorial FittingDemo.C (see below)

Rene

[code]Double_t fitf(Double_t *x, Double_t par) {
return par[0]exp(-120e-9
x[0]/par[1])+par[2];
}
Double_t ftotal(Double_t *x, Double_t *par) {
return fitf(x,par) + fitf(x,&par[3]);
}
void myfit() {
Double_t par[6];

TF1 *fitup = new TF1(“fitup”, fitf,20,300,3);
fitup->SetParameters(155, 2e-6, 1);

TF1 *g1 = new TF1(“Fit1”, fitf,20,28, 3);
TF1 *g2 = new TF1(“Fit2”, fitf,35,300, 3);

total = new TF1(“mstotal”,ftotal,20,306,6);

histup->Fit(g1,“R”);
histup->Fit(g2,“R+”);

g1->GetParameters(&par[0]);
g2->GetParameters(&par[3]);

total->SetParameters(par);

histup->Fit(total,“R+”);
}
[/code]

Thank you :slight_smile:

I was starting to work on that but was getting so many error messages that way as well…

I get the following error message when using the above code:

If I remove /par[1] and make the appropriate modifications then the code works.

What am I doing wrong?

Just a guess but maybe when root varies your par[1] during the fit it becomes zero and you get the mentioned division by zero. I see 2 possibilities to avoid this:

  1. Define your par[1] to be the inverse of your original par[1] and change your code to make a multiplication instead of a division.

  2. Use the TF1::SetParLimits function to limit the range of your par[1] to positive numbers excluding zero (if this would be a valid choice for your special parameter).

Cheers, Mathias

I finally got some “quit time” to sit down and do the data analysis myself - I am teaching a particle physics lab for undergrads. and they are looking at the lifetime of muons.

The above suggestions helped a lot - the fit works. Although I have come across two interesting problems that I need some assistance on:

1:

The fit panel with the statistics in them only shows me the relevant data for the first fit I do - not the final total fit. What command am I missing?

2:

The goodness of fit is actually still taking the spike into account when it does its calculation, even though I am fitting “over” it.

To see what I mean I wrote a macro with the relevant code (see attachments) - I removed the spike from the data by just setting the bin values to “reasonable” values. If the goodness of fit didn’t take the spike region into account then the ChiSq/NDF shouldn’t change - yet it does!

Finally, I was wanting to use TH1F::DrawCopy() in order to copy the histogram into a new one without having the fits move with it, but I couldn’t get it to work. In the end I just created two histograms. How do I avoid doing this?

On a side note - for those who are curious: the spike is due to after pulsing of the PMT’s.

Thanks for all the help :slight_smile:
myfit2.cpp (2.44 KB)
spike_data.root (130 KB)

Try to understand what I did in the file in attachement

Rene
myfit2.cpp (3.29 KB)

Thank you so much for taking the time to help with this question.

I understand what you have done.

One last question: should I be worried about this message I get for the total fit?

add the fit option “E” to fit with the Minos algorithm following the standard Migrad, ie
replace
histup2->Fit(total,“R+”);
by
histup2->Fit(total,“RE+”;

Rene

Thanks for the prompt reply.

I tried that and am still getting the message.

There was a minor bug in the code:

Double_t ftotal(Double_t *x, Double_t *par) 
{ 
   if (reject && x[0] > 28 && x[0] < 35) {
      TF1::RejectPoint();
      return 0;
   }
  return fitf(x,par) + fitf(x,&par[4]); 
} 

&par[4] should actually be &par[2].

Thanks again for all the help.

I do have one last small question:

Why are you changing the range of the total fit?

Fit1’s range is from 20 to 28
Fit2’s range is from 35 to 300

But totalfit is from 20 to 306.

I changed it to go from 20 to 300 and did not notice a difference in the results - am I missing something?

Thanks.