text: #include "PFClusterProducer.h"
  
  #ifdef PFLOW_DEBUG
  #define LOGVERB(x) edm::LogVerbatim(x)
  #define LOGWARN(x) edm::LogWarning(x)
  #define LOGERR(x) edm::LogError(x)
  #define LOGDRESSED(x) edm::LogInfo(x)
  #else
  #define LOGVERB(x) LogTrace(x)
  #define LOGWARN(x) edm::LogWarning(x)
  #define LOGERR(x) edm::LogError(x)
  #define LOGDRESSED(x) LogDebug(x)
  #endif
  
  PFClusterProducer::PFClusterProducer(const edm::ParameterSet& conf)
      : _prodInitClusters(conf.getUntrackedParameter<bool>("prodInitialClusters", false)) {
    _rechitsLabel = consumes<reco::PFRecHitCollection>(conf.getParameter<edm::InputTag>("recHitsSource"));
    //setup rechit cleaners
    const edm::VParameterSet& cleanerConfs = conf.getParameterSetVector("recHitCleaners");
    for (const auto& conf : cleanerConfs) {
      const std::string& cleanerName = conf.getParameter<std::string>("algoName");
      _cleaners.emplace_back(RecHitTopologicalCleanerFactory::get()->create(cleanerName, conf));
    }
    edm::ConsumesCollector sumes = consumesCollector();
  
    // setup seed finding
    const edm::ParameterSet& sfConf = conf.getParameterSet("seedFinder");
    const std::string& sfName = sfConf.getParameter<std::string>("algoName");
    _seedFinder = SeedFinderFactory::get()->create(sfName, sfConf);
    //setup topo cluster builder
    const edm::ParameterSet& initConf = conf.getParameterSet("initialClusteringStep");
    const std::string& initName = initConf.getParameter<std::string>("algoName");
    _initialClustering = InitialClusteringStepFactory::get()->create(initName, initConf, sumes);
    //setup pf cluster builder if requested
    const edm::ParameterSet& pfcConf = conf.getParameterSet("pfClusterBuilder");
    if (!pfcConf.empty()) {
      const std::string& pfcName = pfcConf.getParameter<std::string>("algoName");
      _pfClusterBuilder = PFClusterBuilderFactory::get()->create(pfcName, pfcConf);
    }
    //setup (possible) recalcuation of positions
    const edm::ParameterSet& pConf = conf.getParameterSet("positionReCalc");
    if (!pConf.empty()) {
      const std::string& pName = pConf.getParameter<std::string>("algoName");
      _positionReCalc = PFCPositionCalculatorFactory::get()->create(pName, pConf);
    }
    // see if new need to apply corrections, setup if there.
    const edm::ParameterSet& cConf = conf.getParameterSet("energyCorrector");
    if (!cConf.empty()) {
      const std::string& cName = cConf.getParameter<std::string>("algoName");
      _energyCorrector = PFClusterEnergyCorrectorFactory::get()->create(cName, cConf);
    }
  
    if (_prodInitClusters) {
      produces<reco::PFClusterCollection>("initialClusters");
    }
    produces<reco::PFClusterCollection>();
  }
  
  void PFClusterProducer::beginLuminosityBlock(const edm::LuminosityBlock& lumi, const edm::EventSetup& es) {
    _initialClustering->update(es);
    if (_pfClusterBuilder)
      _pfClusterBuilder->update(es);
    if (_positionReCalc)
      _positionReCalc->update(es);
  }
  
  void PFClusterProducer::produce(edm::Event& e, const edm::EventSetup& es) {
    _initialClustering->reset();
    if (_pfClusterBuilder)
      _pfClusterBuilder->reset();
  
    edm::Handle<reco::PFRecHitCollection> rechits;
    e.getByToken(_rechitsLabel, rechits);
  
    _initialClustering->updateEvent(e);
  
    std::vector<bool> mask(rechits->size(), true);
    for (const auto& cleaner : _cleaners) {
      cleaner->clean(rechits, mask);
    }
  
    std::vector<bool> seedable(rechits->size(), false);
    _seedFinder->findSeeds(rechits, mask, seedable);
  
    auto initialClusters = std::make_unique<reco::PFClusterCollection>();
    _initialClustering->buildClusters(rechits, mask, seedable, *initialClusters);
    LOGVERB("PFClusterProducer::produce()") << *_initialClustering;
  
    auto pfClusters = std::make_unique<reco::PFClusterCollection>();
    pfClusters.reset(new reco::PFClusterCollection);
    if (_pfClusterBuilder) {  // if we've defined a re-clustering step execute it
      _pfClusterBuilder->buildClusters(*initialClusters, seedable, *pfClusters);
      LOGVERB("PFClusterProducer::produce()") << *_pfClusterBuilder;
    } else {
      pfClusters->insert(pfClusters->end(), initialClusters->begin(), initialClusters->end());
    }
  
    if (_positionReCalc) {
      _positionReCalc->calculateAndSetPositions(*pfClusters);
    }
  
    if (_energyCorrector) {
      _energyCorrector->correctEnergies(*pfClusters);
    }
  
    if (_prodInitClusters)
      e.put(std::move(initialClusters), "initialClusters");
    e.put(std::move(pfClusters));
  }
  