Logo ROOT  
Reference Guide
ModulekNN.cxx
Go to the documentation of this file.
1// @(#)root/tmva $Id$
2// Author: Rustem Ospanov
3
4/**********************************************************************************
5 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6 * Package: TMVA *
7 * Class : ModulekNN *
8 * Web : http://tmva.sourceforge.net *
9 * *
10 * Description: *
11 * Implementation *
12 * *
13 * Author: *
14 * Rustem Ospanov <rustem@fnal.gov> - U. of Texas at Austin, USA *
15 * *
16 * Copyright (c) 2007: *
17 * CERN, Switzerland *
18 * MPI-K Heidelberg, Germany *
19 * U. of Texas at Austin, USA *
20 * *
21 * Redistribution and use in source and binary forms, with or without *
22 * modification, are permitted according to the terms listed in LICENSE *
23 * (http://tmva.sourceforge.net/LICENSE) *
24 **********************************************************************************/
25
26/*! \class TMVA::kNN
27\ingroup TMVA
28 kNN::Event describes point in input variable vector-space, with
29 additional functionality like distance between points
30*/
31
32#include "TMVA/ModulekNN.h"
33
34#include "TMVA/MsgLogger.h"
35#include "TMVA/Types.h"
36
37#include "ThreadLocalStorage.h"
38#include "TMath.h"
39#include "TRandom3.h"
40
41#include <assert.h>
42#include <iomanip>
43#include <iostream>
44#include <sstream>
45#include <algorithm>
46
47////////////////////////////////////////////////////////////////////////////////
48/// default constructor
49
51 :fVar(),
52 fWeight(-1.0),
53 fType(-1)
54{
55}
56
57////////////////////////////////////////////////////////////////////////////////
58/// constructor
59
60TMVA::kNN::Event::Event(const VarVec &var, const Double_t weight, const Short_t type)
61 :fVar(var),
62 fWeight(weight),
63 fType(type)
64{
65}
66
67////////////////////////////////////////////////////////////////////////////////
68/// constructor
69
70TMVA::kNN::Event::Event(const VarVec &var, const Double_t weight, const Short_t type, const VarVec &tvec)
71 :fVar(var),
72 fTgt(tvec),
73 fWeight(weight),
74 fType(type)
75{
76}
77
78////////////////////////////////////////////////////////////////////////////////
79/// destructor
80
82{
83}
84
85////////////////////////////////////////////////////////////////////////////////
86/// compute distance
87
88TMVA::kNN::VarType TMVA::kNN::Event::GetDist(const Event &other) const
89{
90 const UInt_t nvar = GetNVar();
91
92 if (nvar != other.GetNVar()) {
93 std::cerr << "Distance: two events have different dimensions" << std::endl;
94 return -1.0;
95 }
96
97 VarType sum = 0.0;
98 for (UInt_t ivar = 0; ivar < nvar; ++ivar) {
99 sum += GetDist(other.GetVar(ivar), ivar);
100 }
101
102 return sum;
103}
104
105////////////////////////////////////////////////////////////////////////////////
106
107void TMVA::kNN::Event::SetTargets(const VarVec &tvec)
108{
109 fTgt = tvec;
110}
111
112////////////////////////////////////////////////////////////////////////////////
113
114const TMVA::kNN::VarVec& TMVA::kNN::Event::GetTargets() const
115{
116 return fTgt;
117}
118
119////////////////////////////////////////////////////////////////////////////////
120
121const TMVA::kNN::VarVec& TMVA::kNN::Event::GetVars() const
122{
123 return fVar;
124}
125
126////////////////////////////////////////////////////////////////////////////////
127/// print
128
130{
131 Print(std::cout);
132}
133
134////////////////////////////////////////////////////////////////////////////////
135/// print
136
137void TMVA::kNN::Event::Print(std::ostream& os) const
138{
139 Int_t dp = os.precision();
140 os << "Event: ";
141 for (UInt_t ivar = 0; ivar != GetNVar(); ++ivar) {
142 if (ivar == 0) {
143 os << "(";
144 }
145 else {
146 os << ", ";
147 }
148
149 os << std::setfill(' ') << std::setw(5) << std::setprecision(3) << GetVar(ivar);
150 }
151
152 if (GetNVar() > 0) {
153 os << ")";
154 }
155 else {
156 os << " no variables";
157 }
158 os << std::setprecision(dp);
159}
160
161////////////////////////////////////////////////////////////////////////////////
162/// streamer
163
164std::ostream& TMVA::kNN::operator<<(std::ostream& os, const TMVA::kNN::Event& event)
165{
166 event.Print(os);
167 return os;
168}
169
170////////////////////////////////////////////////////////////////////////////////
171/// default constructor
172
174 :fDimn(0),
175 fTree(0),
176 fLogger( new MsgLogger("ModulekNN") )
177{
178}
179
180////////////////////////////////////////////////////////////////////////////////
181/// destructor
182
184{
185 if (fTree) {
186 delete fTree; fTree = 0;
187 }
188 delete fLogger;
189}
190
191////////////////////////////////////////////////////////////////////////////////
192/// clean up
193
195{
196 fDimn = 0;
197
198 if (fTree) {
199 delete fTree;
200 fTree = 0;
201 }
202
203 fVarScale.clear();
204 fCount.clear();
205 fEvent.clear();
206 fVar.clear();
207}
208
209////////////////////////////////////////////////////////////////////////////////
210/// add an event to tree
211
213{
214 if (fTree) {
215 Log() << kFATAL << "<Add> Cannot add event: tree is already built" << Endl;
216 return;
217 }
218
219 if (fDimn < 1) {
220 fDimn = event.GetNVar();
221 }
222 else if (fDimn != event.GetNVar()) {
223 Log() << kFATAL << "ModulekNN::Add() - number of dimension does not match previous events" << Endl;
224 return;
225 }
226
227 fEvent.push_back(event);
228
229 for (UInt_t ivar = 0; ivar < fDimn; ++ivar) {
230 fVar[ivar].push_back(event.GetVar(ivar));
231 }
232
233 std::map<Short_t, UInt_t>::iterator cit = fCount.find(event.GetType());
234 if (cit == fCount.end()) {
235 fCount[event.GetType()] = 1;
236 }
237 else {
238 ++(cit->second);
239 }
240}
241
242////////////////////////////////////////////////////////////////////////////////
243/// fill the tree
244
245Bool_t TMVA::kNN::ModulekNN::Fill(const UShort_t odepth, const UInt_t ifrac, const std::string &option)
246{
247 if (fTree) {
248 Log() << kFATAL << "ModulekNN::Fill - tree has already been created" << Endl;
249 return kFALSE;
250 }
251
252 // If trim option is set then find class with lowest number of events
253 // and set that as maximum number of events for all other classes.
254 UInt_t min = 0;
255 if (option.find("trim") != std::string::npos) {
256 for (std::map<Short_t, UInt_t>::const_iterator it = fCount.begin(); it != fCount.end(); ++it) {
257 if (min == 0 || min > it->second) {
258 min = it->second;
259 }
260 }
261
262 Log() << kINFO << "<Fill> Will trim all event types to " << min << " events" << Endl;
263
264 fCount.clear();
265 fVar.clear();
266
267 EventVec evec;
268
269 for (EventVec::const_iterator event = fEvent.begin(); event != fEvent.end(); ++event) {
270 std::map<Short_t, UInt_t>::iterator cit = fCount.find(event->GetType());
271 if (cit == fCount.end()) {
272 fCount[event->GetType()] = 1;
273 }
274 else if (cit->second < min) {
275 ++(cit->second);
276 }
277 else {
278 continue;
279 }
280
281 for (UInt_t d = 0; d < fDimn; ++d) {
282 fVar[d].push_back(event->GetVar(d));
283 }
284
285 evec.push_back(*event);
286 }
287
288 Log() << kINFO << "<Fill> Erased " << fEvent.size() - evec.size() << " events" << Endl;
289
290 fEvent = evec;
291 }
292
293 // clear event count
294 fCount.clear();
295
296 // sort each variable for all events - needs this before Optimize() and ComputeMetric()
297 for (VarMap::iterator it = fVar.begin(); it != fVar.end(); ++it) {
298 std::sort((it->second).begin(), (it->second).end());
299 }
300
301 if (option.find("metric") != std::string::npos && ifrac > 0) {
302 ComputeMetric(ifrac);
303
304 // sort again each variable for all events - needs this before Optimize()
305 // rescaling has changed variable values
306 for (VarMap::iterator it = fVar.begin(); it != fVar.end(); ++it) {
307 std::sort((it->second).begin(), (it->second).end());
308 }
309 }
310
311 // If odepth > 0 then fill first odepth levels
312 // with empty nodes that split separating variable in half for
313 // all child nodes. If odepth = 0 then split variable 0
314 // at the median (in half) and return it as root node
315 fTree = Optimize(odepth);
316
317 if (!fTree) {
318 Log() << kFATAL << "ModulekNN::Fill() - failed to create tree" << Endl;
319 return kFALSE;
320 }
321
322 for (EventVec::const_iterator event = fEvent.begin(); event != fEvent.end(); ++event) {
323 fTree->Add(*event, 0);
324
325 std::map<Short_t, UInt_t>::iterator cit = fCount.find(event->GetType());
326 if (cit == fCount.end()) {
327 fCount[event->GetType()] = 1;
328 }
329 else {
330 ++(cit->second);
331 }
332 }
333
334 for (std::map<Short_t, UInt_t>::const_iterator it = fCount.begin(); it != fCount.end(); ++it) {
335 Log() << kINFO << "<Fill> Class " << it->first << " has " << std::setw(8)
336 << it->second << " events" << Endl;
337 }
338
339 return kTRUE;
340}
341
342////////////////////////////////////////////////////////////////////////////////
343/// find in tree
344/// if tree has been filled then search for nfind closest events
345/// if metic (fVarScale map) is computed then rescale event variables
346/// using previously computed width of variable distribution
347
348Bool_t TMVA::kNN::ModulekNN::Find(Event event, const UInt_t nfind, const std::string &option) const
349{
350 if (!fTree) {
351 Log() << kFATAL << "ModulekNN::Find() - tree has not been filled" << Endl;
352 return kFALSE;
353 }
354 if (fDimn != event.GetNVar()) {
355 Log() << kFATAL << "ModulekNN::Find() - number of dimension does not match training events" << Endl;
356 return kFALSE;
357 }
358 if (nfind < 1) {
359 Log() << kFATAL << "ModulekNN::Find() - requested 0 nearest neighbors" << Endl;
360 return kFALSE;
361 }
362
363 // if variable widths are computed then rescale variable in this event
364 // to same widths as events in stored kd-tree
365 if (!fVarScale.empty()) {
366 event = Scale(event);
367 }
368
369 // latest event for k-nearest neighbor search
370 fkNNEvent = event;
371 fkNNList.clear();
372
373 if(option.find("weight") != std::string::npos)
374 {
375 // recursive kd-tree search for nfind-nearest neighbors
376 // use event weight to find all nearest events
377 // that have sum of weights >= nfind
378 kNN::Find<kNN::Event>(fkNNList, fTree, event, Double_t(nfind), 0.0);
379 }
380 else
381 {
382 // recursive kd-tree search for nfind-nearest neighbors
383 // count nodes and do not use event weight
384 kNN::Find<kNN::Event>(fkNNList, fTree, event, nfind);
385 }
386
387 return kTRUE;
388}
389
390////////////////////////////////////////////////////////////////////////////////
391/// find in tree
392
393Bool_t TMVA::kNN::ModulekNN::Find(const UInt_t nfind, const std::string &option) const
394{
395 if (fCount.empty() || !fTree) {
396 return kFALSE;
397 }
398 typedef std::map<Short_t, UInt_t>::const_iterator const_iterator;
399 TTHREAD_TLS_DECL_ARG(const_iterator,cit,fCount.end());
400
401 if (cit == fCount.end()) {
402 cit = fCount.begin();
403 }
404
405 const Short_t etype = (cit++)->first;
406
407 if (option == "flat") {
408 VarVec dvec;
409 for (UInt_t d = 0; d < fDimn; ++d) {
410 VarMap::const_iterator vit = fVar.find(d);
411 if (vit == fVar.end()) {
412 return kFALSE;
413 }
414
415 const std::vector<Double_t> &vvec = vit->second;
416
417 if (vvec.empty()) {
418 return kFALSE;
419 }
420
421 // assume that vector elements of fVar are sorted
422 const VarType min = vvec.front();
423 const VarType max = vvec.back();
424 const VarType width = max - min;
425
426 if (width < 0.0 || width > 0.0) {
427 dvec.push_back(min + width*GetRndmThreadLocal().Rndm());
428 }
429 else {
430 return kFALSE;
431 }
432 }
433
434 const Event event(dvec, 1.0, etype);
435
436 Find(event, nfind);
437
438 return kTRUE;
439 }
440
441 return kFALSE;
442}
443
444////////////////////////////////////////////////////////////////////////////////
445/// Optimize() balances binary tree for first odepth levels
446/// for each depth we split sorted depth % dimension variables
447/// into \f$ 2^{odepth} \f$ parts
448
450{
451 if (fVar.empty() || fDimn != fVar.size()) {
452 Log() << kWARNING << "<Optimize> Cannot build a tree" << Endl;
453 return 0;
454 }
455
456 const UInt_t size = (fVar.begin()->second).size();
457 if (size < 1) {
458 Log() << kWARNING << "<Optimize> Cannot build a tree without events" << Endl;
459 return 0;
460 }
461
462 VarMap::const_iterator it = fVar.begin();
463 for (; it != fVar.end(); ++it) {
464 if ((it->second).size() != size) {
465 Log() << kWARNING << "<Optimize> # of variables doesn't match between dimensions" << Endl;
466 return 0;
467 }
468 }
469
470 if (double(fDimn*size) < TMath::Power(2.0, double(odepth))) {
471 Log() << kWARNING << "<Optimize> Optimization depth exceeds number of events" << Endl;
472 return 0;
473 }
474
475 Log() << kHEADER << "Optimizing tree for " << fDimn << " variables with " << size << " values" << Endl;
476
477 std::vector<Node<Event> *> pvec, cvec;
478
479 it = fVar.find(0);
480 if (it == fVar.end() || (it->second).size() < 2) {
481 Log() << kWARNING << "<Optimize> Missing 0 variable" << Endl;
482 return 0;
483 }
484
485 const Event pevent(VarVec(fDimn, (it->second)[size/2]), -1.0, -1);
486
487 Node<Event> *tree = new Node<Event>(0, pevent, 0);
488
489 pvec.push_back(tree);
490
491 for (UInt_t depth = 1; depth < odepth; ++depth) {
492 const UInt_t mod = depth % fDimn;
493
494 VarMap::const_iterator vit = fVar.find(mod);
495 if (vit == fVar.end()) {
496 Log() << kFATAL << "Missing " << mod << " variable" << Endl;
497 return 0;
498 }
499 const std::vector<Double_t> &dvec = vit->second;
500
501 if (dvec.size() < 2) {
502 Log() << kFATAL << "Missing " << mod << " variable" << Endl;
503 return 0;
504 }
505
506 UInt_t ichild = 1;
507 for (std::vector<Node<Event> *>::iterator pit = pvec.begin(); pit != pvec.end(); ++pit) {
508 Node<Event> *parent = *pit;
509
510 const VarType lmedian = dvec[size*ichild/(2*pvec.size() + 1)];
511 ++ichild;
512
513 const VarType rmedian = dvec[size*ichild/(2*pvec.size() + 1)];
514 ++ichild;
515
516 const Event levent(VarVec(fDimn, lmedian), -1.0, -1);
517 const Event revent(VarVec(fDimn, rmedian), -1.0, -1);
518
519 Node<Event> *lchild = new Node<Event>(parent, levent, mod);
520 Node<Event> *rchild = new Node<Event>(parent, revent, mod);
521
522 parent->SetNodeL(lchild);
523 parent->SetNodeR(rchild);
524
525 cvec.push_back(lchild);
526 cvec.push_back(rchild);
527 }
528
529 pvec = cvec;
530 cvec.clear();
531 }
532
533 return tree;
534}
535
536////////////////////////////////////////////////////////////////////////////////
537/// compute scale factor for each variable (dimension) so that
538/// distance is computed uniformly along each dimension
539/// compute width of interval that includes (100 - 2*ifrac)% of events
540/// below, assume that in fVar each vector of values is sorted
541
543{
544 if (ifrac == 0) {
545 return;
546 }
547 if (ifrac > 100) {
548 Log() << kFATAL << "ModulekNN::ComputeMetric - fraction can not exceed 100%" << Endl;
549 return;
550 }
551 if (!fVarScale.empty()) {
552 Log() << kFATAL << "ModulekNN::ComputeMetric - metric is already computed" << Endl;
553 return;
554 }
555 if (fEvent.size() < 100) {
556 Log() << kFATAL << "ModulekNN::ComputeMetric - number of events is too small" << Endl;
557 return;
558 }
559
560 const UInt_t lfrac = (100 - ifrac)/2;
561 const UInt_t rfrac = 100 - (100 - ifrac)/2;
562
563 Log() << kINFO << "Computing scale factor for 1d distributions: "
564 << "(ifrac, bottom, top) = (" << ifrac << "%, " << lfrac << "%, " << rfrac << "%)" << Endl;
565
566 fVarScale.clear();
567
568 for (VarMap::const_iterator vit = fVar.begin(); vit != fVar.end(); ++vit) {
569 const std::vector<Double_t> &dvec = vit->second;
570
571 std::vector<Double_t>::const_iterator beg_it = dvec.end();
572 std::vector<Double_t>::const_iterator end_it = dvec.end();
573
574 Int_t dist = 0;
575 for (std::vector<Double_t>::const_iterator dit = dvec.begin(); dit != dvec.end(); ++dit, ++dist) {
576
577 if ((100*dist)/dvec.size() == lfrac && beg_it == dvec.end()) {
578 beg_it = dit;
579 }
580
581 if ((100*dist)/dvec.size() == rfrac && end_it == dvec.end()) {
582 end_it = dit;
583 }
584 }
585
586 if (beg_it == dvec.end() || end_it == dvec.end()) {
587 beg_it = dvec.begin();
588 end_it = dvec.end();
589
590 assert(beg_it != end_it && "Empty vector");
591
592 --end_it;
593 }
594
595 const Double_t lpos = *beg_it;
596 const Double_t rpos = *end_it;
597
598 if (!(lpos < rpos)) {
599 Log() << kFATAL << "ModulekNN::ComputeMetric() - min value is greater than max value" << Endl;
600 continue;
601 }
602
603 // Rustem: please find a solution that does not use distance (it does not exist on solaris)
604 // Log() << kINFO << "Variable " << vit->first
605 // << " included " << distance(beg_it, end_it) + 1
606 // << " events: width = " << std::setfill(' ') << std::setw(5) << std::setprecision(3) << rpos - lpos
607 // << ", (min, max) = (" << std::setfill(' ') << std::setw(5) << std::setprecision(3) << lpos
608 // << ", " << std::setfill(' ') << std::setw(5) << std::setprecision(3) << rpos << ")" << Endl;
609
610 fVarScale[vit->first] = rpos - lpos;
611 }
612
613 fVar.clear();
614
615 for (UInt_t ievent = 0; ievent < fEvent.size(); ++ievent) {
616 fEvent[ievent] = Scale(fEvent[ievent]);
617
618 for (UInt_t ivar = 0; ivar < fDimn; ++ivar) {
619 fVar[ivar].push_back(fEvent[ievent].GetVar(ivar));
620 }
621 }
622}
623
624////////////////////////////////////////////////////////////////////////////////
625/// scale each event variable so that rms of variables is approximately 1.0
626/// this allows comparisons of variables with distinct scales and units
627
629{
630 if (fVarScale.empty()) {
631 return event;
632 }
633
634 if (event.GetNVar() != fVarScale.size()) {
635 Log() << kFATAL << "ModulekNN::Scale() - mismatched metric and event size" << Endl;
636 return event;
637 }
638
639 VarVec vvec(event.GetNVar(), 0.0);
640
641 for (UInt_t ivar = 0; ivar < event.GetNVar(); ++ivar) {
642 std::map<int, Double_t>::const_iterator fit = fVarScale.find(ivar);
643 if (fit == fVarScale.end()) {
644 Log() << kFATAL << "ModulekNN::Scale() - failed to find scale for " << ivar << Endl;
645 continue;
646 }
647
648 if (fit->second > 0.0) {
649 vvec[ivar] = event.GetVar(ivar)/fit->second;
650 }
651 else {
652 Log() << kFATAL << "Variable " << ivar << " has zero width" << Endl;
653 }
654 }
655
656 return Event(vvec, event.GetWeight(), event.GetType(), event.GetTargets());
657}
658
659////////////////////////////////////////////////////////////////////////////////
660/// print
661
663{
664 Print(std::cout);
665}
666
667////////////////////////////////////////////////////////////////////////////////
668/// print
669
670void TMVA::kNN::ModulekNN::Print(std::ostream &os) const
671{
672 os << "----------------------------------------------------------------------"<< std::endl;
673 os << "Printing knn result" << std::endl;
674 os << fkNNEvent << std::endl;
675
676 UInt_t count = 0;
677
678 std::map<Short_t, Double_t> min, max;
679
680 os << "Printing " << fkNNList.size() << " nearest neighbors" << std::endl;
681 for (List::const_iterator it = fkNNList.begin(); it != fkNNList.end(); ++it) {
682 os << ++count << ": " << it->second << ": " << it->first->GetEvent() << std::endl;
683
684 const Event &event = it->first->GetEvent();
685 for (UShort_t ivar = 0; ivar < event.GetNVar(); ++ivar) {
686 if (min.find(ivar) == min.end()) {
687 min[ivar] = event.GetVar(ivar);
688 }
689 else if (min[ivar] > event.GetVar(ivar)) {
690 min[ivar] = event.GetVar(ivar);
691 }
692
693 if (max.find(ivar) == max.end()) {
694 max[ivar] = event.GetVar(ivar);
695 }
696 else if (max[ivar] < event.GetVar(ivar)) {
697 max[ivar] = event.GetVar(ivar);
698 }
699 }
700 }
701
702 if (min.size() == max.size()) {
703 for (std::map<Short_t, Double_t>::const_iterator mit = min.begin(); mit != min.end(); ++mit) {
704 const Short_t i = mit->first;
705 Log() << kINFO << "(var, min, max) = (" << i << "," << min[i] << ", " << max[i] << ")" << Endl;
706 }
707 }
708
709 os << "----------------------------------------------------------------------" << std::endl;
710}
#define d(i)
Definition: RSha256.hxx:102
unsigned short UShort_t
Definition: RtypesCore.h:38
const Bool_t kFALSE
Definition: RtypesCore.h:90
short Short_t
Definition: RtypesCore.h:37
double Double_t
Definition: RtypesCore.h:57
const Bool_t kTRUE
Definition: RtypesCore.h:89
include TDocParser_001 C image html pict1_TDocParser_001 png width
Definition: TDocParser.cxx:121
int type
Definition: TGX11.cxx:120
ostringstream derivative to redirect and format output
Definition: MsgLogger.h:59
Short_t GetType() const
Definition: ModulekNN.h:195
VarType GetDist(VarType var, UInt_t ivar) const
Definition: ModulekNN.h:169
void SetTargets(const VarVec &tvec)
Definition: ModulekNN.cxx:107
const VarVec & GetTargets() const
Definition: ModulekNN.cxx:114
Double_t GetWeight() const
Definition: ModulekNN.h:174
UInt_t GetNVar() const
Definition: ModulekNN.h:187
Event()
default constructor
Definition: ModulekNN.cxx:50
~Event()
destructor
Definition: ModulekNN.cxx:81
void Print() const
print
Definition: ModulekNN.cxx:129
VarType GetVar(UInt_t i) const
Definition: ModulekNN.h:178
const VarVec & GetVars() const
Definition: ModulekNN.cxx:121
Bool_t Fill(const UShort_t odepth, UInt_t ifrac, const std::string &option="")
fill the tree
Definition: ModulekNN.cxx:245
Node< Event > * Optimize(UInt_t optimize_depth)
Optimize() balances binary tree for first odepth levels for each depth we split sorted depth % dimens...
Definition: ModulekNN.cxx:449
void Print() const
print
Definition: ModulekNN.cxx:662
void Clear()
clean up
Definition: ModulekNN.cxx:194
ModulekNN()
default constructor
Definition: ModulekNN.cxx:173
Bool_t Find(Event event, UInt_t nfind=100, const std::string &option="count") const
find in tree if tree has been filled then search for nfind closest events if metic (fVarScale map) is...
Definition: ModulekNN.cxx:348
const Event Scale(const Event &event) const
scale each event variable so that rms of variables is approximately 1.0 this allows comparisons of va...
Definition: ModulekNN.cxx:628
void ComputeMetric(UInt_t ifrac)
compute scale factor for each variable (dimension) so that distance is computed uniformly along each ...
Definition: ModulekNN.cxx:542
~ModulekNN()
destructor
Definition: ModulekNN.cxx:183
void Add(const Event &event)
add an event to tree
Definition: ModulekNN.cxx:212
void SetNodeL(Node *node)
Definition: NodekNN.h:144
void SetNodeR(Node *node)
Definition: NodekNN.h:150
RooCmdArg Optimize(Int_t flag=2)
void Print(std::ostream &os, const OptionType &opt)
double dist(Rotation3D const &r1, Rotation3D const &r2)
Definition: 3DDistances.cxx:48
UInt_t Find(std::list< std::pair< const Node< T > *, Float_t > > &nlist, const Node< T > *node, const T &event, UInt_t nfind)
std::ostream & operator<<(std::ostream &os, const Event &event)
MsgLogger & Endl(MsgLogger &ml)
Definition: MsgLogger.h:158
Double_t Log(Double_t x)
Definition: TMath.h:750
LongDouble_t Power(LongDouble_t x, LongDouble_t y)
Definition: TMath.h:725
Definition: first.py:1
Definition: tree.py:1
static long int sum(long int i)
Definition: Factory.cxx:2275