32 ClassImp(TGraphSmooth);
41 TGraphSmooth::TGraphSmooth(): TNamed()
54 TGraphSmooth::TGraphSmooth(
const char *name): TNamed(name,
"")
67 TGraphSmooth::~TGraphSmooth()
69 if (fGout)
delete fGout;
77 void TGraphSmooth::Smoothin(TGraph *grin)
79 if (fGout) {
delete fGout; fGout = 0;}
83 Double_t *xin =
new Double_t[fNin];
84 Double_t *yin =
new Double_t[fNin];
86 for (i=0;i<fNin;i++) {
87 xin[i] = fGin->GetX()[i];
88 yin[i] = fGin->GetY()[i];
92 Int_t *index =
new Int_t[fNin];
93 TMath::Sort(fNin, xin, index, kFALSE);
94 for (i=0;i<fNin;i++) {
95 fGin->SetPoint(i, xin[index[i]], yin[index[i]]);
98 fMinX = fGin->GetX()[0];
99 fMaxX = fGin->GetX()[fNin-1];
117 TGraph *TGraphSmooth::SmoothKern(TGraph *grin, Option_t *option,
118 Double_t bandwidth, Int_t nout, Double_t *xout)
120 TString opt = option;
123 if (opt.Contains(
"normal")) kernel = 2;
130 fNout = TMath::Max(nout, fNin);
131 delta = (fMaxX - fMinX)/(fNout - 1);
134 index =
new Int_t[nout];
135 TMath::Sort(nout, xout, index, kFALSE);
138 fGout =
new TGraph(fNout);
139 for (Int_t i=0;i<fNout;i++) {
140 if (xout == 0) fGout->SetPoint(i,fMinX + i*delta, 0);
141 else fGout->SetPoint(i,xout[index[i]], 0);
144 BDRksmooth(fGin->GetX(), fGin->GetY(), fNin, fGout->GetX(),
145 fGout->GetY(), fNout, kernel, bandwidth);
147 if (index) {
delete [] index; index = 0;}
157 void TGraphSmooth::BDRksmooth(Double_t *x, Double_t *y, Int_t n, Double_t *xp,
158 Double_t *yp, Int_t np, Int_t kernel, Double_t bw)
161 Double_t cutoff = 0.0;
173 while ((imin < n) && (x[imin] < xp[0] - cutoff))
176 for (Int_t j=0;j<np;j++) {
181 for (Int_t i=imin;i<n;i++) {
182 if (x[i] < x0 - cutoff) imin = i;
183 if (x[i] > x0 + cutoff)
break;
184 xx = TMath::Abs(x[i] - x0)/bw;
185 if (kernel == 1) w = 1;
186 else w = TMath::Exp(-0.5*xx*xx);
223 TGraph *TGraphSmooth::SmoothLowess(TGraph *grin, Option_t *option ,
224 Double_t span, Int_t iter, Double_t delta)
226 TString opt = option;
231 if (delta == 0) {delta = 0.01*(TMath::Abs(fMaxX - fMinX));}
235 fGout =
new TGraphErrors(fNout);
237 for (Int_t i=0;i<fNout;i++) {
238 fGout->SetPoint(i,fGin->GetX()[i], 0);
241 Lowess(fGin->GetX(), fGin->GetY(), fNin, fGout->GetY(), span, iter, delta);
251 void TGraphSmooth::Lowess(Double_t *x, Double_t *y, Int_t n, Double_t *ys,
252 Double_t span, Int_t iter, Double_t delta)
254 Int_t i, iiter, j, last, m1, m2, nleft, nright, ns;
255 Double_t alpha, c1, c9, cmad, cut, d1, d2, denom, r;
268 Double_t *rw = ((TGraphErrors*)fGout)->GetEX();
269 Double_t *res = ((TGraphErrors*)fGout)->GetEY();
272 ns = TMath::Max(2, TMath::Min(n, (Int_t)(span*n + 1e-7)));
276 while (iiter <= iter+1) {
285 d1 = x[i] - x[nleft];
286 d2 = x[nright+1] - x[i];
298 Bool_t iterg1 = iiter>1;
299 Lowest(&x[1], &y[1], n, x[i], ys[i], nleft, nright,
300 res, iterg1, rw, ok);
301 if (!ok) ys[i] = y[i];
305 denom = x[i]-x[last];
308 for(j = last+1; j < i; j++) {
309 alpha = (x[j]-x[last])/denom;
310 ys[j] = alpha*ys[i] + (1.-alpha)*ys[last];
318 cut = x[last] + delta;
319 for (i = last+1; i <= n; i++) {
322 if (x[i] == x[last]) {
327 i = TMath::Max(last+1, i-1);
334 res[i] = y[i+1] - ys[i+1];
340 rw[i] = TMath::Abs(res[i]);
349 cmad = 3.*(rw[m1]+rw[m2]);
356 for(i=0 ; i<n ; i++) {
357 r = TMath::Abs(res[i]);
361 rw[i] = (1.-(r/cmad)*(r/cmad))*(1.-(r/cmad)*(r/cmad));
374 void TGraphSmooth::Lowest(Double_t *x, Double_t *y, Int_t n, Double_t &xs,
375 Double_t &ys, Int_t nleft, Int_t nright, Double_t *w,
376 Bool_t userw, Double_t *rw, Bool_t &ok)
379 Double_t a, b, c, d, h, h1, h9, r, range;
387 h = TMath::Max(xs-x[nleft], x[nright]-xs);
397 r = TMath::Abs(x[j] - xs);
402 d = (r/h)*(r/h)*(r/h);
403 w[j] = (1.- d)*(1.- d)*(1.- d);
408 }
else if (x[j] > xs)
420 for(j=nleft ; j<=nrt ; j++)
425 for(j=nleft ; j<=nrt ; j++)
429 for(j=nleft ; j<=nrt ; j++)
430 c += w[j]*(x[j]-a)*(x[j]-a);
431 if (TMath::Sqrt(c) > 0.001*range) {
434 for(j=nleft; j <= nrt; j++)
435 w[j] *= (b*(x[j]-a) + 1.);
439 for(j=nleft; j <= nrt; j++)
482 TGraph *TGraphSmooth::SmoothSuper(TGraph *grin, Option_t *,
483 Double_t bass, Double_t span, Bool_t isPeriodic, Double_t *w)
485 if (span < 0 || span > 1) {
486 std::cout <<
"Error: Span must be between 0 and 1" << std::endl;
495 if (fMinX < 0 || fMaxX > 1) {
496 std::cout <<
"Error: x must be between 0 and 1 for periodic smooth" << std::endl;
503 fGout =
new TGraph(fNout);
505 for (i=0; i<fNout; i++) {
506 fGout->SetPoint(i,fGin->GetX()[i], 0);
510 Double_t *weight =
new Double_t[fNin];
511 for (i=0; i<fNin; i++) {
512 if (w == 0) weight[i] = 1;
513 else weight[i] = w[i];
517 Int_t nTmp = (fNin+1)*8;
518 Double_t *tmp =
new Double_t[nTmp];
519 for (i=0; i<nTmp; i++) {
523 BDRsupsmu(fNin, fGin->GetX(), fGin->GetY(), weight, iper, span, bass, fGout->GetY(), tmp);
573 void TGraphSmooth::BDRsupsmu(Int_t n, Double_t *x, Double_t *y, Double_t *w,
574 Int_t iper, Double_t span, Double_t alpha, Double_t *smo, Double_t *sc)
580 Double_t sw, sy, resmin, vsmlsq;
584 Double_t spans[3] = { 0.05, 0.2, 0.5 };
587 Double_t eps = 0.001;
607 if (sw > 0.0) a = sy / sw;
608 for (j=1;j<=n;++j) smo[j] = a;
615 while (scale <= 0.0) {
625 if (iper == 2 && (x[1] < 0.0 || x[n] > 1.0)) {
628 if (jper < 1 || jper > 2) {
632 BDRsmooth(n, &x[1], &y[1], &w[1], span, jper, vsmlsq,
633 &smo[1], &sc[sc_offset]);
637 Double_t *h =
new Double_t[n+1];
638 for (i = 1; i <= 3; ++i) {
639 BDRsmooth(n, &x[1], &y[1], &w[1], spans[i - 1], jper, vsmlsq,
640 &sc[((i<<1)-1)*n + 1], &sc[n*7 + 1]);
641 BDRsmooth(n, &x[1], &sc[n*7 + 1], &w[1], spans[1], -jper, vsmlsq,
642 &sc[(i<<1)*n + 1], &h[1]);
645 for (j=1; j<=n; ++j) {
647 for (i=1; i<=3; ++i) {
648 if (sc[j + (i<<1)*n] < resmin) {
649 resmin = sc[j + (i<<1)*n];
650 sc[j + n*7] = spans[i-1];
654 if (alpha>0.0 && alpha<=10.0 && resmin<sc[j + n*6] && resmin>0.0) {
656 d1 = TMath::Max(sml,(resmin/sc[j + n*6]));
658 sc[j + n*7] += (spans[2] - sc[j + n*7]) * TMath::Power(d1, d2);
662 BDRsmooth(n, &x[1], &sc[n*7 + 1], &w[1], spans[1], -jper, vsmlsq,
663 &sc[(n<<1) + 1], &h[1]);
665 for (j=1; j<=n; ++j) {
666 if (sc[j + (n<<1)] <= spans[0]) {
667 sc[j + (n<<1)] = spans[0];
669 if (sc[j + (n<<1)] >= spans[2]) {
670 sc[j + (n<<1)] = spans[2];
672 f = sc[j + (n<<1)] - spans[1];
674 f = -f / (spans[1] - spans[0]);
675 sc[j + (n<<2)] = (1.0 - f) * sc[j + n*3] + f * sc[j + n];
677 f /= spans[2] - spans[1];
678 sc[j + (n<<2)] = (1.0 - f) * sc[j + n*3] + f * sc[j + n*5];
682 BDRsmooth(n, &x[1], &sc[(n<<2) + 1], &w[1], spans[0], -jper, vsmlsq,
694 void TGraphSmooth::BDRsmooth(Int_t n, Double_t *x, Double_t *y, Double_t *w,
695 Double_t span, Int_t iper, Double_t vsmlsq, Double_t *smo, Double_t *acvr)
698 Int_t i, j, j0, in, out, it, jper, ibw;
700 Double_t xm, ym, wt, sy, fbo, fbw;
701 Double_t cvar, var, tmp, xti, xto;
716 jper = TMath::Abs(iper);
718 ibw = (Int_t)(span * 0.5 * n + 0.5);
724 for (i=1; i<=it; ++i) {
738 xm = (fbo * xm + wt * xti) / fbw;
739 ym = (fbo * ym + wt * y[j]) / fbw;
743 tmp = fbw * wt * (xti - xm) / fbo;
745 var += tmp * (xti - xm);
746 cvar += tmp * (y[j] - ym);
749 for (j=1; j<=n; ++j) {
752 if (!(jper != 2 && (out < 1 || in > n))) {
771 tmp = fbo * wt * (xto - xm) / fbw;
773 var -= tmp * (xto - xm);
774 cvar -= tmp * (y[out] - ym);
776 xm = (fbo * xm - wt * xto) / fbw;
777 ym = (fbo * ym - wt * y[out]) / fbw;
783 xm = (fbo * xm + wt * xti) / fbw;
784 ym = (fbo * ym + wt * y[in]) / fbw;
788 tmp = fbw * wt * (xti - xm) / fbo;
790 var += tmp * (xti - xm);
791 cvar += tmp * (y[in] - ym);
798 smo[j] = a * (x[j] - xm) + ym;
817 acvr[j] = TMath::Abs(y[j] - smo[j]) / a;
832 if (x[j + 1] > x[j]) {
846 for (i=j0; i<=j; ++i) {
859 void TGraphSmooth::Approxin(TGraph *grin, Int_t , Double_t &ylow,
860 Double_t &yhigh, Int_t rule, Int_t iTies)
862 if (fGout) {
delete fGout; fGout = 0;}
866 Double_t *xin =
new Double_t[fNin];
867 Double_t *yin =
new Double_t[fNin];
869 for (i=0;i<fNin;i++) {
870 xin[i] = fGin->GetX()[i];
871 yin[i] = fGin->GetY()[i];
875 Int_t *index =
new Int_t[fNin];
876 Int_t *rank =
new Int_t[fNin];
877 Rank(fNin, xin, index, rank, kFALSE);
882 Int_t *dup =
new Int_t[fNin];
883 Double_t *x =
new Double_t[fNin];
884 Double_t *y =
new Double_t[fNin];
885 Double_t vMean, vMin, vMax;
886 for (i=1;i<fNin+1;i++) {
888 vMin = vMean = vMax = yin[index[i-1]];
889 while ((i < fNin) && (rank[index[i]] == rank[index[i-1]])) {
890 vMean += yin[index[i]];
891 vMax = (vMax < yin[index[i]]) ? yin[index[i]] : vMax;
892 vMin = (vMin > yin[index[i]]) ? yin[index[i]] : vMin;
898 x[k] = xin[index[i-1]];
899 if (ndup == 1) {y[k++] = yin[index[i-1]];}
919 for (i=0;i<fNin;i++) {
920 fGin->SetPoint(i, x[i], y[i]);
923 fMinX = fGin->GetX()[0];
924 fMaxX = fGin->GetX()[fNin-1];
933 ylow = fGin->GetY()[0];
934 yhigh = fGin->GetY()[fNin-1];
998 TGraph *TGraphSmooth::Approx(TGraph *grin, Option_t *option, Int_t nout, Double_t *xout,
999 Double_t yleft, Double_t yright, Int_t rule, Double_t f, Option_t *ties)
1001 TString opt = option;
1004 if (opt.Contains(
"linear")) iKind = 1;
1005 else if (opt.Contains(
"constant")) iKind = 2;
1007 if (f < 0 || f > 1) {
1008 std::cout <<
"Error: Invalid f value" << std::endl;
1015 if (opt.Contains(
"ordered")) {
1017 }
else if (opt.Contains(
"mean")) {
1019 }
else if (opt.Contains(
"min")) {
1021 }
else if (opt.Contains(
"max")) {
1024 std::cout <<
"Error: Method not known: " << ties << std::endl;
1029 Double_t ylow = yleft;
1030 Double_t yhigh = yright;
1031 Approxin(grin, iKind, ylow, yhigh, rule, iTies);
1037 fNout = TMath::Max(nout, fNin);
1038 delta = (fMaxX - fMinX)/(fNout - 1);
1041 fGout =
new TGraph(fNout);
1044 for (Int_t i=0;i<fNout;i++) {
1045 if (xout == 0) x = fMinX + i*delta;
1047 Double_t yout = Approx1(x, f, fGin->GetX(), fGin->GetY(), fNin, iKind, ylow, yhigh);
1048 fGout->SetPoint(i,x, yout);
1060 Double_t TGraphSmooth::Approx1(Double_t v, Double_t f, Double_t *x, Double_t *y,
1061 Int_t n, Int_t iKind, Double_t ylow, Double_t yhigh)
1067 if(v < x[i])
return ylow;
1068 if(v > x[j])
return yhigh;
1072 Int_t ij = (i + j)/2;
1073 if(v < x[ij]) j = ij;
1078 if(v == x[j])
return y[j];
1079 if(v == x[i])
return y[i];
1082 return y[i] + (y[j] - y[i]) * ((v - x[i])/(x[j] - x[i]));
1084 return y[i] * (1-f) + y[j] * f;
1094 Int_t TGraphSmooth::Rcmp(Double_t x, Double_t y)
1096 if (x < y)
return -1;
1097 if (x > y)
return 1;
1106 void TGraphSmooth::Psort(Double_t *x, Int_t n, Int_t k)
1111 for (pL = 0, pR = n - 1; pL < pR; ) {
1113 for(i = pL, j = pR; i <= j;) {
1114 while (TGraphSmooth::Rcmp(x[i], v) < 0) i++;
1115 while (TGraphSmooth::Rcmp(v, x[j]) < 0) j--;
1116 if (i <= j) { w = x[i]; x[i++] = x[j]; x[j--] = w; }
1126 void TGraphSmooth::Rank(Int_t n, Double_t *a, Int_t *index, Int_t *rank, Bool_t down)
1135 TMath::Sort(n,a,index,down);
1138 for (Int_t i=0;i<n;i++) {
1139 if ((i > 0) && (a[index[i]] == a[index[i-1]])) {
1140 rank[index[i]] = i-1;
1143 rank[index[i]] = i-k;