- fNTNodes = fNpoints/fBucketSize + ((fNpoints%fBucketSize)?1:0);/*TKDTreeIF::GetNTNodes();*/
- if(!fBoundaries) MakeBoundaries();
- fLambda = 1 + fNDim + (fNDim*(fNDim+1)>>1);
- //printf("after MakeBoundaries() %d\n", memory());
-
- // allocate interpolation nodes
- TKDInterpolatorBase::Build(fNTNodes);
-
- TKDNodeInfo *node = 0x0;
- Float_t *bounds = 0x0;
- Int_t *indexPoints;
- for(int inode=0, tnode = fNnodes; inode<fNTNodes-1; inode++, tnode++){
- node = (TKDNodeInfo*)(*fTNodes)[inode];
- node->Val()[0] = Float_t(fBucketSize)/fNpoints;
- bounds = GetBoundary(tnode);
- for(int idim=0; idim<fNDim; idim++) node->Val()[0] /= (bounds[2*idim+1] - bounds[2*idim]);
- node->Val()[1] = node->Val()[0]/TMath::Sqrt(float(fBucketSize));
-
- indexPoints = GetPointsIndexes(tnode);
- // loop points in this terminal node
- for(int idim=0; idim<fNDim; idim++){
- node->Data()[idim] = 0.;
- for(int ip = 0; ip<fBucketSize; ip++) node->Data()[idim] += fData[idim][indexPoints[ip]];
- node->Data()[idim] /= fBucketSize;
- }
- memcpy(&(node->Data()[fNDim]), bounds, fNDimm*sizeof(Float_t));
- }
-
- // analyze last (incomplete) terminal node
- Int_t counts = fNpoints%fBucketSize;
- counts = counts ? counts : fBucketSize;
- Int_t inode = fNTNodes - 1, tnode = inode + fNnodes;
- node = (TKDNodeInfo*)(*fTNodes)[inode];
- node->Val()[0] = Float_t(counts)/fNpoints;
- bounds = GetBoundary(tnode);
- for(int idim=0; idim<fNDim; idim++) node->Val()[0] /= (bounds[2*idim+1] - bounds[2*idim]);
- node->Val()[1] = node->Val()[0]/TMath::Sqrt(float(counts));
-
- // loop points in this terminal node
- indexPoints = GetPointsIndexes(tnode);
- for(int idim=0; idim<fNDim; idim++){
- node->Data()[idim] = 0.;
- for(int ip = 0; ip<counts; ip++) node->Data()[idim] += fData[idim][indexPoints[ip]];
- node->Data()[idim] /= counts;
- }
- memcpy(&(node->Data()[fNDim]), bounds, fNDimm*sizeof(Float_t));
-
- delete [] fBoundaries;
- fBoundaries = 0x0;
+ TKDTreeIF::Build();
+ if(!fBoundaries) MakeBoundaries();
+ fLambda = 1 + fNDim + (fNDim*(fNDim+1)>>1);
+ //printf("after MakeBoundaries() %d\n", memory());
+
+ // allocate interpolation nodes
+ Int_t fNTNodes = fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);/*TKDTreeIF::GetNTNodes();*/
+ TKDInterpolatorBase::Build(fNTNodes);
+
+ TKDNodeInfo *node = NULL;
+ Float_t *bounds = NULL;
+ Int_t *indexPoints;
+ for(int inode=0, tnode = fNNodes; inode<fNTNodes-1; inode++, tnode++){
+ node = (TKDNodeInfo*)(*fNodes)[inode];
+ node->Val()[0] = Float_t(fBucketSize)/fNPoints;
+ bounds = GetBoundary(tnode);
+ for(int idim=0; idim<fNDim; idim++) node->Val()[0] /= (bounds[2*idim+1] - bounds[2*idim]);
+ node->Val()[1] = node->Val()[0]/TMath::Sqrt(float(fBucketSize));
+
+ indexPoints = GetPointsIndexes(tnode);
+ // loop points in this terminal node
+ for(int idim=0; idim<fNDim; idim++){
+ node->Data()[idim] = 0.;
+ for(int ip = 0; ip<fBucketSize; ip++) node->Data()[idim] += fData[idim][indexPoints[ip]];
+ node->Data()[idim] /= fBucketSize;
+ }
+ memcpy(&(node->Data()[fNDim]), bounds, fNDimm*sizeof(Float_t));
+ }
+
+ // analyze last (incomplete) terminal node
+ Int_t counts = fNPoints%fBucketSize;
+ counts = counts ? counts : fBucketSize;
+ Int_t inode = fNTNodes - 1, tnode = inode + fNNodes;
+ node = (TKDNodeInfo*)(*fNodes)[inode];
+ node->Val()[0] = Float_t(counts)/fNPoints;
+ bounds = GetBoundary(tnode);
+ for(int idim=0; idim<fNDim; idim++){
+ Float_t dx = bounds[2*idim+1]-bounds[2*idim];
+ if(dx < 1.e-30){
+ Warning("TKDPDF::Build()", Form("Terminal bucket index[%d] too narrow on the %d dimension.", inode, idim));
+ continue;
+ }
+ node->Val()[0] /= (bounds[2*idim+1] - bounds[2*idim]);
+ }
+ node->Val()[1] = node->Val()[0]/TMath::Sqrt(float(counts));
+
+ // loop points in this terminal node
+ indexPoints = GetPointsIndexes(tnode);
+ for(int idim=0; idim<fNDim; idim++){
+ node->Data()[idim] = 0.;
+ for(int ip = 0; ip<counts; ip++) node->Data()[idim] += fData[idim][indexPoints[ip]];
+ node->Data()[idim] /= counts;
+ }
+ memcpy(&(node->Data()[fNDim]), bounds, fNDimm*sizeof(Float_t));
+
+ delete [] fBoundaries;
+ fBoundaries = NULL;
+
+ return kTRUE;