51 class TF1Convolution_EvalWrapper
53 std::shared_ptr < TF1 > fFunction1;
54 std::shared_ptr < TF1 > fFunction2;
59 TF1Convolution_EvalWrapper(std::shared_ptr<TF1> &
f1 , std::shared_ptr<TF1> &
f2,
Double_t t)
60 : fFunction1(f1), fFunction2(f2), fT0(t)
69 return fFunction1->EvalPar(xx,
nullptr) * fFunction2->EvalPar(xx+1,
nullptr);
79 TF1 * fnew1 = (
TF1*) function1->IsA()->New();
80 function1->
Copy(*fnew1);
81 fFunction1 = std::shared_ptr<TF1>(fnew1);
84 TF1 * fnew2 = (
TF1*) function2->IsA()->New();
85 function2->
Copy(*fnew2);
86 fFunction2 = std::shared_ptr<TF1>(fnew2);
88 if (fFunction1.get() ==
nullptr|| fFunction2.get() ==
nullptr)
89 Fatal(
"InitializeDataMembers",
"Invalid functions - Abort");
92 fFunction1->GetRange(fXmin, fXmax);
96 fNofParams1 = fFunction1->GetNpar();
97 fNofParams2 = fFunction2->GetNpar();
98 fParams1 = std::vector<Double_t>(fNofParams1);
99 fParams2 = std::vector<Double_t>(fNofParams2);
100 fCstIndex = fFunction2-> GetParNumber(
"Constant");
107 fParNames.reserve( fNofParams1 + fNofParams2);
108 for (
int i=0; i<fNofParams1; i++)
110 fParams1[i] = fFunction1 -> GetParameter(i);
111 fParNames.push_back(fFunction1 -> GetParName(i) );
113 for (
int i=0; i<fNofParams2; i++)
115 fParams2[i] = fFunction2 -> GetParameter(i);
116 if (i != fCstIndex) fParNames.push_back(fFunction2 -> GetParName(i) );
120 fFunction2 -> FixParameter(fCstIndex,1.);
121 fNofParams2 = fNofParams2-1;
122 fParams2.erase(fParams2.begin()+fCstIndex);
130 InitializeDataMembers(function1,function2, useFFT);
138 InitializeDataMembers(function1, function2,useFFT);
153 std::vector < TString > stringarray(2);
154 std::vector < TF1* > funcarray(2);
155 for (
int i=0; i<2; i++)
157 stringarray[i] = ((
TObjString*)((*objarray)[i])) -> GetString();
158 stringarray[i].ReplaceAll(
" ",
"");
159 funcarray[i] = (
TF1*)(
gROOT -> GetListOfFunctions() -> FindObject(stringarray[i]));
161 if (funcarray[i] ==
nullptr) {
164 Error(
"TF1Convolution",
"Invalid formula : %s",stringarray[i].
Data() );
166 fFunction1 = std::shared_ptr<TF1>(
f);
168 fFunction2 = std::shared_ptr<TF1>(
f);
171 InitializeDataMembers(funcarray[0], funcarray[1],useFFT);
187 TF1*
f1 = (
TF1*)(
gROOT -> GetListOfFunctions() -> FindObject(formula1));
188 TF1*
f2 = (
TF1*)(
gROOT -> GetListOfFunctions() -> FindObject(formula2));
191 fFunction1 = std::shared_ptr<TF1>(
new TF1(
"f_conv_1",formula1) );
192 if (!fFunction1->GetFormula()->IsValid() )
193 Error(
"TF1Convolution",
"Invalid formula for : %s",formula1.
Data() );
196 fFunction2 = std::shared_ptr<TF1>(
new TF1(
"f_conv_1",formula2) );
197 if (!fFunction2->GetFormula()->IsValid() )
198 Error(
"TF1Convolution",
"Invalid formula for : %s",formula2.
Data() );
201 InitializeDataMembers(f1, f2,useFFT);
214 Info(
"MakeFFTConv",
"Making FFT convolution using %d points in range [%g,%g]",fNofPoints,fXmin,fXmax);
216 std::vector < Double_t >
x (fNofPoints);
217 std::vector < Double_t > in1(fNofPoints);
218 std::vector < Double_t > in2(fNofPoints);
222 if (fft1 ==
nullptr || fft2 ==
nullptr) {
223 Warning(
"MakeFFTConv",
"Cannot use FFT, probably FFTW package is not available. Switch to numerical convolution");
229 Double_t shift2 = 0.5*(fXmin+fXmax);
231 for (
int i=0; i<fNofPoints; i++)
233 x[i] = fXmin + (fXmax-fXmin)/(fNofPoints-1)*i;
235 in1[i] = fFunction1 -> EvalPar( &x[i],
nullptr);
236 in2[i] = fFunction2 -> EvalPar( &x2,
nullptr);
237 fft1 -> SetPoint(i, in1[i]);
238 fft2 -> SetPoint(i, in2[i]);
246 Double_t re1, re2, im1, im2, out_re, out_im;
248 for (
int i=0;i<=fNofPoints/2.;i++)
250 fft1 -> GetPointComplex(i,re1,im1);
251 fft2 -> GetPointComplex(i,re2,im2);
252 out_re = re1*re2 - im1*im2;
253 out_im = re1*im2 + re2*im1;
254 fftinverse -> SetPoint(i, out_re, out_im);
256 fftinverse -> Transform();
259 if (!fGraphConv) fGraphConv = std::shared_ptr< TGraph >(
new TGraph(fNofPoints));
261 for (
int i=0;i<fNofPoints;i++)
264 int j = i + fNofPoints/2;
265 if (j >= fNofPoints) j -= fNofPoints;
267 fGraphConv->SetPoint(i, x[i], fftinverse->
GetPointReal(j)*(fXmax-fXmin)/(fNofPoints*fNofPoints) );
277 if (!fFlagGraph) MakeFFTConv();
280 return fGraphConv ->
Eval(t);
282 return EvalNumConv(t);
291 TF1Convolution_EvalWrapper fconv( fFunction1, fFunction2, t);
296 result = integrator.
Integral(fXmin, fXmax);
314 if (fFlagFFT) result = EvalFFTConv(t[0]);
315 else result = EvalNumConv(t[0]);
324 if (fGraphConv) fGraphConv -> Set(fNofPoints);
332 bool equalParams =
true;
333 for (
int i=0; i<fNofParams1; i++) {
334 fFunction1 -> SetParameter(i,p[i]);
335 equalParams &= ( fParams1[i] == p[i] );
341 if (fCstIndex!=-1) offset = 1;
342 Int_t totalnofparams = fNofParams1+fNofParams2+offset;
343 for (
int i=fNofParams1; i<totalnofparams; i++) {
350 fFunction2 -> SetParameter(k,p[i-offset2]);
351 equalParams &= ( fParams2[k-offset2] == p[i-offset2] );
352 fParams2[k-offset2] = p[i-offset2];
364 if (!equalParams) fFlagGraph =
false;
384 if (percentage<0)
return;
385 double range = fXmax = fXmin;
386 fXmin -= percentage * range;
387 fXmax += percentage * range;
400 Warning(
"TF1Convolution::SetRange()",
"In FFT mode, range can not be infinite. Infinity has been replaced by range of first function plus a bufferzone to avoid spillover.");
virtual TFormula * GetFormula()
static double p3(double t, double a, double b, double c, double d)
virtual void Copy(TObject &f1) const
Copy this F1 to a new F1.
void Fatal(const char *location, const char *msgfmt,...)
Collectable string class.
TString & ReplaceAll(const TString &s1, const TString &s2)
TRObject operator()(const T1 &t1) const
static const double x2[5]
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString...
static double p2(double t, double a, double b, double c)
void MakeFFTConv()
perform the FFT of the two functions
void Info(const char *location, const char *msgfmt,...)
std::vector< std::vector< double > > Data
void InitializeDataMembers(TF1 *function1, TF1 *function2, Bool_t useFFT)
use copy instead of Clone
static IntegrationOneDim::Type DefaultIntegratorType()
void Error(const char *location, const char *msgfmt,...)
double IntegralLow(const IGenFunction &f, double b)
evaluate the Integral of a function f over the over the semi-infinite interval (-inf,b)
double Integral(Function &f, double a, double b)
evaluate the Integral of a function f over the defined interval (a,b)
void SetRange(Double_t a, Double_t b)
double IntegralUp(const IGenFunction &f, double a)
evaluate the Integral of a function f over the semi-infinite interval (a,+inf)
virtual Double_t GetPointReal(Int_t ipoint, Bool_t fromInput=kFALSE) const =0
static TVirtualFFT * FFT(Int_t ndim, Int_t *n, Option_t *option)
Returns a pointer to the FFT of requested size and type.
Double_t EvalNumConv(Double_t t)
perform numerical convolution could in principle cache the integral in a Graph as it is done for the ...
void SetNofPointsFFT(Int_t n)
User Class for performing numerical integration of a function in one dimension.
static void InitStandardFunctions()
Create the basic function objects.
static double p1(double t, double a, double b)
TF1Convolution(TF1 *function1, TF1 *function2, Bool_t useFFT=true)
constructor from the two function pointer and a flag is using FFT
void Warning(const char *location, const char *msgfmt,...)
graph is sorted in X points
TVirtualFFT is an interface class for Fast Fourier Transforms.
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Double_t operator()(Double_t *t, Double_t *p)
you should not use this method at all Int_t Int_t Double_t Double_t Double_t e
void SetParameters(Double_t *p)
Double_t EvalFFTConv(Double_t t)
double f2(const double *x)
A Graph is a graphics object made of two arrays X and Y with npoints each.
you should not use this method at all Int_t Int_t Double_t Double_t Double_t Int_t Double_t Double_t Double_t Double_t b
void SetExtraRange(Double_t percentage)
const char * Data() const