CMS 3D CMS Logo

Py8toJetInput.cc
Go to the documentation of this file.
2 
6 
7 const std::vector<fastjet::PseudoJet>
8 Py8toJetInput::fillJetAlgoInput( const Event& event, const Event& workEvent,
9  const lhef::LHEEvent* lhee,
10  const std::vector<int>* typeIdx )
11 {
12 
13  fJetInput.clear();
14 
15  Event workEventJet = workEvent;
16 
17  const lhef::HEPEUP& hepeup = *lhee->getHEPEUP();
18 
19  std::set< int > typeSet[3];
20 
21  // FIXME !!!
22  // This is not safe to assume it's 3 because we're passing in a pointer
23  // and we do NOT know what the actuial size is. I'll have to improve it.
24  //
25  for ( size_t i=0; i<3; i++ )
26  {
27  typeSet[i].clear();
28  for ( size_t j=0; j<typeIdx[i].size(); j++ )
29  {
30 
31  // HEPEUP and Py8 event record are shifted by 3
32  // (system particle + 2 beam particles in Py8 event)
33  // ... EXCEPT FOR THE DECAY PRODUCTS IF DONE AT THE ME LEVEL !!!!!
34  // ... in such case, the decay productes get gutted out of the sequence
35  // and get placed in Py8 Event later on...
36  // so we need to figure out the shift
37  int pos = typeIdx[i][j];
38  int shift = 3;
39  // skip the first 2 entrirs in HEPEUP - they're incoming partons
40  for ( int ip=2; ip<pos; ip++ )
41  {
42  // alternative can be: moth1 != 1 && moth2 !=2...
43  // but moth1 == moth2 means pointer to the same mother t
44  // that can only be a resonance, unless moth1==moth2==0
45  //
46  if ( hepeup.MOTHUP[ip].first == hepeup.MOTHUP[ip].second )
47  {
48  shift--;
49  }
50  }
51  pos += shift;
52  // typeSet[i].insert( event[pos].daughter1() );
53  typeSet[i].insert( pos );
54  }
55  }
56 
57  // int iTypeEnd = (typeIdx[1].empty()) ? 1 : 2;
58 
59 // --> FIXME !!!
60  int iType = 0; // only LIGHT jets for now
61  int jetAllow = 0; // hardcoded for now for the same value as is set in Steve's example
62  // at present, not even in use...
63  // int jetMatch = 0; // hardcoded for now for the same value as is set in Steve's example
64 
65  // Loop over particles and decide what to pass to the jet algorithm
66  for (int i = 0; i < workEventJet.size(); ++i)
67  {
68 
69  if (!workEventJet[i].isFinal()) continue;
70 
71  // jetAllow option to disallow certain particle types
72  if (jetAllow == 1)
73  {
74 
75  // Original AG+Py6 algorithm explicitly excludes tops,
76  // leptons and photons.
77  int id = workEventJet[i].idAbs();
78  if ((id >= 11 && id <= 16) || id == ID_TOP || id == ID_PHOTON)
79  {
80  workEventJet[i].statusNeg();
81  continue;
82  }
83  }
84 
85  // Get the index of this particle in original event
86  int idx = workEventJet[i].daughter1();
87 
88  // Start with particle idx, and afterwards track mothers
89  while (true)
90  {
91 
92  // Light jets
93  if (iType == 0)
94  {
95 
96  // Do not include if originates from heavy jet or 'other'
97  if (typeSet[1].find(idx) != typeSet[1].end() ||
98  typeSet[2].find(idx) != typeSet[2].end())
99  {
100  workEventJet[i].statusNeg();
101  break;
102  }
103 
104  // Made it to start of event record so done
105  if (idx == 0)
106  {
107  break;
108  }
109  // Otherwise next mother and continue
110  idx = event[idx].mother1();
111 
112  // Heavy jets
113  }
114  else if (iType == 1)
115  {
116 
117  // Only include if originates from heavy jet
118  if (typeSet[1].find(idx) != typeSet[1].end()) break;
119 
120  // Made it to start of event record with no heavy jet mother,
121  // so DO NOT include particle
122  if (idx == 0)
123  {
124  workEventJet[i].statusNeg();
125  break;
126  }
127 
128  // Otherwise next mother and continue
129  idx = event[idx].mother1();
130 
131  } // if (iType)
132  } // while (true)
133  } // for (i)
134 
135  // For jetMatch = 2, insert ghost particles corresponding to
136  // each hard parton in the original process
137 /*
138  if (jetMatch > 0)
139  {
140 
141  for (int i = 0; i < int(typeIdx[iType].size()); i++)
142  {
143  // Get y/phi of the parton
144  Vec4 pIn = eventProcess[typeIdx[iType][i]].p();
145  double y = Vec4y(pIn);
146  double phi = pIn.phi();
147 
148  // Create a ghost particle and add to the workEventJet
149  double e = MG5_GHOSTENERGY;
150  double e2y = exp(2. * y);
151  double pz = e * (e2y - 1.) / (e2y + 1.);
152  double pt = sqrt(e*e - pz*pz);
153  double px = pt * cos(phi);
154  double py = pt * sin(phi);
155  workEventJet.append(Particle(ID_GLUON, 99, 0, 0, 0, 0, 0, 0,
156  px, py, pz, e, 0., 0, 9.));
157 
158  } // for (i)
159  } // if (jetMatch == 2)
160 */
161 
162  for ( int i=0; i<workEventJet.size(); i++ )
163  {
164 
165  // fisrt, weed out all entries marked with statusNeg();
166  //
167  if ( workEventJet[i].status() < 0 ) continue;
168 
169 
170  // now weed out all entries above etaMax
171  // in principle, we can use etaJetMaxAlgo because it's set equal to etaJetMax
172  // as for etaJetMax, it gets set to memain_.etaclmax
173  //
174  if ( fabs(workEventJet[i].eta()) > fJetEtaMax ) continue ;
175 
176  // need to double check if native FastJet understands Py8 Event format
177  // in general, PseudoJet gets formed from (px,py,pz,E)
178  //
179  fastjet::PseudoJet partTmp = workEventJet[i];
180  fJetInput.push_back( partTmp );
181  }
182 
183  return fJetInput;
184 
185 }
186 
187 
188 int Py8toJetInput::getAncestor( int pos, const Event& fullEvent, const Event& workEvent )
189 {
190 
191  int parentId = fullEvent[pos].mother1();
192  int parentPrevId = 0;
193  int counter = pos;
194 
195  while ( parentId > 0 )
196  {
197  if ( parentId == fullEvent[counter].mother2() ) // carbon copy, keep walking up
198  {
199  parentPrevId = parentId;
200  counter = parentId;
201  parentId = fullEvent[parentPrevId].mother1();
202  continue;
203  }
204 
205  // we get here if not a carbon copy
206 
207  // let's check if it's a normal process, etc.
208  //
209  if ( (parentId < parentPrevId) || parentId < fullEvent[counter].mother2() ) // normal process
210  {
211 
212  // first of all, check if hard block
213  if ( abs(fullEvent[counter].status()) == 22 || abs(fullEvent[counter].status()) == 23 )
214  {
215  // yes, it's the hard block
216  // we got what we want, and can exit now !
217  parentId = counter;
218  break;
219  }
220  else
221  {
222  parentPrevId = parentId;
223  parentId = fullEvent[parentPrevId].mother1();
224  }
225  }
226  else if ( parentId > parentPrevId || parentId > pos ) // "circular"/"forward-pointing parent" - intermediate process
227  {
228  parentId = -1;
229  break;
230  }
231 
232  // additional checks... although we shouldn't be geeting here all that much...
233  //
234  if ( abs(fullEvent[parentId].status()) == 22 || abs(fullEvent[parentId].status())== 23 ) // hard block
235  {
236  break;
237  }
238  if ( abs(fullEvent[parentId].status()) < 22 ) // incoming
239  {
240  parentId = -1;
241  break;
242  }
243  }
244 
245  return parentId;
246 
247 }
248 
249 #include "HepMC/HEPEVT_Wrapper.h"
250 #include <cassert>
251 
252 const std::vector<fastjet::PseudoJet>
254  const lhef::LHEEvent* lhee,
255  const std::vector<int>* )
256 {
257 
258  fJetInput.clear();
259 
260  HepMC::HEPEVT_Wrapper::zero_everything();
261 
262  // service container for further mother-daughters links
263  //
264  std::vector<int> Py8PartonIdx; // position of original (LHE) partons in Py8::Event
265  Py8PartonIdx.clear();
266  std::vector<int> HEPEVTPartonIdx; // position of LHE partons in HEPEVT (incl. ME-generated decays)
267  HEPEVTPartonIdx.clear();
268 
269  // general counter
270  //
271  int index = 0;
272 
273  int Py8PartonCounter = 0;
274  int HEPEVTPartonCounter = 0;
275 
276  // find the fisrt parton that comes from LHE (ME-generated)
277  // skip the incoming particles/partons
278  for ( int iprt=1; iprt<event.size(); iprt++ )
279  {
280  const Particle& part = event[iprt];
281  if ( abs(part.status()) < 22 ) continue; // below 10 is "service"
282  // 11-19 are beam particles; below 10 is "service"
283  // 21 is incoming partons
284  Py8PartonCounter = iprt;
285  break;
286  }
287 
288  const lhef::HEPEUP& hepeup = *lhee->getHEPEUP();
289  // start the counter from 2, because we don't want the incoming particles/oartons !
290  for ( int iprt=2; iprt<hepeup.NUP; iprt++ )
291  {
292  index++;
293  HepMC::HEPEVT_Wrapper::set_id( index, hepeup.IDUP[iprt] );
294  HepMC::HEPEVT_Wrapper::set_status( index, 2 );
295  HepMC::HEPEVT_Wrapper::set_momentum( index, hepeup.PUP[iprt][0], hepeup.PUP[iprt][1], hepeup.PUP[iprt][2], hepeup.PUP[iprt][4] );
296  HepMC::HEPEVT_Wrapper::set_mass( index, hepeup.PUP[iprt][4] );
297  // --> FIXME HepMC::HEPEVT_Wrapper::set_position( index, part.xProd(), part.yProd(), part.zProd(), part.tProd() );
298  HepMC::HEPEVT_Wrapper::set_parents( index, 0, 0 ); // NO, not anymore to the "system particle"
299  HepMC::HEPEVT_Wrapper::set_children( index, 0, 0 );
300  if ( hepeup.MOTHUP[iprt].first > 2 && hepeup.MOTHUP[iprt].second > 2 ) // decay from LHE, will NOT show at the start of Py8 event !!!
301  {
302  HEPEVTPartonCounter++;
303  continue;
304  }
305  Py8PartonIdx.push_back( Py8PartonCounter );
306  Py8PartonCounter++;
307  HEPEVTPartonIdx.push_back( HEPEVTPartonCounter);
308  HEPEVTPartonCounter++;
309  }
310 
311  HepMC::HEPEVT_Wrapper::set_number_entries( index );
312 
313  // now that the initial partons are in, attach parton-level from Pythia8
314  // do NOT reset index as we need to *add* more particles sequentially
315  //
316  for ( int iprt=1; iprt<workEvent.size(); iprt++ ) // from 0-entry (system) or from 1st entry ???
317  {
318 
319  const Particle& part = workEvent[iprt];
320 
321 
322 // if ( part.status() != 62 ) continue;
323  if ( part.status() < 51 ) continue;
324  index++;
325  HepMC::HEPEVT_Wrapper::set_id( index, part.id() );
326 
327  // HepMC::HEPEVT_Wrapper::set_status( index, event.statusHepMC(iprt) );
328  HepMC::HEPEVT_Wrapper::set_status( index, 1 );
329  HepMC::HEPEVT_Wrapper::set_momentum( index, part.px(), part.py(), part.pz(), part.e() );
330  HepMC::HEPEVT_Wrapper::set_mass( index, part.m() );
331  HepMC::HEPEVT_Wrapper::set_position( index, part.xProd(), part.yProd(), part.zProd(), part.tProd() );
332  HepMC::HEPEVT_Wrapper::set_parents( index, 0, 0 ); // just set to 0 like in Py6...
333  // although for some, mother will need to be re-set properly !
334  HepMC::HEPEVT_Wrapper::set_children( index, 0, 0 );
335 
336  // now refine mother-daughters links, where applicable
337 
338  int parentId = getAncestor( part.daughter1(), event, workEvent );
339 
340  if ( parentId <= 0 ) continue;
341 
342  for ( int idx=0; idx<(int)Py8PartonIdx.size(); idx++ )
343  {
344  if ( parentId == Py8PartonIdx[idx] )
345  {
346  int idx1 = HEPEVTPartonIdx[idx];
347  HepMC::HEPEVT_Wrapper::set_parents( index, idx1+1, idx1+1 );
348  break;
349  }
350  }
351 
352  }
353 
354  HepMC::HEPEVT_Wrapper::set_number_entries( index );
355 
356 // --> FIXME HepMC::HEPEVT_Wrapper::set_event_number( fEventNumber ); // well, if you know it... well, it's one of the counters...
357 
358 // HepMC::HEPEVT_Wrapper::print_hepevt();
359 
360  return fJetInput;
361 
362 }
virtual const std::vector< fastjet::PseudoJet > fillJetAlgoInput(const Event &, const Event &, const lhef::LHEEvent *lhee=nullptr, const std::vector< int > *partonList=nullptr)
Definition: Py8toJetInput.cc:8
const std::vector< fastjet::PseudoJet > fillJetAlgoInput(const Event &, const Event &, const lhef::LHEEvent *, const std::vector< int > *partonList=nullptr) override
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
int getAncestor(int, const Event &, const Event &)
const HEPEUP * getHEPEUP() const
Definition: LHEEvent.h:43
std::vector< std::pair< int, int > > MOTHUP
Definition: LesHouches.h:249
std::vector< FiveVector > PUP
Definition: LesHouches.h:261
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
#define end
Definition: vmac.h:39
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
double fJetEtaMax
Definition: Py8toJetInput.h:30
std::vector< int > IDUP
Definition: LesHouches.h:238
part
Definition: HCALResponse.h:20
static std::atomic< unsigned int > counter
static unsigned int const shift
std::vector< fastjet::PseudoJet > fJetInput
Definition: Py8toJetInput.h:34
Definition: event.py:1