00001
00002
00003
00004
00005 #include <memory>
00006 #include "DataFormats/Common/interface/EDProduct.h"
00007 #include "FWCore/Framework/interface/Event.h"
00008 #include "FWCore/Framework/interface/EventSetup.h"
00009 #include "DataFormats/Common/interface/View.h"
00010 #include "DataFormats/Common/interface/Handle.h"
00011 #include "DataFormats/Provenance/interface/ProductID.h"
00012 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00013
00014 #include "DataFormats/JetReco/interface/CaloJetCollection.h"
00015
00016 #include "RecoJets/JetAlgorithms/interface/JetMaker.h"
00017 #include "RecoJets/JetAlgorithms/interface/JetRecoTypes.h"
00018 #include "RecoJets/JetAlgorithms/interface/JetAlgoHelper.h"
00019 #include "RecoJets/JetAlgorithms/interface/ProtoJet.h"
00020 #include "DataFormats/Candidate/interface/CandidateFwd.h"
00021 #include "DataFormats/RecoCandidate/interface/RecoCandidate.h"
00022 #include "DataFormats/Candidate/interface/LeafCandidate.h"
00023
00024 #include "FWCore/Framework/interface/ESHandle.h"
00025 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00026 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00027 #include "DataFormats/Provenance/interface/Provenance.h"
00028 #include "DataFormats/Math/interface/LorentzVector.h"
00029 #include "DataFormats/HcalDetId/interface/HcalDetId.h"
00030 #include "DataFormats/DetId/interface/DetId.h"
00031 #include "DataFormats/Provenance/interface/ParameterSetID.h"
00032
00033 #include "BasePilupSubtractionJetProducer.h"
00034
00035 using namespace std;
00036 using namespace reco;
00037 using namespace JetReco;
00038
00039 namespace {
00040 const bool debug = false;
00041 bool makeCaloJetPU (const string& fTag) {
00042 return fTag == "CaloJetPileupSubtraction";
00043 }
00044
00045 bool makeCaloJet (const string& fTag) {
00046 return fTag == "CaloJet";
00047 }
00048 bool makeGenJet (const string& fTag) {
00049 return fTag == "GenJet";
00050 }
00051 bool makeBasicJet (const string& fTag) {
00052 return fTag == "BasicJet";
00053 }
00054 bool makeGenericJet (const string& fTag) {
00055 return !makeCaloJet (fTag) && !makeGenJet (fTag) && !makeBasicJet (fTag);
00056 }
00057
00058 template <class T>
00059 void dumpJets (const T& fJets) {
00060 for (unsigned i = 0; i < fJets.size(); ++i) {
00061 std::cout << "Jet # " << i << std::endl << fJets[i].print();
00062 }
00063 }
00064 }
00065
00066 namespace cms
00067 {
00068
00069
00070
00071
00072 BasePilupSubtractionJetProducer::BasePilupSubtractionJetProducer(const edm::ParameterSet& conf)
00073 : mSrc (conf.getParameter<edm::InputTag>( "src" )),
00074 mJetType (conf.getUntrackedParameter<string>( "jetType", "CaloJet")),
00075 mVerbose (conf.getUntrackedParameter<bool>("verbose", false)),
00076 mEtInputCut (conf.getParameter<double>("inputEtMin")),
00077 mEInputCut (conf.getParameter<double>("inputEMin")),
00078 mEtJetInputCut (conf.getParameter<double>("inputEtJetMin")),
00079 nSigmaPU (conf.getParameter<double>("nSigmaPU")),
00080 radiusPU (conf.getParameter<double>("radiusPU")),geo(0)
00081 {
00082
00083 std::string alias = conf.getUntrackedParameter<string>( "alias", conf.getParameter<std::string>("@module_label"));
00084 if (!makeCaloJetPU (mJetType)) {
00085 std::cerr << "BasePilupSubtractionJetProducer-> ERROR: wrong jetType '" << mJetType
00086 << "'. The only supported jetType is 'CaloJetPileupSubtraction'" << std::endl;
00087 }
00088 produces<CaloJetCollection>().setBranchAlias (alias);
00089 }
00090
00091
00092 BasePilupSubtractionJetProducer::~BasePilupSubtractionJetProducer() { }
00093
00094 void BasePilupSubtractionJetProducer::beginJob( const edm::EventSetup& iSetup)
00095 {
00096 }
00097
00098
00099 void BasePilupSubtractionJetProducer::produce(edm::Event& e, const edm::EventSetup& fSetup)
00100 {
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 if(geo == 0)
00119 {
00120 edm::ESHandle<CaloGeometry> pG;
00121 fSetup.get<CaloGeometryRecord>().get(pG);
00122 geo = pG.product();
00123 std::vector<DetId> alldid = geo->getValidDetIds();
00124
00125 int ietaold = -10000;
00126 ietamax = -10000;
00127 ietamin = 10000;
00128 for(std::vector<DetId>::const_iterator did=alldid.begin(); did != alldid.end(); did++)
00129 {
00130 if( (*did).det() == DetId::Hcal )
00131 {
00132 HcalDetId hid = HcalDetId(*did);
00133 if( (hid).depth() == 1 )
00134 {
00135
00136 allgeomid.push_back(*did);
00137
00138 if((hid).ieta() != ietaold)
00139 {
00140 ietaold = (hid).ieta();
00141 geomtowers[(hid).ieta()] = 1;
00142 if((hid).ieta() > ietamax) ietamax = (hid).ieta();
00143 if((hid).ieta() < ietamin) ietamin = (hid).ieta();
00144 }
00145 else
00146 {
00147 geomtowers[(hid).ieta()]++;
00148 }
00149 }
00150 }
00151 }
00152 }
00153
00154 for (int i = ietamin; i<ietamax+1; i++)
00155 {
00156 ntowers_with_jets[i] = 0;
00157 }
00158
00159
00160 edm::Handle<edm::View <Candidate> > inputHandle;
00161 e.getByLabel( mSrc, inputHandle);
00162
00163 JetReco::InputCollection input;
00164 input.reserve (inputHandle->size());
00165 for (unsigned i = 0; i < inputHandle->size(); ++i) {
00166 if ((mEtInputCut <= 0 || (*inputHandle)[i].et() > mEtInputCut) &&
00167 (mEInputCut <= 0 || (*inputHandle)[i].energy() > mEInputCut)) {
00168 input.push_back (JetReco::InputItem (&((*inputHandle)[i]), i));
00169 }
00170 }
00171
00172
00173
00174
00175
00176 calculate_pedestal(input);
00177 std::vector<ProtoJet> output;
00178
00179
00180
00181 InputCollection inputTMPN = subtract_pedestal(input);
00182
00183
00184
00185
00186
00187 vector <ProtoJet> firstoutput;
00188
00189
00190
00191
00192
00193 runAlgorithm (inputTMPN, &firstoutput);
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 InputCollection jettowers;
00205 vector <ProtoJet>::iterator protojetTMP = firstoutput.begin ();
00206
00207 for (; protojetTMP != firstoutput.end (); protojetTMP++) {
00208
00209
00210
00211
00212 if( (*protojetTMP).et() < mEtJetInputCut) continue;
00213
00214 ProtoJet::Constituents newtowers;
00215
00216
00217
00218
00219 double eta2 = (*protojetTMP).eta();
00220 double phi2 = (*protojetTMP).phi();
00221 for(vector<HcalDetId>::const_iterator im = allgeomid.begin(); im != allgeomid.end(); im++)
00222 {
00223 double eta1 = geo->getPosition((DetId)(*im)).eta();
00224 double phi1 = geo->getPosition((DetId)(*im)).phi();
00225
00226 double dphi = fabs(phi1-phi2);
00227 double deta = eta1-eta2;
00228 if (dphi > 4.*atan(1.)) dphi = 8.*atan(1.) - dphi;
00229 double dr = sqrt(dphi*dphi+deta*deta);
00230
00231
00232
00233 if( dr < radiusPU) {
00234 ntowers_with_jets[(*im).ieta()]++;
00235
00236
00237
00238
00239
00240 }
00241
00242 }
00243
00244
00245
00246 for (InputCollection::const_iterator it = input.begin(); it != input.end(); it++ ) {
00247
00248 double eta1 = (**it).eta();
00249 double phi1 = (**it).phi();
00250
00251 double dphi = fabs(phi1-phi2);
00252 double deta = eta1-eta2;
00253 if (dphi > 4.*atan(1.)) dphi = 8.*atan(1.) - dphi;
00254 double dr = sqrt(dphi*dphi+deta*deta);
00255
00256 if( dr < radiusPU) {
00257 newtowers.push_back(*it);
00258 jettowers.push_back(*it);
00259
00260 int ieta1 = ieta(&(**it));
00261 int iphi1 = iphi(&(**it));
00262
00263
00264
00265 }
00266
00267 }
00268
00269
00270
00271 (*protojetTMP).putTowers(newtowers);
00272
00273
00274
00275
00276
00277 if (0) {
00278 for (InputCollection::const_iterator itt = input.begin(); itt != input.end(); itt++ ) {
00279
00280 double eta_pu1 = (**itt).eta();
00281 double phi_pu1 = (**itt).phi();
00282
00283 double dphi = fabs(phi_pu1-phi2);
00284 double deta = eta_pu1-eta2;
00285 if (dphi > 4.*atan(1.)) dphi = 8.*atan(1.) - dphi;
00286 double dr = sqrt(dphi*dphi+deta*deta);
00287
00288 if( dr < radiusPU) {
00289 int ieta_pu1 = ieta(&(**itt));
00290 int iphi_pu1 = iphi(&(**itt));
00291
00292
00293
00294
00295
00296 }
00297
00298 }
00299 }
00300
00301
00302
00303
00304 }
00305
00306
00307
00308
00309
00310 InputCollection orphanInput;
00311 for(InputCollection::const_iterator it = input.begin(); it != input.end(); it++ ) {
00312 InputCollection::const_iterator itjet = find(jettowers.begin(),jettowers.end(),*it);
00313 if( itjet == jettowers.end() ) orphanInput.push_back(*it);
00314 }
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 calculate_pedestal(orphanInput);
00339
00340
00341
00342
00343
00344 protojetTMP = firstoutput.begin ();
00345 int kk = 0;
00346 for (; protojetTMP != firstoutput.end (); protojetTMP++) {
00347
00348
00349
00350
00351 if( (*protojetTMP).et() < mEtJetInputCut) continue;
00352
00353
00354
00355 const ProtoJet::Constituents towers = (*protojetTMP).getTowerList();
00356
00357
00358
00359 double offset = 0.;
00360
00361 for(ProtoJet::Constituents::const_iterator ito = towers.begin(); ito != towers.end(); ito++)
00362 {
00363
00364
00365 int it = ieta(&(**ito));
00366
00367
00368
00369
00370 double etnew = (**ito).et() - (*emean.find(it)).second - (*esigma.find(it)).second;
00371
00372
00373
00374 if( etnew <0.) etnew = 0.;
00375
00376 offset = offset + etnew;
00377
00378
00379 }
00380
00381
00382
00383 double mScale = offset/(*protojetTMP).et();
00384
00385
00387 Jet::LorentzVector fP4((*protojetTMP).px()*mScale, (*protojetTMP).py()*mScale,
00388 (*protojetTMP).pz()*mScale, (*protojetTMP).energy()*mScale);
00389
00390
00394 ProtoJet pj(fP4, towers);
00395 kk++;
00396 output.push_back(pj);
00397 }
00398
00399
00400
00401 reco::Jet::Point vertex (0,0,0);
00402
00403 sortByPt (&output);
00404
00405 edm::ESHandle<CaloGeometry> geometry;
00406 fSetup.get<CaloGeometryRecord>().get(geometry);
00407 const CaloSubdetectorGeometry* towerGeometry =
00408 geometry->getSubdetectorGeometry(DetId::Calo, CaloTowerDetId::SubdetId);
00409 auto_ptr<CaloJetCollection> jets (new CaloJetCollection);
00410 for (unsigned iJet = 0; iJet < output.size (); ++iJet) {
00411 ProtoJet* protojet = &(output [iJet]);
00412 const JetReco::InputCollection& constituents = protojet->getTowerList();
00413 CaloJet::Specific specific;
00414 JetMaker::makeSpecific (constituents, *towerGeometry, &specific);
00415 jets->push_back (CaloJet (protojet->p4(), vertex, specific));
00416 Jet* newJet = &(jets->back());
00417
00418 for (unsigned iConstituent = 0; iConstituent < constituents.size (); ++iConstituent) {
00419 newJet->addDaughter (inputHandle->ptrAt (constituents[iConstituent].index ()));
00420 }
00421 newJet->setJetArea (protojet->jetArea ());
00422 newJet->setPileup (protojet->pileup ());
00423 newJet->setNPasses (protojet->nPasses ());
00424 }
00425 if (mVerbose) dumpJets (*jets);
00426 e.put(jets);
00427
00428 }
00429
00430 void BasePilupSubtractionJetProducer::calculate_pedestal(const JetReco::InputCollection& fInputs)
00431 {
00432
00433
00434
00435 map<int,double> emean2;
00436 map<int,int> ntowers;
00437
00438 int ietaold = -10000;
00439 int ieta0 = -100;
00440
00441
00442
00443 for(int i = ietamin; i < ietamax+1; i++)
00444 {
00445 emean[i] = 0.;
00446 emean2[i] = 0.;
00447 esigma[i] = 0.;
00448 ntowers[i] = 0;
00449 }
00450
00451
00452
00453 for (JetReco::InputCollection::const_iterator input_object = fInputs.begin (); input_object != fInputs.end (); input_object++) {
00454
00455 ieta0 = ieta(&(**input_object));
00456
00457
00458
00459
00460
00461
00462 if( ieta0-ietaold != 0 )
00463 {
00464
00465 emean[ieta0] = emean[ieta0]+(**input_object).et();
00466 emean2[ieta0] = emean2[ieta0]+((**input_object).et())*((**input_object).et());
00467 ntowers[ieta0] = 1;
00468
00469 ietaold = ieta0;
00470
00471
00472
00473 }
00474 else
00475 {
00476 emean[ieta0] = emean[ieta0]+(**input_object).et();
00477 emean2[ieta0] = emean2[ieta0]+((**input_object).et())*((**input_object).et());
00478 ntowers[ieta0]++;
00479
00480
00481
00482 }
00483
00484
00485
00486
00487 }
00488
00489
00490
00491
00492 for(map<int,int>::const_iterator gt = geomtowers.begin(); gt != geomtowers.end(); gt++)
00493 {
00494
00495 int it = (*gt).first;
00496
00497 double e1 = (*emean.find(it)).second;
00498 double e2 = (*emean2.find(it)).second;
00499 int nt = (*gt).second - (*ntowers_with_jets.find(it)).second;
00500
00501 if(nt > 0) {
00502 emean[it] = e1/nt;
00503 double eee = e2/nt - e1*e1/(nt*nt);
00504
00505
00506
00507 if(eee<0.) eee = 0.;
00508 esigma[it] = nSigmaPU*sqrt(eee);
00509 }
00510 else
00511 {
00512 emean[it] = 0.;
00513 esigma[it] = 0.;
00514 }
00515
00516
00517
00518
00519
00520
00521
00522
00523 }
00524
00525 }
00526
00527
00528 JetReco::InputCollection BasePilupSubtractionJetProducer::subtract_pedestal(const JetReco::InputCollection& fInputs)
00529 {
00530
00531
00532
00533
00534
00535 JetReco::InputCollection inputCache;
00536
00537 Candidate * mycand;
00538
00539 JetReco::InputCollection inputTMP;
00540 int it = -100;
00541 int ip = -100;
00542 int icand = 0;
00543
00544
00545
00546 for (JetReco::InputCollection::const_iterator input_object = fInputs.begin (); input_object != fInputs.end (); input_object++) {
00547
00548 it = ieta(&(**input_object));
00549 ip = iphi(&(**input_object));
00550
00551 double etnew = (**input_object).et() - (*emean.find(it)).second - (*esigma.find(it)).second;
00552 float mScale = etnew/(**input_object).et();
00553
00554
00555 if(etnew < 0.) mScale = 0.;
00556
00557
00558
00559
00560
00561
00562
00563
00565 math::XYZTLorentzVectorD p4((**input_object).px()*mScale, (**input_object).py()*mScale,
00566 (**input_object).pz()*mScale, (**input_object).energy()*mScale);
00567
00568
00569
00570
00571 if (makeCaloJetPU (mJetType)) {
00572
00573
00574 const CaloTower* ct = dynamic_cast<const CaloTower*>(&(**input_object));
00575
00576
00577
00578 if(ct)
00579 {
00580
00581
00582
00583 mycand = new CaloTower (*ct);
00584
00585
00586 mycand->setP4(p4);
00587
00588
00589 }
00590 else
00591 {
00592 throw cms::Exception("Invalid Constituent") << "CaloJet constituent is not of CaloTower type";
00593 }
00594 }
00595 inputCache.push_back (JetReco::InputItem(mycand,icand));
00596 icand++;
00597 }
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618 return inputCache;
00619 }
00620
00621 int BasePilupSubtractionJetProducer::ieta(const reco::Candidate* in)
00622 {
00623
00624 int it = 0;
00625 if (makeCaloJetPU (mJetType)) {
00626
00627
00628 const CaloTower* ctc = dynamic_cast<const CaloTower*>(in);
00629
00630 if(ctc)
00631 {
00632 it = ctc->id().ieta();
00633 } else
00634 {
00635 throw cms::Exception("Invalid Constituent") << "CaloJet constituent is not of CaloTower type";
00636 }
00637 }
00638
00639 return it;
00640 }
00641
00642 int BasePilupSubtractionJetProducer::iphi(const reco::Candidate* in)
00643 {
00644
00645 int it = 0;
00646 if (makeCaloJetPU (mJetType)) {
00647
00648
00649 const CaloTower* ctc = dynamic_cast<const CaloTower*>(in);
00650 if(ctc)
00651 {
00652 it = ctc->id().iphi();
00653 } else
00654 {
00655 throw cms::Exception("Invalid Constituent") << "CaloJet constituent is not of CaloTower type";
00656 }
00657 }
00658
00659 return it;
00660 }
00661
00662
00663 }