Fork me on GitHub

source: git/external/fastjet/JetDefinition.cc@ 1c8d9db

ImprovedOutputFile Timing dual_readout llp
Last change on this file since 1c8d9db was 35cdc46, checked in by Pavel Demin <demin@…>, 10 years ago

upgrade FastJet to version 3.1.0-beta.1, upgrade Nsubjettiness to version 2.1.0, add SoftKiller version 1.0.0

  • Property mode set to 100644
File size: 16.0 KB
Line 
1//FJSTARTHEADER
2// $Id: JetDefinition.cc 3492 2014-07-30 16:58:20Z soyez $
3//
4// Copyright (c) 2005-2014, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
5//
6//----------------------------------------------------------------------
7// This file is part of FastJet.
8//
9// FastJet is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; either version 2 of the License, or
12// (at your option) any later version.
13//
14// The algorithms that underlie FastJet have required considerable
15// development. They are described in the original FastJet paper,
16// hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
17// FastJet as part of work towards a scientific publication, please
18// quote the version you use and include a citation to the manual and
19// optionally also to hep-ph/0512210.
20//
21// FastJet is distributed in the hope that it will be useful,
22// but WITHOUT ANY WARRANTY; without even the implied warranty of
23// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24// GNU General Public License for more details.
25//
26// You should have received a copy of the GNU General Public License
27// along with FastJet. If not, see <http://www.gnu.org/licenses/>.
28//----------------------------------------------------------------------
29//FJENDHEADER
30
31#include "fastjet/JetDefinition.hh"
32#include "fastjet/Error.hh"
33#include "fastjet/CompositeJetStructure.hh"
34#include<sstream>
35
36FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
37
38using namespace std;
39
40const double JetDefinition::max_allowable_R = 1000.0;
41
42//----------------------------------------------------------------------
43// [NB: implementation was getting complex, so in 2.4-devel moved it
44// from .hh to .cc]
45JetDefinition::JetDefinition(JetAlgorithm jet_algorithm_in,
46 double R_in,
47 Strategy strategy_in,
48 RecombinationScheme recomb_scheme_in,
49 int nparameters) :
50 _jet_algorithm(jet_algorithm_in), _Rparam(R_in), _strategy(strategy_in) {
51
52 // set R parameter or ensure its sensibleness, as appropriate
53 if (_jet_algorithm == ee_kt_algorithm) {
54 _Rparam = 4.0; // introduce a fictional R that ensures that
55 // our clustering sequence will not produce
56 // "beam" jets except when only a single particle remains.
57 // Any value > 2 would have done here
58 } else {
59 // We maintain some limit on R because particles with pt=0, m=0
60 // can have rapidities O(100000) and one doesn't want the
61 // clustering to start including them as if their rapidities were
62 // physical.
63 if (R_in > max_allowable_R) {
64 ostringstream oss;
65 oss << "Requested R = " << R_in << " for jet definition is larger than max_allowable_R = " << max_allowable_R;
66 throw Error(oss.str());
67 }
68 }
69
70 // cross-check the number of parameters that were declared in setting up the
71 // algorithm (passed internally from the public constructors)
72 unsigned int nparameters_expected = n_parameters_for_algorithm(jet_algorithm_in);
73 if (nparameters != (int) nparameters_expected){
74 ostringstream oss;
75 oss << "The jet algorithm you requested ("
76 << jet_algorithm_in << ") should be constructed with " << nparameters_expected
77 << " parameter(s) but was called with " << nparameters << " parameter(s)\n";
78 throw Error(oss.str());
79 }
80
81 // make sure the strategy requested is sensible
82 assert (_strategy != plugin_strategy);
83
84 _plugin = NULL;
85 set_recombination_scheme(recomb_scheme_in);
86 set_extra_param(0.0); // make sure it's defined
87}
88
89
90//----------------------------------------------------------------------
91// returns true if the jet definition involves an algorithm
92// intended for use on a spherical geometry (e.g. e+e- algorithms,
93// as opposed to most pp algorithms, which use a cylindrical,
94// rapidity-phi geometry).
95bool JetDefinition::is_spherical() const {
96 if (jet_algorithm() == plugin_algorithm) {
97 return plugin()->is_spherical();
98 } else {
99 return (jet_algorithm() == ee_kt_algorithm || // as of 2013-02-14, the two
100 jet_algorithm() == ee_genkt_algorithm // native spherical algorithms
101 );
102 }
103}
104
105//----------------------------------------------------------------------
106string JetDefinition::description() const {
107 ostringstream name;
108
109 name << description_no_recombiner();
110
111 if ((jet_algorithm() == plugin_algorithm) || (jet_algorithm() == undefined_jet_algorithm)){
112 return name.str();
113 }
114
115 if (n_parameters_for_algorithm(jet_algorithm()) == 0)
116 name << " with ";
117 else
118 name << " and ";
119 name << recombiner()->description();
120
121 return name.str();
122}
123
124//----------------------------------------------------------------------
125string JetDefinition::description_no_recombiner() const {
126
127 ostringstream name;
128 if (jet_algorithm() == plugin_algorithm) {
129 return plugin()->description();
130 } else if (jet_algorithm() == undefined_jet_algorithm) {
131 return "uninitialised JetDefinition (jet_algorithm=undefined_jet_algorithm)" ;
132 }
133
134 name << algorithm_description(jet_algorithm());
135 switch (n_parameters_for_algorithm(jet_algorithm())){
136 case 0: name << " (NB: no R)"; break;
137 case 1: name << " with R = " << R(); break; // the parameter is always R
138 case 2:
139 // the 1st parameter is always R
140 name << " with R = " << R();
141 // the 2nd depends on the algorithm
142 if (jet_algorithm() == cambridge_for_passive_algorithm){
143 name << "and a special hack whereby particles with kt < "
144 << extra_param() << "are treated as passive ghosts";
145 } else {
146 name << ", p = " << extra_param();
147 }
148 };
149
150 return name.str();
151}
152
153//----------------------------------------------------------------------
154string JetDefinition::algorithm_description(const JetAlgorithm jet_alg){
155 ostringstream name;
156 switch (jet_alg){
157 case plugin_algorithm: return "plugin algorithm";
158 case kt_algorithm: return "Longitudinally invariant kt algorithm";
159 case cambridge_algorithm: return "Longitudinally invariant Cambridge/Aachen algorithm";
160 case antikt_algorithm: return "Longitudinally invariant anti-kt algorithm";
161 case genkt_algorithm: return "Longitudinally invariant generalised kt algorithm";
162 case cambridge_for_passive_algorithm: return "Longitudinally invariant Cambridge/Aachen algorithm";
163 case ee_kt_algorithm: return "e+e- kt (Durham) algorithm (NB: no R)";
164 case ee_genkt_algorithm: return "e+e- generalised kt algorithm";
165 case undefined_jet_algorithm: return "undefined jet algorithm";
166 default:
167 throw Error("JetDefinition::algorithm_description(): unrecognized jet_algorithm");
168 };
169}
170
171//----------------------------------------------------------------------
172unsigned int JetDefinition::n_parameters_for_algorithm(const JetAlgorithm jet_alg){
173 switch (jet_alg) {
174 case ee_kt_algorithm: return 0;
175 case genkt_algorithm:
176 case ee_genkt_algorithm: return 2;
177 default: return 1;
178 };
179}
180
181//----------------------------------------------------------------------
182void JetDefinition::set_recombination_scheme(
183 RecombinationScheme recomb_scheme) {
184 _default_recombiner = JetDefinition::DefaultRecombiner(recomb_scheme);
185
186 // do not forget to delete the existing recombiner if needed
187 if (_shared_recombiner()) _shared_recombiner.reset();
188
189 _recombiner = 0;
190}
191
192void JetDefinition::set_recombiner(const JetDefinition &other_jet_def){
193 // make sure the "invariants" of the other jet def are sensible
194 assert(other_jet_def._recombiner ||
195 other_jet_def.recombination_scheme() != external_scheme);
196
197 // first treat the situation where we're using the default recombiner
198 if (other_jet_def._recombiner == 0){
199 set_recombination_scheme(other_jet_def.recombination_scheme());
200 return;
201 }
202
203 // in other cases, copy the pointer to the recombiner
204 _recombiner = other_jet_def._recombiner;
205 // set the default recombiner appropriately
206 _default_recombiner = DefaultRecombiner(external_scheme);
207 // and set the _shared_recombiner to the same state
208 // as in the other_jet_def, whatever that was
209 _shared_recombiner.reset(other_jet_def._shared_recombiner);
210
211 // NB: it is tempting to go via set_recombiner and then to sort
212 // out the shared part, but this would be dangerous in the
213 // specific (rare?) case where other_jet_def is the same as this
214 // it deletes_recombiner_when_unused. In that case the shared
215 // pointer reset would delete the recombiner.
216}
217
218
219// returns true if the current jet definitions shares the same
220// recombiner as teh one passed as an argument
221bool JetDefinition::has_same_recombiner(const JetDefinition &other_jd) const{
222 // first make sure that they have the same recombination scheme
223 const RecombinationScheme & scheme = recombination_scheme();
224 if (other_jd.recombination_scheme() != scheme) return false;
225
226 // if the scheme is "external", also check that they have the same
227 // recombiner
228 return (scheme != external_scheme)
229 || (recombiner() == other_jd.recombiner());
230}
231
232/// causes the JetDefinition to handle the deletion of the
233/// recombiner when it is no longer used
234void JetDefinition::delete_recombiner_when_unused(){
235 if (_recombiner == 0){
236 throw Error("tried to call JetDefinition::delete_recombiner_when_unused() for a JetDefinition without a user-defined recombination scheme");
237 } else if (_shared_recombiner.get()) {
238 throw Error("Error in JetDefinition::delete_recombiner_when_unused: the recombiner is already scheduled for deletion when unused (or was already set as shared)");
239 }
240
241 _shared_recombiner.reset(_recombiner);
242}
243
244/// allows to let the JetDefinition handle the deletion of the
245/// plugin when it is no longer used
246void JetDefinition::delete_plugin_when_unused(){
247 if (_plugin == 0){
248 throw Error("tried to call JetDefinition::delete_plugin_when_unused() for a JetDefinition without a plugin");
249 }
250
251 _plugin_shared.reset(_plugin);
252}
253
254
255
256string JetDefinition::DefaultRecombiner::description() const {
257 switch(_recomb_scheme) {
258 case E_scheme:
259 return "E scheme recombination";
260 case pt_scheme:
261 return "pt scheme recombination";
262 case pt2_scheme:
263 return "pt2 scheme recombination";
264 case Et_scheme:
265 return "Et scheme recombination";
266 case Et2_scheme:
267 return "Et2 scheme recombination";
268 case BIpt_scheme:
269 return "boost-invariant pt scheme recombination";
270 case BIpt2_scheme:
271 return "boost-invariant pt2 scheme recombination";
272 default:
273 ostringstream err;
274 err << "DefaultRecombiner: unrecognized recombination scheme "
275 << _recomb_scheme;
276 throw Error(err.str());
277 }
278}
279
280
281void JetDefinition::DefaultRecombiner::recombine(
282 const PseudoJet & pa, const PseudoJet & pb,
283 PseudoJet & pab) const {
284
285 double weighta, weightb;
286
287 switch(_recomb_scheme) {
288 case E_scheme:
289 // a call to reset turns out to be somewhat more efficient
290 // than a sum and assignment
291 //pab = pa + pb;
292 pab.reset(pa.px()+pb.px(),
293 pa.py()+pb.py(),
294 pa.pz()+pb.pz(),
295 pa.E ()+pb.E ());
296 return;
297 // all remaining schemes are massless recombinations and locally
298 // we just set weights, while the hard work is done below...
299 case pt_scheme:
300 case Et_scheme:
301 case BIpt_scheme:
302 weighta = pa.perp();
303 weightb = pb.perp();
304 break;
305 case pt2_scheme:
306 case Et2_scheme:
307 case BIpt2_scheme:
308 weighta = pa.perp2();
309 weightb = pb.perp2();
310 break;
311 default:
312 ostringstream err;
313 err << "DefaultRecombiner: unrecognized recombination scheme "
314 << _recomb_scheme;
315 throw Error(err.str());
316 }
317
318 double perp_ab = pa.perp() + pb.perp();
319 if (perp_ab != 0.0) { // weights also non-zero...
320 double y_ab = (weighta * pa.rap() + weightb * pb.rap())/(weighta+weightb);
321
322 // take care with periodicity in phi...
323 double phi_a = pa.phi(), phi_b = pb.phi();
324 if (phi_a - phi_b > pi) phi_b += twopi;
325 if (phi_a - phi_b < -pi) phi_b -= twopi;
326 double phi_ab = (weighta * phi_a + weightb * phi_b)/(weighta+weightb);
327
328 // this is much more efficient...
329 pab.reset_PtYPhiM(perp_ab,y_ab,phi_ab);
330 // pab = PseudoJet(perp_ab*cos(phi_ab),
331 // perp_ab*sin(phi_ab),
332 // perp_ab*sinh(y_ab),
333 // perp_ab*cosh(y_ab));
334 } else { // weights are zero
335 //pab = PseudoJet(0.0,0.0,0.0,0.0);
336 pab.reset(0.0, 0.0, 0.0, 0.0);
337 }
338}
339
340
341void JetDefinition::DefaultRecombiner::preprocess(PseudoJet & p) const {
342 switch(_recomb_scheme) {
343 case E_scheme:
344 case BIpt_scheme:
345 case BIpt2_scheme:
346 break;
347 case pt_scheme:
348 case pt2_scheme:
349 {
350 // these schemes (as in the ktjet implementation) need massless
351 // initial 4-vectors with essentially E=|p|.
352 double newE = sqrt(p.perp2()+p.pz()*p.pz());
353 p.reset_momentum(p.px(), p.py(), p.pz(), newE);
354 // FJ2.x version
355 // int user_index = p.user_index();
356 // p = PseudoJet(p.px(), p.py(), p.pz(), newE);
357 // p.set_user_index(user_index);
358 }
359 break;
360 case Et_scheme:
361 case Et2_scheme:
362 {
363 // these schemes (as in the ktjet implementation) need massless
364 // initial 4-vectors with essentially E=|p|.
365 double rescale = p.E()/sqrt(p.perp2()+p.pz()*p.pz());
366 p.reset_momentum(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E());
367 // FJ2.x version
368 // int user_index = p.user_index();
369 // p = PseudoJet(rescale*p.px(), rescale*p.py(), rescale*p.pz(), p.E());
370 // p.set_user_index(user_index);
371 }
372 break;
373 default:
374 ostringstream err;
375 err << "DefaultRecombiner: unrecognized recombination scheme "
376 << _recomb_scheme;
377 throw Error(err.str());
378 }
379}
380
381void JetDefinition::Plugin::set_ghost_separation_scale(double /*scale*/) const {
382 throw Error("set_ghost_separation_scale not supported");
383}
384
385
386
387//-------------------------------------------------------------------------------
388// helper functions to build a jet made of pieces
389//
390// This is the extended version with support for a user-defined
391// recombination-scheme
392// -------------------------------------------------------------------------------
393
394// build a "CompositeJet" from the vector of its pieces
395//
396// the user passes the reciombination scheme used to "sum" the pieces.
397PseudoJet join(const vector<PseudoJet> & pieces, const JetDefinition::Recombiner & recombiner){
398 // compute the total momentum
399 //--------------------------------------------------
400 PseudoJet result; // automatically initialised to 0
401 if (pieces.size()>0){
402 result = pieces[0];
403 for (unsigned int i=1; i<pieces.size(); i++)
404 recombiner.plus_equal(result, pieces[i]);
405 }
406
407 // attach a CompositeJetStructure to the result
408 //--------------------------------------------------
409 CompositeJetStructure *cj_struct = new CompositeJetStructure(pieces, &recombiner);
410
411 result.set_structure_shared_ptr(SharedPtr<PseudoJetStructureBase>(cj_struct));
412
413 return result;
414}
415
416// build a "CompositeJet" from a single PseudoJet
417PseudoJet join(const PseudoJet & j1,
418 const JetDefinition::Recombiner & recombiner){
419 return join(vector<PseudoJet>(1,j1), recombiner);
420}
421
422// build a "CompositeJet" from two PseudoJet
423PseudoJet join(const PseudoJet & j1, const PseudoJet & j2,
424 const JetDefinition::Recombiner & recombiner){
425 vector<PseudoJet> pieces;
426 pieces.push_back(j1);
427 pieces.push_back(j2);
428 return join(pieces, recombiner);
429}
430
431// build a "CompositeJet" from 3 PseudoJet
432PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3,
433 const JetDefinition::Recombiner & recombiner){
434 vector<PseudoJet> pieces;
435 pieces.push_back(j1);
436 pieces.push_back(j2);
437 pieces.push_back(j3);
438 return join(pieces, recombiner);
439}
440
441// build a "CompositeJet" from 4 PseudoJet
442PseudoJet join(const PseudoJet & j1, const PseudoJet & j2, const PseudoJet & j3, const PseudoJet & j4,
443 const JetDefinition::Recombiner & recombiner){
444 vector<PseudoJet> pieces;
445 pieces.push_back(j1);
446 pieces.push_back(j2);
447 pieces.push_back(j3);
448 pieces.push_back(j4);
449 return join(pieces, recombiner);
450}
451
452
453
454
455FASTJET_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.