#ifndef MARS_MExtralgoSpline #define MARS_MExtralgoSpline #ifndef ROOT_TMath #include #endif class TComplex; class MExtralgoSpline { public: enum ExtractionType_t { kAmplitude, kIntegralRel, kIntegralAbs }; //! Possible time and charge extraction types private: ExtractionType_t fExtractionType; private: //Bool_t fIsOwner; // Owner of derivatives.... // Input Float_t const *fVal; const Int_t fNum; Float_t *fDer1; Float_t *fDer2; Float_t fRiseTime; Float_t fFallTime; Float_t fHeightTm; // Result Float_t fTime; Float_t fTimeDev; Float_t fWidth; Float_t fWidthDev; Float_t fSignal; Float_t fSignalDev; Float_t fHeight; Double_t ReMul(const TComplex &c1, const TComplex &th) const; inline Float_t Eval(Float_t val, Float_t a, Float_t deriv) const { return a*val + (a*a*a-a)*deriv; } // Evaluate value of spline in the interval i with x=[0;1[ inline Float_t Eval(const Int_t i, const Float_t x) const { // Eval(i,x) = (fDer2[i+1]-fDer2[i])*x*x*x + 3*fDer2[i]*x*x + // (fVal[i+1]-fVal[i] -2*fDer2[i]-fDer2[i+1])*x + fVal[i]; // x := [0; 1[ return Eval(fVal[i], 1-x, fDer2[i]) + Eval(fVal[i+1], x, fDer2[i+1]); } // Evaluate first derivative of spline in the interval i with x=[0;1[ inline Double_t EvalDeriv1(const Int_t i, const Float_t x) const { // x := [0; 1[ const Double_t difval = fVal[i+1]-fVal[i]; const Double_t difder = fDer2[i+1]-fDer2[i]; //return 3*difder*x*x + 6*fDer2[i]*x - 2*fDer2[i] - fDer2[i+1] + difval; return 3*difder*x*x + (6*x - 2)*fDer2[i] - fDer2[i+1] + difval; } // Evaluate second derivative of spline in the interval i with x=[0;1[ inline Double_t EvalDeriv2(const Int_t i, const Float_t x) const { // x := [0; 1[ return 6*(fDer2[i+1]*x + fDer2[i]*(1-x)); } Double_t FindY(Int_t i, Bool_t downwards, Double_t y=0, Double_t min=0, Double_t max=1) const; Int_t EvalDerivEq0(const Int_t i, Double_t &x1, Double_t &x2) const; /* inline void EvalDerivEq0(const Int_t i, Float_t &rc1, Float_t &rc2) const { // --- ORIGINAL CODE --- Double_t sumder = fDer2[i]+fDer2[i+1]; Double_t difder = fDer2[i]-fDer2[i+1]; Double_t sqt1 = sumder*sumder - fDer2[i]*fDer2[i+1]; Double_t sqt2 = difder*(fVal[i+1]-fVal[i]); Double_t sqt3 = sqrt(3*sqt1 + 3*sqt2); Double_t denom = -3*(fDer2[i+1]-fDer2[i]); rc1 = (3*fDer2[i] + sqt3)/denom; rc2 = (3*fDer2[i] - sqt3)/denom; // --- NEW CODE --- Double_t sumder = fDer2[i]+fDer2[i+1]; Double_t difder = fDer2[i]-fDer2[i+1]; Double_t sqt1 = sumder*sumder - fDer2[i]*fDer2[i+1]; Double_t sqt2 = difder*(fVal[i+1]-fVal[i]); Double_t sqt3 = sqt1+sqt2<0 ? 0 : sqrt((sqt1 + sqt2)/3); rc1 = (fDer2[i] + sqt3)/difder; rc2 = (fDer2[i] - sqt3)/difder; }*/ // Calculate the "Stammfunktion" of the Eval-function inline Double_t EvalPrimitive(Int_t i, Float_t x) const { Align(i, x); if (x==0) return -fDer2[i]/4; if (x==1) return (fVal[i+1] + fVal[i])/2 - fDer2[i+1]/4 - fDer2[i]/2; const Double_t x2 = x*x; const Double_t x4 = x2*x2; const Double_t x1 = 1-x; const Double_t x14 = x1*x1*x1*x1; return x2*fVal[i+1]/2 + (x4/2-x2)*fDer2[i+1]/2 + (x-x2/2)*fVal[i] + (x2/2-x-x14/4)*fDer2[i]; } inline void Align(Int_t &i, Float_t &x) const { if (i<0) { x += i; i=0; } if (i>=fNum-1) { x += i-(fNum-2); i=fNum-2; } } // Calculate the intgeral of the Eval-function in // bin i from 0 <= a < b < 1 inline Double_t EvalInteg(Int_t i, Float_t a, Float_t b) const { return EvalPrimitive(i, b)-EvalPrimitive(i, a); } // Identical to EvalInteg(i, 0, 1) but much faster // Be carefull: NO RANGECHECK! inline Double_t EvalInteg(Int_t i) const { return (fVal[i+1] + fVal[i])/2 - (fDer2[i+1] + fDer2[i])/4; } // Identical to sum EvalInteg(i, 0, 1) for i=0 to imax) return EvalInteg(max, x0-max, x1-max); // Sum complete intervals Double_t sum = EvalInteg(min, max); // Sum the incomplete intervals at the beginning and end sum += EvalInteg(min-1, 1-(min-x0), 1); sum += EvalInteg(max, 0, x1-max); // return result return sum; } // We search for the maximum from x=i-1 to x=i+1 // (Remeber: i corresponds to the value in bin i, i+1 to the // next bin and i-1 to the last bin) inline void GetMaxAroundI(Int_t i, Float_t &xmax, Float_t &ymax) const { Float_t xmax1=0, xmax2=0; Float_t ymax1=0, ymax2=0; Bool_t rc1 = i>0 && GetMax(i-1, xmax1, ymax1); Bool_t rc2 = i=fNum-1) { xmax2 = fNum-1; ymax2 = fVal[fNum-1]; rc2 = kTRUE; } // Take a default in case no maximum is found // FIXME: Check THIS!!! xmax=i; ymax=fVal[i]; if (rc1) { ymax = ymax1; xmax = xmax1; } else if (rc2) { ymax = ymax2; xmax = xmax2; } if (rc2 && ymax2>ymax) { ymax = ymax2; xmax = xmax2; } } inline Bool_t GetMax(Int_t i, Float_t &xmax, Float_t &ymax, Float_t min=0, Float_t max=1) const { // Find analytical maximum in the bin i in the interval [min,max[ Double_t x1=-1; // This initialisation should not really be Double_t x2=-1; // necessary but makes valgriund happy. if (!EvalDerivEq0(i, x1, x2)) return kFALSE; const Bool_t ismax1 = x1>=min && x1=min && x2