Fork me on GitHub

source: svn/trunk/external/fastjet/plugins/D0RunIICone/ILConeAlgorithm.hpp@ 1368

Last change on this file since 1368 was 859, checked in by Pavel Demin, 12 years ago

update fastjet to version 3.0.3

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision Date
File size: 18.7 KB
Line 
1#ifndef D0RunIIconeJets_ILCONEALGORITHM
2#define D0RunIIconeJets_ILCONEALGORITHM
3// ---------------------------------------------------------------------------
4// ILConeAlgorithm.hpp
5//
6// Created: 28-JUL-2000 Francois Touze (+ Laurent Duflot)
7//
8// Purpose: Implements the Improved Legacy Cone Algorithm
9//
10// Modified:
11// 31-JUL-2000 Laurent Duflot
12// + introduce support for additional informations (ConeJetInfo)
13// 1-AUG-2000 Laurent Duflot
14// + seedET for midpoint jet is -999999., consistent with seedET ordering
15// in ConeSplitMerge: final jets with seedET=-999999. will be midpoint
16// jets which were actually different from stable cones.
17// 4-Aug-2000 Laurent Duflot
18// + remove unecessary copy in TemporaryJet::is_stable()
19// 11-Aug-2000 Laurent Duflot
20// + remove using namespace std
21// + add threshold on item. The input list to makeClusters() IS modified
22// 20-June-2002 John Krane
23// + remove bug in midpoint calculation based on pT weight
24// + started to add new midpoint calculation based on 4-vectors,
25// but not enough info held by this class
26// 24-June-2002 John Krane
27// + modify is_stable() to not iterate if desired
28// (to expand search cone w/out moving it)
29// + added search cone logic for initial jets but not midpoint jets as per
30// agreement with CDF
31// 19-July-2002 John Krane
32// + _SEARCH_CONE size factor now provided by calreco/CalClusterReco.cpp
33// + (default = 1.0 = like original ILCone behavior)
34// 10-Oct-2002 John Krane
35// + Check min Pt of cone with full size first, then iterate with search cone
36// 07-Dec-2002 John Krane
37// + speed up the midpoint phi-wrap solution
38// 01-May-2007 Lars Sonnenschein
39// extracted from D0 software framework and modified to remove subsequent dependencies
40//
41//
42// This file is distributed with FastJet under the terms of the GNU
43// General Public License (v2). Permission to do so has been granted
44// by Lars Sonnenschein and the D0 collaboration (see COPYING for
45// details)
46//
47// History of changes in FastJet compared tothe original version of
48// ProtoJet.hpp
49//
50// 2012-06-12 Gregory Soyez <soyez@fastjet.fr>
51//
52// * Replaced addItem(...) by this->addItem(...) to allow
53// compilation with gcc 4.7 which no longer performs
54// unqualified template lookups. See
55// e.g. http://gcc.gnu.org/gcc-4.7/porting_to.html
56//
57// 2011-12-13 Gregory Soyez <soyez@fastjet.fr>
58//
59// * added license information
60//
61// 2011-11-14 Gregory Soyez <soyez@fastjet.fr>
62//
63// * changed the name of a few parameters to avoid a gcc
64// -Wshadow warning
65//
66// 2009-01-17 Gregory Soyez <soyez@fastjet.fr>
67//
68// * put the code in the fastjet::d0 namespace
69//
70// 2007-12-14 Gavin Salam <salam@lpthe.jussieu.fr>
71//
72// * moved the 'std::vector<ProtoJet<Item> > ilcv' structure
73// containing the info about the final jets from a local
74// variable to a class variable (for integration in the
75// FastJet plugin core)
76//
77// ---------------------------------------------------------------------------
78
79#include <vector>
80#include <list>
81#include <utility> // defines pair<,>
82#include <map>
83#include <algorithm>
84#include <iostream>
85
86
87//#include "energycluster/EnergyClusterReco.hpp"
88//#include "energycluster/ProtoJet.hpp"
89#include "ProtoJet.hpp"
90//#include "energycluster/ConeSplitMerge.hpp"
91#include "ConeSplitMerge.hpp"
92//#include "energycluster/ConeJetInfoChunk.hpp"
93
94#include "inline_maths.h"
95
96///////////////////////////////////////////////////////////////////////////////
97#include <fastjet/internal/base.hh>
98
99FASTJET_BEGIN_NAMESPACE
100
101namespace d0{
102
103using namespace inline_maths;
104
105/*
106 NB: Some attempt at optimizing the code has been made by ordering the object
107 along rapidity but this did not improve the speed. There are traces of
108 these atemps in the code, that will be cleaned up in the future.
109 */
110
111// at most one of those !
112// order the input list and use lower_bound() and upper_bound() to restrict the
113// on item to those that could possibly be in the cone.
114//#define ILCA_USE_ORDERED_LIST
115
116// idem but use an intermediate multimap in hope that lower_bound() and
117// upper_bound() are faster in this case.
118//#define ILCA_USE_MMAP
119
120
121#ifdef ILCA_USE_ORDERED_LIST
122// this class is used to order the item list along rapidity
123template <class Item>
124class rapidity_order
125{
126public:
127 bool operator()(const Item* first, const Item* second)
128 {
129 return (first->y() < second->y());
130 }
131 bool operator()(float const & first, const Item* second)
132 {
133 return (first < second->y());
134 }
135 bool operator()(const Item* first, float const& second)
136 {
137 return (first->y() < second);
138 }
139};
140#endif
141
142
143//template <class Item,class ItemAddress,class IChunk>
144template <class Item>
145class ILConeAlgorithm
146{
147
148public:
149
150 // default constructor (default parameters are crazy: you should not use that
151 // constructor !)
152 ILConeAlgorithm():
153 _CONE_RADIUS(0.),
154 _MIN_JET_ET(99999.),
155 _ET_MIN_RATIO(0.5),
156 _FAR_RATIO(0.5),
157 _SPLIT_RATIO(0.5),
158 _DUPLICATE_DR(0.005),
159 _DUPLICATE_DPT(0.01),
160 _SEARCH_CONE(0.5),
161 _PT_MIN_LEADING_PROTOJET(0),
162 _PT_MIN_SECOND_PROTOJET(0),
163 _MERGE_MAX(10000),
164 _PT_MIN_noMERGE_MAX(0)
165 {;}
166
167 // full constructor
168 ILConeAlgorithm(float cone_radius, float min_jet_Et, float split_ratio,
169 float far_ratio=0.5, float Et_min_ratio=0.5,
170 bool kill_duplicate=true, float duplicate_dR=0.005,
171 float duplicate_dPT=0.01, float search_factor=1.0,
172 float pT_min_leading_protojet=0., float pT_min_second_protojet=0.,
173 int merge_max=10000, float pT_min_nomerge=0.) :
174 // cone radius
175 _CONE_RADIUS(cone_radius),
176 // minimum jet ET
177 _MIN_JET_ET(min_jet_Et),
178 // stable cones must have ET > _ET_MIN_RATIO*_MIN_JET_ET at any iteration
179 _ET_MIN_RATIO(Et_min_ratio),
180 // precluster at least _FAR_RATIO*_CONE_RADIUS away from stable cones
181 _FAR_RATIO(far_ratio),
182 // split or merge criterium
183 _SPLIT_RATIO(split_ratio),
184 _DUPLICATE_DR(duplicate_dR),
185 _DUPLICATE_DPT(duplicate_dPT),
186 _SEARCH_CONE(cone_radius/search_factor),
187 // kill stable cone if within _DUPLICATE_DR and delta(pT)<_DUPLICATE_DPT
188 // of another stable cone.
189 _KILL_DUPLICATE(kill_duplicate),
190 _PT_MIN_LEADING_PROTOJET(pT_min_leading_protojet),
191 _PT_MIN_SECOND_PROTOJET(pT_min_second_protojet),
192 _MERGE_MAX(merge_max),
193 _PT_MIN_noMERGE_MAX(pT_min_nomerge)
194 {;}
195
196 //destructor
197 ~ILConeAlgorithm() {;}
198
199 // make jet clusters using improved legacy cone algorithm
200 //void makeClusters(const EnergyClusterReco* r,
201 void makeClusters(
202 // the input list modified (ordered)
203 std::list<Item> &jets,
204 std::list<const Item*>& itemlist,
205 //float zvertex,
206 ////std::list<const Item*>& itemlist);
207 //const EnergyClusterCollection<ItemAddress>& preclu,
208 //IChunk* chunkptr, ConeJetInfoChunk* infochunkptr,
209 const float Item_ET_Threshold);
210
211 // this will hold the final jets + contents
212 std::vector<ProtoJet<Item> > ilcv;
213
214private:
215
216 float _CONE_RADIUS;
217 float _MIN_JET_ET;
218 float _ET_MIN_RATIO;
219 float _FAR_RATIO;
220 float _SPLIT_RATIO;
221 float _DUPLICATE_DR;
222 float _DUPLICATE_DPT;
223 float _SEARCH_CONE;
224
225 bool _KILL_DUPLICATE;
226
227 float _PT_MIN_LEADING_PROTOJET;
228 float _PT_MIN_SECOND_PROTOJET;
229 int _MERGE_MAX;
230 float _PT_MIN_noMERGE_MAX;
231
232 // private class
233 // This is a ProtoJet with additional methods dist(), midpoint() and
234 // is_stable()
235 class TemporaryJet : public ProtoJet<Item>
236 {
237
238 public :
239
240 TemporaryJet(float seedET) : ProtoJet<Item>(seedET) {;}
241
242 TemporaryJet(float seedET,float y_in,float phi_in) :
243 ProtoJet<Item>(seedET,y_in,phi_in) {;}
244
245 ~TemporaryJet() {;}
246
247 float dist(TemporaryJet& jet) const
248 {
249 return RDelta(this->_y,this->_phi,jet.y(),jet.phi());
250 }
251
252 void midpoint(const TemporaryJet& jet,float & y_out, float & phi_out) const
253 {
254 // Midpoint should probably be computed w/4-vectors but don't
255 // have that info. Preserving Pt-weighted calculation - JPK
256 float pTsum = this->_pT + jet.pT();
257 y_out = (this->_y*this->_pT + jet.y()*jet.pT())/pTsum;
258
259 phi_out = (this->_phi*this->_pT + jet.phi()*jet.pT())/pTsum;
260 // careful with phi-wrap area: convert from [0,2pi] to [-pi,pi]
261 //ls: original D0 code, as of 23/Mar/2007
262 //if ( abs(phi-this->_phi)>2.0 ) { // assumes cones R=1.14 or smaller, merge within 2R only
263 //ls: abs bug fixed 26/Mar/2007
264 if ( fabs(phi_out-this->_phi)>2.0 ) { // assumes cones R=1.14 or smaller, merge within 2R only
265 phi_out = fmod( this->_phi+PI, TWOPI);
266 if (phi_out < 0.0) phi_out += TWOPI;
267 phi_out -= PI;
268
269 float temp=fmod( jet.phi()+PI, TWOPI);
270 if (temp < 0.0) temp += TWOPI;
271 temp -= PI;
272
273 phi_out = (phi_out*this->_pT + temp*jet.pT()) /pTsum;
274 }
275
276 if ( phi_out < 0. ) phi_out += TWOPI;
277 }
278
279
280////////////////////////////////////////
281#ifdef ILCA_USE_MMAP
282 bool is_stable(const std::multimap<float,const Item*>& items,
283 float radius, float min_ET, int max_iterations=50)
284#else
285 bool is_stable(const std::list<const Item*>& itemlist, float radius,
286 float min_ET, int max_iterations=50)
287#endif
288 // Note: max_iterations = 0 will just recompute the jet using the specified cone
289 {
290 float radius2 = radius*radius;
291 float Rcut= 1.E-06;
292
293
294 // ?? if(_Increase_Delta_R) Rcut= 1.E-04;
295 bool stable= true;
296 int trial= 0;
297 float Yst;
298 float PHIst;
299 do {
300 trial++;
301 //std::cout << " trial " << trial << " " << _y << " " << _phi << std::endl;
302 Yst = this->_y;
303 PHIst= this->_phi;
304 //cout << "is_stable beginning do loop: this->_pT=" << this->_pT << " this->_y=" << this->_y << " this->_phi=" << this->_phi << endl;
305 this->erase();
306
307 this->setJet(Yst,PHIst,0.0);
308
309
310#ifdef ILCA_USE_ORDERED_LIST
311 std::list<const Item*>::const_iterator lower =
312 lower_bound(itemlist.begin(),itemlist.end(),Yst-radius,
313 rapidity_order<Item>());
314 std::list<const Item*>::const_iterator upper =
315 upper_bound(itemlist.begin(),itemlist.end(),Yst+radius,
316 rapidity_order<Item>());
317 for(std::list<const Item*>::const_iterator tk = lower; tk != upper; ++tk) {
318 //std::cout << " is_stable: item y=" << (*tk)->y() << " phi=" << (*tk)->phi() << " RD2=" << RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) << " " << Yst-radius << " " << Yst+radius << endl;
319 if(RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) <= radius2)
320 {
321 this->addItem(*tk);
322 }
323 }
324#else
325#ifdef ILCA_USE_MMAP
326 // need to loop only on the subset with Yst-R < y < Yst+R
327 for ( std::multimap<float,const Item*>::const_iterator
328 tk = items.lower_bound(Yst-radius);
329 tk != items.upper_bound(Yst+radius); ++tk )
330 {
331 //std::cout << " item " << (*tk)->y() << " " << (*tk)->phi() << " " << RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) << " " << Yst-radius << " " << Yst+radius << endl;
332 if(RD2(((*tk).second)->y(),((*tk).second)->phi(),Yst,PHIst) <= radius2)
333 {
334 this->addItem((*tk).second);
335 }
336 }
337
338#else
339
340 //cout << " is_stable: itemlist.size()=" << itemlist.size() << endl;
341 for(typename std::list<const Item*>::const_iterator tk = itemlist.begin(); tk != itemlist.end(); ++tk)
342 {
343 //std::cout << " is_stable: item (*tk)->y()=" << (*tk)->y() << " (*tk)->phi=" << (*tk)->phi() << " RD2=" << RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) << " Yst-rad=" << Yst-radius << " Yst+rad=" << Yst+radius << endl;
344 if(RD2((*tk)->y(),(*tk)->phi(),Yst,PHIst) <= radius2)
345 {
346 //cout << "add item to *tk" << endl;
347 this->addItem(*tk);
348 }
349 }
350#endif
351#endif
352
353 //std::cout << "is_stable, before update: jet this->_y=" << this->_y << " _phi=" << this->_phi << " _pT=" << this->_pT << " min_ET=" << min_ET << std::endl;
354 this->updateJet();
355 //std::cout << "is_stable, after update: jet this->_y=" << this->_y << " _phi=" << this->_phi << " _pT=" << this->_pT << " min_ET=" << min_ET << std::endl;
356
357 if(this->_pT < min_ET )
358 {
359 stable= false;
360 break;
361 }
362 //cout << "is_stable end while loop: this->_pT=" << this->_pT << " this->_y=" << this->_y << " this->_phi=" << this->_phi << endl;
363 } while(RD2(this->_y,this->_phi,Yst,PHIst) >= Rcut && trial <= max_iterations);
364 //std::cout << " trial stable " << trial << " " << stable << std::endl;
365 return stable;
366 }
367
368 private :
369
370 };
371};
372///////////////////////////////////////////////////////////////////////////////
373//template <class Item,class ItemAddress,class IChunk>
374//void ILConeAlgorithm <Item,ItemAddress,IChunk>::
375template <class Item>
376void ILConeAlgorithm <Item>::
377//makeClusters(const EnergyClusterReco* r,
378makeClusters(
379 std::list<Item> &jets,
380 std::list<const Item*>& ilist,
381 //float Zvertex,
382 ////std::list<const Item*>& ilist)
383 //const EnergyClusterCollection<ItemAddress>& preclu,
384 //IChunk* chunkptr, ConeJetInfoChunk* infochunkptr,
385 const float Item_ET_Threshold)
386{
387 // remove items below threshold
388 for ( typename std::list<const Item*>::iterator it = ilist.begin();
389
390 it != ilist.end(); )
391 {
392 if ( (*it)->pT() < Item_ET_Threshold )
393 {
394 it = ilist.erase(it);
395 }
396 else ++it;
397 }
398
399 // create an energy cluster collection for jets
400 //EnergyClusterCollection<ItemAddress>* ptrcol;
401 //Item* ptrcol;
402 //r->createClusterCollection(chunkptr,ptrcol);
403 ////std::vector<const EnergyCluster<ItemAddress>*> ecv;
404 std::vector<const Item*> ecv;
405 for ( typename std::list<const Item*>::iterator it = ilist.begin();
406 it != ilist.end(); it++) {
407 ecv.push_back(*it);
408 }
409
410
411 //preclu.getClusters(ecv);
412 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% need to fill here vector ecv
413
414 //std::cout << " number of seed clusters: " << ecv.size() << std::endl;
415
416 // skip precluster close to jets
417 float far_def = _FAR_RATIO*_CONE_RADIUS * _FAR_RATIO*_CONE_RADIUS;
418
419 // skip if jet Et is below some value
420 float ratio= _MIN_JET_ET*_ET_MIN_RATIO;
421
422
423#ifdef ILCA_USE_ORDERED_LIST
424 // sort the list in rapidity order
425 ilist.sort(rapidity_order<Item>());
426#else
427#ifdef ILCA_USE_MMAP
428 // create a y ordered list of items
429 std::multimap<float,const Item*> items;
430 std::list<const Item*>::const_iterator it;
431 for(it = ilist.begin(); it != ilist.end(); ++it)
432 {
433 pair<float,const Item*> p((*it)->y(),*it);
434 items.insert(p);
435 }
436#endif
437#endif
438
439 std::vector<ProtoJet<Item> > mcoll;
440 std::vector<TemporaryJet> scoll;
441
442
443 // find stable jets around seeds
444 //typename std::vector<const EnergyCluster<ItemAddress>* >::iterator jclu;
445 typename std::vector<const Item*>::iterator jclu;
446 for(jclu = ecv.begin(); jclu != ecv.end(); ++jclu)
447 {
448 //const EnergyCluster<ItemAddress>* ptr= *jclu;
449 const Item* ptr= *jclu;
450 float p[4];
451 ptr->p4vec(p);
452 float Yst = P2y(p);
453 float PHIst= P2phi(p);
454
455 // don't keep preclusters close to jet
456 bool is_far= true;
457 // ?? if(_Kill_Far_Clusters) {
458 for(unsigned int i = 0; i < scoll.size(); ++i)
459 {
460 float y = scoll[i].y();
461 float phi= scoll[i].phi();
462 if(RD2(Yst,PHIst,y,phi) < far_def)
463 {
464 is_far= false;
465 break;
466 }
467 }
468 // ?? }
469
470 if(is_far)
471 {
472 TemporaryJet jet(ptr->pT(),Yst,PHIst);
473 //cout << "temporary jet: pt=" << ptr->pT() << " y=" << Yst << " phi=" << PHIst << endl;
474
475 // Search cones are smaller, so contain less jet Et
476 // Don't throw out too many little jets during search phase!
477 // Strategy: check Et first with full cone, then search with low-GeV min_et thresh
478#ifdef ILCA_USE_MMAP
479 if(jet.is_stable(items,_CONE_RADIUS,ratio,0) && jet.is_stable(items,_SEARCH_CONE,3.0))
480#else
481 if(jet.is_stable(ilist,_CONE_RADIUS,ratio,0) && jet.is_stable(ilist,_SEARCH_CONE,3.0))
482#endif
483 {
484
485 //cout << "temporary jet is stable" << endl;
486
487// jpk Resize the found jets
488#ifdef ILCA_USE_MMAP
489 jet.is_stable(items,_CONE_RADIUS,ratio,0) ;
490#else
491 jet.is_stable(ilist,_CONE_RADIUS,ratio,0) ;
492#endif
493 //cout << "found jet has been resized if any" << endl;
494
495 if ( _KILL_DUPLICATE )
496 {
497 // check if we are not finding the same jet again
498 float distmax = 999.; int imax = -1;
499 for(unsigned int i = 0; i < scoll.size(); ++i)
500 {
501 float dist = jet.dist(scoll[i]);
502 if ( dist < distmax )
503 {
504 distmax = dist;
505 imax = i;
506 }
507 }
508 if ( distmax > _DUPLICATE_DR ||
509 fabs((jet.pT()-scoll[imax].pT())/scoll[imax].pT())>_DUPLICATE_DPT )
510 {
511 scoll.push_back(jet);
512 mcoll.push_back(jet);
513 //std::cout << " stable cone " << jet.y() << " " << jet.phi() << " " << jet.pT() << std::endl;
514 }
515 /*
516 else
517 {
518 std::cout << " jet too close to a found jet " << distmax << " " <<
519 fabs((jet.pT()-scoll[imax].pT())/scoll[imax].pT()) << std::endl;
520 }
521 */
522 }
523 else
524 {
525 scoll.push_back(jet);
526 mcoll.push_back(jet);
527 //std::cout << " stable cone " << jet.y() << " " << jet.phi() << " " << jet.pT() << std::endl;
528 }
529
530 }
531 }
532 }
533
534 // find stable jets around midpoints
535 for(unsigned int i = 0; i < scoll.size(); ++i)
536 {
537 for(unsigned int k = i+1; k < scoll.size(); ++k)
538 {
539 float djet= scoll[i].dist(scoll[k]);
540 if(djet > _CONE_RADIUS && djet < 2.*_CONE_RADIUS)
541 {
542 float y_mid,phi_mid;
543 scoll[i].midpoint(scoll[k],y_mid,phi_mid);
544 TemporaryJet jet(-999999.,y_mid,phi_mid);
545 //std::cout << " midpoint: " << scoll[i].pT() << " " << scoll[i].info().seedET() << " " << scoll[k].pT() << " " << scoll[k].info().seedET() << " " << y_mid << " " << phi_mid << std::endl;
546
547// midpoint jets are full size
548#ifdef ILCA_USE_MMAP
549 if(jet.is_stable(items,_CONE_RADIUS,ratio))
550#else
551 if(jet.is_stable(ilist,_CONE_RADIUS,ratio))
552#endif
553 {
554 mcoll.push_back(jet);
555 //std::cout << " stable midpoint cone " << jet.y() << " " << jet.phi() << " " << jet.pT() << std::endl;
556 }
557 }
558 }
559 }
560
561
562 // do a pT ordered splitting/merging
563 ConeSplitMerge<Item> pjets(mcoll);
564 ilcv.clear();
565 pjets.split_merge(ilcv,_SPLIT_RATIO, _PT_MIN_LEADING_PROTOJET, _PT_MIN_SECOND_PROTOJET, _MERGE_MAX, _PT_MIN_noMERGE_MAX);
566
567
568 for(unsigned int i = 0; i < ilcv.size(); ++i)
569 {
570 if ( ilcv[i].pT() > _MIN_JET_ET )
571 {
572 //EnergyCluster<ItemAddress>* ptrclu;
573 Item ptrclu;
574 //r->createCluster(ptrcol,ptrclu);
575
576 std::list<const Item*> tlist=ilcv[i].LItems();
577 typename std::list<const Item*>::iterator tk;
578 for(tk = tlist.begin(); tk != tlist.end(); ++tk)
579 {
580 //ItemAddress addr= (*tk)->address();
581 float pk[4];
582 (*tk)->p4vec(pk);
583 //std::cout << (*tk)->index <<" " << (*tk) << std::endl;
584 //float emE= (*tk)->emE();
585 //r->addClusterItem(ptrclu,addr,pk,emE);
586 //ptrclu->Add(*tk);
587 ptrclu.Add(**tk);
588 }
589 // print out
590 //ptrclu->print(cout);
591
592 //infochunkptr->addInfo(ilcv[i].info());
593 jets.push_back(ptrclu);
594 }
595 }
596}
597
598} // namespace d0
599
600FASTJET_END_NAMESPACE
601
602#endif
603
604
Note: See TracBrowser for help on using the repository browser.