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)
65 return fFunction1->Eval(x) * fFunction2->Eval(fT0-x);
75 TF1 * fnew1 = (
TF1*) function1->IsA()->New();
76 function1->
Copy(*fnew1);
77 fFunction1 = std::shared_ptr<TF1>(fnew1);
80 TF1 * fnew2 = (
TF1*) function2->IsA()->New();
81 function2->
Copy(*fnew2);
82 fFunction2 = std::shared_ptr<TF1>(fnew2);
84 if (fFunction1.get() ==
nullptr|| fFunction2.get() ==
nullptr)
85 Fatal(
"InitializeDataMembers",
"Invalid functions - Abort");
88 fFunction1->GetRange(fXmin, fXmax);
92 fNofParams1 = fFunction1->GetNpar();
93 fNofParams2 = fFunction2->GetNpar();
94 fParams1 = std::vector<Double_t>(fNofParams1);
95 fParams2 = std::vector<Double_t>(fNofParams2);
96 fCstIndex = fFunction2-> GetParNumber(
"Constant");
103 fParNames.reserve( fNofParams1 + fNofParams2);
104 for (
int i=0; i<fNofParams1; i++)
106 fParams1[i] = fFunction1 -> GetParameter(i);
107 fParNames.push_back(fFunction1 -> GetParName(i) );
109 for (
int i=0; i<fNofParams2; i++)
111 fParams2[i] = fFunction2 -> GetParameter(i);
112 if (i != fCstIndex) fParNames.push_back(fFunction2 -> GetParName(i) );
116 fFunction2 -> FixParameter(fCstIndex,1.);
117 fNofParams2 = fNofParams2-1;
118 fParams2.erase(fParams2.begin()+fCstIndex);
126 InitializeDataMembers(function1,function2, useFFT);
134 InitializeDataMembers(function1, function2,useFFT);
149 std::vector < TString > stringarray(2);
150 std::vector < TF1* > funcarray(2);
151 for (
int i=0; i<2; i++)
153 stringarray[i] = ((
TObjString*)((*objarray)[i])) -> GetString();
154 stringarray[i].ReplaceAll(
" ",
"");
155 funcarray[i] = (
TF1*)(
gROOT -> GetListOfFunctions() -> FindObject(stringarray[i]));
157 if (funcarray[i] ==
nullptr) {
160 Error(
"TF1Convolution",
"Invalid formula : %s",stringarray[i].
Data() );
162 fFunction1 = std::shared_ptr<TF1>(
f);
164 fFunction2 = std::shared_ptr<TF1>(
f);
167 InitializeDataMembers(funcarray[0], funcarray[1],useFFT);
183 TF1*
f1 = (
TF1*)(
gROOT -> GetListOfFunctions() -> FindObject(formula1));
184 TF1*
f2 = (
TF1*)(
gROOT -> GetListOfFunctions() -> FindObject(formula2));
187 fFunction1 = std::shared_ptr<TF1>(
new TF1(
"f_conv_1",formula1) );
188 if (!fFunction1->GetFormula()->IsValid() )
189 Error(
"TF1Convolution",
"Invalid formula for : %s",formula1.
Data() );
192 fFunction2 = std::shared_ptr<TF1>(
new TF1(
"f_conv_1",formula2) );
193 if (!fFunction2->GetFormula()->IsValid() )
194 Error(
"TF1Convolution",
"Invalid formula for : %s",formula2.
Data() );
197 InitializeDataMembers(f1, f2,useFFT);
210 Info(
"MakeFFTConv",
"Making FFT convolution using %d points in range [%g,%g]",fNofPoints,fXmin,fXmax);
212 std::vector < Double_t >
x (fNofPoints);
213 std::vector < Double_t > in1(fNofPoints);
214 std::vector < Double_t > in2(fNofPoints);
218 if (fft1 ==
nullptr || fft2 ==
nullptr) {
219 Warning(
"MakeFFTConv",
"Cannot use FFT, probably FFTW package is not available. Switch to numerical convolution");
225 Double_t shift2 = 0.5*(fXmin+fXmax);
227 for (
int i=0; i<fNofPoints; i++)
229 x[i] = fXmin + (fXmax-fXmin)/(fNofPoints-1)*i;
231 in1[i] = fFunction1 -> EvalPar( &x[i],
nullptr);
232 in2[i] = fFunction2 -> EvalPar( &x2,
nullptr);
233 fft1 -> SetPoint(i, in1[i]);
234 fft2 -> SetPoint(i, in2[i]);
242 Double_t re1, re2, im1, im2, out_re, out_im;
244 for (
int i=0;i<=fNofPoints/2.;i++)
246 fft1 -> GetPointComplex(i,re1,im1);
247 fft2 -> GetPointComplex(i,re2,im2);
248 out_re = re1*re2 - im1*im2;
249 out_im = re1*im2 + re2*im1;
250 fftinverse -> SetPoint(i, out_re, out_im);
252 fftinverse -> Transform();
255 if (!fGraphConv) fGraphConv = std::shared_ptr< TGraph >(
new TGraph(fNofPoints));
257 for (
int i=0;i<fNofPoints;i++)
260 int j = i + fNofPoints/2;
261 if (j >= fNofPoints) j -= fNofPoints;
263 fGraphConv->SetPoint(i, x[i], fftinverse->
GetPointReal(j)*(fXmax-fXmin)/(fNofPoints*fNofPoints) );
272 if (!fFlagGraph) MakeFFTConv();
275 return fGraphConv ->
Eval(t);
277 return EvalNumConv(t);
286 TF1Convolution_EvalWrapper fconv( fFunction1, fFunction2, t);
291 result = integrator.
Integral(fXmin, fXmax);
309 if (fFlagFFT) result = EvalFFTConv(t[0]);
310 else result = EvalNumConv(t[0]);
319 if (fGraphConv) fGraphConv -> Set(fNofPoints);
327 bool equalParams =
true;
328 for (
int i=0; i<fNofParams1; i++) {
329 fFunction1 -> SetParameter(i,p[i]);
330 equalParams &= ( fParams1[i] == p[i] );
336 if (fCstIndex!=-1) offset = 1;
337 Int_t totalnofparams = fNofParams1+fNofParams2+offset;
338 for (
int i=fNofParams1; i<totalnofparams; i++) {
345 fFunction2 -> SetParameter(k,p[i-offset2]);
346 equalParams &= ( fParams2[k-offset2] == p[i-offset2] );
347 fParams2[k-offset2] = p[i-offset2];
359 if (!equalParams) fFlagGraph =
false;
379 if (percentage<0)
return;
380 double range = fXmax = fXmin;
381 fXmin -= percentage * range;
382 fXmax += percentage * range;
395 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,...)
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)
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.
void SetExtraRange(Double_t percentage)
const char * Data() const