CMS 3D CMS Logo

HadronizerFilter.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 //
4 
5 // class template HadronizerFilter<HAD> provides an EDFilter which uses
6 // the hadronizer type HAD to read in external partons and hadronize them,
7 // and decay the resulting particles, in the CMS framework.
8 
9 #ifndef gen_HadronizerFilter_h
10 #define gen_HadronizerFilter_h
11 
12 #include <memory>
13 #include <string>
14 #include <vector>
15 
31 #include "CLHEP/Random/RandomEngine.h"
32 
33 // #include "GeneratorInterface/ExternalDecays/interface/ExternalDecayDriver.h"
34 
36 
37 // LHE Run
40 
41 // LHE Event
44 
45 
51 
52 
53 namespace edm
54 {
55  template <class HAD, class DEC> class HadronizerFilter : public one::EDFilter<EndRunProducer,
56  BeginLuminosityBlockProducer,
57  EndLuminosityBlockProducer,
58  one::WatchRuns,
59  one::WatchLuminosityBlocks,
60  one::SharedResources>
61  {
62  public:
63  typedef HAD Hadronizer;
64  typedef DEC Decayer;
65 
66  // The given ParameterSet will be passed to the contained
67  // Hadronizer object.
68  explicit HadronizerFilter(ParameterSet const& ps);
69 
70  ~HadronizerFilter() override;
71 
72  bool filter(Event& e, EventSetup const& es) override;
73  void beginRun(Run const&, EventSetup const&) override;
74  void endRun(Run const&, EventSetup const&) override;
75  void endRunProduce(Run &, EventSetup const&) override;
76  void beginLuminosityBlock(LuminosityBlock const&, EventSetup const&) override;
78  void endLuminosityBlock(LuminosityBlock const&, EventSetup const&) override;
79  void endLuminosityBlockProduce(LuminosityBlock &, EventSetup const&) override;
80 
81  private:
82  Hadronizer hadronizer_;
83  // gen::ExternalDecayDriver* decayer_;
84  Decayer* decayer_;
90  unsigned int nAttempts_;
91  };
92 
93  //------------------------------------------------------------------------
94  //
95  // Implementation
96 
97  template <class HAD, class DEC>
99  EDFilter(),
100  hadronizer_(ps),
101  decayer_(nullptr),
102  filter_(nullptr),
107  nAttempts_(1)
108  {
110  //this is called each time a module registers that it will produce a LHERunInfoProduct
111  if (iBD.unwrappedTypeID() == edm::TypeID(typeid(LHERunInfoProduct)) &&
112  iBD.branchType() == InRun) {
113  ++(this->counterRunInfoProducts_);
114  this->eventProductToken_ = consumes<LHEEventProduct>(InputTag((iBD.moduleLabel()=="externalLHEProducer") ? "externalLHEProducer" : "source"));
116  this->runInfoProductToken_ = consumes<LHERunInfoProduct,InRun>(InputTag(iBD.moduleLabel(), iBD.productInstanceName(), iBD.processName()));
117  }
118  });
119 
120  // TODO:
121  // Put the list of types produced by the filters here.
122  // The current design calls for:
123  // * LHEGeneratorInfo
124  // * LHEEvent
125  // * HepMCProduct
126  // But I can not find the LHEGeneratorInfo class; it might need to
127  // be invented.
128 
129  std::vector<std::string> const& sharedResources = hadronizer_.sharedResources();
130  for(auto const& resource : sharedResources) {
131  usesResource(resource);
132  }
133 
134  if ( ps.exists("ExternalDecays") )
135  {
136  //decayer_ = new gen::ExternalDecayDriver(ps.getParameter<ParameterSet>("ExternalDecays"));
137  ParameterSet ps1 = ps.getParameter<ParameterSet>("ExternalDecays");
138  decayer_ = new Decayer(ps1);
139 
140  std::vector<std::string> const& sharedResourcesDec = decayer_->sharedResources();
141  for(auto const& resource : sharedResourcesDec) {
142  usesResource(resource);
143  }
144  }
145 
146  if ( ps.exists("HepMCFilter") ) {
147  ParameterSet psfilter = ps.getParameter<ParameterSet>("HepMCFilter");
148  filter_ = new HepMCFilterDriver(psfilter);
149  }
150 
151  //initialize setting for multiple hadronization attempts
152  if (ps.exists("nAttempts")) {
153  nAttempts_ = ps.getParameter<unsigned int>("nAttempts");
154  }
155 
156  // This handles the case where there are no shared resources, because you
157  // have to declare something when the SharedResources template parameter was used.
158  if(sharedResources.empty() && (!decayer_ || decayer_->sharedResources().empty())) {
159  usesResource(edm::uniqueSharedResourceName());
160  }
161 
162  produces<edm::HepMCProduct>("unsmeared");
163  produces<GenEventInfoProduct>();
164  produces<GenLumiInfoHeader, edm::Transition::BeginLuminosityBlock>();
165  produces<GenLumiInfoProduct, edm::Transition::EndLuminosityBlock>();
166  produces<GenRunInfoProduct, edm::Transition::EndRun>();
167  if(filter_)
168  produces<GenFilterInfo, edm::Transition::EndLuminosityBlock>();
169  }
170 
171  template <class HAD, class DEC>
173  {
174  if (decayer_) delete decayer_;
175  if (filter_) delete filter_;
176  }
177 
178  template <class HAD, class DEC>
179  bool
181  {
182  RandomEngineSentry<HAD> randomEngineSentry(&hadronizer_, ev.streamID());
183  RandomEngineSentry<DEC> randomEngineSentryDecay(decayer_, ev.streamID());
184 
185  hadronizer_.setEDMEvent(ev);
186 
187  // get LHE stuff and pass to hadronizer!
188  //
190  ev.getByToken(eventProductToken_, product);
191 
192  std::unique_ptr<HepMC::GenEvent> finalEvent;
193  std::unique_ptr<GenEventInfoProduct> finalGenEventInfo;
194 
195  //sum of weights for events passing hadronization
196  double waccept = 0;
197  //number of accepted events
198  unsigned int naccept = 0;
199 
200  for (unsigned int itry = 0; itry<nAttempts_; ++itry) {
201 
202  hadronizer_.setLHEEvent(std::make_unique<lhef::LHEEvent>(hadronizer_.getLHERunInfo(), *product) );
203 
204  // hadronizer_.generatePartons();
205  if ( !hadronizer_.hadronize() ) continue ;
206 
207  // this is "fake" stuff
208  // in principle, decays are done as part of full event generation,
209  // except for particles that are marked as to be kept stable
210  // but we currently keep in it the design, because we might want
211  // to use such feature for other applications
212  //
213  if ( !hadronizer_.decay() ) continue;
214 
215  std::unique_ptr<HepMC::GenEvent> event (hadronizer_.getGenEvent());
216  if( !event.get() ) continue;
217 
218  // The external decay driver is being added to the system,
219  // it should be called here
220  //
221  if ( decayer_ )
222  {
223  auto lheEvent = hadronizer_.getLHEEvent();
224  auto t = decayer_->decay( event.get(),lheEvent.get() );
225  if(t != event.get()) {
226  event.reset(t);
227  }
228  hadronizer_.setLHEEvent(std::move(lheEvent));
229  }
230 
231  if ( !event.get() ) continue;
232 
233  // check and perform if there're any unstable particles after
234  // running external decay packges
235  //
236  hadronizer_.resetEvent( std::move(event) );
237  if ( !hadronizer_.residualDecay() ) continue;
238 
239  hadronizer_.finalizeEvent();
240 
241  event = hadronizer_.getGenEvent();
242  if ( !event.get() ) continue;
243 
244  event->set_event_number( ev.id().event() );
245 
246  std::unique_ptr<GenEventInfoProduct> genEventInfo(hadronizer_.getGenEventInfo());
247  if (!genEventInfo.get())
248  {
249  // create GenEventInfoProduct from HepMC event in case hadronizer didn't provide one
250  genEventInfo.reset(new GenEventInfoProduct(event.get()));
251  }
252 
253  //if HepMCFilter was specified, test event
254  if (filter_ && !filter_->filter(event.get(), genEventInfo->weight())) continue;
255 
256  waccept += genEventInfo->weight();
257  ++naccept;
258 
259  //keep the LAST accepted event (which is equivalent to choosing randomly from the accepted events)
260  finalEvent = std::move(event);
261  finalGenEventInfo = std::move(genEventInfo);
262 
263  }
264 
265  if (!naccept) return false;
266 
267 
268 
269  //adjust event weights if necessary (in case input event was attempted multiple times)
270  if (nAttempts_>1) {
271  double multihadweight = double(naccept)/double(nAttempts_);
272 
273  //adjust weight for GenEventInfoProduct
274  finalGenEventInfo->weights()[0] *= multihadweight;
275 
276  //adjust weight for HepMC GenEvent (used e.g for RIVET)
277  finalEvent->weights()[0] *= multihadweight;
278  }
279 
280  ev.put(std::move(finalGenEventInfo));
281 
282  std::unique_ptr<HepMCProduct> bare_product(new HepMCProduct());
283  bare_product->addHepMCData( finalEvent.release() );
284  ev.put(std::move(bare_product), "unsmeared");
285 
286  return true;
287  }
288 
289  template <class HAD, class DEC>
290  void
292  {
293 
294  // this is run-specific
295 
296  // get LHE stuff and pass to hadronizer!
297 
300  << "More than one LHERunInfoProduct present";
301 
302  if(counterRunInfoProducts_ == 0)
304  << "No LHERunInfoProduct present";
305 
306  edm::Handle<LHERunInfoProduct> lheRunInfoProduct;
307  run.getByLabel(runInfoProductTag_, lheRunInfoProduct);
308  //TODO: fix so that this actually works with getByToken commented below...
309  //run.getByToken(runInfoProductToken_, lheRunInfoProduct);
310 
311  hadronizer_.setLHERunInfo( std::make_unique<lhef::LHERunInfo>(*lheRunInfoProduct) );
312  lhef::LHERunInfo* lheRunInfo = hadronizer_.getLHERunInfo().get();
313  lheRunInfo->initLumi();
314 
315  }
316 
317  template <class HAD, class DEC>
318  void
320 
321  template <class HAD, class DEC>
322  void
324  {
325  // Retrieve the LHE run info summary and transfer determined
326  // cross-section into the generator run info
327 
328  const lhef::LHERunInfo* lheRunInfo = hadronizer_.getLHERunInfo().get();
329  lhef::LHERunInfo::XSec xsec = lheRunInfo->xsec();
330 
331  GenRunInfoProduct& genRunInfo = hadronizer_.getGenRunInfo();
332  genRunInfo.setInternalXSec( GenRunInfoProduct::XSec(xsec.value(), xsec.error()) );
333 
334  // If relevant, record the integrated luminosity for this run
335  // here. To do so, we would need a standard function to invoke on
336  // the contained hadronizer that would report the integrated
337  // luminosity.
338 
339  hadronizer_.statistics();
340  if ( decayer_ ) decayer_->statistics();
341  if ( filter_ ) filter_->statistics();
342  lheRunInfo->statistics();
343 
344  std::unique_ptr<GenRunInfoProduct> griproduct( new GenRunInfoProduct(genRunInfo) );
345  r.put(std::move(griproduct));
346  }
347 
348  template <class HAD, class DEC>
349  void
351  {}
352 
353  template <class HAD, class DEC>
354  void
356  {
357  lhef::LHERunInfo* lheRunInfo = hadronizer_.getLHERunInfo().get();
358  lheRunInfo->initLumi();
359 
360  RandomEngineSentry<HAD> randomEngineSentry(&hadronizer_, lumi.index());
361  RandomEngineSentry<DEC> randomEngineSentryDecay(decayer_, lumi.index());
362 
363  hadronizer_.randomizeIndex(lumi,randomEngineSentry.randomEngine());
364 
365  if ( !hadronizer_.readSettings(1) )
367  << "Failed to read settings for the hadronizer "
368  << hadronizer_.classname() << " \n";
369 
370  if ( decayer_ )
371  {
372  decayer_->init(es);
373  if ( !hadronizer_.declareStableParticles( decayer_->operatesOnParticles() ) )
375  << "Failed to declare stable particles in hadronizer "
376  << hadronizer_.classname()
377  << " for internal parton generation\n";
378  if ( !hadronizer_.declareSpecialSettings( decayer_->specialSettings() ) )
380  << "Failed to declare special settings in hadronizer "
381  << hadronizer_.classname()
382  << "\n";
383  }
384 
385  if (filter_) {
387  }
388 
389  if (! hadronizer_.initializeForExternalPartons())
391  << "Failed to initialize hadronizer "
392  << hadronizer_.classname()
393  << " for external parton generation\n";
394 
395  std::unique_ptr<GenLumiInfoHeader> genLumiInfoHeader(hadronizer_.getGenLumiInfoHeader());
397 
398  }
399 
400  template <class HAD, class DEC>
401  void
403  {}
404 
405  template <class HAD, class DEC>
406  void
408  {
409  const lhef::LHERunInfo* lheRunInfo = hadronizer_.getLHERunInfo().get();
410 
411 
412  std::vector<lhef::LHERunInfo::Process> LHELumiProcess = lheRunInfo->getLumiProcesses();
413  std::vector<GenLumiInfoProduct::ProcessInfo> GenLumiProcess;
414  for(unsigned int i=0; i < LHELumiProcess.size(); i++){
415  lhef::LHERunInfo::Process thisProcess=LHELumiProcess[i];
416 
418  temp.setProcess(thisProcess.process());
419  temp.setLheXSec(thisProcess.getLHEXSec().value(),thisProcess.getLHEXSec().error());
420  temp.setNPassPos(thisProcess.nPassPos());
421  temp.setNPassNeg(thisProcess.nPassNeg());
422  temp.setNTotalPos(thisProcess.nTotalPos());
423  temp.setNTotalNeg(thisProcess.nTotalNeg());
424  temp.setTried(thisProcess.tried().n(), thisProcess.tried().sum(), thisProcess.tried().sum2());
425  temp.setSelected(thisProcess.selected().n(), thisProcess.selected().sum(), thisProcess.selected().sum2());
426  temp.setKilled(thisProcess.killed().n(), thisProcess.killed().sum(), thisProcess.killed().sum2());
427  temp.setAccepted(thisProcess.accepted().n(), thisProcess.accepted().sum(), thisProcess.accepted().sum2());
428  temp.setAcceptedBr(thisProcess.acceptedBr().n(), thisProcess.acceptedBr().sum(), thisProcess.acceptedBr().sum2());
429  GenLumiProcess.push_back(temp);
430  }
431  std::unique_ptr<GenLumiInfoProduct> genLumiInfo(new GenLumiInfoProduct());
432  genLumiInfo->setHEPIDWTUP(lheRunInfo->getHEPRUP()->IDWTUP);
433  genLumiInfo->setProcessInfo( GenLumiProcess );
434 
435  lumi.put(std::move(genLumiInfo));
436 
437 
438  // produce GenFilterInfo if HepMCFilter is called
439  if (filter_) {
440 
441  std::unique_ptr<GenFilterInfo> thisProduct(new GenFilterInfo(
446  filter_->sumpass_w(),
447  filter_->sumpass_w2(),
448  filter_->sumtotal_w(),
450  ));
451  lumi.put(std::move(thisProduct));
452  }
453 
454 
455  }
456 
457 
458 }
459 
460 #endif // gen_HadronizerFilter_h
T getParameter(std::string const &) const
void callWhenNewProductsRegistered(std::function< void(BranchDescription const &)> const &func)
Definition: ProducerBase.h:79
EventNumber_t event() const
Definition: EventID.h:41
unsigned int nTotalPos() const
Definition: LHERunInfo.h:122
bool getByLabel(std::string const &label, Handle< PROD > &result) const
Definition: Run.h:280
void beginRun(Run const &, EventSetup const &) override
void setTried(unsigned int n, double sum, double sum2)
unsigned int n() const
Definition: LHERunInfo.h:102
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:125
BranchType const & branchType() const
void setSelected(unsigned int n, double sum, double sum2)
LuminosityBlockIndex index() const
unsigned int numEventsPassNeg() const
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:517
unsigned int numEventsTotalPos() const
void setKilled(unsigned int n, double sum, double sum2)
#define nullptr
bool exists(std::string const &parameterName) const
checks if a parameter exists
XSec xsec() const
Definition: LHERunInfo.cc:199
bool ev
std::string const & processName() const
double sumtotal_w2() const
HadronizerFilter(ParameterSet const &ps)
void endLuminosityBlockProduce(LuminosityBlock &, EventSetup const &) override
void setInternalXSec(const XSec &xsec)
const std::vector< Process > & getLumiProcesses() const
Definition: LHERunInfo.h:171
XSec getLHEXSec() const
Definition: LHERunInfo.h:118
void setAccepted(unsigned int n, double sum, double sum2)
std::string const & moduleLabel() const
void beginLuminosityBlockProduce(LuminosityBlock &, EventSetup const &) override
void setAcceptedBr(unsigned int n, double sum, double sum2)
std::string const & productInstanceName() const
void put(std::unique_ptr< PROD > product)
Put a new product.
double sumpass_w() const
TypeID unwrappedTypeID() const
double sumtotal_w() const
unsigned int counterRunInfoProducts_
void endRun(Run const &, EventSetup const &) override
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
unsigned int nTotalNeg() const
Definition: LHERunInfo.h:123
EDGetTokenT< LHEEventProduct > eventProductToken_
double sum2() const
Definition: LHERunInfo.h:104
unsigned int nPassPos() const
Definition: LHERunInfo.h:120
const HEPRUP * getHEPRUP() const
Definition: LHERunInfo.h:52
bool filter(Event &e, EventSetup const &es) override
void statistics() const
EDGetTokenT< LHERunInfoProduct > runInfoProductToken_
unsigned int numEventsPassPos() const
Counter killed() const
Definition: LHERunInfo.h:127
void put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Run.h:108
void setLheXSec(double value, double err)
double sum() const
Definition: LHERunInfo.h:103
edm::EventID id() const
Definition: EventBase.h:59
HLT enums.
void endRunProduce(Run &, EventSetup const &) override
unsigned int numEventsTotalNeg() const
StreamID streamID() const
Definition: Event.h:95
Counter acceptedBr() const
Definition: LHERunInfo.h:129
Counter accepted() const
Definition: LHERunInfo.h:128
double sumpass_w2() const
void endLuminosityBlock(LuminosityBlock const &, EventSetup const &) override
Counter selected() const
Definition: LHERunInfo.h:126
Counter tried() const
Definition: LHERunInfo.h:125
std::string uniqueSharedResourceName()
unsigned int nPassNeg() const
Definition: LHERunInfo.h:121
bool filter(const HepMC::GenEvent *evt, double weight=1.)
def move(src, dest)
Definition: eostools.py:511
void beginLuminosityBlock(LuminosityBlock const &, EventSetup const &) override
HepMCFilterDriver * filter_
Definition: event.py:1
Definition: Run.h:45
void statistics() const
Definition: LHERunInfo.cc:297