#include "TKDInterpolator.h" #include "TLinearFitter.h" #include "TVector.h" #include "TTree.h" #include "TH2.h" #include "TObjArray.h" #include "TObjString.h" #include "TPad.h" #include "TBox.h" #include "TGraph.h" #include "TMarker.h" #include "TRandom.h" #include "TROOT.h" ClassImp(TKDInterpolator) ClassImp(TKDInterpolator::TKDNodeInfo) ///////////////////////////////////////////////////////////////////// // Memory setup of protected data memebers // fRefPoints : evaluation point of PDF for each terminal node of underlying KD Tree. // | 1st terminal node (fNDim point coordinates) | 2nd terminal node (fNDim point coordinates) | ... // // fRefValues : evaluation value/error of PDF for each terminal node of underlying KD Tree. // | 1st terminal node (value) | 2nd terminal node (value) | ... | 1st terminal node (error) | 2nd terminal node (error) | ... // // status = |0|0|0|0|0|1(tri-cubic weights)|1(STORE)|1 INT(0 COG )| ///////////////////////////////////////////////////////////////////// //_________________________________________________________________ TKDInterpolator::TKDNodeInfo::TKDNodeInfo(const Int_t dim): fNDim(dim) ,fRefPoint(0x0) ,fRefValue(0.) ,fCov() ,fPar() ,fPDFstatus(kFALSE) { if(fNDim) Build(dim); } //_________________________________________________________________ TKDInterpolator::TKDNodeInfo::~TKDNodeInfo() { if(fRefPoint) delete [] fRefPoint; } //_________________________________________________________________ void TKDInterpolator::TKDNodeInfo::Build(const Int_t dim) { if(!dim) return; fNDim = dim; Int_t lambda = Int_t(1 + fNDim + .5*fNDim*(fNDim+1)); if(fRefPoint) delete [] fRefPoint; fRefPoint = new Float_t[fNDim]; fCov.ResizeTo(lambda, lambda); fPar.ResizeTo(lambda); return; } //_________________________________________________________________ TKDInterpolator::TKDInterpolator() : TKDTreeIF() ,fNTNodes(0) ,fTNodes(0x0) ,fStatus(4) ,fLambda(0) ,fDepth(-1) ,fRefPoints(0x0) ,fBuffer(0x0) ,fKDhelper(0x0) ,fFitter(0x0) { // Default constructor. To be used with care since in this case building // of data structure is completly left to the user responsability. } //_________________________________________________________________ TKDInterpolator::TKDInterpolator(Int_t npoints, Int_t ndim, UInt_t bsize, Float_t **data) : TKDTreeIF(npoints, ndim, bsize, data) ,fNTNodes(GetNTerminalNodes()) ,fTNodes(0x0) ,fStatus(4) ,fLambda(0) ,fDepth(-1) ,fRefPoints(0x0) ,fBuffer(0x0) ,fKDhelper(0x0) ,fFitter(0x0) { // Wrapper constructor for the similar TKDTree one. Build(); } //_________________________________________________________________ TKDInterpolator::TKDInterpolator(TTree *t, const Char_t *var, const Char_t *cut, UInt_t bsize, Long64_t nentries, Long64_t firstentry) : TKDTreeIF() ,fNTNodes(0) ,fTNodes(0x0) ,fStatus(4) ,fLambda(0) ,fDepth(-1) ,fRefPoints(0x0) ,fBuffer(0x0) ,fKDhelper(0x0) ,fFitter(0x0) { // Alocate data from a tree. The variables which have to be analysed are // defined in the "var" parameter as a colon separated list. The format should // be identical to that used by TTree::Draw(). // // TObjArray *vars = TString(var).Tokenize(":"); fNDim = vars->GetEntriesFast(); fNDimm = 2*fNDim; if(fNDim > 6/*kDimMax*/) Warning("TKDInterpolator(TTree*, const Char_t, const Char_t, UInt_t)", Form("Variable number exceed maximum dimension %d. Results are unpredictable.", 6/*kDimMax*/)); fBucketSize = bsize; Int_t np; Double_t *v; for(int idim=0; idimDraw(((TObjString*)(*vars)[idim])->GetName(), cut, "goff", nentries, firstentry))){ Warning("TKDInterpolator(TTree*, const Char_t, const Char_t, UInt_t)", Form("Can not access data for keys %s. Key defined on tree :", ((TObjString*)(*vars)[idim])->GetName() )); TIterator *it = (t->GetListOfLeaves())->MakeIterator(); TObject *o; while(o = (*it)()) printf("\t%s\n", o->GetName()); continue; } if(!fNpoints){ fNpoints = np; Info("TKDInterpolator(TTree*, const Char_t, const Char_t, UInt_t)", Form("Allocating %d data points in %d dimensions.", fNpoints, fNDim)); fData = new Float_t*[fNDim]; for(int idim=0; idimGetV1(); for(int ip=0; ipFindNearestNeighbors(pointF, npoints+1, index, dist)){ Error("Eval()", Form("Failed retriving %d neighbours for point:", npoints)); for(int idim=0; idimClearPoints(); for(int in=0; inAddPoint(fBuffer, fTNodes[index[in]].fRefValue, fTNodes[index[in]].fRefValue*sig/w); } npoints += 4; } while(fFitter->Eval()); // retrive fitter results TMatrixD cov(fLambda, fLambda); TVectorD par(fLambda); fFitter->GetCovarianceMatrix(cov); fFitter->GetParameters(par); Double_t chi2 = fFitter->GetChisquare()/(npoints - 4 - fLambda); // store results if(fStatus&2 && fStatus&1){ fTNodes[node].fPar = par; fTNodes[node].fCov = cov; fTNodes[node].fPDFstatus = kTRUE; } // Build df/dpi|x values Double_t *fdfdp = &fBuffer[fLambda]; ipar = 0; fdfdp[ipar++] = 1.; for(int idim=0; idimSetFormula(Form("hyp%d", fNDim+1)); // // // Float_t pointF[50]; // for(int idim=0; idimClearPoints(); // do{ // if(!fKDhelper->FindNearestNeighbors(pointF, npoints+1, index, dist)){ // Error("Eval()", Form("Failed retriving %d neighbours for point:", npoints)); // for(int idim=0; idimAddPoint(fBuffer, fRefValues[index[in]], fRefValues[index[in]]*uncertainty); // } // istart = npoints; // npoints += 4; // } while(fFitter->Eval()); // delete [] w; // // // calculate evaluation // // fFitter->PrintResults(3); // TMatrixD cov(lambda, lambda); // TVectorD par(lambda); // fFitter->GetCovarianceMatrix(cov); // fFitter->GetParameters(par); // // // Build temporary array to keep values df/dpi|x // Double_t f[100]; // ipar = 0; // f[ipar++] = 1.; // for(int idim=0; idimGetChisquare()/(npoints - 4 - lambda); // // for(int ipar=0; ipar> depth != 1) continue; nnodes++; } //printf("depth %d nodes %d\n", depth, nnodes); TH2 *h2 = 0x0; if(!(h2 = (TH2S*)gROOT->FindObject("hNodes"))) h2 = new TH2S("hNodes", "", 100, fRange[2*ax1], fRange[2*ax1+1], 100, fRange[2*ax2], fRange[2*ax2+1]); h2->GetXaxis()->SetTitle(Form("x_{%d}", ax1)); h2->GetYaxis()->SetTitle(Form("x_{%d}", ax2)); h2->Draw(); const Float_t border = 0.;//1.E-4; TBox *node_array = new TBox[nnodes], *node; Float_t *bounds = 0x0; nnodes = 0; for(int inode = 0; inode <= 2*fNnodes; inode++){ if(depth == -1){ if(!IsTerminal(inode)) continue; } else if((inode+1) >> depth != 1) continue; node = &node_array[nnodes++]; //node = new TBox(bounds[2*ax1]+border, bounds[2*ax2]+border, bounds[2*ax1+1]-border, bounds[2*ax2+1]-border); node->SetFillStyle(3002); node->SetFillColor(50+Int_t(gRandom->Uniform()*50.)); bounds = GetBoundary(inode); node->DrawBox(bounds[2*ax1]+border, bounds[2*ax2]+border, bounds[2*ax1+1]-border, bounds[2*ax2+1]-border); } if(depth != -1) return; // Draw reference points TGraph *ref = new TGraph(GetNTerminalNodes()); ref->SetMarkerStyle(3); ref->SetMarkerSize(.7); ref->SetMarkerColor(2); for(int inode = 0; inode < GetNTerminalNodes(); inode++) ref->SetPoint(inode, fTNodes[inode].fRefPoint[ax1], fTNodes[inode].fRefPoint[ax2]); ref->Draw("p"); return; } //_________________________________________________________________ void TKDInterpolator::DrawNode(Int_t tnode, UInt_t ax1, UInt_t ax2) { // Draw node "node" and the data points within. // // Observation: // This function creates some graphical objects // but don't delete it. Abusing this function may cause memory leaks ! if(tnode < 0 || tnode >= GetNTerminalNodes()){ Warning("DrawNode()", Form("Terminal node %d outside defined range.", tnode)); return; } Int_t inode = tnode; tnode += fNnodes; // select zone of interest in the indexes array Int_t *index = GetPointsIndexes(tnode); Int_t nPoints = (tnode == 2*fNnodes) ? fNpoints%fBucketSize : fBucketSize; // draw data points TGraph *g = new TGraph(nPoints); g->SetMarkerStyle(7); for(int ip = 0; ipSetPoint(ip, fData[ax1][index[ip]], fData[ax2][index[ip]]); // draw estimation point TMarker *m=new TMarker(fTNodes[inode].fRefPoint[ax1], fTNodes[inode].fRefPoint[ax2], 20); m->SetMarkerColor(2); m->SetMarkerSize(1.7); // draw node contour Float_t *bounds = GetBoundary(tnode); TBox *n = new TBox(bounds[2*ax1], bounds[2*ax2], bounds[2*ax1+1], bounds[2*ax2+1]); n->SetFillStyle(0); if(gPad) gPad->Clear(); g->Draw("ap"); m->Draw(); n->Draw(); return; } //__________________________________________________________________ void TKDInterpolator::SetIntInterpolation(const Bool_t on) { // Set interpolation bit to "on" and build/delete memory if(on) fStatus += fStatus&1 ? 0 : 1; else fStatus += fStatus&1 ? -1 : 0; TString formula; if(on) formula = Form("hyp%d", fLambda-1); else { formula = "1"; for(int idim=0; idimSetFormula(formula.Data()); } //_________________________________________________________________ void TKDInterpolator::SetSetStore(const Bool_t on) { // Set store bit to "on" and build/delete memory if(on){ fStatus += fStatus&2 ? 0 : 2; /* if(!fCov){ fPDFstatus = new Bool_t[fNTNodes]; fCov = new TMatrixD[fNTNodes]; fPar = new TVectorD[fNTNodes]; for(int i=0; i