CMS 3D CMS Logo

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