/** SiPixelClusterProducer.cc * --------------------------------------------------------------- * Description: see SiPixelClusterProducer.h * Author: P. Maksimovic (porting from original ORCA version) * History: Oct 14, 2005, initial version * Get rid of the noiseVector. d.k. 28/3/06 * Implementation of the DetSetVector container. V.Chiochia, May 06 * SiPixelClusterCollection typedef of DetSetVector V.Chiochia, June 06 * Introduce the DetSet local container (cache) for speed. d.k. 05/07 * * --------------------------------------------------------------- */ // Our own stuff #include "SiPixelClusterProducer.h" #include "PixelThresholdClusterizer.h" // Geometry #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h" #include "Geometry/TrackerGeometryBuilder/interface/PixelGeomDetUnit.h" // Data Formats #include "DataFormats/Common/interface/DetSetVector.h" #include "DataFormats/SiPixelDigi/interface/PixelDigi.h" #include "DataFormats/DetId/interface/DetId.h" // Database payloads #include "CalibTracker/SiPixelESProducers/interface/SiPixelGainCalibrationService.h" #include "CalibTracker/SiPixelESProducers/interface/SiPixelGainCalibrationOfflineService.h" #include "CalibTracker/SiPixelESProducers/interface/SiPixelGainCalibrationForHLTService.h" // Framework #include "DataFormats/Common/interface/Handle.h" #include "FWCore/Framework/interface/ESHandle.h" // STL #include <vector> #include <memory> #include <string> #include <iostream> // MessageLogger #include "FWCore/MessageLogger/interface/MessageLogger.h" //--------------------------------------------------------------------------- //! Constructor: set the ParameterSet and defer all thinking to setupClusterizer(). //--------------------------------------------------------------------------- SiPixelClusterProducer::SiPixelClusterProducer(edm::ParameterSet const& conf) : theSiPixelGainCalibration_(nullptr), clusterMode_( conf.getUntrackedParameter<std::string>("ClusterMode","PixelThresholdClusterizer") ), clusterizer_(nullptr), // the default, in case we fail to make one readyToCluster_(false), // since we obviously aren't maxTotalClusters_( conf.getParameter<int32_t>( "maxNumberOfClusters" ) ), payloadType_( conf.getParameter<std::string>( "payloadType" ) ) { if ( clusterMode_ == "PixelThresholdReclusterizer" ) tPixelClusters = consumes<SiPixelClusterCollectionNew>( conf.getParameter<edm::InputTag>("src") ); else tPixelDigi = consumes<edm::DetSetVector<PixelDigi>>( conf.getParameter<edm::InputTag>("src") ); //--- Declare to the EDM what kind of collections we will be making. produces<SiPixelClusterCollectionNew>(); if (strcmp(payloadType_.c_str(), "HLT") == 0) theSiPixelGainCalibration_ = new SiPixelGainCalibrationForHLTService(conf); else if (strcmp(payloadType_.c_str(), "Offline") == 0) theSiPixelGainCalibration_ = new SiPixelGainCalibrationOfflineService(conf); else if (strcmp(payloadType_.c_str(), "Full") == 0) theSiPixelGainCalibration_ = new SiPixelGainCalibrationService(conf); //--- Make the algorithm(s) according to what the user specified //--- in the ParameterSet. setupClusterizer(conf); } // Destructor SiPixelClusterProducer::~SiPixelClusterProducer() { delete clusterizer_; delete theSiPixelGainCalibration_; } //--------------------------------------------------------------------------- //! The "Event" entrypoint: gets called by framework for every event //--------------------------------------------------------------------------- void SiPixelClusterProducer::produce(edm::Event& e, const edm::EventSetup& es) { //Setup gain calibration service theSiPixelGainCalibration_->setESObjects( es ); // Step A.1: get input data edm::Handle< SiPixelClusterCollectionNew > inputClusters; edm::Handle< edm::DetSetVector<PixelDigi> > inputDigi; if ( clusterMode_ == "PixelThresholdReclusterizer" ) e.getByToken(tPixelClusters, inputClusters); else e.getByToken(tPixelDigi, inputDigi); // Step A.2: get event setup edm::ESHandle<TrackerGeometry> geom; es.get<TrackerDigiGeometryRecord>().get( geom ); edm::ESHandle<TrackerTopology> trackerTopologyHandle; es.get<TrackerTopologyRcd>().get(trackerTopologyHandle); tTopo_ = trackerTopologyHandle.product(); // Step B: create the final output collection auto output = std::make_unique< SiPixelClusterCollectionNew>(); //FIXME: put a reserve() here // Step C: Iterate over DetIds and invoke the pixel clusterizer algorithm // on each DetUnit if ( clusterMode_ == "PixelThresholdReclusterizer" ) run(*inputClusters, geom, *output ); else run(*inputDigi, geom, *output ); // Step D: write output to file output->shrink_to_fit(); e.put(std::move(output)); } //--------------------------------------------------------------------------- //! Set up the specific algorithm we are going to use. //! TO DO: in the future, we should allow for a different algorithm for //! each detector subset (e.g. barrel vs forward, per layer, etc). //--------------------------------------------------------------------------- void SiPixelClusterProducer::setupClusterizer(const edm::ParameterSet& conf) { if ( clusterMode_ == "PixelThresholdReclusterizer" || clusterMode_ == "PixelThresholdClusterizer" ) { clusterizer_ = new PixelThresholdClusterizer(conf); clusterizer_->setSiPixelGainCalibrationService(theSiPixelGainCalibration_); readyToCluster_ = true; } else { edm::LogError("SiPixelClusterProducer") << "[SiPixelClusterProducer]:" <<" choice " << clusterMode_ << " is invalid.\n" << "Possible choices:\n" << " PixelThresholdClusterizer"; readyToCluster_ = false; } } //--------------------------------------------------------------------------- //! Iterate over DetUnits, and invoke the PixelClusterizer on each. //--------------------------------------------------------------------------- template<typename T> void SiPixelClusterProducer::run(const T & input, const edm::ESHandle<TrackerGeometry> & geom, edmNew::DetSetVector<SiPixelCluster> & output) { if ( ! readyToCluster_ ) { edm::LogError("SiPixelClusterProducer") <<" at least one clusterizer is not ready -- can't run!" ; // TO DO: throw an exception here? The user may want to know... return; // clusterizer is invalid, bail out } int numberOfDetUnits = 0; int numberOfClusters = 0; // Iterate on detector units typename T::const_iterator DSViter = input.begin(); for( ; DSViter != input.end(); DSViter++) { ++numberOfDetUnits; // LogDebug takes very long time, get rid off. //LogDebug("SiStripClusterizer") << "[SiPixelClusterProducer::run] DetID" << DSViter->id; std::vector<short> badChannels; DetId detIdObject(DSViter->detId()); // Comment: At the moment the clusterizer depends on geometry // to access information as the pixel topology (number of columns // and rows in a detector module). // In the future the geometry service will be replaced with // a ES service. const GeomDetUnit * geoUnit = geom->idToDetUnit( detIdObject ); const PixelGeomDetUnit * pixDet = dynamic_cast<const PixelGeomDetUnit*>(geoUnit); if (! pixDet) { // Fatal error! TO DO: throw an exception! assert(0); } { // Produce clusters for this DetUnit and store them in // a DetSet edmNew::DetSetVector<SiPixelCluster>::FastFiller spc(output, DSViter->detId()); clusterizer_->clusterizeDetUnit(*DSViter, pixDet, tTopo_, badChannels, spc); if ( spc.empty() ) { spc.abort(); } else { numberOfClusters += spc.size(); } } // spc is not deleted and detsetvector updated if ((maxTotalClusters_ >= 0) && (numberOfClusters > maxTotalClusters_)) { edm::LogError("TooManyClusters") << "Limit on the number of clusters exceeded. An empty cluster collection will be produced instead.\n"; edmNew::DetSetVector<SiPixelCluster> empty; empty.swap(output); break; } } // end of DetUnit loop //LogDebug ("SiPixelClusterProducer") << " Executing " // << clusterMode_ << " resulted in " << numberOfClusters // << " SiPixelClusters in " << numberOfDetUnits << " DetUnits."; } #include "FWCore/PluginManager/interface/ModuleDef.h" #include "FWCore/Framework/interface/MakerMacros.h" DEFINE_FWK_MODULE(SiPixelClusterProducer);