]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STAT/Macros/kNNTest.C
Coding conventions
[u/mrichter/AliRoot.git] / STAT / Macros / kNNTest.C
1 #include <malloc.h>
2
3 #include "TSystem.h"
4 #include "TFile.h"
5 #include "TTree.h"
6 #include "TH2I.h"
7 #include "TLegend.h"
8 #include "TRandom.h"
9 #include "TString.h"
10 #include "TGraph.h"
11 #include "TMarker.h"
12 #include "TStopwatch.h"
13 #include "../src/TKDPDF.h"
14 #include "../src/TKDTree.h"
15
16 void kNNTest(const int np = 10000, const int ndim = 2);
17 void kNNDraw(const Float_t *p, const int kNN=20);
18 void build(const Int_t ndim = 2, const Int_t nstat = 1000000);
19 Float_t Mem();
20
21
22 //______________________________________________________________
23 void kNNTest(const int np, const int ndim)
24 {
25 // Test speed and quality of nearest neighbors search.
26 // The results are compared with a simple loop search through the data.
27 // The macro should run in compiled mode.
28
29         const int ntimes = 1000; // times to repeate kNN search
30         const Int_t kNN = 1; // number of neighbors
31
32         Float_t **x = new Float_t*[ndim];
33         for(int idim =0 ; idim<ndim; idim++){
34                 x[idim] = new Float_t[np];
35                 for(int ip=0; ip<np; ip++) x[idim][ip] = gRandom->Gaus();
36         }
37         TKDTreeIF nnFinder(np, ndim, 1, x);
38         
39         // generate test sample
40         Float_t **p = new Float_t*[ntimes];
41         for(int ip =0 ; ip<ntimes; ip++){
42                 p[ip] = new Float_t[ndim];
43                 for(int idim=0; idim<ndim; idim++) p[ip][idim] = gRandom->Gaus();
44         }
45
46
47         Int_t *index;
48         Float_t *d;
49         TStopwatch timer;
50         timer.Start(kTRUE);
51         for(int itime=0; itime<ntimes; itime++) nnFinder.FindNearestNeighbors(p[itime], kNN, index, d);
52         timer.Stop();
53         printf("kDTree NN calculation.\n");
54         printf("cpu = %f [ms] real = %f [ms]\n", 1.E3*timer.CpuTime()/ntimes, 1.E3*timer.RealTime()/ntimes);
55         printf("Points indexes in increasing order of their distance to the target point.\n");
56         for(int i=0; i<kNN; i++){
57                 printf("%5d [%7.4f] ", index[i], d[i]);
58                 if(i%5==4) printf("\n");
59         }
60         printf("\n");
61         
62         // draw kNN
63         TLegend *leg = new TLegend(.7, .7, .9, .9);
64         leg->SetBorderSize(1);
65         leg->SetHeader("NN finders");
66         TH2 *h2 = new TH2I("h2", "", 100, -2., 2., 100, -2., 2.);
67         h2->Draw(); h2->SetStats(kFALSE);
68         TMarker *mp = new TMarker(p[ntimes-1][0], p[ntimes-1][1], 3);
69         mp->SetMarkerColor(4);
70         mp->Draw(); leg->AddEntry(mp, "Target", "p");
71         TGraph *gKD = new TGraph(kNN);
72         gKD->SetMarkerStyle(24);
73         gKD->SetMarkerColor(2);
74         gKD->SetMarkerSize(.5);
75         for(int ip=0; ip<kNN; ip++) gKD->SetPoint(ip, x[0][index[ip]], x[1][index[ip]]);
76         gKD->Draw("p"); leg->AddEntry(gKD, "kDTree", "p");
77         
78
79                 
80         // STAND ALONE
81         Float_t ftmp, gtmp, dist;
82         Int_t itmp, jtmp;
83         Int_t   fkNN[kNN];
84         Float_t fkNNdist[kNN];
85         for(int i=0; i<kNN; i++) fkNNdist[i] = 9999.;
86
87         // calculate
88         timer.Start(kTRUE);
89         for(int idx=0; idx<np; idx++){
90                 // calculate distance in the L1 metric
91                 dist = 0.;
92                 for(int idim=0; idim<ndim; idim++) dist += TMath::Abs(p[ntimes-1][idim] - x[idim][idx]);
93                 if(dist >= fkNNdist[kNN-1]) continue;
94
95                 //insert neighbor
96                 int iNN=0;
97                 while(dist >= fkNNdist[iNN]) iNN++;
98                 itmp = fkNN[iNN]; ftmp = fkNNdist[iNN];
99                 fkNN[iNN]     = idx;
100                 fkNNdist[iNN] = dist;
101                 for(int ireplace=iNN+1; ireplace<kNN; ireplace++){
102                         jtmp = fkNN[ireplace]; gtmp = fkNNdist[ireplace];
103                         fkNN[ireplace] = itmp; fkNNdist[ireplace] = ftmp;
104                         itmp = jtmp; ftmp = gtmp;
105                         if(ftmp == 9999.) break;
106                 }
107         }
108         timer.Stop();
109         printf("\nStand Alone NN calculation.\n");
110         printf("cpu = %f [ms] real = %f [ms]\n", 1.E3*timer.CpuTime(), 1.E3*timer.RealTime());
111         printf("Points indexes in increasing order of their distance to the target point.\n");
112         for(int i=0; i<kNN; i++){
113                 printf("%5d [%7.4f] ", fkNN[i], fkNNdist[i]);
114                 if(i%5==4) printf("\n");
115         }
116         printf("\n");   
117
118         TGraph *gSA = new TGraph(kNN);
119         gSA->SetMarkerStyle(24);
120         for(int ip=0; ip<kNN; ip++) gSA->SetPoint(ip, x[0][fkNN[ip]], x[1][fkNN[ip]]);
121
122         gSA->Draw("p"); leg->AddEntry(gSA, "Stand Alone", "p");
123         leg->Draw();
124         
125         for(int ip=0; ip<ntimes; ip++) delete [] p[ip];
126         delete [] p;
127         for(int idim=0; idim<ndim; idim++) delete [] x[idim];
128         delete [] x;
129 }
130
131
132 //______________________________________________________________
133 Float_t p[]={1.4, -.6}; //}{1.7, -.4};
134 void kNNDraw(const Float_t *p, const int kNN)
135 {
136 // Test memory consumption and draw "kNN" nearest neighbours of point "p".
137 // The distance (in the L1 metric) is encoded in the color code.
138
139         const Int_t npoints = 10000;
140         Float_t *data0 =  new Float_t[npoints*2];
141   Float_t *data[2];
142   data[0] = &data0[0];
143   data[1] = &data0[npoints];
144   for (Int_t i=0;i<npoints;i++) {
145     data[1][i]= gRandom->Gaus();
146     data[0][i]= gRandom->Gaus();
147   }
148
149         TKDPDF pdf(npoints, 2, 100, data);
150         pdf.DrawNode(pdf.GetNodeIndex(p));
151         
152         TMarker *mp = new TMarker(p[0], p[1], 3);
153         mp->SetMarkerColor(4);
154         mp->Draw();
155                 
156         Int_t *index, color;
157         Float_t *d, d0, pknn[2];
158         Float_t start = Mem();
159         pdf.FindNearestNeighbors(p, kNN, index, d);
160         Float_t end = Mem();
161         printf("FindNearestNeighbors memory usage %fKB\n", end-start);
162         d0 = d[kNN-1];
163         TMarker *ma = new TMarker[kNN];
164         for(int ip=0; ip<kNN; ip++){
165                 pdf.GetDataPoint(index[ip], pknn);
166                 color = 101 - Int_t(50. * d[ip]/d0);
167                 ma[ip].SetMarkerStyle(4);
168                 ma[ip].SetMarkerColor(color);
169                 ma[ip].DrawMarker(pknn[0], pknn[1]);
170         }
171 }
172
173
174 //______________________________________________________________
175 Float_t Mem()
176 {
177   // size in KB
178   static struct mallinfo memdebug; 
179   memdebug = mallinfo();
180   return memdebug.uordblks/1024.;
181 }
182
183 //______________________________________________________________
184 void build(const Int_t ndim, const Int_t nstat)
185 {
186 // Build "nstat" data points in "ndim" dimensions taken from an
187 // uncorrelated 2D Gauss distribution.
188         
189
190         printf("build data ... \n");
191         Double_t pntTrain[ndim];
192         TFile *f = TFile::Open(Form("%dD_Gauss.root", ndim), "RECREATE");
193         TTree *t = new TTree("db", "gauss database");
194         for(int idim=0; idim<ndim; idim++) t->Branch(Form("x%d", idim), &pntTrain[idim], Form("x%d/D", idim));
195         
196         for(int istat=0; istat<nstat; istat++){
197                 for(int idim=0; idim<ndim; idim++) pntTrain[idim] = gRandom->Gaus();
198                 t->Fill();
199         }
200         f->cd();
201         t->Write();
202         f->Close();
203         delete f;
204 }
205