CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CATopJetAlgorithm.cc
Go to the documentation of this file.
1 // Original author: Brock Tweedie (JHU)
2 // Ported to CMSSW by: Sal Rappoccio (JHU)
3 // $Id: CATopJetAlgorithm.cc,v 1.6 2010/03/12 10:38:45 jdolen Exp $
4 
12 
13 
14 using namespace std;
15 using namespace reco;
16 using namespace edm;
17 
18 
19 // Run the algorithm
20 // ------------------
21 void CATopJetAlgorithm::run( const vector<fastjet::PseudoJet> & cell_particles,
22  vector<CompoundPseudoJet> & hardjetsOutput,
23  edm::EventSetup const & c )
24 {
25  if ( verbose_ ) cout << "Welcome to CATopSubJetAlgorithm::run" << endl;
26 
27  // Sum Et of the event
28  double sumEt = 0.;
29 
30  //make a list of input objects ordered by ET and calculate sum et
31  // list of fastjet pseudojet constituents
32  for (unsigned i = 0; i < cell_particles.size(); ++i) {
33  sumEt += cell_particles[i].perp();
34  }
35 
36  // Determine which bin we are in for et clustering
37  int sumEtBinId = -1;
38  for ( unsigned int i = 0; i < sumEtBins_.size(); ++i ) {
39  if ( sumEt > sumEtBins_[i] ) sumEtBinId = i;
40  }
41  if ( verbose_ ) cout << "Using sumEt = " << sumEt << ", bin = " << sumEtBinId << endl;
42 
43  // If the sum et is too low, exit
44  if ( sumEtBinId < 0 ) {
45  return;
46  }
47 
48  // empty 4-vector
49  fastjet::PseudoJet blankJetA(0,0,0,0);
50  blankJetA.set_user_index(-1);
51  const fastjet::PseudoJet blankJet = blankJetA;
52 
53  // Define adjacency variables which depend on which sumEtBin we are in
54  double deltarcut = deltarBins_[sumEtBinId];
55  double nCellMin = nCellBins_[sumEtBinId];
56 
57  if ( verbose_ )cout<<"useAdjacency_ = "<<useAdjacency_<<endl;
58  if ( verbose_ && useAdjacency_==0)cout<<"No Adjacency"<<endl;
59  if ( verbose_ && useAdjacency_==1)cout<<"using deltar adjacency"<<endl;
60  if ( verbose_ && useAdjacency_==2)cout<<"using modified adjacency"<<endl;
61  if ( verbose_ && useAdjacency_==3)cout<<"using calorimeter nearest neighbor based adjacency"<<endl;
62  if ( verbose_ && useAdjacency_==1)cout << "Using deltarcut = " << deltarcut << endl;
63  if ( verbose_ && useAdjacency_==3)cout << "Using nCellMin = " << nCellMin << endl;
64 
65 
66  // Define strategy, recombination scheme, and jet definition
67  fastjet::Strategy strategy = fastjet::Best;
68  fastjet::RecombinationScheme recombScheme = fastjet::E_scheme;
69 
70  // pick algorithm
71  fastjet::JetAlgorithm algorithm = static_cast<fastjet::JetAlgorithm>( algorithm_ );
72 
73  fastjet::JetDefinition jetDef( algorithm,
74  rBins_[sumEtBinId], recombScheme, strategy);
75 
76  if ( verbose_ ) cout << "About to do jet clustering in CA" << endl;
77  // run the jet clustering
78  fastjet::ClusterSequence clusterSeq(cell_particles, jetDef);
79 
80  if ( verbose_ ) cout << "Getting inclusive jets" << endl;
81  // Get the transient inclusive jets
82  vector<fastjet::PseudoJet> inclusiveJets = clusterSeq.inclusive_jets(ptMin_);
83 
84  if ( verbose_ ) cout << "Getting central jets" << endl;
85  // Find the transient central jets
86  vector<fastjet::PseudoJet> centralJets;
87  for (unsigned int i = 0; i < inclusiveJets.size(); i++) {
88 
89  if (inclusiveJets[i].perp() > ptMin_ && fabs(inclusiveJets[i].rapidity()) < centralEtaCut_) {
90  centralJets.push_back(inclusiveJets[i]);
91  }
92  }
93  // Sort the transient central jets in Et
94  GreaterByEtPseudoJet compEt;
95  sort( centralJets.begin(), centralJets.end(), compEt );
96 
97  // These will store the 4-vectors of each hard jet
98  vector<math::XYZTLorentzVector> p4_hardJets;
99 
100  // These will store the indices of each subjet that
101  // are present in each jet
102  vector<vector<int> > indices( centralJets.size() );
103 
104  // Loop over central jets, attempt to find substructure
105  vector<fastjet::PseudoJet>::iterator jetIt = centralJets.begin(),
106  centralJetsBegin = centralJets.begin(),
107  centralJetsEnd = centralJets.end();
108  if ( verbose_ )cout<<"Loop over jets"<<endl;
109  int i=0;
110  for ( ; jetIt != centralJetsEnd; ++jetIt ) {
111  if ( verbose_ )cout<<"\nJet "<<i<<endl;
112  i++;
113  fastjet::PseudoJet localJet = *jetIt;
114 
115  // Get the 4-vector for this jet
116  p4_hardJets.push_back( math::XYZTLorentzVector(localJet.px(), localJet.py(), localJet.pz(), localJet.e() ));
117 
118  // jet decomposition. try to find 3 or 4 hard, well-localized subjets, characteristic of a boosted top.
119  if ( verbose_ )cout<<"local jet pt = "<<localJet.perp()<<endl;
120  if ( verbose_ )cout<<"deltap = "<<ptFracBins_[sumEtBinId]<<endl;
121 
122  double ptHard = ptFracBins_[sumEtBinId]*localJet.perp();
123  vector<fastjet::PseudoJet> leftoversAll;
124 
125  // stage 1: primary decomposition. look for when the jet declusters into two hard subjets
126  if ( verbose_ ) cout << "Doing decomposition 1" << endl;
127  fastjet::PseudoJet ja, jb;
128  vector<fastjet::PseudoJet> leftovers1;
129  bool hardBreak1 = decomposeJet(localJet,clusterSeq,cell_particles,ptHard,nCellMin,deltarcut,ja,jb,leftovers1);
130  leftoversAll.insert(leftoversAll.end(),leftovers1.begin(),leftovers1.end());
131 
132  // stage 2: secondary decomposition. look for when the hard subjets found above further decluster into two hard sub-subjets
133  //
134  // ja -> jaa+jab ?
135  if ( verbose_ ) cout << "Doing decomposition 2. ja->jaa+jab?" << endl;
136  fastjet::PseudoJet jaa, jab;
137  vector<fastjet::PseudoJet> leftovers2a;
138  bool hardBreak2a = false;
139  if (hardBreak1) hardBreak2a = decomposeJet(ja,clusterSeq,cell_particles,ptHard,nCellMin,deltarcut,jaa,jab,leftovers2a);
140  leftoversAll.insert(leftoversAll.end(),leftovers2a.begin(),leftovers2a.end());
141  // jb -> jba+jbb ?
142  if ( verbose_ ) cout << "Doing decomposition 2. ja->jba+jbb?" << endl;
143  fastjet::PseudoJet jba, jbb;
144  vector<fastjet::PseudoJet> leftovers2b;
145  bool hardBreak2b = false;
146  if (hardBreak1) hardBreak2b = decomposeJet(jb,clusterSeq,cell_particles,ptHard,nCellMin,deltarcut,jba,jbb,leftovers2b);
147  leftoversAll.insert(leftoversAll.end(),leftovers2b.begin(),leftovers2b.end());
148 
149  // NOTE: it might be good to consider some checks for whether these subjets can be further decomposed. e.g., the above procedure leaves
150  // open the possibility of "subjets" that actually consist of two or more distinct hard clusters. however, this kind of thing
151  // is a rarity for the simulations so far considered.
152 
153  // proceed if one or both of the above hard subjets successfully decomposed
154  if ( verbose_ ) cout << "Done with decomposition" << endl;
155 
156  int nBreak2 = 0;
157  fastjet::PseudoJet hardA = blankJet, hardB = blankJet, hardC = blankJet, hardD = blankJet;
158  if (!hardBreak2a && !hardBreak2b) { nBreak2 = 0; hardA = ja; hardB = jb; hardC = blankJet; hardD = blankJet; }
159  if ( hardBreak2a && !hardBreak2b) { nBreak2 = 1; hardA = jaa; hardB = jab; hardC = jb; hardD = blankJet; }
160  if (!hardBreak2a && hardBreak2b) { nBreak2 = 1; hardA = jba; hardB = jbb; hardC = ja; hardD = blankJet;}
161  if ( hardBreak2a && hardBreak2b) { nBreak2 = 2; hardA = jaa; hardB = jab; hardC = jba; hardD = jbb; }
162 
163  // check if we are left with >= 3 hard subjets
164  fastjet::PseudoJet subjet1 = blankJet;
165  fastjet::PseudoJet subjet2 = blankJet;
166  fastjet::PseudoJet subjet3 = blankJet;
167  fastjet::PseudoJet subjet4 = blankJet;
168  subjet1 = hardA; subjet2 = hardB; subjet3 = hardC; subjet4 = hardD;
169 
170  // record the hard subjets
171  vector<fastjet::PseudoJet> hardSubjets;
172 
173  if ( subjet1.user_index() >= 0 )
174  hardSubjets.push_back(subjet1);
175  if ( subjet2.user_index() >= 0 )
176  hardSubjets.push_back(subjet2);
177  if ( subjet3.user_index() >= 0 )
178  hardSubjets.push_back(subjet3);
179  if ( subjet4.user_index() >= 0 )
180  hardSubjets.push_back(subjet4);
181  sort(hardSubjets.begin(), hardSubjets.end(), compEt );
182 
183  // create the subjets objects to put into the "output" objects
184  vector<CompoundPseudoSubJet> subjetsOutput;
185  std::vector<fastjet::PseudoJet>::const_iterator itSubJetBegin = hardSubjets.begin(),
186  itSubJet = itSubJetBegin, itSubJetEnd = hardSubjets.end();
187  for (; itSubJet != itSubJetEnd; ++itSubJet ){
188  // if ( verbose_ ) cout << "Adding input collection element " << (*itSubJet).user_index() << endl;
189  // if ( (*itSubJet).user_index() >= 0 && (*itSubJet).user_index() < cell_particles.size() )
190 
191  // Get the transient subjet constituents from fastjet
192  vector<fastjet::PseudoJet> subjetFastjetConstituents = clusterSeq.constituents( *itSubJet );
193 
194  // Get the indices of the constituents
195  vector<int> constituents;
196 
197  // Loop over the constituents and get the indices
198  vector<fastjet::PseudoJet>::const_iterator fastSubIt = subjetFastjetConstituents.begin(),
199  transConstBegin = subjetFastjetConstituents.begin(),
200  transConstEnd = subjetFastjetConstituents.end();
201  for ( ; fastSubIt != transConstEnd; ++fastSubIt ) {
202  if ( fastSubIt->user_index() >= 0 && static_cast<unsigned int>(fastSubIt->user_index()) < cell_particles.size() ) {
203  constituents.push_back( fastSubIt->user_index() );
204  }
205  }
206 
207  // Make a CompoundPseudoSubJet object to hold this subjet and the indices of its constituents
208  subjetsOutput.push_back( CompoundPseudoSubJet( *itSubJet, constituents ) );
209  }
210 
211 
212  // Make a CompoundPseudoJet object to hold this hard jet, and the subjets that make it up
213  hardjetsOutput.push_back( CompoundPseudoJet( *jetIt, subjetsOutput ) );
214 
215  }
216 }
217 
218 
219 
220 
221 //-----------------------------------------------------------------------
222 // determine whether two clusters (made of calorimeter towers) are living on "adjacent" cells. if they are, then
223 // we probably shouldn't consider them to be independent objects!
224 //
225 // From Sal: Ignoring genjet case
226 //
227 bool CATopJetAlgorithm::adjacentCells(const fastjet::PseudoJet & jet1, const fastjet::PseudoJet & jet2,
228  const vector<fastjet::PseudoJet> & cell_particles,
229  const fastjet::ClusterSequence & theClusterSequence,
230  double nCellMin ) const {
231 
232 
233  double eta1 = jet1.rapidity();
234  double phi1 = jet1.phi();
235  double eta2 = jet2.rapidity();
236  double phi2 = jet2.phi();
237 
238  double deta = abs(eta2 - eta1) / 0.087;
239  double dphi = fabs( reco::deltaPhi(phi2,phi1) ) / 0.087;
240 
241  return ( ( deta + dphi ) <= nCellMin );
242 }
243 
244 
245 
246 //-------------------------------------------------------------------------
247 // attempt to decompose a jet into "hard" subjets, where hardness is set by ptHard
248 //
249 bool CATopJetAlgorithm::decomposeJet(const fastjet::PseudoJet & theJet,
250  const fastjet::ClusterSequence & theClusterSequence,
251  const vector<fastjet::PseudoJet> & cell_particles,
252  double ptHard, double nCellMin, double deltarcut,
253  fastjet::PseudoJet & ja, fastjet::PseudoJet & jb,
254  vector<fastjet::PseudoJet> & leftovers) const {
255 
256  bool goodBreak;
257  fastjet::PseudoJet j = theJet;
258  double InputObjectPt = j.perp();
259  if ( verbose_ )cout<<"Input Object Pt = "<<InputObjectPt<<endl;
260  if ( verbose_ )cout<<"ptHard = "<<ptHard<<endl;
261  leftovers.clear();
262  if ( verbose_ )cout<<"start while loop"<<endl;
263 
264  while (1) { // watch out for infinite loop!
265  goodBreak = theClusterSequence.has_parents(j,ja,jb);
266  if (!goodBreak){
267  if ( verbose_ )cout<<"bad break. this is one cell. can't decluster anymore."<<endl;
268  break; // this is one cell, can't decluster anymore
269  }
270 
271  if ( verbose_ )cout<<"good break. ja Pt = "<<ja.perp()<<" jb Pt = "<<jb.perp()<<endl;
272 
274 
275  // check if clusters are adjacent using a constant deltar adjacency.
276  double clusters_deltar=fabs(ja.eta()-jb.eta())+fabs(deltaPhi(ja.phi(),jb.phi()));
277 
278  if ( verbose_ && useAdjacency_ ==1)cout<<"clusters_deltar = "<<clusters_deltar<<endl;
279  if ( verbose_ && useAdjacency_ ==1)cout<<"deltar cut = "<<deltarcut<<endl;
280 
281  if ( useAdjacency_==1 && clusters_deltar < deltarcut){
282  if ( verbose_ )cout<<"clusters too close. consant adj. break."<<endl;
283  break;
284  }
285 
286  // Check if clusters are adjacent using a DeltaR adjacency which is a function of pT.
287  double clusters_deltaR=deltaR( ja.eta(), ja.phi(), jb.eta(), jb.phi() );
288 
289  if ( verbose_ && useAdjacency_ ==2)cout<<"clusters_deltaR = "<<clusters_deltaR<<endl;
290  if ( verbose_ && useAdjacency_ ==2)cout<<"0.4-0.0004*InputObjectPt = "<<0.4-0.0004*InputObjectPt<<endl;
291 
292  if ( useAdjacency_==2 && clusters_deltaR < 0.4-0.0004*InputObjectPt)
293  {
294  if ( verbose_ )cout<<"clusters too close. modified adj. break."<<endl;
295  break;
296  }
297 
298  // Check if clusters are adjacent in the calorimeter.
299  if ( useAdjacency_==3 && adjacentCells(ja,jb,cell_particles,theClusterSequence,nCellMin) ){
300  if ( verbose_ )cout<<"clusters too close in the calorimeter. calorimeter adj. break."<<endl;
301  break; // the clusters are "adjacent" in the calorimeter => shouldn't have decomposed
302  }
303 
304  if ( verbose_ )cout<<"clusters pass distance cut"<<endl;
305 
307 
308  if ( verbose_ )cout<<"ptHard = "<<ptHard<<endl;
309 
310  if (ja.perp() < ptHard && jb.perp() < ptHard){
311  if ( verbose_ )cout<<"two soft clusters. dead end"<<endl;
312  break; // broke into two soft clusters, dead end
313  }
314 
315  if (ja.perp() > ptHard && jb.perp() > ptHard){
316  if ( verbose_ )cout<<"two hard clusters. done"<<endl;
317  return true; // broke into two hard clusters, we're done!
318  }
319 
320  else if (ja.perp() > jb.perp()) { // broke into one hard and one soft, ditch the soft one and try again
321  if ( verbose_ )cout<<"ja hard jb soft. try to split hard. j = ja"<<endl;
322  j = ja;
323  vector<fastjet::PseudoJet> particles = theClusterSequence.constituents(jb);
324  leftovers.insert(leftovers.end(),particles.begin(),particles.end());
325  }
326  else {
327  if ( verbose_ )cout<<"ja hard jb soft. try to split hard. j = jb"<<endl;
328  j = jb;
329  vector<fastjet::PseudoJet> particles = theClusterSequence.constituents(ja);
330  leftovers.insert(leftovers.end(),particles.begin(),particles.end());
331  }
332  }
333 
334  if ( verbose_ )cout<<"did not decluster."<<endl; // did not decluster into hard subjets
335 
336  ja.reset(0,0,0,0);
337  jb.reset(0,0,0,0);
338  leftovers.clear();
339  return false;
340 }
int i
Definition: DBlmapReader.cc:9
void run(const std::vector< fastjet::PseudoJet > &cell_particles, std::vector< CompoundPseudoJet > &hardjetsOutput, edm::EventSetup const &c)
Find the ProtoJets from the collection of input Candidates.
double deltaPhi(float phi1, float phi2)
Definition: VectorUtil.h:30
T perp() const
Magnitude of transverse component.
#define abs(x)
Definition: mlp_lapack.h:159
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:30
bool adjacentCells(const fastjet::PseudoJet &jet1, const fastjet::PseudoJet &jet2, const std::vector< fastjet::PseudoJet > &cell_particles, const fastjet::ClusterSequence &theClusterSequence, double nCellMin) const
bool decomposeJet(const fastjet::PseudoJet &theJet, const fastjet::ClusterSequence &theClusterSequence, const std::vector< fastjet::PseudoJet > &cell_particles, double ptHard, double nCellMin, double deltarcut, fastjet::PseudoJet &ja, fastjet::PseudoJet &jb, std::vector< fastjet::PseudoJet > &leftovers) const
CompoundPseudoJet holds an association of fastjet::PseudoJets that represent a &quot;hard&quot; top jet with su...
int j
Definition: DBlmapReader.cc:9
double deltaR(double eta1, double eta2, double phi1, double phi2)
Definition: TreeUtility.cc:17
double deltaPhi(double phi1, double phi2)
Definition: deltaPhi.h:12
tuple cout
Definition: gather_cfg.py:41