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 "RecoJets/FFTJetAlgorithms/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(double, fixedScale),
00135 init_param(double, minStableScale),
00136 init_param(double, maxStableScale),
00137 init_param(double, stabilityAlpha),
00138 init_param(double, noiseLevel),
00139 init_param(unsigned, nClustersRequested),
00140 init_param(double, gridScanMaxEta),
00141 init_param(std::string, recombinationAlgorithm),
00142 init_param(bool, isCrisp),
00143 init_param(double, unlikelyBgWeight),
00144 init_param(double, recombinationDataCutoff),
00145 resolution(parse_resolution(ps.getParameter<std::string>("resolution"))),
00146
00147 minLevel(0),
00148 maxLevel(0),
00149 usedLevel(0),
00150 unused(0.0),
00151 iterationsPerformed(1U),
00152 constituents(200)
00153 {
00154
00155 if (resumConstituents && !assignConstituents)
00156 throw cms::Exception("FFTJetBadConfig")
00157 << "Can't resum constituents if they are not assigned"
00158 << std::endl;
00159
00160 produces<reco::FFTJetProducerSummary>(outputLabel);
00161 const std::string alias(ps.getUntrackedParameter<std::string>(
00162 "alias", outputLabel));
00163 jet_type_switch(makeProduces, alias, outputLabel);
00164
00165
00166
00167
00168 iniScales = fftjet_ScaleSet_parser(
00169 ps.getParameter<edm::ParameterSet>("InitialScales"));
00170 checkConfig(iniScales, "invalid set of scales");
00171 std::sort(iniScales->begin(), iniScales->end(), std::greater<double>());
00172
00173
00174
00175
00176
00177 }
00178
00179
00180 FFTJetProducer::~FFTJetProducer()
00181 {
00182 }
00183
00184
00185
00186
00187 template<class Real>
00188 void FFTJetProducer::loadSparseTreeData(const edm::Event& iEvent)
00189 {
00190 typedef reco::PattRecoTree<Real,reco::PattRecoPeak<Real> > StoredTree;
00191
00192
00193 edm::Handle<StoredTree> input;
00194 iEvent.getByLabel(treeLabel, input);
00195
00196 if (!input->isSparse())
00197 throw cms::Exception("FFTJetBadConfig")
00198 << "The stored clustering tree is not sparse" << std::endl;
00199
00200 sparsePeakTreeFromStorable(*input, iniScales.get(), getEventScale(), &sparseTree);
00201 sparseTree.sortNodes();
00202 }
00203
00204
00205 void FFTJetProducer::selectPreclusters(
00206 const SparseTree& tree,
00207 const fftjet::Functor1<bool,fftjet::Peak>& peakSelector,
00208 std::vector<fftjet::Peak>* preclusters)
00209 {
00210 nodes.clear();
00211 selectTreeNodes(tree, peakSelector, &nodes);
00212
00213
00214 const unsigned nNodes = nodes.size();
00215 const SparseTree::NodeId* pnodes = nNodes ? &nodes[0] : 0;
00216 preclusters->reserve(nNodes);
00217 for (unsigned i=0; i<nNodes; ++i)
00218 preclusters->push_back(
00219 sparseTree.uncheckedNode(pnodes[i]).getCluster());
00220
00221
00222 fftjet::Peak* clusters = nNodes ? &(*preclusters)[0] : 0;
00223 for (unsigned i=0; i<nNodes; ++i)
00224 clusters[i].setStatus(resolution);
00225 }
00226
00227
00228 void FFTJetProducer::selectTreeNodes(
00229 const SparseTree& tree,
00230 const fftjet::Functor1<bool,fftjet::Peak>& peakSelect,
00231 std::vector<SparseTree::NodeId>* mynodes)
00232 {
00233 minLevel = maxLevel = usedLevel = 0;
00234
00235
00236
00237 switch (resolution)
00238 {
00239 case FIXED:
00240 {
00241 usedLevel = tree.getLevel(fixedScale);
00242 tree.getPassingNodes(usedLevel, peakSelect, mynodes);
00243 }
00244 break;
00245
00246 case MAXIMALLY_STABLE:
00247 {
00248 const unsigned minStartingLevel = maxStableScale > 0.0 ?
00249 tree.getLevel(maxStableScale) : 0;
00250 const unsigned maxStartingLevel = minStableScale > 0.0 ?
00251 tree.getLevel(minStableScale) : UINT_MAX;
00252
00253 if (tree.stableClusterCount(
00254 peakSelect, &minLevel, &maxLevel, stabilityAlpha,
00255 minStartingLevel, maxStartingLevel))
00256 {
00257 usedLevel = (minLevel + maxLevel)/2;
00258 tree.getPassingNodes(usedLevel, peakSelect, mynodes);
00259 }
00260 }
00261 break;
00262
00263 case GLOBALLY_ADAPTIVE:
00264 {
00265 const bool stable = tree.clusterCountLevels(
00266 nClustersRequested, peakSelect, &minLevel, &maxLevel);
00267 if (minLevel || maxLevel)
00268 {
00269 usedLevel = (minLevel + maxLevel)/2;
00270 if (!stable)
00271 {
00272 const int maxlev = tree.maxStoredLevel();
00273 bool levelFound = false;
00274 for (int delta=0; delta<=maxlev && !levelFound; ++delta)
00275 for (int ifac=1; ifac>-2 && !levelFound; ifac-=2)
00276 {
00277 const int level = usedLevel + ifac*delta;
00278 if (level > 0 && level <= maxlev)
00279 if (occupancy[level] == nClustersRequested)
00280 {
00281 usedLevel = level;
00282 levelFound = true;
00283 }
00284 }
00285 assert(levelFound);
00286 }
00287 }
00288 else
00289 {
00290
00291
00292 usedLevel = 1;
00293 const unsigned occ1 = occupancy[1];
00294 if (nClustersRequested >= occ1)
00295 {
00296 const unsigned maxlev = tree.maxStoredLevel();
00297 if (nClustersRequested > occupancy[maxlev])
00298 usedLevel = maxlev;
00299 else
00300 {
00301
00302
00303 unsigned bestDelta = nClustersRequested > occ1 ?
00304 nClustersRequested - occ1 : occ1 - nClustersRequested;
00305 for (unsigned level=2; level<=maxlev; ++level)
00306 {
00307 const unsigned n = occupancy[level];
00308 const unsigned d = nClustersRequested > n ?
00309 nClustersRequested - n : n - nClustersRequested;
00310 if (d < bestDelta)
00311 {
00312 bestDelta = d;
00313 usedLevel = level;
00314 }
00315 }
00316 }
00317 }
00318 }
00319 tree.getPassingNodes(usedLevel, peakSelect, mynodes);
00320 }
00321 break;
00322
00323 case LOCALLY_ADAPTIVE:
00324 {
00325 usedLevel = tree.getLevel(fixedScale);
00326 tree.getMagS2OptimalNodes(peakSelect, nClustersRequested,
00327 usedLevel, mynodes, &thresholds);
00328 }
00329 break;
00330
00331 default:
00332 assert(!"ERROR in FFTJetProducer::selectTreeNodes : "
00333 "should never get here! This is a bug. Please report.");
00334 }
00335 }
00336
00337
00338 void FFTJetProducer::prepareRecombinationScales()
00339 {
00340 const unsigned nClus = preclusters.size();
00341 if (nClus)
00342 {
00343 fftjet::Peak* clus = &preclusters[0];
00344 fftjet::Functor1<double,fftjet::Peak>&
00345 scaleCalc(*recoScaleCalcPeak);
00346 fftjet::Functor1<double,fftjet::Peak>&
00347 ratioCalc(*recoScaleRatioCalcPeak);
00348 fftjet::Functor1<double,fftjet::Peak>&
00349 factorCalc(*memberFactorCalcPeak);
00350
00351 for (unsigned i=0; i<nClus; ++i)
00352 {
00353 clus[i].setRecoScale(scaleCalc(clus[i]));
00354 clus[i].setRecoScaleRatio(ratioCalc(clus[i]));
00355 clus[i].setMembershipFactor(factorCalc(clus[i]));
00356 }
00357 }
00358 }
00359
00360
00361 void FFTJetProducer::buildGridAlg()
00362 {
00363 int minBin = energyFlow->getEtaBin(-gridScanMaxEta);
00364 if (minBin < 0)
00365 minBin = 0;
00366 int maxBin = energyFlow->getEtaBin(gridScanMaxEta) + 1;
00367 if (maxBin < 0)
00368 maxBin = 0;
00369
00370 fftjet::DefaultRecombinationAlgFactory<
00371 Real,VectorLike,BgData,VBuilder> factory;
00372 if (factory[recombinationAlgorithm] == NULL)
00373 throw cms::Exception("FFTJetBadConfig")
00374 << "Invalid grid recombination algorithm \""
00375 << recombinationAlgorithm << "\"" << std::endl;
00376 gridAlg = std::auto_ptr<GridAlg>(
00377 factory[recombinationAlgorithm]->create(
00378 jetMembershipFunction.get(),
00379 bgMembershipFunction.get(),
00380 unlikelyBgWeight, recombinationDataCutoff,
00381 isCrisp, false, assignConstituents, minBin, maxBin));
00382 }
00383
00384
00385 void FFTJetProducer::loadEnergyFlow(const edm::Event& iEvent)
00386 {
00387 edm::Handle<DiscretizedEnergyFlow> input;
00388 iEvent.getByLabel(treeLabel, input);
00389
00390
00391 bool rebuildGrid = energyFlow.get() == NULL;
00392 if (!rebuildGrid)
00393 rebuildGrid =
00394 !(energyFlow->nEta() == input->nEtaBins() &&
00395 energyFlow->nPhi() == input->nPhiBins() &&
00396 energyFlow->etaMin() == input->etaMin() &&
00397 energyFlow->etaMax() == input->etaMax() &&
00398 energyFlow->phiBin0Edge() == input->phiBin0Edge());
00399 if (rebuildGrid)
00400 {
00401
00402 energyFlow = std::auto_ptr<fftjet::Grid2d<Real> >(
00403 new fftjet::Grid2d<Real>(
00404 input->nEtaBins(), input->etaMin(), input->etaMax(),
00405 input->nPhiBins(), input->phiBin0Edge(), input->title()));
00406 buildGridAlg();
00407 }
00408 energyFlow->blockSet(input->data(), input->nEtaBins(), input->nPhiBins());
00409 }
00410
00411
00412 bool FFTJetProducer::checkConvergence(const std::vector<RecoFFTJet>& previous,
00413 std::vector<RecoFFTJet>& nextSet)
00414 {
00415 fftjet::Functor2<double,RecoFFTJet,RecoFFTJet>&
00416 distanceCalc(*jetDistanceCalc);
00417
00418 const unsigned nJets = previous.size();
00419 const RecoFFTJet* prev = &previous[0];
00420 RecoFFTJet* next = &nextSet[0];
00421
00422
00423 bool converged = true;
00424 for (unsigned i=0; i<nJets; ++i)
00425 {
00426 const double d = distanceCalc(prev[i], next[i]);
00427 next[i].setConvergenceDistance(d);
00428 if (i < nJetsRequiredToConverge && d > convergenceDistance)
00429 converged = false;
00430 }
00431
00432 return converged;
00433 }
00434
00435
00436 unsigned FFTJetProducer::iterateJetReconstruction()
00437 {
00438 fftjet::Functor1<double,RecoFFTJet>& scaleCalc(*recoScaleCalcJet);
00439 fftjet::Functor1<double,RecoFFTJet>& ratioCalc(*recoScaleRatioCalcJet);
00440 fftjet::Functor1<double,RecoFFTJet>& factorCalc(*memberFactorCalcJet);
00441
00442 const unsigned nJets = recoJets.size();
00443
00444 unsigned iterNum = 1U;
00445 bool converged = false;
00446 for (; iterNum<maxIterations && !converged; ++iterNum)
00447 {
00448
00449 const RecoFFTJet* jets = &recoJets[0];
00450 iterPreclusters.clear();
00451 iterPreclusters.reserve(nJets);
00452 for (unsigned i=0; i<nJets; ++i)
00453 {
00454 const RecoFFTJet& jet(jets[i]);
00455 fftjet::Peak p(jet.precluster());
00456 p.setEtaPhi(jet.vec().Eta(), jet.vec().Phi());
00457 p.setRecoScale(scaleCalc(jet));
00458 p.setRecoScaleRatio(ratioCalc(jet));
00459 p.setMembershipFactor(factorCalc(jet));
00460 iterPreclusters.push_back(p);
00461 }
00462
00463
00464 int status = 0;
00465 if (useGriddedAlgorithm)
00466 status = gridAlg->run(iterPreclusters, *energyFlow,
00467 &noiseLevel, 1U, 1U,
00468 &iterJets, &unclustered, &unused);
00469 else
00470 status = recoAlg->run(iterPreclusters, eventData, &noiseLevel, 1U,
00471 &iterJets, &unclustered, &unused);
00472 if (status)
00473 throw cms::Exception("FFTJetInterface")
00474 << "FFTJet algorithm failed" << std::endl;
00475 assert(iterJets.size() == nJets);
00476
00477
00478 converged = checkConvergence(recoJets, iterJets);
00479
00480
00481 iterJets.swap(recoJets);
00482 }
00483
00484
00485 assert(preclusters.size() == nJets);
00486 RecoFFTJet* jets = &recoJets[0];
00487 for (unsigned i=0; i<nJets; ++i)
00488 {
00489 const fftjet::Peak& oldp(preclusters[i]);
00490 jets[i].setPeakEtaPhi(oldp.eta(), oldp.phi());
00491 }
00492
00493
00494
00495
00496
00497 if (!converged)
00498 ++iterNum;
00499
00500 return iterNum;
00501 }
00502
00503
00504 void FFTJetProducer::determineGriddedConstituents()
00505 {
00506 const unsigned nJets = recoJets.size();
00507 const unsigned* clusterMask = gridAlg->getClusterMask();
00508 const int nEta = gridAlg->getLastNEta();
00509 const int nPhi = gridAlg->getLastNPhi();
00510 const fftjet::Grid2d<Real>& g(*energyFlow);
00511
00512 const unsigned nInputs = eventData.size();
00513 const VectorLike* inp = nInputs ? &eventData[0] : 0;
00514 const unsigned* candIdx = nInputs ? &candidateIndex[0] : 0;
00515 for (unsigned i=0; i<nInputs; ++i)
00516 {
00517 const VectorLike& item(inp[i]);
00518 const int iPhi = g.getPhiBin(item.Phi());
00519 const int iEta = g.getEtaBin(item.Eta());
00520 const unsigned mask = iEta >= 0 && iEta < nEta ?
00521 clusterMask[iEta*nPhi + iPhi] : 0;
00522 assert(mask <= nJets);
00523 constituents[mask].push_back(inputCollection->ptrAt(candIdx[i]));
00524 }
00525 }
00526
00527
00528 void FFTJetProducer::determineVectorConstituents()
00529 {
00530 const unsigned nJets = recoJets.size();
00531 const unsigned* clusterMask = recoAlg->getClusterMask();
00532 const unsigned maskLength = recoAlg->getLastNData();
00533 assert(maskLength == eventData.size());
00534
00535 const unsigned* candIdx = maskLength ? &candidateIndex[0] : 0;
00536 for (unsigned i=0; i<maskLength; ++i)
00537 {
00538
00539
00540
00541
00542 const unsigned mask = clusterMask[i];
00543 assert(mask <= nJets);
00544 constituents[mask].push_back(inputCollection->ptrAt(candIdx[i]));
00545 }
00546 }
00547
00548
00549
00550
00551 template <typename T>
00552 void FFTJetProducer::writeJets(edm::Event& iEvent,
00553 const edm::EventSetup& iSetup)
00554 {
00555 using namespace reco;
00556
00557 typedef FFTAnyJet<T> OutputJet;
00558 typedef std::vector<OutputJet> OutputCollection;
00559
00560
00561
00562
00563 const double cellArea = useGriddedAlgorithm &&
00564 recombinationDataCutoff < 0.0 ?
00565 energyFlow->etaBinWidth() * energyFlow->phiBinWidth() : 0.0;
00566
00567
00568 std::auto_ptr<OutputCollection> jets(new OutputCollection());
00569 const unsigned nJets = recoJets.size();
00570 jets->reserve(nJets);
00571
00572 for (unsigned ijet=0; ijet<nJets; ++ijet)
00573 {
00574 const RecoFFTJet& myjet(recoJets[ijet]);
00575
00576
00577 VectorLike jet4vec(myjet.vec());
00578 if (resumConstituents)
00579 {
00580 VectorLike sum(0.0, 0.0, 0.0, 0.0);
00581 const unsigned nCon = constituents[ijet+1].size();
00582 const reco::CandidatePtr* cn = nCon ? &constituents[ijet+1][0] : 0;
00583 for (unsigned i=0; i<nCon; ++i)
00584 sum += cn[i]->p4();
00585 jet4vec = sum;
00586 }
00587
00588
00589
00590
00591 T jet;
00592 writeSpecific(jet, jet4vec, vertexUsed(),
00593 constituents[ijet+1], iSetup);
00594
00595
00596 jet.setJetArea(cellArea*myjet.ncells());
00597
00598
00599 jets->push_back(OutputJet(jet, jetToStorable<float>(myjet)));
00600 }
00601
00602
00603 iEvent.put(jets, outputLabel);
00604 }
00605
00606
00607 void FFTJetProducer::saveResults(edm::Event& ev, const edm::EventSetup& iSetup)
00608 {
00609
00610 jet_type_switch(writeJets, ev, iSetup);
00611
00612
00613 VectorLike unclusE(unclustered);
00614 if (resumConstituents)
00615 {
00616 VectorLike sum(0.0, 0.0, 0.0, 0.0);
00617 const unsigned nCon = constituents[0].size();
00618 const reco::CandidatePtr* cn = nCon ? &constituents[0][0] : 0;
00619 for (unsigned i=0; i<nCon; ++i)
00620 sum += cn[i]->p4();
00621 unclusE = sum;
00622 }
00623
00624
00625 const double minScale = minLevel ? sparseTree.getScale(minLevel) : 0.0;
00626 const double maxScale = maxLevel ? sparseTree.getScale(maxLevel) : 0.0;
00627 const double scaleUsed = usedLevel ? sparseTree.getScale(usedLevel) : 0.0;
00628
00629 std::auto_ptr<reco::FFTJetProducerSummary> summary(
00630 new reco::FFTJetProducerSummary(
00631 thresholds, occupancy, unclusE,
00632 constituents[0], unused,
00633 minScale, maxScale, scaleUsed,
00634 preclusters.size(), iterationsPerformed,
00635 iterationsPerformed == 1U ||
00636 iterationsPerformed <= maxIterations));
00637 ev.put(summary, outputLabel);
00638 }
00639
00640
00641
00642 void FFTJetProducer::produce(edm::Event& iEvent,
00643 const edm::EventSetup& iSetup)
00644 {
00645
00646 if (storeInSinglePrecision())
00647 loadSparseTreeData<float>(iEvent);
00648 else
00649 loadSparseTreeData<double>(iEvent);
00650
00651
00652 if (assignConstituents || !(useGriddedAlgorithm && reuseExistingGrid))
00653 loadInputCollection(iEvent);
00654
00655
00656 if (useGriddedAlgorithm)
00657 {
00658 if (reuseExistingGrid)
00659 loadEnergyFlow(iEvent);
00660 else
00661 discretizeEnergyFlow();
00662 }
00663
00664
00665 sparseTree.occupancyInScaleSpace(*peakSelector, &occupancy);
00666
00667
00668 preclusters.clear();
00669 selectPreclusters(sparseTree, *peakSelector, &preclusters);
00670
00671
00672 prepareRecombinationScales();
00673
00674
00675
00676
00677 assignMembershipFunctions(&preclusters);
00678
00679
00680 int status = 0;
00681 if (useGriddedAlgorithm)
00682 status = gridAlg->run(preclusters, *energyFlow,
00683 &noiseLevel, 1U, 1U,
00684 &recoJets, &unclustered, &unused);
00685 else
00686 status = recoAlg->run(preclusters, eventData, &noiseLevel, 1U,
00687 &recoJets, &unclustered, &unused);
00688 if (status)
00689 throw cms::Exception("FFTJetInterface")
00690 << "FFTJet algorithm failed (first iteration)" << std::endl;
00691
00692
00693 if (maxIterations > 1U && !recoJets.empty())
00694 iterationsPerformed = iterateJetReconstruction();
00695 else
00696 iterationsPerformed = 1U;
00697
00698
00699
00700 const unsigned nJets = recoJets.size();
00701 if (constituents.size() <= nJets)
00702 constituents.resize(nJets + 1U);
00703 if (assignConstituents)
00704 {
00705 for (unsigned i=0; i<=nJets; ++i)
00706 constituents[i].clear();
00707 if (useGriddedAlgorithm)
00708 determineGriddedConstituents();
00709 else
00710 determineVectorConstituents();
00711 }
00712
00713
00714 saveResults(iEvent, iSetup);
00715 }
00716
00717
00718 std::auto_ptr<fftjet::Functor1<bool,fftjet::Peak> >
00719 FFTJetProducer::parse_peakSelector(const edm::ParameterSet& ps)
00720 {
00721 return fftjet_PeakSelector_parser(
00722 ps.getParameter<edm::ParameterSet>("PeakSelectorConfiguration"));
00723 }
00724
00725
00726
00727 std::auto_ptr<fftjet::ScaleSpaceKernel>
00728 FFTJetProducer::parse_jetMembershipFunction(const edm::ParameterSet& ps)
00729 {
00730 return fftjet_MembershipFunction_parser(
00731 ps.getParameter<edm::ParameterSet>("jetMembershipFunction"));
00732 }
00733
00734
00735
00736 std::auto_ptr<AbsBgFunctor>
00737 FFTJetProducer::parse_bgMembershipFunction(const edm::ParameterSet& ps)
00738 {
00739 return fftjet_BgFunctor_parser(
00740 ps.getParameter<edm::ParameterSet>("bgMembershipFunction"));
00741 }
00742
00743
00744
00745 std::auto_ptr<fftjet::Functor1<double,fftjet::Peak> >
00746 FFTJetProducer::parse_recoScaleCalcPeak(const edm::ParameterSet& ps)
00747 {
00748 return fftjet_PeakFunctor_parser(
00749 ps.getParameter<edm::ParameterSet>("recoScaleCalcPeak"));
00750 }
00751
00752
00753
00754 std::auto_ptr<fftjet::Functor1<double,fftjet::Peak> >
00755 FFTJetProducer::parse_recoScaleRatioCalcPeak(const edm::ParameterSet& ps)
00756 {
00757 return fftjet_PeakFunctor_parser(
00758 ps.getParameter<edm::ParameterSet>("recoScaleRatioCalcPeak"));
00759 }
00760
00761
00762
00763 std::auto_ptr<fftjet::Functor1<double,fftjet::Peak> >
00764 FFTJetProducer::parse_memberFactorCalcPeak(const edm::ParameterSet& ps)
00765 {
00766 return fftjet_PeakFunctor_parser(
00767 ps.getParameter<edm::ParameterSet>("memberFactorCalcPeak"));
00768 }
00769
00770
00771 std::auto_ptr<fftjet::Functor1<double,FFTJetProducer::RecoFFTJet> >
00772 FFTJetProducer::parse_recoScaleCalcJet(const edm::ParameterSet& ps)
00773 {
00774 return fftjet_JetFunctor_parser(
00775 ps.getParameter<edm::ParameterSet>("recoScaleCalcJet"));
00776 }
00777
00778
00779 std::auto_ptr<fftjet::Functor1<double,FFTJetProducer::RecoFFTJet> >
00780 FFTJetProducer::parse_recoScaleRatioCalcJet(const edm::ParameterSet& ps)
00781 {
00782 return fftjet_JetFunctor_parser(
00783 ps.getParameter<edm::ParameterSet>("recoScaleRatioCalcJet"));
00784 }
00785
00786
00787 std::auto_ptr<fftjet::Functor1<double,FFTJetProducer::RecoFFTJet> >
00788 FFTJetProducer::parse_memberFactorCalcJet(const edm::ParameterSet& ps)
00789 {
00790 return fftjet_JetFunctor_parser(
00791 ps.getParameter<edm::ParameterSet>("memberFactorCalcJet"));
00792 }
00793
00794
00795 std::auto_ptr<fftjet::Functor2<
00796 double,FFTJetProducer::RecoFFTJet,FFTJetProducer::RecoFFTJet> >
00797 FFTJetProducer::parse_jetDistanceCalc(const edm::ParameterSet& ps)
00798 {
00799 return fftjet_JetDistance_parser(
00800 ps.getParameter<edm::ParameterSet>("jetDistanceCalc"));
00801 }
00802
00803
00804 void FFTJetProducer::assignMembershipFunctions(std::vector<fftjet::Peak>*)
00805 {
00806 }
00807
00808
00809
00810 void FFTJetProducer::beginJob()
00811 {
00812 const edm::ParameterSet& ps(myConfiguration);
00813
00814
00815 peakSelector = parse_peakSelector(ps);
00816 checkConfig(peakSelector, "invalid peak selector");
00817
00818 jetMembershipFunction = parse_jetMembershipFunction(ps);
00819 checkConfig(jetMembershipFunction, "invalid jet membership function");
00820
00821 bgMembershipFunction = parse_bgMembershipFunction(ps);
00822 checkConfig(bgMembershipFunction, "invalid noise membership function");
00823
00824
00825 if (!useGriddedAlgorithm)
00826 {
00827 fftjet::DefaultVectorRecombinationAlgFactory<
00828 VectorLike,BgData,VBuilder> factory;
00829 if (factory[recombinationAlgorithm] == NULL)
00830 throw cms::Exception("FFTJetBadConfig")
00831 << "Invalid vector recombination algorithm \""
00832 << recombinationAlgorithm << "\"" << std::endl;
00833 recoAlg = std::auto_ptr<RecoAlg>(
00834 factory[recombinationAlgorithm]->create(
00835 jetMembershipFunction.get(),
00836 &VectorLike::Et, &VectorLike::Eta, &VectorLike::Phi,
00837 bgMembershipFunction.get(),
00838 unlikelyBgWeight, isCrisp, false, assignConstituents));
00839 }
00840 else if (!reuseExistingGrid)
00841 {
00842 energyFlow = fftjet_Grid2d_parser(
00843 ps.getParameter<edm::ParameterSet>("GridConfiguration"));
00844 checkConfig(energyFlow, "invalid discretization grid");
00845 buildGridAlg();
00846 }
00847
00848
00849 recoScaleCalcPeak = parse_recoScaleCalcPeak(ps);
00850 checkConfig(recoScaleCalcPeak, "invalid spec for the "
00851 "reconstruction scale calculator from peaks");
00852
00853
00854 recoScaleRatioCalcPeak = parse_recoScaleRatioCalcPeak(ps);
00855 checkConfig(recoScaleRatioCalcPeak, "invalid spec for the "
00856 "reconstruction scale ratio calculator from peaks");
00857
00858
00859 memberFactorCalcPeak = parse_memberFactorCalcPeak(ps);
00860 checkConfig(memberFactorCalcPeak, "invalid spec for the "
00861 "membership function factor calculator from peaks");
00862
00863 if (maxIterations > 1)
00864 {
00865
00866 recoScaleCalcJet = parse_recoScaleCalcJet(ps);
00867 checkConfig(recoScaleCalcJet, "invalid spec for the "
00868 "reconstruction scale calculator from jets");
00869
00870 recoScaleRatioCalcJet = parse_recoScaleRatioCalcJet(ps);
00871 checkConfig(recoScaleRatioCalcJet, "invalid spec for the "
00872 "reconstruction scale ratio calculator from jets");
00873
00874 memberFactorCalcJet = parse_memberFactorCalcJet(ps);
00875 checkConfig(memberFactorCalcJet, "invalid spec for the "
00876 "membership function factor calculator from jets");
00877
00878 jetDistanceCalc = parse_jetDistanceCalc(ps);
00879 checkConfig(memberFactorCalcJet, "invalid spec for the "
00880 "jet distance calculator");
00881 }
00882 }
00883
00884
00885
00886 void FFTJetProducer::endJob()
00887 {
00888 }
00889
00890
00891 DEFINE_FWK_MODULE(FFTJetProducer);