CMS 3D CMS Logo

VirtualJetProducer.cc
Go to the documentation of this file.
1 //
3 // VirtualJetProducer
4 // ------------------
5 //
6 // 04/21/2009 Philipp Schieferdecker <philipp.schieferdecker@cern.ch>
8 
12 
16 
25 
40 
41 #include "fastjet/SISConePlugin.hh"
42 #include "fastjet/CMSIterativeConePlugin.hh"
43 #include "fastjet/ATLASConePlugin.hh"
44 #include "fastjet/CDFMidPointPlugin.hh"
45 
46 #include <iostream>
47 #include <memory>
48 #include <algorithm>
49 #include <limits>
50 #include <cmath>
51 #include <vdt/vdtMath.h>
52 
53 using namespace std;
54 
55 
56 namespace reco {
57  namespace helper {
59  bool operator()( const fastjet::PseudoJet & t1, const fastjet::PseudoJet & t2 ) const {
60  return t1.perp2() > t2.perp2();
61  }
62  };
63 
64  }
65 }
66 
67 //______________________________________________________________________________
68 const char *const VirtualJetProducer::JetType::names[] = {
69  "BasicJet","GenJet","CaloJet","PFJet","TrackJet","PFClusterJet"
70 };
71 
72 
73 //______________________________________________________________________________
76 {
77  const char *const *pos = std::find(names, names + LastJetType, name);
78  if (pos == names + LastJetType) {
79  std::string errorMessage="Requested jetType not supported: "+name+"\n";
80  throw cms::Exception("Configuration",errorMessage);
81  }
82  return (Type)(pos-names);
83 }
84 
85 
87 {
88 
89 
90  if ( writeCompound_ ) {
91  produces<reco::BasicJetCollection>();
92  }
93 
94  if (makeCaloJet(jetTypeE)) {
95  produces<reco::CaloJetCollection>(tag).setBranchAlias(alias);
96  }
97  else if (makePFJet(jetTypeE)) {
98  produces<reco::PFJetCollection>(tag).setBranchAlias(alias);
99  }
100  else if (makeGenJet(jetTypeE)) {
101  produces<reco::GenJetCollection>(tag).setBranchAlias(alias);
102  }
103  else if (makeTrackJet(jetTypeE)) {
104  produces<reco::TrackJetCollection>(tag).setBranchAlias(alias);
105  }
106  else if (makePFClusterJet(jetTypeE)) {
107  produces<reco::PFClusterJetCollection>(tag).setBranchAlias(alias);
108  }
109  else if (makeBasicJet(jetTypeE)) {
110  produces<reco::BasicJetCollection>(tag).setBranchAlias(alias);
111  }
112 }
113 
115 // construction / destruction
117 
118 //______________________________________________________________________________
120  : moduleLabel_ (iConfig.getParameter<string> ("@module_label"))
121  , src_ (iConfig.getParameter<edm::InputTag>("src"))
122  , srcPVs_ (iConfig.getParameter<edm::InputTag>("srcPVs"))
123  , jetType_ (iConfig.getParameter<string> ("jetType"))
124  , jetAlgorithm_ (iConfig.getParameter<string> ("jetAlgorithm"))
125  , rParam_ (iConfig.getParameter<double> ("rParam"))
126  , inputEtMin_ (iConfig.getParameter<double> ("inputEtMin"))
127  , inputEMin_ (iConfig.getParameter<double> ("inputEMin"))
128  , jetPtMin_ (iConfig.getParameter<double> ("jetPtMin"))
129  , doPVCorrection_(iConfig.getParameter<bool> ("doPVCorrection"))
130  , restrictInputs_(false)
131  , maxInputs_(99999999)
132  , doAreaFastjet_ (iConfig.getParameter<bool> ("doAreaFastjet"))
133  , useExplicitGhosts_(false)
134  , doAreaDiskApprox_ (false)
135  , doRhoFastjet_ (iConfig.getParameter<bool> ("doRhoFastjet"))
136  , voronoiRfact_ (-9)
137  , doPUOffsetCorr_(iConfig.getParameter<bool> ("doPUOffsetCorr"))
138  , puWidth_(0)
139  , nExclude_(0)
140  , jetCollInstanceName_ ("")
141  , writeCompound_ ( false )
142  , verbosity_(0)
143  , fromHTTTopJetProducer_(0)
144 {
145  anomalousTowerDef_ = std::auto_ptr<AnomalousTower>(new AnomalousTower(iConfig));
146 
147  //
148  // additional parameters to think about:
149  // - overlap threshold (set to 0.75 for the time being)
150  // - p parameter for generalized kT (set to -2 for the time being)
151  // - fastjet PU subtraction parameters (not yet considered)
152  //
153  if (jetAlgorithm_=="SISCone") {
154  fjPlugin_ = PluginPtr( new fastjet::SISConePlugin(rParam_,0.75,0,0.0,false,
155  fastjet::SISConePlugin::SM_pttilde) );
156  fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(&*fjPlugin_) );
157  }
158  else if (jetAlgorithm_=="IterativeCone") {
159  fjPlugin_ = PluginPtr(new fastjet::CMSIterativeConePlugin(rParam_,1.0));
160  fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
161  }
162  else if (jetAlgorithm_=="CDFMidPoint") {
163  fjPlugin_ = PluginPtr(new fastjet::CDFMidPointPlugin(rParam_,0.75));
164  fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
165  }
166  else if (jetAlgorithm_=="ATLASCone") {
167  fjPlugin_ = PluginPtr(new fastjet::ATLASConePlugin(rParam_));
168  fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(&*fjPlugin_));
169  }
170  else if (jetAlgorithm_=="Kt")
171  fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(fastjet::kt_algorithm,rParam_));
172  else if (jetAlgorithm_=="CambridgeAachen")
173  fjJetDefinition_= JetDefPtr(new fastjet::JetDefinition(fastjet::cambridge_algorithm,
174  rParam_) );
175  else if (jetAlgorithm_=="AntiKt")
176  fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::antikt_algorithm,rParam_) );
177  else if (jetAlgorithm_=="GeneralizedKt")
178  fjJetDefinition_= JetDefPtr( new fastjet::JetDefinition(fastjet::genkt_algorithm,
179  rParam_,-2) );
180  else
181  throw cms::Exception("Invalid jetAlgorithm")
182  <<"Jet algorithm for VirtualJetProducer is invalid, Abort!\n";
183 
185 
186  if ( iConfig.exists("jetCollInstanceName") ) {
187  jetCollInstanceName_ = iConfig.getParameter<string>("jetCollInstanceName");
188  }
189 
190  if ( doPUOffsetCorr_ ) {
191 
192  if(iConfig.exists("subtractorName")) puSubtractorName_ = iConfig.getParameter<string> ("subtractorName");
194 
195  if(puSubtractorName_.empty()){
196  edm::LogWarning("VirtualJetProducer") << "Pile Up correction on; however, pile up type is not specified. Using default... \n";
197  subtractor_ = boost::shared_ptr<PileUpSubtractor>(new PileUpSubtractor(iConfig, consumesCollector()));
198  }else{
199  subtractor_ = boost::shared_ptr<PileUpSubtractor>(PileUpSubtractorFactory::get()->create( puSubtractorName_, iConfig, consumesCollector()));
200  }
201  }
202 
203  // use explicit ghosts in the fastjet clustering sequence?
204  if ( iConfig.exists("useExplicitGhosts") ) {
205  useExplicitGhosts_ = iConfig.getParameter<bool>("useExplicitGhosts");
206  }
207 
208  // do approximate disk-based area calculation => warn if conflicting request
209  if (iConfig.exists("doAreaDiskApprox")) {
210  doAreaDiskApprox_ = iConfig.getParameter<bool>("doAreaDiskApprox");
212  throw cms::Exception("Conflicting area calculations") << "Both the calculation of jet area via fastjet and via an analytical disk approximation have been requested. Please decide on one.\n";
213 
214  }
215  // turn off jet collection output for speed
216  // Voronoi-based area calculation allows for an empirical scale factor
217  if (iConfig.exists("voronoiRfact"))
218  voronoiRfact_ = iConfig.getParameter<double>("voronoiRfact");
219 
220 
221  // do fasjet area / rho calcluation? => accept corresponding parameters
222  if ( doAreaFastjet_ || doRhoFastjet_ ) {
223  // Eta range of jets to be considered for Rho calculation
224  // Should be at most (jet acceptance - jet radius)
225  double rhoEtaMax=iConfig.getParameter<double>("Rho_EtaMax");
226  // default Ghost_EtaMax should be 5
227  double ghostEtaMax = iConfig.getParameter<double>("Ghost_EtaMax");
228  // default Active_Area_Repeats 1
229  int activeAreaRepeats = iConfig.getParameter<int> ("Active_Area_Repeats");
230  // default GhostArea 0.01
231  double ghostArea = iConfig.getParameter<double> ("GhostArea");
232  if (voronoiRfact_ <= 0) {
233  fjActiveArea_ = ActiveAreaSpecPtr(new fastjet::GhostedAreaSpec(ghostEtaMax,activeAreaRepeats,ghostArea));
234  fjActiveArea_->set_fj2_placement(true);
235  if ( ! useExplicitGhosts_ ) {
236  fjAreaDefinition_ = AreaDefinitionPtr( new fastjet::AreaDefinition(fastjet::active_area, *fjActiveArea_ ) );
237  } else {
238  fjAreaDefinition_ = AreaDefinitionPtr( new fastjet::AreaDefinition(fastjet::active_area_explicit_ghosts, *fjActiveArea_ ) );
239  }
240  }
241  fjRangeDef_ = RangeDefPtr( new fastjet::RangeDefinition(rhoEtaMax) );
242  }
243 
244  // restrict inputs to first "maxInputs" towers?
245  if ( iConfig.exists("restrictInputs") ) {
246  restrictInputs_ = iConfig.getParameter<bool>("restrictInputs");
247  maxInputs_ = iConfig.getParameter<unsigned int>("maxInputs");
248  }
249 
250 
251  string alias=iConfig.getUntrackedParameter<string>("alias",moduleLabel_);
252 
253 
254  // Check to see if we are writing compound jets for substructure
255  // and jet grooming
256  if ( iConfig.exists("writeCompound") ) {
257  writeCompound_ = iConfig.getParameter<bool>("writeCompound");
258  }
259 
260  // make the "produces" statements
262 
263  doFastJetNonUniform_ = false;
264  if(iConfig.exists("doFastJetNonUniform")) doFastJetNonUniform_ = iConfig.getParameter<bool> ("doFastJetNonUniform");
266  puCenters_ = iConfig.getParameter<std::vector<double> >("puCenters");
267  puWidth_ = iConfig.getParameter<double>("puWidth");
268  nExclude_ = iConfig.getParameter<unsigned int>("nExclude");
269  }
270 
271  useDeterministicSeed_ = false;
272  minSeed_ = 0;
273  if ( iConfig.exists("useDeterministicSeed") ) {
274  useDeterministicSeed_ = iConfig.getParameter<bool>("useDeterministicSeed");
275  minSeed_ = iConfig.getParameter<unsigned int>("minSeed");
276  }
277 
278  if ( iConfig.exists("verbosity" ) ) {
279  verbosity_ = iConfig.getParameter<int>("verbosity");
280  }
281 
282  produces<std::vector<double> >("rhos");
283  produces<std::vector<double> >("sigmas");
284  produces<double>("rho");
285  produces<double>("sigma");
286 
287  if (!srcPVs_.label().empty()) input_vertex_token_ = consumes<reco::VertexCollection>(srcPVs_);
288  input_candidateview_token_ = consumes<reco::CandidateView>(src_);
289  input_candidatefwdptr_token_ = consumes<std::vector<edm::FwdPtr<reco::PFCandidate> > >(src_);
290  input_packedcandidatefwdptr_token_ = consumes<std::vector<edm::FwdPtr<pat::PackedCandidate> > >(src_);
291 
292 }
293 
294 //______________________________________________________________________________
296 {
297 }
298 
299 
301 // implementation of member functions
303 
304 //______________________________________________________________________________
306 {
307 
308  // If requested, set the fastjet random seed to a deterministic function
309  // of the run/lumi/event.
310  // NOTE!!! The fastjet random number sequence is a global singleton.
311  // Thus, we have to create an object and get access to the global singleton
312  // in order to change it.
313  if ( useDeterministicSeed_ ) {
314  fastjet::GhostedAreaSpec gas;
315  std::vector<int> seeds(2);
316  unsigned int runNum_uint = static_cast <unsigned int> (iEvent.id().run());
317  unsigned int evNum_uint = static_cast <unsigned int> (iEvent.id().event());
318  seeds[0] = std::max(runNum_uint,minSeed_ + 3) + 3 * evNum_uint;
319  seeds[1] = std::max(runNum_uint,minSeed_ + 5) + 5 * evNum_uint;
320  gas.set_random_status(seeds);
321  }
322 
323  LogDebug("VirtualJetProducer") << "Entered produce\n";
324  //determine signal vertex2
325  vertex_=reco::Jet::Point(0,0,0);
327  LogDebug("VirtualJetProducer") << "Adding PV info\n";
329  iEvent.getByToken(input_vertex_token_ , pvCollection);
330  if (pvCollection->size()>0) vertex_=pvCollection->begin()->position();
331  }
332 
333  // For Pileup subtraction using offset correction:
334  // set up geometry map
335  if ( doPUOffsetCorr_ ) {
336  subtractor_->setupGeometryMap(iEvent, iSetup);
337  }
338 
339  // clear data
340  LogDebug("VirtualJetProducer") << "Clear data\n";
341  fjInputs_.clear();
342  fjJets_.clear();
343  inputs_.clear();
344 
345  // get inputs and convert them to the fastjet format (fastjet::PeudoJet)
347 
349  edm::Handle< std::vector<edm::FwdPtr<pat::PackedCandidate> > > packedinputsHandleAsFwdPtr;
350 
351  bool isView = iEvent.getByToken(input_candidateview_token_, inputsHandle);
352  if ( isView ) {
353  if ( inputsHandle->size() == 0) {
354  output( iEvent, iSetup );
355  return;
356  }
357  for (size_t i = 0; i < inputsHandle->size(); ++i) {
358  inputs_.push_back(inputsHandle->ptrAt(i));
359  }
360  } else {
361  bool isPF = iEvent.getByToken(input_candidatefwdptr_token_, pfinputsHandleAsFwdPtr);
362  if ( isPF ) {
363  if ( pfinputsHandleAsFwdPtr->size() == 0) {
364  output( iEvent, iSetup );
365  return;
366  }
367  for (size_t i = 0; i < pfinputsHandleAsFwdPtr->size(); ++i) {
368  if ( (*pfinputsHandleAsFwdPtr)[i].ptr().isAvailable() ) {
369  inputs_.push_back( (*pfinputsHandleAsFwdPtr)[i].ptr() );
370  }
371  else if ( (*pfinputsHandleAsFwdPtr)[i].backPtr().isAvailable() ) {
372  inputs_.push_back( (*pfinputsHandleAsFwdPtr)[i].backPtr() );
373  }
374  }
375  } else {
376  iEvent.getByToken(input_packedcandidatefwdptr_token_, packedinputsHandleAsFwdPtr);
377  if ( packedinputsHandleAsFwdPtr->size() == 0) {
378  output( iEvent, iSetup );
379  return;
380  }
381  for (size_t i = 0; i < packedinputsHandleAsFwdPtr->size(); ++i) {
382  if ( (*packedinputsHandleAsFwdPtr)[i].ptr().isAvailable() ) {
383  inputs_.push_back( (*packedinputsHandleAsFwdPtr)[i].ptr() );
384  }
385  else if ( (*packedinputsHandleAsFwdPtr)[i].backPtr().isAvailable() ) {
386  inputs_.push_back( (*packedinputsHandleAsFwdPtr)[i].backPtr() );
387  }
388  }
389  }
390  }
391  LogDebug("VirtualJetProducer") << "Got inputs\n";
392 
393  // Convert candidates to fastjet::PseudoJets.
394  // Also correct to Primary Vertex. Will modify fjInputs_
395  // and use inputs_
396  fjInputs_.reserve(inputs_.size());
397  inputTowers();
398  LogDebug("VirtualJetProducer") << "Inputted towers\n";
399 
400  // For Pileup subtraction using offset correction:
401  // Subtract pedestal.
402  if ( doPUOffsetCorr_ ) {
403  subtractor_->setDefinition(fjJetDefinition_);
405  subtractor_->calculatePedestal(fjInputs_);
406  subtractor_->subtractPedestal(fjInputs_);
407  LogDebug("VirtualJetProducer") << "Subtracted pedestal\n";
408  }
409  // Run algorithm. Will modify fjJets_ and allocate fjClusterSeq_.
410  // This will use fjInputs_
411  runAlgorithm( iEvent, iSetup );
412 
413  // if ( doPUOffsetCorr_ ) {
414  // subtractor_->setAlgorithm(fjClusterSeq_);
415  // }
416 
417  LogDebug("VirtualJetProducer") << "Ran algorithm\n";
418  // For Pileup subtraction using offset correction:
419  // Now we find jets and need to recalculate their energy,
420  // mark towers participated in jet,
421  // remove occupied towers from the list and recalculate mean and sigma
422  // put the initial towers collection to the jet,
423  // and subtract from initial towers in jet recalculated mean and sigma of towers
424  if ( doPUOffsetCorr_ ) {
425  LogDebug("VirtualJetProducer") << "Do PUOffsetCorr\n";
426  vector<fastjet::PseudoJet> orphanInput;
427  subtractor_->calculateOrphanInput(orphanInput);
428  subtractor_->calculatePedestal(orphanInput);
429  subtractor_->offsetCorrectJets();
430  }
431  // Write the output jets.
432  // This will (by default) call the member function template
433  // "writeJets", but can be overridden.
434  // this will use inputs_
435  output( iEvent, iSetup );
436  LogDebug("VirtualJetProducer") << "Wrote jets\n";
437 
438  // Clear the work vectors so that memory is free for other modules.
439  // Use the trick of swapping with an empty vector so that the memory
440  // is actually given back rather than silently kept.
441  decltype(fjInputs_)().swap(fjInputs_);
442  decltype(fjJets_)().swap(fjJets_);
443  decltype(inputs_)().swap(inputs_);
444 
445  return;
446 }
447 
448 //______________________________________________________________________________
449 
451 {
452  auto inBegin = inputs_.begin(),
453  inEnd = inputs_.end(), i = inBegin;
454  for (; i != inEnd; ++i ) {
455  auto const & input = **i;
456  // std::cout << "CaloTowerVI jets " << input->pt() << " " << input->et() << ' '<< input->energy() << ' ' << (isAnomalousTower(input) ? " bad" : " ok") << std::endl;
457  if (edm::isNotFinite(input.pt())) continue;
458  if (input.et() <inputEtMin_) continue;
459  if (input.energy()<inputEMin_) continue;
460  if (isAnomalousTower(*i)) continue;
461  // Change by SRR : this is no longer an error nor warning, this can happen with PU mitigation algos.
462  // Also switch to something more numerically safe. (VI: 10^-42GeV????)
463  if (input.pt() < 100 * std::numeric_limits<double>::epsilon() ) {
464  continue;
465  }
467  const CaloTower & tower = dynamic_cast<const CaloTower &>(input);
468  auto const & ct = tower.p4(vertex_); // very expensive as computed in eta/phi
469  fjInputs_.emplace_back(ct.px(),ct.py(),ct.pz(),ct.energy());
470  //std::cout << "tower:" << *tower << '\n';
471  }
472  else {
473  /*
474  if(makePFJet(jetTypeE)) {
475  reco::PFCandidate& pfc = (reco::PFCandidate&)input;
476  std::cout << "PF cand:" << pfc << '\n';
477  }
478  */
479  fjInputs_.emplace_back(input.px(),input.py(),input.pz(),
480  input.energy());
481  }
482  fjInputs_.back().set_user_index(i - inBegin);
483  }
484 
485  if ( restrictInputs_ && fjInputs_.size() > maxInputs_ ) {
487  std::sort(fjInputs_.begin(), fjInputs_.end(), pTComparator);
488  fjInputs_.resize(maxInputs_);
489  edm::LogWarning("JetRecoTooManyEntries") << "Too many inputs in the event, limiting to first " << maxInputs_ << ". Output is suspect.";
490  }
491 }
492 
493 //______________________________________________________________________________
495 {
496  if (!makeCaloJet(jetTypeE))
497  return false;
498  else
499  return (*anomalousTowerDef_)(*input);
500 }
501 
502 //------------------------------------------------------------------------------
503 // This is pure virtual.
504 //______________________________________________________________________________
505 // void VirtualJetProducer::runAlgorithm( edm::Event & iEvent, edm::EventSetup const& iSetup,
506 // std::vector<edm::Ptr<reco::Candidate> > const & inputs_);
507 
508 //______________________________________________________________________________
509 void VirtualJetProducer::copyConstituents(const vector<fastjet::PseudoJet>& fjConstituents,
510  reco::Jet* jet)
511 {
512  for (unsigned int i=0;i<fjConstituents.size();++i) {
513  int index = fjConstituents[i].user_index();
514  if ( index >= 0 && static_cast<unsigned int>(index) < inputs_.size() )
515  jet->addDaughter(inputs_[index]);
516  }
517 }
518 
519 
520 //______________________________________________________________________________
521 vector<reco::CandidatePtr>
522 VirtualJetProducer::getConstituents(const vector<fastjet::PseudoJet>&fjConstituents)
523 {
524  vector<reco::CandidatePtr> result; result.reserve(fjConstituents.size()/2);
525  for (unsigned int i=0;i<fjConstituents.size();i++) {
526  auto index = fjConstituents[i].user_index();
527  if ( index >= 0 && static_cast<unsigned int>(index) < inputs_.size() ) {
528  result.emplace_back(inputs_[index]);
529  }
530  }
531  return result;
532 }
533 
534 
535 //_____________________________________________________________________________
536 
538 {
539  // Write jets and constitutents. Will use fjJets_, inputs_
540  // and fjClusterSeq_
541 
542  if ( !writeCompound_ ) {
543  switch( jetTypeE ) {
544  case JetType::CaloJet :
545  writeJets<reco::CaloJet>( iEvent, iSetup);
546  break;
547  case JetType::PFJet :
548  writeJets<reco::PFJet>( iEvent, iSetup);
549  break;
550  case JetType::GenJet :
551  writeJets<reco::GenJet>( iEvent, iSetup);
552  break;
553  case JetType::TrackJet :
554  writeJets<reco::TrackJet>( iEvent, iSetup);
555  break;
556  case JetType::PFClusterJet :
557  writeJets<reco::PFClusterJet>( iEvent, iSetup);
558  break;
559  case JetType::BasicJet :
560  writeJets<reco::BasicJet>( iEvent, iSetup);
561  break;
562  default:
563  throw cms::Exception("InvalidInput") << "invalid jet type in VirtualJetProducer\n";
564  break;
565  };
566  } else {
567  // Write jets and constitutents.
568  switch( jetTypeE ) {
569  case JetType::CaloJet :
570  writeCompoundJets<reco::CaloJet>( iEvent, iSetup );
571  break;
572  case JetType::PFJet :
573  writeCompoundJets<reco::PFJet>( iEvent, iSetup );
574  break;
575  case JetType::GenJet :
576  writeCompoundJets<reco::GenJet>( iEvent, iSetup );
577  break;
578  case JetType::BasicJet :
579  writeCompoundJets<reco::BasicJet>( iEvent, iSetup );
580  break;
581  default:
582  throw cms::Exception("InvalidInput") << "invalid jet type in CompoundJetProducer\n";
583  break;
584  };
585  }
586 }
587 
588 namespace {
589 template< typename T >
590 struct Area { static float get(T const &) {return 0;}};
591 
592 template<>
593 struct Area<reco::CaloJet>{ static float get(reco::CaloJet const & jet) {
594  return jet.getSpecific().mTowersArea;
595 }
596 };
597 }
598 
599 template< typename T >
601 {
602  // std::cout << "writeJets " << typeid(T).name()
603  // << (doRhoFastjet_ ? " doRhoFastjet " : "")
604  // << (doAreaFastjet_ ? " doAreaFastjet " : "")
605  // << (doAreaDiskApprox_ ? " doAreaDiskApprox " : "")
606  // << std::endl;
607 
608  if (doRhoFastjet_) {
609  // declare jet collection without the two jets,
610  // for unbiased background estimation.
611  std::vector<fastjet::PseudoJet> fjexcluded_jets;
612  fjexcluded_jets=fjJets_;
613 
614  if(fjexcluded_jets.size()>2) fjexcluded_jets.resize(nExclude_);
615 
617  auto rhos = std::make_unique<std::vector<double>>();
618  auto sigmas = std::make_unique<std::vector<double>>();
619  int nEta = puCenters_.size();
620  rhos->reserve(nEta);
621  sigmas->reserve(nEta);
622  fastjet::ClusterSequenceAreaBase const* clusterSequenceWithArea =
623  dynamic_cast<fastjet::ClusterSequenceAreaBase const *> ( &*fjClusterSeq_ );
624 
625  if (clusterSequenceWithArea ==nullptr ){
626  if (fjJets_.size() > 0) {
627  throw cms::Exception("LogicError")<<"fjClusterSeq is not initialized while inputs are present\n ";
628  }
629  } else {
630  for(int ie = 0; ie < nEta; ++ie){
631  double eta = puCenters_[ie];
632  double etamin=eta-puWidth_;
633  double etamax=eta+puWidth_;
634  fastjet::RangeDefinition range_rho(etamin,etamax);
635  fastjet::BackgroundEstimator bkgestim(*clusterSequenceWithArea,range_rho);
636  bkgestim.set_excluded_jets(fjexcluded_jets);
637  rhos->push_back(bkgestim.rho());
638  sigmas->push_back(bkgestim.sigma());
639  }
640  }
641  iEvent.put(std::move(rhos),"rhos");
642  iEvent.put(std::move(sigmas),"sigmas");
643  }else{
644  auto rho = std::make_unique<double>(0.0);
645  auto sigma = std::make_unique<double>(0.0);
646  double mean_area = 0;
647 
648  fastjet::ClusterSequenceAreaBase const* clusterSequenceWithArea =
649  dynamic_cast<fastjet::ClusterSequenceAreaBase const *> ( &*fjClusterSeq_ );
650  /*
651  const double nemptyjets = clusterSequenceWithArea->n_empty_jets(*fjRangeDef_);
652  if(( nemptyjets < -15 ) || ( nemptyjets > fjRangeDef_->area()+ 15)) {
653  edm::LogWarning("StrangeNEmtpyJets") << "n_empty_jets is : " << clusterSequenceWithArea->n_empty_jets(*fjRangeDef_) << " with range " << fjRangeDef_->description() << ".";
654  }
655  */
656  if (clusterSequenceWithArea ==nullptr ){
657  if (fjJets_.size() > 0) {
658  throw cms::Exception("LogicError")<<"fjClusterSeq is not initialized while inputs are present\n ";
659  }
660  } else {
661  clusterSequenceWithArea->get_median_rho_and_sigma(*fjRangeDef_,false,*rho,*sigma,mean_area);
662  if((*rho < 0)|| (edm::isNotFinite(*rho))) {
663  edm::LogError("BadRho") << "rho value is " << *rho << " area:" << mean_area << " and n_empty_jets: " << clusterSequenceWithArea->n_empty_jets(*fjRangeDef_) << " with range " << fjRangeDef_->description()
664  <<". Setting rho to rezo.";
665  *rho = 0;
666  }
667  }
668  iEvent.put(std::move(rho),"rho");
669  iEvent.put(std::move(sigma),"sigma");
670  }
671  } // doRhoFastjet_
672 
673  // produce output jet collection
674 
675  using namespace reco;
676 
677  // allocate fjJets_.size() Ts in vector
678  auto jets = std::make_unique<std::vector<T>>(fjJets_.size());
679 
680  // Distance between jet centers and overlap area -- for disk-based area calculation
681  using RIJ = std::pair<double,double>;
682  std::vector<RIJ> rijStorage(fjJets_.size()*(fjJets_.size()/2));
683  RIJ * rij[fjJets_.size()];
684  unsigned int k=0;
685  for (unsigned int ijet=0;ijet<fjJets_.size();++ijet) {
686  rij[ijet] = &rijStorage[k]; k+=ijet;
687  }
688 
689  float etaJ[fjJets_.size()], phiJ[fjJets_.size()];
690 
691  auto orParam_ = 1./rParam_;
692  // fill jets
693  for (unsigned int ijet=0;ijet<fjJets_.size();++ijet) {
694  auto & jet = (*jets)[ijet];
695  // get the fastjet jet
696  const fastjet::PseudoJet& fjJet = fjJets_[ijet];
697  // get the constituents from fastjet
698  std::vector<fastjet::PseudoJet> const & fjConstituents = fastjet::sorted_by_pt(fjJet.constituents());
699  // convert them to CandidatePtr vector
700  std::vector<CandidatePtr> const & constituents = getConstituents(fjConstituents);
701 
702  // write the specifics to the jet (simultaneously sets 4-vector, vertex).
703  // These are overridden functions that will call the appropriate
704  // specific allocator.
706  Particle::LorentzVector(fjJet.px(),
707  fjJet.py(),
708  fjJet.pz(),
709  fjJet.E()),
710  vertex_,
711  constituents, iSetup);
712  phiJ[ijet] = jet.phi();
713  etaJ[ijet] = jet.eta();
714  }
715 
716  // calcuate the jet area
717  for (unsigned int ijet=0;ijet<fjJets_.size();++ijet) {
718  // calcuate the jet area
719  double jetArea=0.0;
720  // get the fastjet jet
721  const auto & fjJet = fjJets_[ijet];
722  if ( doAreaFastjet_ && fjJet.has_area() ) {
723  jetArea = fjJet.area();
724  }
725  else if ( doAreaDiskApprox_ ) {
726  // Here it is assumed that fjJets_ is in decreasing order of pT,
727  // which should happen in FastjetJetProducer::runAlgorithm()
728  jetArea = M_PI;
729  RIJ * distance = rij[ijet];
730  for (unsigned jJet = 0; jJet < ijet; ++jJet) {
731  distance[jJet].first = std::sqrt(reco::deltaR2(etaJ[ijet],phiJ[ijet], etaJ[jJet],phiJ[jJet]))*orParam_;
732  distance[jJet].second = reco::helper::VirtualJetProducerHelper::intersection(distance[jJet].first);
733  jetArea -=distance[jJet].second;
734  for (unsigned kJet = 0; kJet < jJet; ++kJet) {
735  jetArea += reco::helper::VirtualJetProducerHelper::intersection(distance[jJet].first, distance[kJet].first, rij[jJet][kJet].first,
736  distance[jJet].second, distance[kJet].second, rij[jJet][kJet].second);
737  } // end loop over harder jets
738  } // end loop over harder jets
739  jetArea *= (rParam_*rParam_);
740  }
741  auto & jet = (*jets)[ijet];
742  jet.setJetArea (jetArea);
743 
744  if(doPUOffsetCorr_){
745  jet.setPileup(subtractor_->getPileUpEnergy(ijet));
746  }else{
747  jet.setPileup (0.0);
748  }
749 
750  // std::cout << "area " << ijet << " " << jetArea << " " << Area<T>::get(jet) << std::endl;
751  // std::cout << "JetVI " << ijet << ' '<< jet.pt() << " " << jet.et() << ' '<< jet.energy() << ' '<< jet.mass() << std::endl;
752 
753  }
754  // put the jets in the collection
756 }
757 
759 template< class T>
761 {
762  if ( verbosity_ >= 1 ) {
763  std::cout << "<VirtualJetProducer::writeCompoundJets (moduleLabel = " << moduleLabel_ << ")>:" << std::endl;
764  }
765 
766  // get a list of output jets
767  auto jetCollection = std::make_unique<reco::BasicJetCollection>();
768  // get a list of output subjets
769  auto subjetCollection = std::make_unique<std::vector<T>>();
770 
771  // This will store the handle for the subjets after we write them
772  edm::OrphanHandle< std::vector<T> > subjetHandleAfterPut;
773  // this is the mapping of subjet to hard jet
774  std::vector< std::vector<int> > indices;
775  // this is the list of hardjet 4-momenta
776  std::vector<math::XYZTLorentzVector> p4_hardJets;
777  // this is the hardjet areas
778  std::vector<double> area_hardJets;
779 
780  // Loop over the hard jets
781  std::vector<fastjet::PseudoJet>::const_iterator it = fjJets_.begin(),
782  iEnd = fjJets_.end(),
783  iBegin = fjJets_.begin();
784  indices.resize( fjJets_.size() );
785  for ( ; it != iEnd; ++it ) {
786  fastjet::PseudoJet const & localJet = *it;
787  unsigned int jetIndex = it - iBegin;
788  // Get the 4-vector for the hard jet
789  p4_hardJets.push_back( math::XYZTLorentzVector(localJet.px(), localJet.py(), localJet.pz(), localJet.e() ));
790  double localJetArea = 0.0;
791  if ( doAreaFastjet_ && localJet.has_area() ) {
792  localJetArea = localJet.area();
793  }
794  area_hardJets.push_back( localJetArea );
795 
796  // create the subjet list
797  std::vector<fastjet::PseudoJet> constituents;
798  if ( it->has_pieces() ) {
799  constituents = it->pieces();
800  } else if ( it->has_constituents() ) {
801  constituents = it->constituents();
802  }
803 
804  std::vector<fastjet::PseudoJet>::const_iterator itSubJetBegin = constituents.begin(),
805  itSubJet = itSubJetBegin, itSubJetEnd = constituents.end();
806  for (; itSubJet != itSubJetEnd; ++itSubJet ){
807 
808  fastjet::PseudoJet const & subjet = *itSubJet;
809  if ( verbosity_ >= 1 ) {
810  std::cout << "subjet #" << (itSubJet - itSubJetBegin) << ": Pt = " << subjet.pt() << ", eta = " << subjet.eta() << ", phi = " << subjet.phi() << ", mass = " << subjet.m()
811  << " (#constituents = " << subjet.constituents().size() << ")" << std::endl;
812  std::vector<fastjet::PseudoJet> subjet_constituents = subjet.constituents();
813  int idx_constituent = 0;
814  for ( std::vector<fastjet::PseudoJet>::const_iterator constituent = subjet_constituents.begin();
815  constituent != subjet_constituents.end(); ++constituent ) {
816  if ( constituent->pt() < 1.e-3 ) continue; // CV: skip ghosts
817  std::cout << " constituent #" << idx_constituent << ": Pt = " << constituent->pt() << ", eta = " << constituent->eta() << ", phi = " << constituent->phi() << ","
818  << " mass = " << constituent->m() << std::endl;
819  ++idx_constituent;
820  }
821  }
822 
823  if ( verbosity_ >= 1 ) {
824  std::cout << "subjet #" << (itSubJet - itSubJetBegin) << ": Pt = " << subjet.pt() << ", eta = " << subjet.eta() << ", phi = " << subjet.phi() << ", mass = " << subjet.m()
825  << " (#constituents = " << subjet.constituents().size() << ")" << std::endl;
826  std::vector<fastjet::PseudoJet> subjet_constituents = subjet.constituents();
827  int idx_constituent = 0;
828  for ( std::vector<fastjet::PseudoJet>::const_iterator constituent = subjet_constituents.begin();
829  constituent != subjet_constituents.end(); ++constituent ) {
830  if ( constituent->pt() < 1.e-3 ) continue; // CV: skip ghosts
831  std::cout << " constituent #" << idx_constituent << ": Pt = " << constituent->pt() << ", eta = " << constituent->eta() << ", phi = " << constituent->phi() << ","
832  << " mass = " << constituent->m() << std::endl;
833  ++idx_constituent;
834  }
835  }
836 
837  math::XYZTLorentzVector p4Subjet(subjet.px(), subjet.py(), subjet.pz(), subjet.e() );
839 
840  // This will hold ptr's to the subjets
841  std::vector<reco::CandidatePtr> subjetConstituents;
842 
843  // Get the transient subjet constituents from fastjet
844  std::vector<fastjet::PseudoJet> subjetFastjetConstituents = subjet.constituents();
845  std::vector<reco::CandidatePtr> constituents =
846  getConstituents(subjetFastjetConstituents );
847 
848  indices[jetIndex].push_back( subjetCollection->size() );
849 
850  // Add the concrete subjet type to the subjet list to write to event record
851  T jet;
852  reco::writeSpecific( jet, p4Subjet, point, constituents, iSetup);
853  double subjetArea = 0.0;
854  if ( doAreaFastjet_ && itSubJet->has_area() ){
855  subjetArea = itSubJet->area();
856  }
857  jet.setJetArea( subjetArea );
858  subjetCollection->push_back( jet );
859  }
860  }
861 
862  // put subjets into event record
863  subjetHandleAfterPut = iEvent.put(std::move(subjetCollection), jetCollInstanceName_);
864 
865  // Now create the hard jets with ptr's to the subjets as constituents
866  std::vector<math::XYZTLorentzVector>::const_iterator ip4 = p4_hardJets.begin(),
867  ip4Begin = p4_hardJets.begin(),
868  ip4End = p4_hardJets.end();
869 
870  for ( ; ip4 != ip4End; ++ip4 ) {
871  int p4_index = ip4 - ip4Begin;
872  std::vector<int> & ind = indices[p4_index];
873  std::vector<reco::CandidatePtr> i_hardJetConstituents;
874  // Add the subjets to the hard jet
875  for( std::vector<int>::const_iterator isub = ind.begin();
876  isub != ind.end(); ++isub ) {
877  reco::CandidatePtr candPtr( subjetHandleAfterPut, *isub, false );
878  i_hardJetConstituents.push_back( candPtr );
879  }
881  reco::BasicJet toput( *ip4, point, i_hardJetConstituents);
882  toput.setJetArea( area_hardJets[ip4 - ip4Begin] );
883  jetCollection->push_back( toput );
884  }
885 
886  // put hard jets into event record
887  // Store the Orphan handle for adding HTT information
888  edm::OrphanHandle<reco::BasicJetCollection> oh = iEvent.put(std::move(jetCollection));
889 
891  addHTTTopJetTagInfoCollection( iEvent, iSetup, oh);
892  }
893 
894 }
#define LogDebug(id)
RunNumber_t run() const
Definition: EventID.h:39
boost::shared_ptr< fastjet::AreaDefinition > AreaDefinitionPtr
void writeJets(edm::Event &iEvent, edm::EventSetup const &iSetup)
JetType::Type jetTypeE
T getParameter(std::string const &) const
EventNumber_t event() const
Definition: EventID.h:41
T getUntrackedParameter(std::string const &, T const &) const
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:122
reco::Particle::Point vertex_
Definition: helper.py:1
Jets made from CaloTowers.
Definition: CaloJet.h:29
virtual void addHTTTopJetTagInfoCollection(edm::Event &iEvent, const edm::EventSetup &iSetup, edm::OrphanHandle< reco::BasicJetCollection > &oh)
static const HistoName names[]
math::PtEtaPhiMLorentzVector p4(double vtxZ) const
Definition: CaloTower.cc:129
edm::EDGetTokenT< reco::CandidateView > input_candidateview_token_
virtual std::vector< reco::CandidatePtr > getConstituents(const std::vector< fastjet::PseudoJet > &fjConstituents)
std::vector< fastjet::PseudoJet > fjJets_
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:457
Ptr< value_type > ptrAt(size_type i) const
virtual void inputTowers()
edm::EDGetTokenT< std::vector< edm::FwdPtr< pat::PackedCandidate > > > input_packedcandidatefwdptr_token_
Base class for all types of Jets.
Definition: Jet.h:20
boost::shared_ptr< fastjet::JetDefinition::Plugin > PluginPtr
bool exists(std::string const &parameterName) const
checks if a parameter exists
size_type size() const
std::string puSubtractorName_
std::vector< double > puCenters_
virtual void copyConstituents(const std::vector< fastjet::PseudoJet > &fjConstituents, reco::Jet *jet)
Jets made from CaloTowers.
Definition: BasicJet.h:20
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:20
virtual void runAlgorithm(edm::Event &iEvent, const edm::EventSetup &iSetup)=0
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:116
static std::string const input
Definition: EdmProvDump.cc:44
void writeCompoundJets(edm::Event &iEvent, edm::EventSetup const &iSetup)
function template to write out the outputs
bool operator()(const fastjet::PseudoJet &t1, const fastjet::PseudoJet &t2) const
boost::shared_ptr< fastjet::RangeDefinition > RangeDefPtr
U second(std::pair< T, U > const &p)
bool makePFJet(const JetType::Type &fTag)
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
virtual bool isAnomalousTower(reco::CandidatePtr input)
virtual void setJetArea(float fArea)
set jet area
Definition: Jet.h:103
std::vector< fastjet::PseudoJet > fjInputs_
int iEvent
Definition: GenABIO.cc:230
std::string jetCollInstanceName_
boost::shared_ptr< PileUpSubtractor > subtractor_
bool isNotFinite(T x)
Definition: isFinite.h:10
std::vector< edm::Ptr< reco::Candidate > > inputs_
auto const T2 &decltype(t1.eta()) t2
Definition: deltaR.h:16
ClusterSequencePtr fjClusterSeq_
virtual void makeProduces(std::string s, std::string tag="")
ConsumesCollector consumesCollector()
Use a ConsumesCollector to gather consumes information from helper functions.
T sqrt(T t)
Definition: SSEVec.h:18
vector< PseudoJet > jets
math::XYZPoint Point
point in the space
Definition: Particle.h:25
void set_excluded_jets(const std::vector< PseudoJet > &excluded_jets)
boost::shared_ptr< fastjet::JetDefinition > JetDefPtr
std::auto_ptr< AnomalousTower > anomalousTowerDef_
ActiveAreaSpecPtr fjActiveArea_
#define M_PI
int k[5][pyjets_maxn]
edm::EDGetTokenT< reco::VertexCollection > input_vertex_token_
double rho()
synonym for median rho [[do we have this? Both?]]
edm::EDGetTokenT< std::vector< edm::FwdPtr< reco::PFCandidate > > > input_candidatefwdptr_token_
static const char *const names[]
T1 deltaR2(T1 eta1, T2 phi1, T3 eta2, T4 phi2)
Definition: deltaR.h:36
double sigma()
get the sigma
std::string const & label() const
Definition: InputTag.h:36
edm::EventID id() const
Definition: EventBase.h:58
fixed size matrix
virtual void produce(edm::Event &iEvent, const edm::EventSetup &iSetup) override
HLT enums.
VirtualJetProducer(const edm::ParameterSet &iConfig)
boost::shared_ptr< fastjet::GhostedAreaSpec > ActiveAreaSpecPtr
void addDaughter(const CandidatePtr &)
add a daughter via a reference
AreaDefinitionPtr fjAreaDefinition_
virtual void output(edm::Event &iEvent, edm::EventSetup const &iSetup)
long double T
bool makeCaloJet(const JetType::Type &fTag)
static Type byName(const std::string &name)
def move(src, dest)
Definition: eostools.py:510
T get(const Candidate &c)
Definition: component.h:55
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
math::PtEtaPhiELorentzVectorF LorentzVector
math::XYZPoint Point
point in the space
Definition: LeafCandidate.h:27
void writeSpecific(reco::CaloJet &jet, reco::Particle::LorentzVector const &p4, reco::Particle::Point const &point, std::vector< reco::CandidatePtr > const &constituents, edm::EventSetup const &c)
Definition: JetSpecific.cc:41