ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/VHbbAnalysis/VHbbDataFormats/interface/Njettiness.hh
Revision: 1.1.2.1
Committed: Tue Nov 27 05:04:18 2012 UTC (12 years, 5 months ago) by ntran
Content type: text/plain
Branch: hbbsubstructDevPostHCP
CVS Tags: hbbsubstructDev_6, hbbsubstructDev_5
Changes since 1.1: +547 -0 lines
Log Message:
major update, including new proposal for FJ3 inputs to step 2

File Contents

# User Rev Content
1 ntran 1.1.2.1 // Njettiness Package
2     // Version 0.4.1 (January 22, 2012)
3     // Questions/Comments? jthaler@jthaler.net
4    
5     // Copyright (c) 2011-12, Jesse Thaler, Ken Van Tilburg, and Christopher K.
6     // Vermilion
7     //
8     //----------------------------------------------------------------------
9     // This file is part of the N-jettiness package ("N-jettiness").
10     //
11     // N-jettiness is free software; you can redistribute it and/or modify
12     // it under the terms of the GNU General Public License as published by
13     // the Free Software Foundation; either version 3 of the License, or
14     // (at your option) any later version.
15     //
16     // SpartyJet is distributed in the hope that it will be useful,
17     // but WITHOUT ANY WARRANTY; without even the implied warranty of
18     // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     // GNU General Public License for more details.
20     //
21     // You should have received a copy of the GNU General Public License
22     // along with SpartyJet; if not, write to the Free Software
23     // Foundation, Inc.:
24     // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25     //----------------------------------------------------------------------
26    
27    
28     #ifndef __NJETTINESS_HH__
29     #define __NJETTINESS_HH__
30    
31    
32     #include "fastjet/PseudoJet.hh"
33     #include "fastjet/ClusterSequence.hh"
34     #include <cmath>
35     #include <vector>
36     #include <list>
37    
38     ///////
39     //
40     // Helper classes
41     //
42     ///////
43    
44    
45     // Parameters that define Njettiness
46     class NsubParameters {
47     private:
48     double _beta; // angular weighting exponent
49     double _R0; // characteristic jet radius (for normalization)
50     double _Rcutoff; // Cutoff scale for cone jet finding (default is large number such that no boundaries are used)
51    
52     public:
53     NsubParameters(const double mybeta, const double myR0, const double myRcutoff=10000.0) :
54     _beta(mybeta), _R0(myR0), _Rcutoff(myRcutoff) {}
55     double beta() const {return _beta;}
56     double R0() const {return _R0;}
57     double Rcutoff() const {return _Rcutoff;}
58     };
59    
60     // Parameters that change minimization procedure.
61     // Set automatically when you choose NsubAxesMode, but can be adjusted manually as well
62     class KmeansParameters {
63     private:
64     int _n_iterations; // Number of iterations to run (0 for no minimization, 1 for one-pass, >>1 for global minimum)
65     double _precision; // Desired precision in axes alignment
66     int _halt; // maximum number of steps per iteration
67     double _noise_range;// noise range for random initialization
68    
69     public:
70     KmeansParameters() : _n_iterations(0), _precision(0.0), _halt(0), _noise_range(0.0) {}
71     KmeansParameters(const int my_n_iterations, double my_precision, int my_halt, double my_noise_range) :
72     _n_iterations(my_n_iterations), _precision(my_precision), _halt(my_halt), _noise_range(my_noise_range) {}
73     int n_iterations() const { return _n_iterations;}
74     double precision() const {return _precision;}
75     int halt() const {return _halt;}
76     double noise_range() const {return _noise_range;}
77     };
78    
79     // helper class for minimization
80     class LightLikeAxis {
81     private:
82     double _rap, _phi, _weight, _mom;
83    
84     public:
85     LightLikeAxis() : _rap(0.0), _phi(0.0), _weight(0.0), _mom(0.0) {}
86     LightLikeAxis(double my_rap, double my_phi, double my_weight, double my_mom) :
87     _rap(my_rap), _phi(my_phi), _weight(my_weight), _mom(my_mom) {}
88     double rap() const {return _rap;}
89     double phi() const {return _phi;}
90     double weight() const {return _weight;}
91     double mom() const {return _mom;}
92     void set_rap(double my_set_rap) {_rap = my_set_rap;}
93     void set_phi(double my_set_phi) {_phi = my_set_phi;}
94     void set_weight(double my_set_weight) {_weight = my_set_weight;}
95     void set_mom(double my_set_mom) {_mom = my_set_mom;}
96     void reset(double my_rap, double my_phi, double my_weight, double my_mom) {_rap=my_rap; _phi=my_phi; _weight=my_weight; _mom=my_mom;}
97     };
98    
99     ///////
100     //
101     // Functions for minimization.
102     // TODO: Wrap these in N-subjettiness class
103     //
104     ///////
105    
106     inline double sq(double x) {return x*x;}
107    
108     // Calculates distance between two points in rapidity-azimuth plane
109     double DistanceSq(double rap1, double phi1, double rap2, double phi2) {
110     double distRap = rap1-rap2;
111     double distPhi = std::fabs(phi1-phi2);
112     if (distPhi > M_PI) {distPhi = 2.0*M_PI - distPhi;}
113     return sq(distRap) + sq(distPhi);
114     }
115    
116     inline double Distance(double rap1, double phi1, double rap2, double phi2) {
117     return std::sqrt(DistanceSq(rap1, phi1, rap2, phi2));
118     }
119    
120    
121     // Given starting axes, update to find better axes
122     template <int N>
123     std::vector<LightLikeAxis> UpdateAxesFast(const std::vector <LightLikeAxis> & old_axes,
124     const std::vector <fastjet::PseudoJet> & inputJets,
125     NsubParameters paraNsub, double precision) {
126     assert(old_axes.size() == N);
127    
128     // some storage, declared static to save allocation/re-allocation costs
129     static LightLikeAxis new_axes[N];
130     static fastjet::PseudoJet new_jets[N];
131     for (int n = 0; n < N; ++n) {
132     new_axes[n].reset(0.0,0.0,0.0,0.0);
133     #ifdef FASTJET2
134     new_jets[n].reset(0.0,0.0,0.0,0.0);
135     #else
136     // use cheaper reset if available
137     new_jets[n].reset_momentum(0.0,0.0,0.0,0.0);
138     #endif
139     }
140    
141    
142     double beta = paraNsub.beta();
143     double Rcutoff = paraNsub.Rcutoff();
144    
145     /////////////// Assignment Step //////////////////////////////////////////////////////////
146     std::vector<int> assignment_index(inputJets.size());
147     int k_assign = -1;
148    
149     for (unsigned i = 0; i < inputJets.size(); i++){
150     double smallestDist = 1000000.0;
151     for (int k = 0; k < N; k++) {
152     double thisDist = DistanceSq(inputJets[i].rap(),inputJets[i].phi(),old_axes[k].rap(),old_axes[k].phi());
153     if (thisDist < smallestDist) {
154     smallestDist = thisDist;
155     k_assign = k;
156     }
157     }
158     if (smallestDist > sq(Rcutoff)) {k_assign = -1;}
159     assignment_index[i] = k_assign;
160     }
161    
162     //////////////// Update Step /////////////////////////////////////////////////////////////
163     double distPhi, old_dist;
164     for (unsigned i = 0; i < inputJets.size(); i++) {
165     int old_jet_i = assignment_index[i];
166     if (old_jet_i == -1) {continue;}
167    
168     const fastjet::PseudoJet& inputJet_i = inputJets[i];
169     LightLikeAxis& new_axis_i = new_axes[old_jet_i];
170     double inputPhi_i = inputJet_i.phi();
171     double inputRap_i = inputJet_i.rap();
172    
173     // optimize pow() call
174     // add noise (the precision term) to make sure we don't divide by zero
175     if (beta == 1.0) {
176     double DR = std::sqrt(sq(precision) + DistanceSq(inputRap_i, inputPhi_i, old_axes[old_jet_i].rap(), old_axes[old_jet_i].phi()));
177     old_dist = 1.0/DR;
178     } else if (beta == 2.0) {
179     old_dist = 1.0;
180     } else if (beta == 0.0) {
181     double DRSq = sq(precision) + DistanceSq(inputRap_i, inputPhi_i, old_axes[old_jet_i].rap(), old_axes[old_jet_i].phi());
182     old_dist = 1.0/DRSq;
183     } else {
184     old_dist = sq(precision) + DistanceSq(inputRap_i, inputPhi_i, old_axes[old_jet_i].rap(), old_axes[old_jet_i].phi());
185     old_dist = std::pow(old_dist, (0.5*beta-1.0));
186     }
187    
188     // rapidity sum
189     new_axis_i.set_rap(new_axis_i.rap() + inputJet_i.perp() * inputRap_i * old_dist);
190     // phi sum
191     distPhi = inputPhi_i - old_axes[old_jet_i].phi();
192     if (fabs(distPhi) <= M_PI){
193     new_axis_i.set_phi( new_axis_i.phi() + inputJet_i.perp() * inputPhi_i * old_dist );
194     } else if (distPhi > M_PI) {
195     new_axis_i.set_phi( new_axis_i.phi() + inputJet_i.perp() * (-2*M_PI + inputPhi_i) * old_dist );
196     } else if (distPhi < -M_PI) {
197     new_axis_i.set_phi( new_axis_i.phi() + inputJet_i.perp() * (+2*M_PI + inputPhi_i) * old_dist );
198     }
199     // weights sum
200     new_axis_i.set_weight( new_axis_i.weight() + inputJet_i.perp() * old_dist );
201     // momentum magnitude sum
202     new_jets[old_jet_i] += inputJet_i;
203     }
204     // normalize sums
205     for (int k = 0; k < N; k++) {
206     if (new_axes[k].weight() == 0) {
207     // no particles were closest to this axis! Return to old axis instead of (0,0,0,0)
208     new_axes[k] = old_axes[k];
209     } else {
210     new_axes[k].set_rap( new_axes[k].rap() / new_axes[k].weight() );
211     new_axes[k].set_phi( new_axes[k].phi() / new_axes[k].weight() );
212     new_axes[k].set_phi( std::fmod(new_axes[k].phi() + 2*M_PI, 2*M_PI) );
213     new_axes[k].set_mom( std::sqrt(new_jets[k].modp2()) );
214     }
215     }
216     std::vector<LightLikeAxis> new_axes_vec(N);
217     for (unsigned k = 0; k < N; ++k) new_axes_vec[k] = new_axes[k];
218     return new_axes_vec;
219     }
220    
221    
222     // Given starting axes, update to find better axes
223     // (This is just a wrapper for the templated version above.)
224     std::vector<LightLikeAxis> UpdateAxes(const std::vector <LightLikeAxis> & old_axes,
225     const std::vector <fastjet::PseudoJet> & inputJets, NsubParameters paraNsub, double precision) {
226     int N = old_axes.size();
227     switch (N) {
228     case 1: return UpdateAxesFast<1>(old_axes, inputJets, paraNsub, precision);
229     case 2: return UpdateAxesFast<2>(old_axes, inputJets, paraNsub, precision);
230     case 3: return UpdateAxesFast<3>(old_axes, inputJets, paraNsub, precision);
231     case 4: return UpdateAxesFast<4>(old_axes, inputJets, paraNsub, precision);
232     case 5: return UpdateAxesFast<5>(old_axes, inputJets, paraNsub, precision);
233     case 6: return UpdateAxesFast<6>(old_axes, inputJets, paraNsub, precision);
234     case 7: return UpdateAxesFast<7>(old_axes, inputJets, paraNsub, precision);
235     case 8: return UpdateAxesFast<8>(old_axes, inputJets, paraNsub, precision);
236     case 9: return UpdateAxesFast<9>(old_axes, inputJets, paraNsub, precision);
237     case 10: return UpdateAxesFast<10>(old_axes, inputJets, paraNsub, precision);
238     case 11: return UpdateAxesFast<11>(old_axes, inputJets, paraNsub, precision);
239     case 12: return UpdateAxesFast<12>(old_axes, inputJets, paraNsub, precision);
240     case 13: return UpdateAxesFast<13>(old_axes, inputJets, paraNsub, precision);
241     case 14: return UpdateAxesFast<14>(old_axes, inputJets, paraNsub, precision);
242     case 15: return UpdateAxesFast<15>(old_axes, inputJets, paraNsub, precision);
243     case 16: return UpdateAxesFast<16>(old_axes, inputJets, paraNsub, precision);
244     case 17: return UpdateAxesFast<17>(old_axes, inputJets, paraNsub, precision);
245     case 18: return UpdateAxesFast<18>(old_axes, inputJets, paraNsub, precision);
246     case 19: return UpdateAxesFast<19>(old_axes, inputJets, paraNsub, precision);
247     case 20: return UpdateAxesFast<20>(old_axes, inputJets, paraNsub, precision);
248     default: std::cout << "N-jettiness is hard-coded to only allow up to 20 jets!" << std::endl;
249     return std::vector<LightLikeAxis>();
250     }
251    
252     }
253    
254    
255     // Go from internal LightLikeAxis to PseudoJet
256     // TODO: Make part of LightLikeAxis class.
257     std::vector<fastjet::PseudoJet> ConvertToPseudoJet(const std::vector <LightLikeAxis>& axes) {
258    
259     int n_jets = axes.size();
260    
261     double px, py, pz, E;
262     std::vector<fastjet::PseudoJet> FourVecJets;
263     for (int k = 0; k < n_jets; k++) {
264     E = axes[k].mom();
265     pz = (std::exp(2.0*axes[k].rap()) - 1.0) / (std::exp(2.0*axes[k].rap()) + 1.0) * E;
266     px = std::cos(axes[k].phi()) * std::sqrt( std::pow(E,2) - std::pow(pz,2) );
267     py = std::sin(axes[k].phi()) * std::sqrt( std::pow(E,2) - std::pow(pz,2) );
268     fastjet::PseudoJet temp = fastjet::PseudoJet(px,py,pz,E);
269     FourVecJets.push_back(temp);
270     }
271     return FourVecJets;
272     }
273    
274     // N-subjettiness pieces
275     std::vector<double> ConstituentTauValue(const std::vector <fastjet::PseudoJet> & particles, const std::vector<fastjet::PseudoJet>& axes, const NsubParameters& paraNsub) {// Returns the sub-tau values, i.e. a std::vector of the contributions to tau_N of each Voronoi region (or region within R_0)
276     double beta = paraNsub.beta();
277     double R0 = paraNsub.R0();
278     double Rcutoff = paraNsub.Rcutoff();
279    
280     std::vector<double> tauNum(axes.size(), 0.0), tau(axes.size());
281     double tauDen = 0.0;
282     int j_min = 0;
283     for (unsigned i = 0; i < particles.size(); i++) {
284     // find minimum distance; start with 0'th axis for reference
285     double minR = std::sqrt(particles[i].squared_distance(axes[0]));
286     for (unsigned j = 1; j < axes.size(); j++) {
287     double tempR = std::sqrt(particles[i].squared_distance(axes[j])); // delta R distance
288     if (tempR < minR) {minR = tempR; j_min = j;}
289     }
290     if (minR > Rcutoff) {minR = Rcutoff;}
291     tauNum[j_min] += particles[i].perp() * std::pow(minR,beta);
292     tauDen += particles[i].perp() * std::pow(R0,beta);
293     }
294     for (unsigned j = 0; j < axes.size(); j++) {
295     tau[j] = tauNum[j]/tauDen;
296     }
297     return tau;
298     }
299    
300     // N-subjettiness values
301     double TauValue(const std::vector <fastjet::PseudoJet>& particles, const std::vector<fastjet::PseudoJet>& axes,const NsubParameters& paraNsub) {// Calculates tau_N
302     std::vector<double> tau_vec = ConstituentTauValue(particles, axes, paraNsub);
303     double tau = 0.0;
304     for (unsigned j = 0; j < tau_vec.size(); j++) {tau += tau_vec[j];}
305     return tau;
306     }
307    
308     // Get exclusive kT subjets
309     std::vector<fastjet::PseudoJet> GetKTAxes(int n_jets, const std::vector <fastjet::PseudoJet> & inputJets) {
310     fastjet::JetDefinition jet_def = fastjet::JetDefinition(fastjet::kt_algorithm,M_PI/2.0,fastjet::E_scheme,fastjet::Best);
311     fastjet::ClusterSequence jet_clust_seq(inputJets, jet_def);
312     return jet_clust_seq.exclusive_jets(n_jets);
313     }
314    
315     // Get exclusive CA subjets
316     std::vector<fastjet::PseudoJet> GetCAAxes(int n_jets, const std::vector <fastjet::PseudoJet> & inputJets) {
317     fastjet::JetDefinition jet_def = fastjet::JetDefinition(fastjet::cambridge_algorithm,M_PI/2.0,fastjet::E_scheme,fastjet::Best);
318     fastjet::ClusterSequence jet_clust_seq(inputJets, jet_def);
319     return jet_clust_seq.exclusive_jets(n_jets);
320     }
321    
322     // Get inclusive anti kT hardest subjets
323     std::vector<fastjet::PseudoJet> GetAntiKTAxes(int n_jets, double R0, const std::vector <fastjet::PseudoJet> & inputJets) {
324     fastjet::JetDefinition jet_def = fastjet::JetDefinition(fastjet::antikt_algorithm,R0,fastjet::E_scheme,fastjet::Best);
325     fastjet::ClusterSequence jet_clust_seq(inputJets, jet_def);
326     std::vector<fastjet::PseudoJet> myJets = sorted_by_pt(jet_clust_seq.inclusive_jets());
327     myJets.resize(n_jets); // only keep n hardest
328     return myJets;
329     }
330    
331    
332     // Get minimization axes
333     std::vector<fastjet::PseudoJet> GetMinimumAxes(const std::vector <fastjet::PseudoJet> & seedAxes, const std::vector <fastjet::PseudoJet> & inputJets, KmeansParameters para,
334     NsubParameters paraNsub) {
335     int n_jets = seedAxes.size();
336     double noise = 0, tau = 10000.0, tau_tmp, cmp;
337     std::vector< LightLikeAxis > new_axes(n_jets, LightLikeAxis(0,0,0,0)), old_axes(n_jets, LightLikeAxis(0,0,0,0));
338     std::vector<fastjet::PseudoJet> tmp_min_axes, min_axes;
339     for (int l = 0; l < para.n_iterations(); l++) { // Do minimization procedure multiple times
340     // Add noise to guess for the axes
341     for (int k = 0; k < n_jets; k++) {
342     if ( 0 == l ) { // Don't add noise on first pass
343     old_axes[k].set_rap( seedAxes[k].rap() + noise );
344     old_axes[k].set_phi( seedAxes[k].phi() + noise );
345     } else {
346     noise = ((double)rand()/(double)RAND_MAX) * para.noise_range() * 2 - para.noise_range();
347     old_axes[k].set_rap( seedAxes[k].rap() + noise );
348     noise = ((double)rand()/(double)RAND_MAX) * para.noise_range() * 2 - para.noise_range();
349     old_axes[k].set_phi( seedAxes[k].phi() + noise );
350     }
351     }
352     cmp = 100.0; int h = 0;
353     while (cmp > para.precision() && h < para.halt()) { // Keep updating axes until near-convergence or too many update steps
354     cmp = 0.0; h++;
355     new_axes = UpdateAxes(old_axes, inputJets, paraNsub, para.precision()); // Update axes
356     for (int k = 0; k < n_jets; k++) {
357     cmp += Distance(new_axes[k].rap(),new_axes[k].phi(),old_axes[k].rap(),old_axes[k].phi());
358     }
359     cmp = cmp / ((double) n_jets);
360     old_axes = new_axes;
361     }
362     tmp_min_axes = ConvertToPseudoJet(old_axes); // Convert axes directions into four-std::vectors
363     tau_tmp = TauValue(inputJets, tmp_min_axes,paraNsub);
364     if (tau_tmp < tau) {tau = tau_tmp; min_axes = tmp_min_axes;} // Keep axes and tau only if they are best so far
365     }
366     return min_axes;
367     }
368    
369     ///////
370     //
371     // Main Njettiness Class
372     //
373     ///////
374    
375     class Njettiness {
376     public:
377     enum AxesMode {
378     kt_axes, // exclusive kt axes
379     ca_axes, // exclusive ca axes
380     antikt_0p2_axes, // inclusive hardest axes with antikt-0.2
381     min_axes, // axes that minimize N-subjettiness (100 passes by default)
382     manual_axes, // set your own axes with setAxes()
383     onepass_kt_axes, // one-pass minimization from kt starting point
384     onepass_ca_axes, // one-pass minimization from ca starting point
385     onepass_antikt_0p2_axes, // one-pass minimization from antikt-0.2 starting point
386     onepass_manual_axes // one-pass minimization from manual starting point
387     };
388    
389     private:
390     AxesMode _axes; //Axes mode choice
391     NsubParameters _paraNsub; //Parameters for Njettiness
392     KmeansParameters _paraKmeans; //Parameters for Minimization Procedure (set by NsubAxesMode automatically, but can change manually if desired)
393    
394     std::vector<fastjet::PseudoJet> _currentAxes;
395    
396     void establishAxes(unsigned n_jets, const std::vector <fastjet::PseudoJet> & inputs);
397    
398     public:
399     Njettiness(AxesMode axes, NsubParameters paraNsub);
400    
401     void setParaKmeans(KmeansParameters newPara) {_paraKmeans = newPara;}
402     void setParaNsub(NsubParameters newPara) {_paraNsub = newPara;}
403    
404     // setAxes for Manual mode
405     void setAxes(std::vector<fastjet::PseudoJet> myAxes) {
406     assert((_axes == manual_axes) || (_axes == onepass_manual_axes));
407     _currentAxes = myAxes;
408     }
409    
410     // The value of N-subjettiness
411     double getTau(unsigned n_jets, const std::vector<fastjet::PseudoJet> & inputJets) {
412     if (inputJets.size() <= n_jets) {
413     _currentAxes = inputJets;
414     _currentAxes.resize(n_jets,fastjet::PseudoJet(0.0,0.0,0.0,0.0));
415     return 0.0;
416     }
417     establishAxes(n_jets, inputJets); // sets current Axes
418     return TauValue(inputJets,_currentAxes,_paraNsub);
419     }
420    
421     // get axes used by getTau.
422     std::vector<fastjet::PseudoJet> currentAxes() {
423     return _currentAxes;
424     }
425    
426     // partition inputs by Voronoi (each vector stores indices corresponding to inputJets)
427     std::vector<std::list<int> > getPartition(const std::vector<fastjet::PseudoJet> & inputJets);
428    
429     // partition inputs by Voronoi
430     std::vector<fastjet::PseudoJet> getJets(const std::vector<fastjet::PseudoJet> & inputJets);
431    
432     };
433    
434    
435     //Use NsubAxesMode to pick which type of axes to use
436     void Njettiness::establishAxes(unsigned int n_jets, const std::vector <fastjet::PseudoJet> & inputs) {
437     switch (_axes) {
438     case kt_axes:
439     _currentAxes = GetKTAxes(n_jets,inputs);
440     break;
441     case ca_axes:
442     _currentAxes = GetCAAxes(n_jets,inputs);
443     break;
444     case antikt_0p2_axes:
445     _currentAxes = GetAntiKTAxes(n_jets,0.2,inputs);
446     break;
447     case onepass_kt_axes:
448     case min_axes:
449     _currentAxes = GetKTAxes(n_jets,inputs);
450     _currentAxes = GetMinimumAxes(_currentAxes, inputs, _paraKmeans, _paraNsub);
451     break;
452     case onepass_ca_axes:
453     _currentAxes = GetCAAxes(n_jets,inputs);
454     _currentAxes = GetMinimumAxes(_currentAxes, inputs, _paraKmeans, _paraNsub);
455     break;
456     case onepass_antikt_0p2_axes:
457     _currentAxes = GetAntiKTAxes(n_jets,0.2,inputs);
458     _currentAxes = GetMinimumAxes(_currentAxes, inputs, _paraKmeans, _paraNsub);
459     break;
460     case onepass_manual_axes:
461     assert(_currentAxes.size() == n_jets);
462     _currentAxes = GetMinimumAxes(_currentAxes, inputs, _paraKmeans, _paraNsub);
463     break;
464     case manual_axes:
465     assert(_currentAxes.size() == n_jets);
466     break;
467     default:
468     assert(false);
469     break;
470     }
471     }
472    
473     //Constructor sets KmeansParameters from NsubAxesMode input
474     Njettiness::Njettiness(AxesMode axes, NsubParameters paraNsub) : _axes(axes), _paraNsub(paraNsub), _paraKmeans() {
475     switch (_axes) {
476     case kt_axes:
477     case ca_axes:
478     case antikt_0p2_axes:
479     _paraKmeans = KmeansParameters(0,0.0,0,0.0);
480     break;
481     case onepass_kt_axes:
482     case onepass_ca_axes:
483     case onepass_antikt_0p2_axes:
484     case onepass_manual_axes:
485     _paraKmeans = KmeansParameters(1,0.0001,1000,0.8);
486     break;
487     case min_axes:
488     _paraKmeans = KmeansParameters(100,0.0001,1000,0.8);
489     break;
490     case manual_axes:
491     _paraKmeans = KmeansParameters(0,0.0,0,0.0);
492     break;
493     default:
494     assert(false);
495     break;
496     }
497     }
498    
499    
500     // Partition a list of particles according to which N-jettiness axis they are closest to.
501     // Return a vector of length _currentAxes.size() (which should be N).
502     // Each vector element is a list of ints corresponding to the indices in
503     // particles of the particles belonging to that jet.
504     std::vector<std::list<int> > Njettiness::getPartition(const std::vector<fastjet::PseudoJet> & particles) {
505     double Rcutoff = _paraNsub.Rcutoff();
506    
507     std::vector<std::list<int> > partitions(_currentAxes.size());
508    
509     int j_min = -1;
510     for (unsigned i = 0; i < particles.size(); i++) {
511     // find minimum distance
512     double minR = 10000.0; // large number
513     for (unsigned j = 0; j < _currentAxes.size(); j++) {
514     double tempR = std::sqrt(particles[i].squared_distance(_currentAxes[j])); // delta R distance
515     if (tempR < minR) {
516     minR = tempR;
517     j_min = j;
518     }
519     }
520     if (minR > Rcutoff) {
521     // do nothing
522     } else {
523     partitions[j_min].push_back(i);
524     }
525     }
526     return partitions;
527     }
528    
529    
530     // Having found axes, assign each particle in particles to an axis, and return a set of jets.
531     // Each jet is the sum of particles closest to an axis (Njet = Naxes).
532     std::vector<fastjet::PseudoJet> Njettiness::getJets(const std::vector<fastjet::PseudoJet> & particles) {
533    
534     std::vector<fastjet::PseudoJet> jets(_currentAxes.size());
535    
536     std::vector<std::list<int> > partition = getPartition(particles);
537     for (unsigned j = 0; j < partition.size(); ++j) {
538     std::list<int>::const_iterator it, itE;
539     for (it = partition[j].begin(), itE = partition[j].end(); it != itE; ++it) {
540     jets[j] += particles[*it];
541     }
542     }
543     return jets;
544     }
545    
546     #endif
547