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 }
lhef::LHEEvent::getHEPEUP
const HEPEUP * getHEPEUP() const
Definition: LHEEvent.h:38
counter
Definition: counter.py:1
mps_fire.i
i
Definition: mps_fire.py:355
lhef::HEPEUP::MOTHUP
std::vector< std::pair< int, int > > MOTHUP
Definition: LesHouches.h:234
mps_update.status
status
Definition: mps_update.py:69
pos
Definition: PixelAliasList.h:18
Py8toJetInput::ID_PHOTON
Definition: Py8toJetInput.h:31
spr::find
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
training_settings.idx
idx
Definition: training_settings.py:16
end
#define end
Definition: vmac.h:39
lhef::HEPEUP::NUP
int NUP
Definition: LesHouches.h:184
part
part
Definition: HCALResponse.h:20
PVValHelper::eta
Definition: PVValidationHelpers.h:69
Py8toJetInputHEPEVT::fillJetAlgoInput
const std::vector< fastjet::PseudoJet > fillJetAlgoInput(const Event &, const Event &, const lhef::LHEEvent *, const std::vector< int > *partonList=nullptr) override
Definition: Py8toJetInput.cc:220
Event
Py8toJetInput::fJetEtaMax
double fJetEtaMax
Definition: Py8toJetInput.h:32
Py8toJetInput::ID_TOP
Definition: Py8toJetInput.h:31
Py8toJetInput::fillJetAlgoInput
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
LHERunInfo.h
lhef::LHEEvent
Definition: LHEEvent.h:23
createfilelist.int
int
Definition: createfilelist.py:10
counter
static std::atomic< unsigned int > counter
Definition: SharedResourceNames.cc:15
lhef::HEPEUP
Definition: LesHouches.h:138
Py8toJetInput::fJetInput
std::vector< fastjet::PseudoJet > fJetInput
Definition: Py8toJetInput.h:36
edm::shift
static unsigned const int shift
Definition: LuminosityBlockID.cc:7
lhef::HEPEUP::IDUP
std::vector< int > IDUP
Definition: LesHouches.h:223
Particle
Definition: Particle.py:1
LHEEvent.h
AlignmentPI::index
index
Definition: AlignmentPayloadInspectorHelper.h:46
Py8toJetInput.h
funct::abs
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
dqmiolumiharvest.j
j
Definition: dqmiolumiharvest.py:66
event
Definition: event.py:1
event
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
lhef::HEPEUP::PUP
std::vector< FiveVector > PUP
Definition: LesHouches.h:246
Py8toJetInput::getAncestor
int getAncestor(int, const Event &, const Event &)
Definition: Py8toJetInput.cc:164
LHECommonBlocks.h