00001
00002
00003
00004
00005
00013
00014
00015
00016
00017
00018
00019
00020 #include <iostream>
00021 #include <fstream>
00022 #include <algorithm>
00023
00024
00025 #include "RecoJets/FFTJetProducers/plugins/FFTJetProducer.h"
00026
00027
00028 #include "fftjet/VectorRecombinationAlgFactory.hh"
00029 #include "fftjet/RecombinationAlgFactory.hh"
00030
00031
00032 #include "FWCore/Framework/interface/MakerMacros.h"
00033 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00034
00035
00036 #include "DataFormats/Common/interface/View.h"
00037 #include "DataFormats/Common/interface/Handle.h"
00038 #include "DataFormats/VertexReco/interface/Vertex.h"
00039 #include "DataFormats/JetReco/interface/FFTCaloJetCollection.h"
00040 #include "DataFormats/JetReco/interface/FFTGenJetCollection.h"
00041 #include "DataFormats/JetReco/interface/FFTPFJetCollection.h"
00042 #include "DataFormats/JetReco/interface/FFTJPTJetCollection.h"
00043 #include "DataFormats/JetReco/interface/FFTBasicJetCollection.h"
00044 #include "DataFormats/JetReco/interface/FFTTrackJetCollection.h"
00045 #include "DataFormats/Candidate/interface/Candidate.h"
00046 #include "DataFormats/JetReco/interface/FFTJetProducerSummary.h"
00047
00048 #include "RecoJets/FFTJetProducers/interface/FFTJetParameterParser.h"
00049
00050 #include "RecoJets/FFTJetAlgorithms/interface/clusteringTreeConverters.h"
00051 #include "RecoJets/FFTJetAlgorithms/interface/jetConverters.h"
00052 #include "DataFormats/JetReco/interface/DiscretizedEnergyFlow.h"
00053
00054 #include "RecoJets/JetProducers/interface/JetSpecific.h"
00055
00056
00057 #define make_param(type, varname) const \
00058 type & varname (ps.getParameter< type >( #varname ))
00059
00060 #define init_param(type, varname) varname (ps.getParameter< type >( #varname ))
00061
00062
00063
00064
00065
00066
00067
00068
00069 #define jet_type_switch(method, arg1, arg2) do {\
00070 switch (jetType)\
00071 {\
00072 case CALOJET:\
00073 method <reco::CaloJet> ( arg1 , arg2 );\
00074 break;\
00075 case PFJET:\
00076 method <reco::PFJet> ( arg1 , arg2 );\
00077 break;\
00078 case GENJET:\
00079 method <reco::GenJet> ( arg1 , arg2 );\
00080 break;\
00081 case TRACKJET:\
00082 method <reco::TrackJet> ( arg1 , arg2 );\
00083 break;\
00084 case BASICJET:\
00085 method <reco::BasicJet> ( arg1 , arg2 );\
00086 break;\
00087 default:\
00088 assert(!"ERROR in FFTJetProducer : invalid jet type."\
00089 " This is a bug. Please report.");\
00090 }\
00091 } while(0);
00092
00093 using namespace fftjetcms;
00094
00095 FFTJetProducer::Resolution FFTJetProducer::parse_resolution(
00096 const std::string& name)
00097 {
00098 if (!name.compare("fixed"))
00099 return FIXED;
00100 else if (!name.compare("maximallyStable"))
00101 return MAXIMALLY_STABLE;
00102 else if (!name.compare("globallyAdaptive"))
00103 return GLOBALLY_ADAPTIVE;
00104 else if (!name.compare("locallyAdaptive"))
00105 return LOCALLY_ADAPTIVE;
00106 else
00107 throw cms::Exception("FFTJetBadConfig")
00108 << "Invalid resolution specification \""
00109 << name << "\"" << std::endl;
00110 }
00111
00112
00113 template <typename T>
00114 void FFTJetProducer::makeProduces(
00115 const std::string& alias, const std::string& tag)
00116 {
00117 produces<std::vector<reco::FFTAnyJet<T> > >(tag).setBranchAlias(alias);
00118 }
00119
00120
00121
00122
00123 FFTJetProducer::FFTJetProducer(const edm::ParameterSet& ps)
00124 : FFTJetInterface(ps),
00125 myConfiguration(ps),
00126 init_param(edm::InputTag, treeLabel),
00127 init_param(bool, useGriddedAlgorithm),
00128 init_param(bool, reuseExistingGrid),
00129 init_param(unsigned, maxIterations),
00130 init_param(unsigned, nJetsRequiredToConverge),
00131 init_param(double, convergenceDistance),
00132 init_param(bool, assignConstituents),
00133 init_param(bool, resumConstituents),
00134 init_param(bool, calculatePileup),
00135 init_param(bool, subtractPileup),
00136 init_param(bool, subtractPileupAs4Vec),
00137 init_param(edm::InputTag, pileupLabel),
00138 init_param(double, fixedScale),
00139 init_param(double, minStableScale),
00140 init_param(double, maxStableScale),
00141 init_param(double, stabilityAlpha),
00142 init_param(double, noiseLevel),
00143 init_param(unsigned, nClustersRequested),
00144 init_param(double, gridScanMaxEta),
00145 init_param(std::string, recombinationAlgorithm),
00146 init_param(bool, isCrisp),
00147 init_param(double, unlikelyBgWeight),
00148 init_param(double, recombinationDataCutoff),
00149 resolution(parse_resolution(ps.getParameter<std::string>("resolution"))),
00150
00151 minLevel(0),
00152 maxLevel(0),
00153 usedLevel(0),
00154 unused(0.0),
00155 iterationsPerformed(1U),
00156 constituents(200)
00157 {
00158
00159 if (resumConstituents && !assignConstituents)
00160 throw cms::Exception("FFTJetBadConfig")
00161 << "Can't resum constituents if they are not assigned"
00162 << std::endl;
00163
00164 produces<reco::FFTJetProducerSummary>(outputLabel);
00165 const std::string alias(ps.getUntrackedParameter<std::string>(
00166 "alias", outputLabel));
00167 jet_type_switch(makeProduces, alias, outputLabel);
00168
00169
00170
00171
00172 iniScales = fftjet_ScaleSet_parser(
00173 ps.getParameter<edm::ParameterSet>("InitialScales"));
00174 checkConfig(iniScales, "invalid set of scales");
00175 std::sort(iniScales->begin(), iniScales->end(), std::greater<double>());
00176
00177
00178
00179
00180
00181 }
00182
00183
00184 FFTJetProducer::~FFTJetProducer()
00185 {
00186 }
00187
00188
00189
00190
00191 template<class Real>
00192 void FFTJetProducer::loadSparseTreeData(const edm::Event& iEvent)
00193 {
00194 typedef reco::PattRecoTree<Real,reco::PattRecoPeak<Real> > StoredTree;
00195
00196
00197 edm::Handle<StoredTree> input;
00198 iEvent.getByLabel(treeLabel, input);
00199
00200 if (!input->isSparse())
00201 throw cms::Exception("FFTJetBadConfig")
00202 << "The stored clustering tree is not sparse" << std::endl;
00203
00204 sparsePeakTreeFromStorable(*input, iniScales.get(),
00205 getEventScale(), &sparseTree);
00206 sparseTree.sortNodes();
00207 }
00208
00209
00210 void FFTJetProducer::selectPreclusters(
00211 const SparseTree& tree,
00212 const fftjet::Functor1<bool,fftjet::Peak>& peakSelector,
00213 std::vector<fftjet::Peak>* preclusters)
00214 {
00215 nodes.clear();
00216 selectTreeNodes(tree, peakSelector, &nodes);
00217
00218
00219 const unsigned nNodes = nodes.size();
00220 const SparseTree::NodeId* pnodes = nNodes ? &nodes[0] : 0;
00221 preclusters->reserve(nNodes);
00222 for (unsigned i=0; i<nNodes; ++i)
00223 preclusters->push_back(
00224 sparseTree.uncheckedNode(pnodes[i]).getCluster());
00225
00226
00227
00228 fftjet::Peak* clusters = nNodes ? &(*preclusters)[0] : 0;
00229 for (unsigned i=0; i<nNodes; ++i)
00230 {
00231 clusters[i].setCode(pnodes[i]);
00232 clusters[i].setStatus(resolution);
00233 }
00234 }
00235
00236
00237 void FFTJetProducer::selectTreeNodes(
00238 const SparseTree& tree,
00239 const fftjet::Functor1<bool,fftjet::Peak>& peakSelect,
00240 std::vector<SparseTree::NodeId>* mynodes)
00241 {
00242 minLevel = maxLevel = usedLevel = 0;
00243
00244
00245
00246 switch (resolution)
00247 {
00248 case FIXED:
00249 {
00250 usedLevel = tree.getLevel(fixedScale);
00251 tree.getPassingNodes(usedLevel, peakSelect, mynodes);
00252 }
00253 break;
00254
00255 case MAXIMALLY_STABLE:
00256 {
00257 const unsigned minStartingLevel = maxStableScale > 0.0 ?
00258 tree.getLevel(maxStableScale) : 0;
00259 const unsigned maxStartingLevel = minStableScale > 0.0 ?
00260 tree.getLevel(minStableScale) : UINT_MAX;
00261
00262 if (tree.stableClusterCount(
00263 peakSelect, &minLevel, &maxLevel, stabilityAlpha,
00264 minStartingLevel, maxStartingLevel))
00265 {
00266 usedLevel = (minLevel + maxLevel)/2;
00267 tree.getPassingNodes(usedLevel, peakSelect, mynodes);
00268 }
00269 }
00270 break;
00271
00272 case GLOBALLY_ADAPTIVE:
00273 {
00274 const bool stable = tree.clusterCountLevels(
00275 nClustersRequested, peakSelect, &minLevel, &maxLevel);
00276 if (minLevel || maxLevel)
00277 {
00278 usedLevel = (minLevel + maxLevel)/2;
00279 if (!stable)
00280 {
00281 const int maxlev = tree.maxStoredLevel();
00282 bool levelFound = false;
00283 for (int delta=0; delta<=maxlev && !levelFound; ++delta)
00284 for (int ifac=1; ifac>-2 && !levelFound; ifac-=2)
00285 {
00286 const int level = usedLevel + ifac*delta;
00287 if (level > 0 && level <= maxlev)
00288 if (occupancy[level] == nClustersRequested)
00289 {
00290 usedLevel = level;
00291 levelFound = true;
00292 }
00293 }
00294 assert(levelFound);
00295 }
00296 }
00297 else
00298 {
00299
00300
00301 usedLevel = 1;
00302 const unsigned occ1 = occupancy[1];
00303 if (nClustersRequested >= occ1)
00304 {
00305 const unsigned maxlev = tree.maxStoredLevel();
00306 if (nClustersRequested > occupancy[maxlev])
00307 usedLevel = maxlev;
00308 else
00309 {
00310
00311
00312 unsigned bestDelta = nClustersRequested > occ1 ?
00313 nClustersRequested - occ1 : occ1 - nClustersRequested;
00314 for (unsigned level=2; level<=maxlev; ++level)
00315 {
00316 const unsigned n = occupancy[level];
00317 const unsigned d = nClustersRequested > n ?
00318 nClustersRequested - n : n - nClustersRequested;
00319 if (d < bestDelta)
00320 {
00321 bestDelta = d;
00322 usedLevel = level;
00323 }
00324 }
00325 }
00326 }
00327 }
00328 tree.getPassingNodes(usedLevel, peakSelect, mynodes);
00329 }
00330 break;
00331
00332 case LOCALLY_ADAPTIVE:
00333 {
00334 usedLevel = tree.getLevel(fixedScale);
00335 tree.getMagS2OptimalNodes(peakSelect, nClustersRequested,
00336 usedLevel, mynodes, &thresholds);
00337 }
00338 break;
00339
00340 default:
00341 assert(!"ERROR in FFTJetProducer::selectTreeNodes : "
00342 "should never get here! This is a bug. Please report.");
00343 }
00344 }
00345
00346
00347 void FFTJetProducer::prepareRecombinationScales()
00348 {
00349 const unsigned nClus = preclusters.size();
00350 if (nClus)
00351 {
00352 fftjet::Peak* clus = &preclusters[0];
00353 fftjet::Functor1<double,fftjet::Peak>&
00354 scaleCalc(*recoScaleCalcPeak);
00355 fftjet::Functor1<double,fftjet::Peak>&
00356 ratioCalc(*recoScaleRatioCalcPeak);
00357 fftjet::Functor1<double,fftjet::Peak>&
00358 factorCalc(*memberFactorCalcPeak);
00359
00360 for (unsigned i=0; i<nClus; ++i)
00361 {
00362 clus[i].setRecoScale(scaleCalc(clus[i]));
00363 clus[i].setRecoScaleRatio(ratioCalc(clus[i]));
00364 clus[i].setMembershipFactor(factorCalc(clus[i]));
00365 }
00366 }
00367 }
00368
00369
00370 void FFTJetProducer::buildGridAlg()
00371 {
00372 int minBin = energyFlow->getEtaBin(-gridScanMaxEta);
00373 if (minBin < 0)
00374 minBin = 0;
00375 int maxBin = energyFlow->getEtaBin(gridScanMaxEta) + 1;
00376 if (maxBin < 0)
00377 maxBin = 0;
00378
00379 fftjet::DefaultRecombinationAlgFactory<
00380 Real,VectorLike,BgData,VBuilder> factory;
00381 if (factory[recombinationAlgorithm] == NULL)
00382 throw cms::Exception("FFTJetBadConfig")
00383 << "Invalid grid recombination algorithm \""
00384 << recombinationAlgorithm << "\"" << std::endl;
00385 gridAlg = std::auto_ptr<GridAlg>(
00386 factory[recombinationAlgorithm]->create(
00387 jetMembershipFunction.get(),
00388 bgMembershipFunction.get(),
00389 unlikelyBgWeight, recombinationDataCutoff,
00390 isCrisp, false, assignConstituents, minBin, maxBin));
00391 }
00392
00393
00394 bool FFTJetProducer::loadEnergyFlow(
00395 const edm::Event& iEvent, const edm::InputTag& label,
00396 std::auto_ptr<fftjet::Grid2d<fftjetcms::Real> >& flow)
00397 {
00398 edm::Handle<reco::DiscretizedEnergyFlow> input;
00399 iEvent.getByLabel(label, input);
00400
00401
00402 bool rebuildGrid = flow.get() == NULL;
00403 if (!rebuildGrid)
00404 rebuildGrid =
00405 !(flow->nEta() == input->nEtaBins() &&
00406 flow->nPhi() == input->nPhiBins() &&
00407 flow->etaMin() == input->etaMin() &&
00408 flow->etaMax() == input->etaMax() &&
00409 flow->phiBin0Edge() == input->phiBin0Edge());
00410 if (rebuildGrid)
00411 {
00412
00413 flow = std::auto_ptr<fftjet::Grid2d<Real> >(
00414 new fftjet::Grid2d<Real>(
00415 input->nEtaBins(), input->etaMin(), input->etaMax(),
00416 input->nPhiBins(), input->phiBin0Edge(), input->title()));
00417 }
00418 flow->blockSet(input->data(), input->nEtaBins(), input->nPhiBins());
00419 return rebuildGrid;
00420 }
00421
00422
00423 bool FFTJetProducer::checkConvergence(const std::vector<RecoFFTJet>& previous,
00424 std::vector<RecoFFTJet>& nextSet)
00425 {
00426 fftjet::Functor2<double,RecoFFTJet,RecoFFTJet>&
00427 distanceCalc(*jetDistanceCalc);
00428
00429 const unsigned nJets = previous.size();
00430 const RecoFFTJet* prev = &previous[0];
00431 RecoFFTJet* next = &nextSet[0];
00432
00433
00434 bool converged = true;
00435 for (unsigned i=0; i<nJets; ++i)
00436 {
00437 const double d = distanceCalc(prev[i], next[i]);
00438 next[i].setConvergenceDistance(d);
00439 if (i < nJetsRequiredToConverge && d > convergenceDistance)
00440 converged = false;
00441 }
00442
00443 return converged;
00444 }
00445
00446
00447 unsigned FFTJetProducer::iterateJetReconstruction()
00448 {
00449 fftjet::Functor1<double,RecoFFTJet>& scaleCalc(*recoScaleCalcJet);
00450 fftjet::Functor1<double,RecoFFTJet>& ratioCalc(*recoScaleRatioCalcJet);
00451 fftjet::Functor1<double,RecoFFTJet>& factorCalc(*memberFactorCalcJet);
00452
00453 const unsigned nJets = recoJets.size();
00454
00455 unsigned iterNum = 1U;
00456 bool converged = false;
00457 for (; iterNum<maxIterations && !converged; ++iterNum)
00458 {
00459
00460 const RecoFFTJet* jets = &recoJets[0];
00461 iterPreclusters.clear();
00462 iterPreclusters.reserve(nJets);
00463 for (unsigned i=0; i<nJets; ++i)
00464 {
00465 const RecoFFTJet& jet(jets[i]);
00466 fftjet::Peak p(jet.precluster());
00467 p.setEtaPhi(jet.vec().Eta(), jet.vec().Phi());
00468 p.setRecoScale(scaleCalc(jet));
00469 p.setRecoScaleRatio(ratioCalc(jet));
00470 p.setMembershipFactor(factorCalc(jet));
00471 iterPreclusters.push_back(p);
00472 }
00473
00474
00475 int status = 0;
00476 if (useGriddedAlgorithm)
00477 status = gridAlg->run(iterPreclusters, *energyFlow,
00478 &noiseLevel, 1U, 1U,
00479 &iterJets, &unclustered, &unused);
00480 else
00481 status = recoAlg->run(iterPreclusters, eventData, &noiseLevel, 1U,
00482 &iterJets, &unclustered, &unused);
00483 if (status)
00484 throw cms::Exception("FFTJetInterface")
00485 << "FFTJet algorithm failed" << std::endl;
00486 assert(iterJets.size() == nJets);
00487
00488
00489 converged = checkConvergence(recoJets, iterJets);
00490
00491
00492 iterJets.swap(recoJets);
00493 }
00494
00495
00496 assert(preclusters.size() == nJets);
00497 RecoFFTJet* jets = &recoJets[0];
00498 for (unsigned i=0; i<nJets; ++i)
00499 {
00500 const fftjet::Peak& oldp(preclusters[i]);
00501 jets[i].setPeakEtaPhi(oldp.eta(), oldp.phi());
00502 }
00503
00504
00505
00506
00507
00508 if (!converged)
00509 ++iterNum;
00510
00511 return iterNum;
00512 }
00513
00514
00515 void FFTJetProducer::determineGriddedConstituents()
00516 {
00517 const unsigned nJets = recoJets.size();
00518 const unsigned* clusterMask = gridAlg->getClusterMask();
00519 const int nEta = gridAlg->getLastNEta();
00520 const int nPhi = gridAlg->getLastNPhi();
00521 const fftjet::Grid2d<Real>& g(*energyFlow);
00522
00523 const unsigned nInputs = eventData.size();
00524 const VectorLike* inp = nInputs ? &eventData[0] : 0;
00525 const unsigned* candIdx = nInputs ? &candidateIndex[0] : 0;
00526 for (unsigned i=0; i<nInputs; ++i)
00527 {
00528 const VectorLike& item(inp[i]);
00529 const int iPhi = g.getPhiBin(item.Phi());
00530 const int iEta = g.getEtaBin(item.Eta());
00531 const unsigned mask = iEta >= 0 && iEta < nEta ?
00532 clusterMask[iEta*nPhi + iPhi] : 0;
00533 assert(mask <= nJets);
00534 constituents[mask].push_back(inputCollection->ptrAt(candIdx[i]));
00535 }
00536 }
00537
00538
00539 void FFTJetProducer::determineVectorConstituents()
00540 {
00541 const unsigned nJets = recoJets.size();
00542 const unsigned* clusterMask = recoAlg->getClusterMask();
00543 const unsigned maskLength = recoAlg->getLastNData();
00544 assert(maskLength == eventData.size());
00545
00546 const unsigned* candIdx = maskLength ? &candidateIndex[0] : 0;
00547 for (unsigned i=0; i<maskLength; ++i)
00548 {
00549
00550
00551
00552
00553 const unsigned mask = clusterMask[i];
00554 assert(mask <= nJets);
00555 constituents[mask].push_back(inputCollection->ptrAt(candIdx[i]));
00556 }
00557 }
00558
00559
00560
00561
00562 template <typename T>
00563 void FFTJetProducer::writeJets(edm::Event& iEvent,
00564 const edm::EventSetup& iSetup)
00565 {
00566 using namespace reco;
00567
00568 typedef FFTAnyJet<T> OutputJet;
00569 typedef std::vector<OutputJet> OutputCollection;
00570
00571
00572
00573
00574 double cellArea = useGriddedAlgorithm &&
00575 recombinationDataCutoff < 0.0 ?
00576 energyFlow->etaBinWidth() * energyFlow->phiBinWidth() : 0.0;
00577
00578 if (calculatePileup)
00579 cellArea = pileupEnergyFlow->etaBinWidth() *
00580 pileupEnergyFlow->phiBinWidth();
00581
00582
00583 std::auto_ptr<OutputCollection> jets(new OutputCollection());
00584 const unsigned nJets = recoJets.size();
00585 jets->reserve(nJets);
00586
00587 for (unsigned ijet=0; ijet<nJets; ++ijet)
00588 {
00589 RecoFFTJet& myjet(recoJets[ijet]);
00590
00591
00592 VectorLike jet4vec(myjet.vec());
00593 if (resumConstituents)
00594 {
00595 VectorLike sum(0.0, 0.0, 0.0, 0.0);
00596 const unsigned nCon = constituents[ijet+1].size();
00597 const reco::CandidatePtr* cn = nCon ? &constituents[ijet+1][0] : 0;
00598 for (unsigned i=0; i<nCon; ++i)
00599 sum += cn[i]->p4();
00600 jet4vec = sum;
00601 setJetStatusBit(&myjet, CONSTITUENTS_RESUMMED, true);
00602 }
00603
00604
00605 if (calculatePileup && subtractPileup)
00606 {
00607 if (subtractPileupAs4Vec)
00608 {
00609 jet4vec -= pileup[ijet];
00610 setJetStatusBit(&myjet, PILEUP_SUBTRACTED_4VEC, true);
00611 }
00612 else
00613 {
00614 const double pt = jet4vec.Pt();
00615 if (pt > 0.0)
00616 {
00617 const double pileupPt = pileup[ijet].Pt();
00618 jet4vec *= ((pt - pileupPt)/pt);
00619 }
00620 setJetStatusBit(&myjet, PILEUP_SUBTRACTED_PT, true);
00621 }
00622 }
00623
00624
00625
00626
00627 T jet;
00628 writeSpecific(jet, jet4vec, vertexUsed(),
00629 constituents[ijet+1], iSetup);
00630
00631
00632 double ncells = myjet.ncells();
00633 if (calculatePileup)
00634 {
00635 ncells = cellCountsVec[ijet];
00636 setJetStatusBit(&myjet, PILEUP_CALCULATED, true);
00637 }
00638 jet.setJetArea(cellArea*ncells);
00639
00640
00641 FFTJet<float> fj(jetToStorable<float>(myjet));
00642 fj.setFourVec(jet4vec);
00643 if (calculatePileup)
00644 {
00645 fj.setPileup(pileup[ijet]);
00646 fj.setNCells(ncells);
00647 }
00648 jets->push_back(OutputJet(jet, fj));
00649 }
00650
00651
00652 iEvent.put(jets, outputLabel);
00653 }
00654
00655
00656 void FFTJetProducer::saveResults(edm::Event& ev, const edm::EventSetup& iSetup)
00657 {
00658
00659 jet_type_switch(writeJets, ev, iSetup);
00660
00661
00662 VectorLike unclusE(unclustered);
00663 if (resumConstituents)
00664 {
00665 VectorLike sum(0.0, 0.0, 0.0, 0.0);
00666 const unsigned nCon = constituents[0].size();
00667 const reco::CandidatePtr* cn = nCon ? &constituents[0][0] : 0;
00668 for (unsigned i=0; i<nCon; ++i)
00669 sum += cn[i]->p4();
00670 unclusE = sum;
00671 }
00672
00673
00674 const double minScale = minLevel ? sparseTree.getScale(minLevel) : 0.0;
00675 const double maxScale = maxLevel ? sparseTree.getScale(maxLevel) : 0.0;
00676 const double scaleUsed = usedLevel ? sparseTree.getScale(usedLevel) : 0.0;
00677
00678 std::auto_ptr<reco::FFTJetProducerSummary> summary(
00679 new reco::FFTJetProducerSummary(
00680 thresholds, occupancy, unclusE,
00681 constituents[0], unused,
00682 minScale, maxScale, scaleUsed,
00683 preclusters.size(), iterationsPerformed,
00684 iterationsPerformed == 1U ||
00685 iterationsPerformed <= maxIterations));
00686 ev.put(summary, outputLabel);
00687 }
00688
00689
00690
00691 void FFTJetProducer::produce(edm::Event& iEvent,
00692 const edm::EventSetup& iSetup)
00693 {
00694
00695 if (storeInSinglePrecision())
00696 loadSparseTreeData<float>(iEvent);
00697 else
00698 loadSparseTreeData<double>(iEvent);
00699
00700
00701 if (assignConstituents || !(useGriddedAlgorithm && reuseExistingGrid))
00702 loadInputCollection(iEvent);
00703
00704
00705 if (useGriddedAlgorithm)
00706 {
00707 if (reuseExistingGrid)
00708 {
00709 if (loadEnergyFlow(iEvent, treeLabel, energyFlow))
00710 buildGridAlg();
00711 }
00712 else
00713 discretizeEnergyFlow();
00714 }
00715
00716
00717 sparseTree.occupancyInScaleSpace(*peakSelector, &occupancy);
00718
00719
00720 preclusters.clear();
00721 selectPreclusters(sparseTree, *peakSelector, &preclusters);
00722
00723
00724 prepareRecombinationScales();
00725
00726
00727
00728
00729 assignMembershipFunctions(&preclusters);
00730
00731
00732 int status = 0;
00733 if (useGriddedAlgorithm)
00734 status = gridAlg->run(preclusters, *energyFlow,
00735 &noiseLevel, 1U, 1U,
00736 &recoJets, &unclustered, &unused);
00737 else
00738 status = recoAlg->run(preclusters, eventData, &noiseLevel, 1U,
00739 &recoJets, &unclustered, &unused);
00740 if (status)
00741 throw cms::Exception("FFTJetInterface")
00742 << "FFTJet algorithm failed (first iteration)" << std::endl;
00743
00744
00745 if (maxIterations > 1U && !recoJets.empty())
00746 iterationsPerformed = iterateJetReconstruction();
00747 else
00748 iterationsPerformed = 1U;
00749
00750
00751
00752 const unsigned nJets = recoJets.size();
00753 if (constituents.size() <= nJets)
00754 constituents.resize(nJets + 1U);
00755 if (assignConstituents)
00756 {
00757 for (unsigned i=0; i<=nJets; ++i)
00758 constituents[i].clear();
00759 if (useGriddedAlgorithm)
00760 determineGriddedConstituents();
00761 else
00762 determineVectorConstituents();
00763 }
00764
00765
00766 if (calculatePileup)
00767 {
00768 determinePileupDensity(iEvent, pileupLabel, pileupEnergyFlow);
00769 determinePileup();
00770 assert(pileup.size() == recoJets.size());
00771 }
00772
00773
00774 saveResults(iEvent, iSetup);
00775 }
00776
00777
00778 std::auto_ptr<fftjet::Functor1<bool,fftjet::Peak> >
00779 FFTJetProducer::parse_peakSelector(const edm::ParameterSet& ps)
00780 {
00781 return fftjet_PeakSelector_parser(
00782 ps.getParameter<edm::ParameterSet>("PeakSelectorConfiguration"));
00783 }
00784
00785
00786
00787 std::auto_ptr<fftjet::ScaleSpaceKernel>
00788 FFTJetProducer::parse_jetMembershipFunction(const edm::ParameterSet& ps)
00789 {
00790 return fftjet_MembershipFunction_parser(
00791 ps.getParameter<edm::ParameterSet>("jetMembershipFunction"));
00792 }
00793
00794
00795
00796 std::auto_ptr<AbsBgFunctor>
00797 FFTJetProducer::parse_bgMembershipFunction(const edm::ParameterSet& ps)
00798 {
00799 return fftjet_BgFunctor_parser(
00800 ps.getParameter<edm::ParameterSet>("bgMembershipFunction"));
00801 }
00802
00803
00804
00805 std::auto_ptr<fftjet::Functor1<double,fftjet::Peak> >
00806 FFTJetProducer::parse_recoScaleCalcPeak(const edm::ParameterSet& ps)
00807 {
00808 return fftjet_PeakFunctor_parser(
00809 ps.getParameter<edm::ParameterSet>("recoScaleCalcPeak"));
00810 }
00811
00812
00813
00814 std::auto_ptr<fftjetcms::AbsPileupCalculator>
00815 FFTJetProducer::parse_pileupDensityCalc(const edm::ParameterSet& ps)
00816 {
00817 return fftjet_PileupCalculator_parser(
00818 ps.getParameter<edm::ParameterSet>("pileupDensityCalc"));
00819 }
00820
00821
00822
00823 std::auto_ptr<fftjet::Functor1<double,fftjet::Peak> >
00824 FFTJetProducer::parse_recoScaleRatioCalcPeak(const edm::ParameterSet& ps)
00825 {
00826 return fftjet_PeakFunctor_parser(
00827 ps.getParameter<edm::ParameterSet>("recoScaleRatioCalcPeak"));
00828 }
00829
00830
00831
00832 std::auto_ptr<fftjet::Functor1<double,fftjet::Peak> >
00833 FFTJetProducer::parse_memberFactorCalcPeak(const edm::ParameterSet& ps)
00834 {
00835 return fftjet_PeakFunctor_parser(
00836 ps.getParameter<edm::ParameterSet>("memberFactorCalcPeak"));
00837 }
00838
00839
00840 std::auto_ptr<fftjet::Functor1<double,FFTJetProducer::RecoFFTJet> >
00841 FFTJetProducer::parse_recoScaleCalcJet(const edm::ParameterSet& ps)
00842 {
00843 return fftjet_JetFunctor_parser(
00844 ps.getParameter<edm::ParameterSet>("recoScaleCalcJet"));
00845 }
00846
00847
00848 std::auto_ptr<fftjet::Functor1<double,FFTJetProducer::RecoFFTJet> >
00849 FFTJetProducer::parse_recoScaleRatioCalcJet(const edm::ParameterSet& ps)
00850 {
00851 return fftjet_JetFunctor_parser(
00852 ps.getParameter<edm::ParameterSet>("recoScaleRatioCalcJet"));
00853 }
00854
00855
00856 std::auto_ptr<fftjet::Functor1<double,FFTJetProducer::RecoFFTJet> >
00857 FFTJetProducer::parse_memberFactorCalcJet(const edm::ParameterSet& ps)
00858 {
00859 return fftjet_JetFunctor_parser(
00860 ps.getParameter<edm::ParameterSet>("memberFactorCalcJet"));
00861 }
00862
00863
00864 std::auto_ptr<fftjet::Functor2<
00865 double,FFTJetProducer::RecoFFTJet,FFTJetProducer::RecoFFTJet> >
00866 FFTJetProducer::parse_jetDistanceCalc(const edm::ParameterSet& ps)
00867 {
00868 return fftjet_JetDistance_parser(
00869 ps.getParameter<edm::ParameterSet>("jetDistanceCalc"));
00870 }
00871
00872
00873 void FFTJetProducer::assignMembershipFunctions(std::vector<fftjet::Peak>*)
00874 {
00875 }
00876
00877
00878
00879 void FFTJetProducer::beginJob()
00880 {
00881 const edm::ParameterSet& ps(myConfiguration);
00882
00883
00884 peakSelector = parse_peakSelector(ps);
00885 checkConfig(peakSelector, "invalid peak selector");
00886
00887 jetMembershipFunction = parse_jetMembershipFunction(ps);
00888 checkConfig(jetMembershipFunction, "invalid jet membership function");
00889
00890 bgMembershipFunction = parse_bgMembershipFunction(ps);
00891 checkConfig(bgMembershipFunction, "invalid noise membership function");
00892
00893
00894 if (!useGriddedAlgorithm)
00895 {
00896 fftjet::DefaultVectorRecombinationAlgFactory<
00897 VectorLike,BgData,VBuilder> factory;
00898 if (factory[recombinationAlgorithm] == NULL)
00899 throw cms::Exception("FFTJetBadConfig")
00900 << "Invalid vector recombination algorithm \""
00901 << recombinationAlgorithm << "\"" << std::endl;
00902 recoAlg = std::auto_ptr<RecoAlg>(
00903 factory[recombinationAlgorithm]->create(
00904 jetMembershipFunction.get(),
00905 &VectorLike::Et, &VectorLike::Eta, &VectorLike::Phi,
00906 bgMembershipFunction.get(),
00907 unlikelyBgWeight, isCrisp, false, assignConstituents));
00908 }
00909 else if (!reuseExistingGrid)
00910 {
00911 energyFlow = fftjet_Grid2d_parser(
00912 ps.getParameter<edm::ParameterSet>("GridConfiguration"));
00913 checkConfig(energyFlow, "invalid discretization grid");
00914 buildGridAlg();
00915 }
00916
00917
00918 if (calculatePileup)
00919 {
00920 pileupEnergyFlow = fftjet_Grid2d_parser(
00921 ps.getParameter<edm::ParameterSet>("PileupGridConfiguration"));
00922 checkConfig(pileupEnergyFlow, "invalid pileup density grid");
00923
00924 pileupDensityCalc = parse_pileupDensityCalc(ps);
00925 checkConfig(pileupDensityCalc, "invalid pile-up density calculator");
00926 }
00927
00928
00929 recoScaleCalcPeak = parse_recoScaleCalcPeak(ps);
00930 checkConfig(recoScaleCalcPeak, "invalid spec for the "
00931 "reconstruction scale calculator from peaks");
00932
00933
00934 recoScaleRatioCalcPeak = parse_recoScaleRatioCalcPeak(ps);
00935 checkConfig(recoScaleRatioCalcPeak, "invalid spec for the "
00936 "reconstruction scale ratio calculator from peaks");
00937
00938
00939 memberFactorCalcPeak = parse_memberFactorCalcPeak(ps);
00940 checkConfig(memberFactorCalcPeak, "invalid spec for the "
00941 "membership function factor calculator from peaks");
00942
00943 if (maxIterations > 1)
00944 {
00945
00946 recoScaleCalcJet = parse_recoScaleCalcJet(ps);
00947 checkConfig(recoScaleCalcJet, "invalid spec for the "
00948 "reconstruction scale calculator from jets");
00949
00950 recoScaleRatioCalcJet = parse_recoScaleRatioCalcJet(ps);
00951 checkConfig(recoScaleRatioCalcJet, "invalid spec for the "
00952 "reconstruction scale ratio calculator from jets");
00953
00954 memberFactorCalcJet = parse_memberFactorCalcJet(ps);
00955 checkConfig(memberFactorCalcJet, "invalid spec for the "
00956 "membership function factor calculator from jets");
00957
00958 jetDistanceCalc = parse_jetDistanceCalc(ps);
00959 checkConfig(memberFactorCalcJet, "invalid spec for the "
00960 "jet distance calculator");
00961 }
00962 }
00963
00964
00965 void FFTJetProducer::setJetStatusBit(RecoFFTJet* jet,
00966 const int mask, const bool value)
00967 {
00968 int status = jet->status();
00969 if (value)
00970 status |= mask;
00971 else
00972 status &= ~mask;
00973 jet->setStatus(status);
00974 }
00975
00976
00977 void FFTJetProducer::determinePileupDensity(
00978 const edm::Event& iEvent, const edm::InputTag& label,
00979 std::auto_ptr<fftjet::Grid2d<fftjetcms::Real> >& density)
00980 {
00981 edm::Handle<reco::FFTJetPileupSummary> summary;
00982 iEvent.getByLabel(label, summary);
00983
00984 const reco::FFTJetPileupSummary& s(*summary);
00985 const AbsPileupCalculator& calc(*pileupDensityCalc);
00986 const bool phiDependent = calc.isPhiDependent();
00987
00988 fftjet::Grid2d<Real>& g(*density);
00989 const unsigned nEta = g.nEta();
00990 const unsigned nPhi = g.nPhi();
00991
00992 for (unsigned ieta=0; ieta<nEta; ++ieta)
00993 {
00994 const double eta(g.etaBinCenter(ieta));
00995
00996 if (phiDependent)
00997 {
00998 for (unsigned iphi=0; iphi<nPhi; ++iphi)
00999 {
01000 const double phi(g.phiBinCenter(iphi));
01001 g.uncheckedSetBin(ieta, iphi, calc(eta, phi, s));
01002 }
01003 }
01004 else
01005 {
01006 const double pil = calc(eta, 0.0, s);
01007 for (unsigned iphi=0; iphi<nPhi; ++iphi)
01008 g.uncheckedSetBin(ieta, iphi, pil);
01009 }
01010 }
01011 }
01012
01013
01014 void FFTJetProducer::determinePileup()
01015 {
01016
01017 if (!isCrisp)
01018 assert(!"Pile-up subtraction for fuzzy clustering "
01019 "is not implemented yet");
01020
01021
01022 const unsigned nJets = recoJets.size();
01023 pileup.resize(nJets);
01024 if (nJets == 0)
01025 return;
01026 const VectorLike zero;
01027 for (unsigned i=0; i<nJets; ++i)
01028 pileup[i] = zero;
01029
01030
01031 const fftjet::Grid2d<Real>& g(*pileupEnergyFlow);
01032 const unsigned nEta = g.nEta();
01033 const unsigned nPhi = g.nPhi();
01034 const double cellArea = g.etaBinWidth() * g.phiBinWidth();
01035
01036
01037 fftjet::Functor1<double,RecoFFTJet>& scaleCalc(*recoScaleCalcJet);
01038 fftjet::Functor1<double,RecoFFTJet>& ratioCalc(*recoScaleRatioCalcJet);
01039 fftjet::Functor1<double,RecoFFTJet>& factorCalc(*memberFactorCalcJet);
01040
01041
01042 memFcns2dVec.resize(nJets);
01043 fftjet::AbsKernel2d** memFcns2d = &memFcns2dVec[0];
01044
01045 doubleBuf.resize(nJets*4U + nJets*nPhi);
01046 double* recoScales = &doubleBuf[0];
01047 double* recoScaleRatios = recoScales + nJets;
01048 double* memFactors = recoScaleRatios + nJets;
01049 double* dEta = memFactors + nJets;
01050 double* dPhiBuf = dEta + nJets;
01051
01052 cellCountsVec.resize(nJets);
01053 unsigned* cellCounts = &cellCountsVec[0];
01054
01055
01056 for (unsigned ijet=0; ijet<nJets; ++ijet)
01057 {
01058 const RecoFFTJet& jet(recoJets[ijet]);
01059 const fftjet::Peak& peak(jet.precluster());
01060
01061
01062
01063 fftjet::AbsMembershipFunction* m3d =
01064 dynamic_cast<fftjet::AbsMembershipFunction*>(
01065 peak.membershipFunction());
01066 if (m3d == 0)
01067 m3d = dynamic_cast<fftjet::AbsMembershipFunction*>(
01068 jetMembershipFunction.get());
01069 if (m3d)
01070 {
01071 assert(!"Pile-up subtraction for 3-d membership functions "
01072 "is not implemented yet");
01073 }
01074 else
01075 {
01076 fftjet::AbsKernel2d* m2d =
01077 dynamic_cast<fftjet::AbsKernel2d*>(
01078 peak.membershipFunction());
01079 if (m2d == 0)
01080 m2d = dynamic_cast<fftjet::AbsKernel2d*>(
01081 jetMembershipFunction.get());
01082 assert(m2d);
01083 memFcns2d[ijet] = m2d;
01084 }
01085 recoScales[ijet] = scaleCalc(jet);
01086 recoScaleRatios[ijet] = ratioCalc(jet);
01087 memFactors[ijet] = factorCalc(jet);
01088 cellCounts[ijet] = 0U;
01089
01090 const double jetPhi = jet.vec().Phi();
01091 for (unsigned iphi=0; iphi<nPhi; ++iphi)
01092 {
01093 double dphi = g.phiBinCenter(iphi) - jetPhi;
01094 while (dphi > M_PI)
01095 dphi -= (2.0*M_PI);
01096 while (dphi < -M_PI)
01097 dphi += (2.0*M_PI);
01098 dPhiBuf[iphi*nJets+ijet] = dphi;
01099 }
01100 }
01101
01102
01103
01104 VBuilder vMaker;
01105 for (unsigned ieta=0; ieta<nEta; ++ieta)
01106 {
01107 const double eta(g.etaBinCenter(ieta));
01108 const Real* databuf = g.data() + ieta*nPhi;
01109
01110
01111 for (unsigned ijet=0; ijet<nJets; ++ijet)
01112 dEta[ijet] = eta - recoJets[ijet].vec().Eta();
01113
01114 for (unsigned iphi=0; iphi<nPhi; ++iphi)
01115 {
01116 double maxW(0.0);
01117 unsigned maxWJet(nJets);
01118 const double* dPhi = dPhiBuf + iphi*nJets;
01119
01120 for (unsigned ijet=0; ijet<nJets; ++ijet)
01121 {
01122 if (recoScaleRatios[ijet] > 0.0)
01123 memFcns2d[ijet]->setScaleRatio(recoScaleRatios[ijet]);
01124 const double f = memFactors[ijet]*
01125 (*memFcns2d[ijet])(dEta[ijet], dPhi[ijet],
01126 recoScales[ijet]);
01127 if (f > maxW)
01128 {
01129 maxW = f;
01130 maxWJet = ijet;
01131 }
01132 }
01133
01134 if (maxWJet < nJets)
01135 {
01136 pileup[maxWJet] += vMaker(cellArea*databuf[iphi],
01137 eta, g.phiBinCenter(iphi));
01138 cellCounts[maxWJet]++;
01139 }
01140 }
01141 }
01142 }
01143
01144
01145
01146 void FFTJetProducer::endJob()
01147 {
01148 }
01149
01150
01151
01152 DEFINE_FWK_MODULE(FFTJetProducer);