00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TSystem.h"
00013 #include "TMatrixD.h"
00014 #include "TRandom.h"
00015 #include "TGraph.h"
00016 #include "TStopwatch.h"
00017 #include "TKDTree.h"
00018
00019
00020
00021
00022 void TestBuild(const Int_t npoints = 1000000, const Int_t bsize = 100);
00023 void TestConstr(const Int_t npoints = 1000000, const Int_t bsize = 100);
00024 void TestSpeed(Int_t npower2 = 20, Int_t bsize = 10);
00025
00026
00027
00028
00029
00030
00031 Float_t Mem()
00032 {
00033
00034 ProcInfo_t procInfo;
00035 gSystem->GetProcInfo(&procInfo);
00036 return procInfo.fMemVirtual;
00037 }
00038
00039
00040 void kDTreeTest()
00041 {
00042
00043
00044
00045 printf("\n\tTesting kDTree memory usage ...\n");
00046 TestBuild();
00047 printf("\n\tTesting kDTree speed ...\n");
00048 TestSpeed();
00049 }
00050
00051
00052 void TestBuild(const Int_t npoints, const Int_t bsize){
00053
00054
00055
00056 Float_t *data0 = new Float_t[npoints*2];
00057 Float_t *data[2];
00058 data[0] = &data0[0];
00059 data[1] = &data0[npoints];
00060 for (Int_t i=0;i<npoints;i++) {
00061 data[1][i]= gRandom->Rndm();
00062 data[0][i]= gRandom->Rndm();
00063 }
00064 Float_t before =Mem();
00065 TKDTreeIF *kdtree = new TKDTreeIF(npoints, 2, bsize, data);
00066 kdtree->Build();
00067 Float_t after = Mem();
00068 printf("Memory usage %f KB\n",after-before);
00069 delete kdtree;
00070 Float_t end = Mem();
00071 printf("Memory leak %f KB\n", end-before);
00072 return;
00073 }
00074
00075
00076 void TestMembers()
00077 {
00078
00079
00080
00081
00082
00083
00084
00085 TKDTreeIF *kdtree = 0x0;
00086 Int_t npoints = 33;
00087 Int_t bsize = 10;
00088 Float_t *data0 = new Float_t[200];
00089 Float_t *data1 = new Float_t[200];
00090 for (Int_t i=0;i<npoints;i++) {
00091 data0[i]= gRandom->Rndm();
00092 data1[i]= gRandom->Rndm();
00093 }
00094
00095 kdtree = new TKDTreeIF(npoints, 2, bsize);
00096 kdtree->SetData(0, data0);
00097 kdtree->SetData(1, data1);
00098 kdtree->Build();
00099
00100 printf("fNNodes %d, fRowT0 %d, fCrossNode %d, fOffset %d\n",kdtree->GetNNodes(), kdtree->GetRowT0(), kdtree->GetCrossNode(), kdtree->GetOffset());
00101 delete kdtree;
00102 npoints = 44;
00103 for (Int_t i=0;i<npoints;i++) {
00104 data0[i]= gRandom->Rndm();
00105 data1[i]= gRandom->Rndm();
00106 }
00107 kdtree = new TKDTreeIF(npoints, 2, bsize);
00108 kdtree->SetData(0, data0);
00109 kdtree->SetData(1, data1);
00110 kdtree->Build();
00111
00112 printf("fNNodes %d, fRowT0 %d, fCrossNode %d, fOffset %d\n",kdtree->GetNNodes(), kdtree->GetRowT0(), kdtree->GetCrossNode(), kdtree->GetOffset());
00113 delete kdtree;
00114 npoints = 55;
00115 for (Int_t i=0;i<npoints;i++) {
00116 data0[i]= gRandom->Rndm();
00117 data1[i]= gRandom->Rndm();
00118 }
00119 kdtree = new TKDTreeIF(npoints, 2, bsize);
00120 kdtree->SetData(0, data0);
00121 kdtree->SetData(1, data1);
00122 kdtree->Build();
00123
00124 printf("fNNodes %d, fRowT0 %d, fCrossNode %d, fOffset %d\n",kdtree->GetNNodes(), kdtree->GetRowT0(), kdtree->GetCrossNode(), kdtree->GetOffset());
00125 delete kdtree;
00126 npoints = 66;
00127 for (Int_t i=0;i<npoints;i++) {
00128 data0[i]= gRandom->Rndm();
00129 data1[i]= gRandom->Rndm();
00130 }
00131 kdtree = new TKDTreeIF(npoints, 2, bsize);
00132 kdtree->SetData(0, data0);
00133 kdtree->SetData(1, data1);
00134 kdtree->Build();
00135
00136 printf("fNNodes %d, fRowT0 %d, fCrossNode %d, fOffset %d\n",kdtree->GetNNodes(), kdtree->GetRowT0(), kdtree->GetCrossNode(), kdtree->GetOffset());
00137 delete kdtree;
00138 npoints = 77;
00139 for (Int_t i=0;i<npoints;i++) {
00140 data0[i]= gRandom->Rndm();
00141 data1[i]= gRandom->Rndm();
00142 }
00143 kdtree = new TKDTreeIF(npoints, 2, bsize);
00144 kdtree->SetData(0, data0);
00145 kdtree->SetData(1, data1);
00146 kdtree->Build();
00147
00148 printf("fNNodes %d, fRowT0 %d, fCrossNode %d, fOffset %d\n",kdtree->GetNNodes(), kdtree->GetRowT0(), kdtree->GetCrossNode(), kdtree->GetOffset());
00149 delete kdtree;
00150 npoints = 88;
00151 for (Int_t i=0;i<npoints;i++) {
00152 data0[i]= gRandom->Rndm();
00153 data1[i]= gRandom->Rndm();
00154 }
00155 kdtree = new TKDTreeIF(npoints, 2, bsize);
00156 kdtree->SetData(0, data0);
00157 kdtree->SetData(1, data1);
00158 kdtree->Build();
00159
00160 printf("fNNodes %d, fRowT0 %d, fCrossNode %d, fOffset %d\n",kdtree->GetNNodes(), kdtree->GetRowT0(), kdtree->GetCrossNode(), kdtree->GetOffset());
00161 delete kdtree;
00162
00163
00164
00165 delete data0;
00166 delete data1;
00167 }
00168
00169
00170
00171
00172 void TestConstr(const Int_t npoints, const Int_t bsize)
00173 {
00174
00175
00176
00177
00178 Float_t *data0 = new Float_t[npoints*2];
00179 Float_t *data[2];
00180 data[0] = &data0[0];
00181 data[1] = &data0[npoints];
00182 for (Int_t i=0;i<npoints;i++) {
00183 data[1][i]= gRandom->Rndm();
00184 data[0][i]= gRandom->Rndm();
00185 }
00186 Float_t before =Mem();
00187 TKDTreeIF *kdtree1 = new TKDTreeIF(npoints, 2, bsize, data);
00188 kdtree1->Build();
00189 TKDTreeIF *kdtree2 = new TKDTreeIF(npoints, 2, bsize);
00190 kdtree2->SetData(0, data[0]);
00191 kdtree2->SetData(1, data[1]);
00192 kdtree2->Build();
00193 Int_t nnodes = kdtree1->GetNNodes();
00194 if (nnodes - kdtree2->GetNNodes()>1){
00195 printf("different number of nodes\n");
00196 return;
00197 }
00198 for (Int_t inode=0; inode<nnodes; inode++){
00199 Float_t value1 = kdtree1->GetNodeValue(inode);
00200 Float_t value2 = kdtree2->GetNodeValue(inode);
00201 if (TMath::Abs(value1-value2 > 0.001)){
00202 printf("node %d value: %f %f\n", inode, kdtree1->GetNodeValue(inode), kdtree2->GetNodeValue(inode));
00203 }
00204 }
00205 delete kdtree1;
00206 delete kdtree2;
00207 Float_t end = Mem();
00208 printf("Memory leak %f KB\n", end-before);
00209 return;
00210 }
00211
00212
00213
00214 void TestSpeed(Int_t npower2, Int_t bsize)
00215 {
00216
00217
00218
00219 if(npower2 < 10){
00220 printf("Please specify a power of 2 greater than 10\n");
00221 return;
00222 }
00223
00224 Int_t npoints = Int_t(pow(2., npower2))*bsize;
00225 Float_t *data0 = new Float_t[npoints*2];
00226 Float_t *data[2];
00227 data[0] = &data0[0];
00228 data[1] = &data0[npoints];
00229 for (Int_t i=0;i<npoints;i++) {
00230 data[1][i]= gRandom->Rndm();
00231 data[0][i]= gRandom->Rndm();
00232 }
00233
00234 TGraph *g = new TGraph(npower2-10);
00235 g->SetMarkerStyle(7);
00236 TStopwatch timer;
00237 Int_t tpoints;
00238 TKDTreeIF *kdtree = 0x0;
00239 for(int i=10; i<npower2; i++){
00240 tpoints = Int_t(pow(2., i))*bsize;
00241 timer.Start(kTRUE);
00242 kdtree = new TKDTreeIF(tpoints, 2, bsize, data);
00243 kdtree->Build();
00244 timer.Stop();
00245 g->SetPoint(i-10, i, timer.CpuTime());
00246 printf("npoints [%d] nodes [%d] cpu time %f [s]\n", tpoints, kdtree->GetNNodes(), timer.CpuTime());
00247
00248 delete kdtree;
00249 }
00250 g->Draw("apl");
00251 return;
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 void TestNeighbors()
00368 {
00369
00370
00371
00372 Int_t npoints = 10000;
00373 Int_t nn = 100;
00374 Int_t ntimes = 100;
00375 Int_t bsize = 10;
00376
00377 Double_t *x = new Double_t[npoints];
00378 Double_t *y = new Double_t[npoints];
00379 Double_t *z = new Double_t[npoints];
00380 for (Int_t i=0; i<npoints; i++){
00381 x[i] = gRandom->Uniform(-100, 100);
00382 y[i] = gRandom->Uniform(-100, 100);
00383 z[i] = gRandom->Uniform(-100, 100);
00384 }
00385
00386 Int_t diff1=0;
00387
00388
00389 Double_t *dist = new Double_t[npoints];
00390 Int_t *index = new Int_t[npoints];
00391
00392
00393 TKDTreeID *kdtree = new TKDTreeID(npoints, 3, bsize);
00394 kdtree->SetData(0, x);
00395 kdtree->SetData(1, y);
00396 kdtree->SetData(2, z);
00397 kdtree->Build();
00398 Int_t *index2 = new Int_t[nn];
00399 Double_t *dist2 = new Double_t[nn];
00400 Double_t point[3];
00401
00402 for (Int_t itime=0; itime<ntimes; itime++){
00403 Int_t ipoint = Int_t(gRandom->Uniform(0, npoints));
00404
00405 for (Int_t i=0; i<npoints; i++){
00406 dist[i]=0;
00407
00408 dist[i]+=(x[i]-x[ipoint])*(x[i]-x[ipoint]);
00409 dist[i]+=(y[i]-y[ipoint])*(y[i]-y[ipoint]);
00410 dist[i]+=(z[i]-z[ipoint])*(z[i]-z[ipoint]);
00411 dist[i]=TMath::Sqrt(dist[i]);
00412
00413 }
00414 TMath::Sort(npoints, dist, index, kFALSE);
00415
00416 point[0]=x[ipoint];
00417 point[1]=y[ipoint];
00418 point[2]=z[ipoint];
00419
00420 kdtree->FindNearestNeighbors(point, nn, index2, dist2);
00421
00422
00423 for (Int_t inn=0; inn<nn; inn++){
00424 if (TMath::Abs(dist2[inn]-dist[index[inn]])>1E-8) {
00425 diff1++;
00426
00427 }
00428
00429
00430 }
00431 }
00432
00433 printf("Nearest neighbors found for %d random points\n", ntimes);
00434 printf("%d neighbors are wrong compared to \"brute force\" method\n", diff1);
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 delete [] x;
00446 delete [] y;
00447 delete [] z;
00448 delete [] index;
00449 delete [] dist;
00450 delete [] index2;
00451 delete [] dist2;
00452 }
00453
00454
00455 void TestRange()
00456 {
00457
00458
00459
00460 Int_t npoints = Int_t(gRandom->Uniform(0, 100000));
00461 Double_t range = gRandom->Uniform(20, 100);
00462
00463 printf("%d points, range=%f\n", npoints, range);
00464 Int_t ntimes = 10;
00465 Double_t *x = new Double_t[npoints];
00466 Double_t *y = new Double_t[npoints];
00467 Double_t *z = new Double_t[npoints];
00468 for (Int_t i=0; i<npoints; i++){
00469 x[i] = gRandom->Uniform(-100, 100);
00470 y[i] = gRandom->Uniform(-100, 100);
00471 z[i] = gRandom->Uniform(-100, 100);
00472 }
00473
00474 Int_t *results1 = new Int_t[npoints];
00475 std::vector<Int_t> results2;
00476 Int_t np1;
00477
00478
00479 Int_t bsize = 10;
00480 TKDTreeID *kdtree = new TKDTreeID(npoints, 3, bsize);
00481 kdtree->SetData(0, x);
00482 kdtree->SetData(1, y);
00483 kdtree->SetData(2, z);
00484 kdtree->Build();
00485 Double_t *dist = new Double_t[npoints];
00486 Int_t *index = new Int_t[npoints];
00487 Int_t ndiff = 0;
00488 for (Int_t itime=0; itime<ntimes; itime++){
00489 Double_t point[3];
00490 point[0]=gRandom->Uniform(-90, 90);
00491 point[1]=gRandom->Uniform(-90, 90);
00492 point[2]=gRandom->Uniform(-90, 90);
00493
00494
00495 for (Int_t ipoint=0; ipoint<npoints; ipoint++){
00496 dist[ipoint]=0;
00497 dist[ipoint]+=(x[ipoint]-point[0])*(x[ipoint]-point[0]);
00498 dist[ipoint]+=(y[ipoint]-point[1])*(y[ipoint]-point[1]);
00499 dist[ipoint]+=(z[ipoint]-point[2])*(z[ipoint]-point[2]);
00500 dist[ipoint]=TMath::Sqrt(dist[ipoint]);
00501 index[ipoint]=ipoint;
00502 }
00503 TMath::Sort(npoints, dist, index, kFALSE);
00504 np1=0;
00505 while (np1<npoints && dist[index[np1]]<=range){
00506 results1[np1]=index[np1];
00507 np1++;
00508 }
00509 results2.clear();
00510 kdtree->FindInRange(point, range, results2);
00511
00512 if (TMath::Abs(np1 - Int_t(results2.size()))>0.1) {
00513 ndiff++;
00514 printf("different numbers of points found, %d %d\n", np1, Int_t(results2.size()));
00515 continue;
00516 }
00517
00518
00519 TMath::Sort(np1, results1, index, kFALSE);
00520 std::sort(results2.begin(), results2.end());
00521
00522 for (Int_t i=0; i<np1; i++){
00523 if (TMath::Abs(results1[index[i]]-results2[i])>1E-8) ndiff++;
00524 }
00525 }
00526 printf("%d differences found between \"brute force\" method and kd-tree\n", ndiff);
00527
00528 delete [] x;
00529 delete [] y;
00530 delete [] z;
00531 delete [] index;
00532 delete [] dist;
00533 delete [] results1;
00534 delete kdtree;
00535 }
00536
00537
00538
00539
00540
00541 int main() {
00542 kDTreeTest();
00543 return 0;
00544 }