TKDEFGT.cxx

Go to the documentation of this file.
00001 // @(#)root/gl:$Id: TKDEFGT.cxx 29602 2009-07-28 10:23:20Z brun $
00002 // Author: Timur Pocheptsov  2009
00003 /*************************************************************************
00004  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00005  * All rights reserved.                                                  *
00006  *                                                                       *
00007  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00008  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00009  *************************************************************************/
00010 #include <climits>
00011 
00012 #include "TError.h"
00013 #include "TMath.h"
00014 
00015 #include "TKDEFGT.h"
00016 #include "TGL5D.h"
00017 
00018 //   Kernel density estimator based on Fast Gauss Transform.
00019 //   
00020 //   Nice implementation of FGT by Sebastien Paris
00021 //   can be found here:
00022 //      http://www.mathworks.com/matlabcentral/fileexchange/17438
00023 //      
00024 //   This version is based on his work.
00025 
00026 //______________________________________________________________________________
00027 TKDEFGT::TKDEFGT()
00028          : fDim(0),
00029            fP(0),
00030            fK(0),
00031            fSigma(1.),
00032            fPD(0),
00033            fModelValid(kFALSE)
00034 {
00035    //Constructor.
00036 }
00037 
00038 namespace {
00039 
00040 UInt_t NChooseK(UInt_t n, UInt_t k);
00041 
00042 }
00043 
00044 //______________________________________________________________________________
00045 TKDEFGT::~TKDEFGT()
00046 {
00047    //Destructor.
00048 }
00049 
00050 //______________________________________________________________________________
00051 void TKDEFGT::BuildModel(const std::vector<Double_t> &sources, Double_t sigma, 
00052                          UInt_t dim, UInt_t p, UInt_t k)
00053 {
00054    //Calculate coefficients for FGT.
00055    if (!sources.size()) {
00056       Warning("TKDEFGT::BuildModel", "Bad input - zero size vector");
00057       return;
00058    }
00059 
00060    if (!dim) {
00061       Warning("TKDEFGT::BuildModel", "Number of dimensions is zero");
00062       return;
00063    }
00064 
00065    if (!p) {
00066       Warning("TKDEFGT::BuildModel", "Order of truncation is zero, 8 will be used");
00067       p = 8;
00068    }
00069    
00070    fDim = dim;
00071    fP = p;
00072    const UInt_t nP = UInt_t(sources.size()) / fDim;
00073    fK = !k ? UInt_t(TMath::Sqrt(Double_t(nP))) : k;
00074    fSigma = sigma;
00075    fPD = NChooseK(fP + fDim - 1, fDim);
00076 
00077    fWeights.assign(nP, 1.);
00078    fXC.assign(fDim * fK, 0.);
00079    fA_K.assign(fPD * fK, 0.);
00080    fIndxc.assign(fK, 0);
00081    fIndx.assign(nP, 0);
00082    fXhead.assign(fK, 0);
00083    fXboxsz.assign(fK, 0);
00084    fDistC.assign(nP, 0.);
00085    fC_K.assign(fPD, 0.);
00086    fHeads.assign(fDim + 1, 0);
00087    fCinds.assign(fPD, 0);
00088    fDx.assign(fDim, 0.);
00089    fProds.assign(fPD, 0.);
00090 
00091    Kcenter(sources);
00092    Compute_C_k();
00093    Compute_A_k(sources);
00094 
00095    fModelValid = kTRUE;
00096 }
00097 
00098 //______________________________________________________________________________
00099 void TKDEFGT::BuildModel(const TGL5DDataSet *sources, Double_t sigma, UInt_t p, UInt_t k)
00100 {
00101    //Calculate coefficients for FGT.
00102    //Alternative specialized version for data from TTree.
00103    if (!sources->SelectedSize()) {
00104       Warning("TKDEFGT::BuildModel", "Bad input - zero size vector");
00105       return;
00106    }
00107 
00108    fDim = 3;
00109 
00110    if (!p) {
00111       Warning("TKDEFGT::BuildModel", "Order of truncation is zero, 8 will be used");
00112       p = 8;
00113    }
00114 
00115    fP = p;
00116    const UInt_t nP = sources->SelectedSize();
00117    fK = !k ? UInt_t(TMath::Sqrt(Double_t(nP))) : k;
00118    fSigma = sigma;
00119    fPD = NChooseK(fP + fDim - 1, fDim);
00120          
00121    fWeights.assign(nP, 1.);
00122    fXC.assign(fDim * fK, 0.);
00123    fA_K.assign(fPD * fK, 0.);
00124    fIndxc.assign(fK, 0);
00125    fIndx.assign(nP, 0);
00126    fXhead.assign(fK, 0);
00127    fXboxsz.assign(fK, 0);
00128    fDistC.assign(nP, 0.);
00129    fC_K.assign(fPD, 0.);
00130    fHeads.assign(fDim + 1, 0);
00131    fCinds.assign(fPD, 0);
00132    fDx.assign(fDim, 0.);
00133    fProds.assign(fPD, 0.);
00134 
00135    Kcenter(sources);
00136    Compute_C_k();
00137    Compute_A_k(sources);
00138 
00139    fModelValid = kTRUE;
00140 }
00141 
00142 void BuildModel();
00143 
00144 namespace {
00145 
00146 Double_t DDist(const Double_t *x , const Double_t *y , Int_t d);
00147 Double_t DDist(Double_t x1, Double_t y1, Double_t z1, Double_t x2, Double_t y2, Double_t z2);
00148 
00149 UInt_t Idmax(const std::vector<Double_t> &x , UInt_t n);
00150 
00151 }
00152 
00153 //______________________________________________________________________________
00154 void TKDEFGT::Kcenter(const std::vector<double> &x)
00155 {
00156    //Solve kcenter task.
00157    
00158    //Randomly pick one node as the first center.
00159    const UInt_t nP = UInt_t(x.size()) / fDim;
00160    
00161    UInt_t *indxc = &fIndxc[0];
00162    UInt_t ind = 1;
00163    *indxc++ = ind;
00164    
00165    const Double_t *x_j   = &x[0];
00166    const Double_t *x_ind = &x[0] + ind * fDim;
00167    
00168    for (UInt_t j = 0; j < nP; x_j += fDim, ++j) {
00169       fDistC[j] = (j == ind) ? 0. : DDist(x_j , x_ind , fDim);
00170       fIndx[j] = 0;
00171    }
00172 
00173    for (UInt_t i = 1 ; i < fK; ++i) {
00174       ind = Idmax(fDistC, nP);
00175       *indxc++ = ind;
00176       x_j      = &x[0];
00177       x_ind    = &x[0] + ind * fDim;
00178       for (UInt_t j = 0; j < nP; x_j += fDim, ++j) {
00179          const Double_t temp = (j==ind) ? 0.0 : DDist(x_j, x_ind, fDim);
00180          if (temp < fDistC[j]) {
00181             fDistC[j] = temp;
00182             fIndx[j]   = i;
00183          }
00184       }
00185    }
00186    
00187    for (UInt_t i = 0, nd = 0 ; i < nP; i++, nd += fDim) {
00188       fXboxsz[fIndx[i]]++;
00189       Int_t ibase = fIndx[i] * fDim;
00190       for (UInt_t j = 0 ; j < fDim; ++j)
00191          fXC[j + ibase] += x[j + nd];
00192    }
00193    
00194    for (UInt_t i = 0, ibase = 0; i < fK ; ++i, ibase += fDim) {
00195       const Double_t temp = 1. / fXboxsz[i];
00196       for (UInt_t j = 0; j < fDim; ++j)
00197          fXC[j + ibase] *= temp;
00198    }
00199 }
00200 
00201 //______________________________________________________________________________
00202 void TKDEFGT::Kcenter(const TGL5DDataSet *sources)
00203 {
00204    //Solve kcenter task. Version for dim == 3 and data from TTree.
00205    //Randomly pick one node as the first center.
00206    const UInt_t nP = sources->SelectedSize();
00207    
00208    UInt_t *indxc = &fIndxc[0];
00209    *indxc++ = 1;
00210    
00211    {
00212    //Block to limit the scope of x_ind etc.
00213    const Double_t x_ind = sources->V1(1);
00214    const Double_t y_ind = sources->V2(1);
00215    const Double_t z_ind = sources->V3(1);
00216    
00217    for (UInt_t j = 0; j < nP; ++j) {
00218       const Double_t x_j = sources->V1(j);
00219       const Double_t y_j = sources->V2(j);
00220       const Double_t z_j = sources->V3(j);
00221       fDistC[j] = (j == 1) ? 0. : DDist(x_j, y_j, z_j, x_ind, y_ind, z_ind);
00222       fIndx[j] = 0;
00223    }
00224    //Block to limit the scope of x_ind etc.
00225    }
00226 
00227    for (UInt_t i = 1 ; i < fK; ++i) {
00228       const UInt_t ind = Idmax(fDistC, nP);
00229       const Double_t x_ind = sources->V1(ind);
00230       const Double_t y_ind = sources->V2(ind);
00231       const Double_t z_ind = sources->V3(ind);
00232 
00233       *indxc++ = ind;
00234       for (UInt_t j = 0; j < nP; ++j) {
00235          const Double_t x_j = sources->V1(j);
00236          const Double_t y_j = sources->V2(j);
00237          const Double_t z_j = sources->V3(j);
00238 
00239          const Double_t temp = (j==ind) ? 0.0 : DDist(x_j, y_j, z_j, x_ind, y_ind, z_ind);
00240          if (temp < fDistC[j]) {
00241             fDistC[j] = temp;
00242             fIndx[j]   = i;
00243          }
00244       }
00245    }
00246    
00247    for (UInt_t i = 0, nd = 0 ; i < nP; i++, nd += fDim) {
00248       fXboxsz[fIndx[i]]++;
00249       UInt_t ibase = fIndx[i] * fDim;
00250       fXC[ibase]     += sources->V1(i);
00251       fXC[ibase + 1] += sources->V2(i);
00252       fXC[ibase + 2] += sources->V3(i);
00253    }
00254    
00255    for (UInt_t i = 0, ibase = 0; i < fK ; ++i, ibase += fDim) {
00256       const Double_t temp = 1. / fXboxsz[i];
00257       for (UInt_t j = 0; j < fDim; ++j)
00258          fXC[j + ibase] *= temp;
00259    }
00260 }
00261 
00262 //______________________________________________________________________________
00263 void TKDEFGT::Compute_C_k()
00264 {
00265    //Coefficients C_K.
00266    fHeads[fDim] = UINT_MAX;
00267    fCinds[0] = 0;
00268    fC_K[0] = 1.0;
00269    
00270    for (UInt_t k = 1, t = 1, tail = 1; k < fP; ++k, tail = t) {
00271       for (UInt_t i = 0; i < fDim; ++i) {
00272          const UInt_t head = fHeads[i];
00273          fHeads[i] = t;
00274          for (UInt_t j = head; j < tail; ++j, ++t) {
00275             fCinds[t] = (j < fHeads[i + 1]) ? fCinds[j] + 1 : 1;
00276             fC_K[t]   = 2.0 * fC_K[j];
00277             fC_K[t]  /= fCinds[t];
00278          }
00279       }
00280    }
00281 }
00282 
00283 //______________________________________________________________________________
00284 void TKDEFGT::Compute_A_k(const std::vector<Double_t> &x)
00285 {
00286    //Coefficients A_K.
00287    const Double_t ctesigma = 1. / fSigma;
00288    const UInt_t nP = UInt_t(x.size()) / fDim;
00289    
00290    for (UInt_t n = 0; n < nP; n++) {
00291       UInt_t nbase    = n * fDim;
00292       UInt_t ix2c     = fIndx[n];
00293       UInt_t ix2cbase = ix2c * fDim;
00294       UInt_t ind      = ix2c * fPD;
00295       Double_t temp   = fWeights[n];
00296       Double_t sum    = 0.0;
00297       
00298       for (UInt_t i = 0; i < fDim; ++i) {
00299          fDx[i]    = (x[i + nbase] - fXC[i + ix2cbase]) * ctesigma;
00300          sum      += fDx[i] * fDx[i];
00301          fHeads[i] = 0;
00302       }
00303 
00304       fProds[0] = TMath::Exp(-sum);
00305 
00306       for (UInt_t k = 1, t = 1, tail = 1; k < fP; ++k, tail = t) {
00307          for (UInt_t i = 0; i < fDim; ++i) {
00308             const UInt_t head = fHeads[i];
00309             fHeads[i] = t;
00310             const Double_t temp1 = fDx[i];
00311             for (UInt_t j = head; j < tail; ++j, ++t)
00312                fProds[t] = temp1 * fProds[j];
00313          }
00314       }
00315 
00316       for (UInt_t i = 0 ; i < fPD ; i++)
00317          fA_K[i + ind] += temp * fProds[i];
00318    }
00319 
00320    for (UInt_t k = 0; k < fK; ++k) {
00321       const UInt_t ind = k * fPD;
00322       for (UInt_t i = 0; i < fPD; ++i)
00323          fA_K[i + ind] *= fC_K[i];
00324    }
00325 }
00326 
00327 //______________________________________________________________________________
00328 void TKDEFGT::Compute_A_k(const TGL5DDataSet *sources)
00329 {
00330    //Coefficients A_K. Special case for TTree and dim == 3.
00331    const Double_t ctesigma = 1. / fSigma;
00332    const UInt_t nP = sources->SelectedSize();
00333    
00334    for (UInt_t n = 0; n < nP; n++) {
00335       UInt_t ix2c     = fIndx[n];
00336       UInt_t ix2cbase = ix2c * 3;
00337       UInt_t ind      = ix2c * fPD;
00338       Double_t temp   = fWeights[n];
00339       Double_t sum    = 0.0;
00340 
00341       fDx[0] = (sources->V1(n) - fXC[ix2cbase]) * ctesigma;
00342       fDx[1] = (sources->V2(n) - fXC[ix2cbase + 1]) * ctesigma;
00343       fDx[2] = (sources->V3(n) - fXC[ix2cbase + 2]) * ctesigma;
00344       
00345       sum += (fDx[0] * fDx[0] + fDx[1] * fDx[1] + fDx[2] * fDx[2]);
00346       fHeads[0] = fHeads[1] = fHeads[2] = 0;
00347 
00348       fProds[0] = TMath::Exp(-sum);
00349 
00350       for (UInt_t k = 1, t = 1, tail = 1; k < fP; ++k, tail = t) {
00351          for (UInt_t i = 0; i < 3; ++i) {
00352             const UInt_t head = fHeads[i];
00353             fHeads[i] = t;
00354             const Double_t temp1 = fDx[i];
00355             for (UInt_t j = head; j < tail; ++j, ++t)
00356                fProds[t] = temp1 * fProds[j];
00357          }
00358       }
00359 
00360       for (UInt_t i = 0 ; i < fPD ; i++)
00361          fA_K[i + ind] += temp * fProds[i];
00362    }
00363 
00364    for (UInt_t k = 0; k < fK; ++k) {
00365       const Int_t ind = k * fPD;
00366       for (UInt_t i = 0; i < fPD; ++i)
00367          fA_K[i + ind] *= fC_K[i];
00368    }
00369 }
00370 
00371 namespace {
00372 
00373 UInt_t InvNChooseK(UInt_t d, UInt_t cnk);
00374 
00375 }
00376 
00377 //______________________________________________________________________________
00378 void TKDEFGT::Predict(const std::vector<Double_t> &ts, std::vector<Double_t> &v, Double_t eval)const
00379 {
00380    //Calculate densities.
00381    
00382    if (!fModelValid) {
00383       Error("TKDEFGT::Predict", "Call BuildModel first!");
00384       return;
00385    }
00386    
00387    if (!ts.size()) {
00388       Warning("TKDEFGT::Predict", "Empty targets vector.");
00389       return;
00390    }
00391 
00392    v.assign(ts.size() / fDim, 0.);
00393    
00394    fHeads.assign(fDim + 1, 0);
00395    fDx.assign(fDim, 0.);
00396    fProds.assign(fPD, 0.);
00397    
00398    const Double_t ctesigma = 1. / fSigma;
00399    const UInt_t p  = InvNChooseK(fDim , fPD);
00400    const UInt_t nP = UInt_t(ts.size()) / fDim;
00401    
00402    for (UInt_t m = 0; m < nP; ++m) {
00403       Double_t temp = 0.;
00404       const UInt_t mbase = m * fDim;
00405       
00406       for (UInt_t kn = 0 ; kn < fK ; ++kn) {
00407          const UInt_t xbase = kn * fDim;
00408          const UInt_t ind = kn * fPD;
00409          Double_t sum2  = 0.0;
00410          for (UInt_t i = 0; i < fDim ; ++i) {
00411             fDx[i] = (ts[i + mbase] - fXC[i + xbase]) * ctesigma;
00412             sum2 += fDx[i] * fDx[i];
00413             fHeads[i] = 0;
00414          }
00415 
00416          if (sum2 > eval) continue; //skip to next kn
00417 
00418          fProds[0] = TMath::Exp(-sum2);
00419 
00420          for (UInt_t k = 1, t = 1, tail = 1; k < p; ++k, tail = t) {
00421             for (UInt_t i = 0; i < fDim; ++i) {
00422                UInt_t head = fHeads[i];
00423                fHeads[i] = t;
00424                const Double_t temp1 = fDx[i];
00425                for (UInt_t j = head; j < tail; ++j, ++t)
00426                   fProds[t] = temp1 * fProds[j];
00427             }
00428          }
00429 
00430          for (UInt_t i = 0 ; i < fPD ; ++i)
00431             temp += fA_K[i + ind] * fProds[i];
00432       }
00433 
00434       v[m] = temp;
00435    }
00436    
00437    Double_t dMin = v[0], dMax = dMin;
00438    for (UInt_t i = 1; i < nP; ++i) {
00439       dMin = TMath::Min(dMin, v[i]);
00440       dMax = TMath::Max(dMax, v[i]);
00441    }
00442    
00443    const Double_t dRange = dMax - dMin;
00444    for (UInt_t i = 0; i < nP; ++i)
00445       v[i] = (v[i] - dMin) / dRange;
00446 
00447    dMin = v[0], dMax = dMin;
00448    for (UInt_t i = 1; i < nP; ++i) {
00449       dMin = TMath::Min(dMin, v[i]);
00450       dMax = TMath::Max(dMax, v[i]);
00451    }
00452 }
00453 
00454 namespace {
00455 
00456 //______________________________________________________________________________
00457 UInt_t NChooseK(UInt_t n, UInt_t k)
00458 {
00459    //n is always >= k.
00460    UInt_t n_k = n - k;
00461    if (k < n_k) {
00462       k = n_k;
00463       n_k = n - k;
00464    }
00465    UInt_t nchsk = 1;
00466    for (UInt_t i = 1; i <= n_k; ++i) {
00467       nchsk *= ++k;
00468       nchsk /= i;
00469    }
00470 
00471    return nchsk;
00472 }
00473 
00474 //______________________________________________________________________________
00475 Double_t DDist(Double_t x1, Double_t y1, Double_t z1, Double_t x2, Double_t y2, Double_t z2)
00476 {
00477    return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
00478 }
00479 
00480 //______________________________________________________________________________
00481 Double_t DDist(const Double_t *x , const Double_t *y , Int_t d)
00482 {
00483    Double_t t = 0., s = 0.;
00484 
00485    for (Int_t i = 0 ; i < d ; i++) {
00486       t  = (x[i] - y[i]);
00487       s += (t * t);
00488    }
00489 
00490    return s;
00491 }
00492 
00493 //______________________________________________________________________________
00494 UInt_t Idmax(const std::vector<Double_t> &x , UInt_t n)
00495 {
00496    UInt_t k = 0;
00497    Double_t t = -1.0;
00498    for (UInt_t i = 0; i < n; ++i) {
00499       if (t < x[i]) {
00500          t = x[i];
00501          k = i;
00502       }
00503    }
00504 
00505    return k;
00506 }
00507 
00508 //______________________________________________________________________________
00509 UInt_t InvNChooseK(UInt_t d, UInt_t cnk)
00510 {
00511    UInt_t cted = 1;
00512    for (UInt_t i = 2 ; i <= d ; ++i)
00513       cted *= i;
00514 
00515    const UInt_t cte = cnk * cted;
00516    UInt_t p = 2, ctep = 2;
00517 
00518    for (UInt_t i = p + 1; i < p + d; ++i)
00519       ctep *= i;
00520 
00521    while (ctep != cte) {
00522       ctep = ((p + d) * ctep) / p;
00523       ++p;
00524    }
00525 
00526    return p;
00527 }
00528 
00529 }//anonymous namespace.

Generated on Tue Jul 5 14:18:10 2011 for ROOT_528-00b_version by  doxygen 1.5.1