CMS 3D CMS Logo

SiPixelDigitizer.cc
Go to the documentation of this file.
1 // -*- C++ -*-
2 //
3 // Package: SiPixelDigitizer
4 // Class: SiPixelDigitizer
5 //
13 //
14 // Original Author: Michele Pioppi-INFN perugia
15 // Modifications: Freya Blekman - Cornell University
16 // Created: Mon Sep 26 11:08:32 CEST 2005
17 //
18 //
19 
20 // system include files
21 #include <memory>
22 #include <set>
23 
24 // user include files
25 #include "SiPixelDigitizer.h"
27 #include "PixelDigiAddTempInfo.h"
29 
47 
50 
51 // user include files
53 
56 
58 
62 //Random Number
67 
68 //
69 // constants, enums and typedefs
70 //
71 
72 //
73 // static data member definitions
74 //
75 
76 //
77 // constructors and destructor
78 //
79 //using namespace std;
80 
81 namespace cms {
83  edm::ProducesCollector producesCollector,
85  : firstInitializeEvent_(true),
86  firstFinalizeEvent_(true),
87  applyLateReweighting_(
88  iConfig.exists("applyLateReweighting") ? iConfig.getParameter<bool>("applyLateReweighting") : false),
89  store_SimHitEntryExitPoints_(iConfig.exists("store_SimHitEntryExitPoints")
90  ? iConfig.getParameter<bool>("store_SimHitEntryExitPoints")
91  : false),
92  _pixeldigialgo(),
93  hitsProducer(iConfig.getParameter<std::string>("hitsProducer")),
94  trackerContainers(iConfig.getParameter<std::vector<std::string> >("RoutList")),
95  pilotBlades(iConfig.exists("enablePilotBlades") ? iConfig.getParameter<bool>("enablePilotBlades") : false),
96  NumberOfEndcapDisks(iConfig.exists("NumPixelEndcap") ? iConfig.getParameter<int>("NumPixelEndcap") : 2),
97  tTopoToken_(iC.esConsumes()),
98  pDDToken_(iC.esConsumes(edm::ESInputTag("", iConfig.getParameter<std::string>("PixGeometryType")))),
99  pSetupToken_(iC.esConsumes()) {
100  edm::LogInfo("PixelDigitizer ") << "Enter the Pixel Digitizer";
101 
102  edm::LogInfo("PixelDigitizer ") << " applyLateReweighting_ " << applyLateReweighting_;
103 
104  const std::string alias("simSiPixelDigis");
105 
106  producesCollector.produces<edm::DetSetVector<PixelDigi> >().setBranchAlias(alias);
107  producesCollector.produces<edm::DetSetVector<PixelDigiSimLink> >().setBranchAlias(alias + "siPixelDigiSimLink");
109  producesCollector.produces<edm::DetSetVector<PixelSimHitExtraInfo> >().setBranchAlias(alias +
110  "siPixelExtraSimHit");
111 
112  for (auto const& trackerContainer : trackerContainers) {
113  edm::InputTag tag(hitsProducer, trackerContainer);
114  iC.consumes<std::vector<PSimHit> >(edm::InputTag(hitsProducer, trackerContainer));
115  }
117  if (!rng.isAvailable()) {
118  throw cms::Exception("Configuration")
119  << "SiPixelDigitizer requires the RandomNumberGeneratorService\n"
120  "which is not present in the configuration file. You must add the service\n"
121  "in the configuration file or remove the modules that require it.";
122  }
123 
124  _pixeldigialgo = std::make_unique<SiPixelDigitizerAlgorithm>(iConfig, iC);
125  if (NumberOfEndcapDisks != 2)
126  producesCollector.produces<PixelFEDChannelCollection>();
127  }
128 
129  SiPixelDigitizer::~SiPixelDigitizer() { edm::LogInfo("PixelDigitizer ") << "Destruct the Pixel Digitizer"; }
130 
131  //
132  // member functions
133  //
134 
135  void SiPixelDigitizer::accumulatePixelHits(edm::Handle<std::vector<PSimHit> > hSimHits,
136  size_t globalSimHitIndex,
137  const unsigned int tofBin,
138  edm::EventSetup const& iSetup) {
139  if (hSimHits.isValid()) {
140  std::set<unsigned int> detIds;
141  std::vector<PSimHit> const& simHits = *hSimHits.product();
142  const TrackerTopology* tTopo = &iSetup.getData(tTopoToken_);
143  _pixeldigialgo->fillSimHitMaps(simHits, tofBin);
144  for (std::vector<PSimHit>::const_iterator it = simHits.begin(), itEnd = simHits.end(); it != itEnd;
145  ++it, ++globalSimHitIndex) {
146  unsigned int detId = (*it).detUnitId();
147  if (detIds.insert(detId).second) {
148  // The insert succeeded, so this detector element has not yet been processed.
149  assert(detectorUnits[detId]);
150  if (detectorUnits[detId] &&
151  detectorUnits[detId]
152  ->type()
153  .isTrackerPixel()) { // this test could be avoided and changed into a check of pixdet!=0
154  std::map<unsigned int, PixelGeomDetUnit const*>::iterator itDet = detectorUnits.find(detId);
155  if (itDet == detectorUnits.end())
156  continue;
157  auto pixdet = itDet->second;
158  assert(pixdet != nullptr);
159  //access to magnetic field in global coordinates
160  GlobalVector bfield = pSetup->inTesla(pixdet->surface().position());
161  LogDebug("PixelDigitizer ") << "B-field(T) at " << pixdet->surface().position()
162  << "(cm): " << pSetup->inTesla(pixdet->surface().position());
163  _pixeldigialgo->accumulateSimHits(
164  it, itEnd, globalSimHitIndex, tofBin, pixdet, bfield, tTopo, randomEngine_);
165  }
166  }
167  }
168  }
169  }
170 
172  if (firstInitializeEvent_) {
173  _pixeldigialgo->init(iSetup);
174  firstInitializeEvent_ = false;
175  }
176 
177  // Make sure that the first crossing processed starts indexing the sim hits from zero.
178  // This variable is used so that the sim hits from all crossing frames have sequential
179  // indices used to create the digi-sim link (if configured to do so) rather than starting
180  // from zero for each crossing.
182 
183  // Cache random number engine
185  randomEngine_ = &rng->getEngine(e.streamID());
186 
187  _pixeldigialgo->initializeEvent();
188  pDD = &iSetup.getData(pDDToken_);
189  pSetup = &iSetup.getData(pSetupToken_);
190  const TrackerTopology* tTopo = &iSetup.getData(tTopoToken_);
191 
192  // FIX THIS! We only need to clear and (re)fill this map when the geometry type IOV changes. Use ESWatcher to determine this.
193  if (true) { // Replace with ESWatcher
194  detectorUnits.clear();
195  for (const auto& iu : pDD->detUnits()) {
196  unsigned int detId = iu->geographicalId().rawId();
197  if (iu->type().isTrackerPixel()) {
198  auto pixdet = dynamic_cast<const PixelGeomDetUnit*>(iu);
199  assert(pixdet != nullptr);
200  if (iu->subDetector() ==
201  GeomDetEnumerators::SubDetector::PixelEndcap) { // true ONLY for the phase 0 pixel deetctor
202  unsigned int disk = tTopo->layer(detId); // using the generic layer method
203  //if using pilot blades, then allowing it for current detector only
204  if ((disk == 3) && ((!pilotBlades) && (NumberOfEndcapDisks == 2)))
205  continue;
206  }
207  detectorUnits.insert(std::make_pair(detId, pixdet));
208  }
209  }
210  }
211  }
212 
214  // Step A: Get Inputs
215  for (vstring::const_iterator i = trackerContainers.begin(), iEnd = trackerContainers.end(); i != iEnd; ++i) {
218 
219  iEvent.getByLabel(tag, simHits);
220  unsigned int tofBin = PixelDigiSimLink::LowTof;
221  if ((*i).find(std::string("HighTof")) != std::string::npos)
222  tofBin = PixelDigiSimLink::HighTof;
223  accumulatePixelHits(simHits, crossingSimHitIndexOffset_[tag.encode()], tofBin, iSetup);
224  // Now that the hits have been processed, I'll add the amount of hits in this crossing on to
225  // the global counter. Next time accumulateStripHits() is called it will count the sim hits
226  // as though they were on the end of this collection.
227  // Note that this is only used for creating digi-sim links (if configured to do so).
228  // std::cout << "index offset, current hit count = " << crossingSimHitIndexOffset_[tag.encode()] << ", " << simHits->size() << std::endl;
229  if (simHits.isValid())
230  crossingSimHitIndexOffset_[tag.encode()] += simHits->size();
231  }
232  }
233 
235  edm::EventSetup const& iSetup,
236  edm::StreamID const& streamID) {
237  // Step A: Get Inputs
238  for (vstring::const_iterator i = trackerContainers.begin(), iEnd = trackerContainers.end(); i != iEnd; ++i) {
241 
242  iEvent.getByLabel(tag, simHits);
243  unsigned int tofBin = PixelDigiSimLink::LowTof;
244  if ((*i).find(std::string("HighTof")) != std::string::npos)
245  tofBin = PixelDigiSimLink::HighTof;
246  accumulatePixelHits(simHits, crossingSimHitIndexOffset_[tag.encode()], tofBin, iSetup);
247  // Now that the hits have been processed, I'll add the amount of hits in this crossing on to
248  // the global counter. Next time accumulateStripHits() is called it will count the sim hits
249  // as though they were on the end of this collection.
250  // Note that this is only used for creating digi-sim links (if configured to do so).
251  // std::cout << "index offset, current hit count = " << crossingSimHitIndexOffset_[tag.encode()] << ", " << simHits->size() << std::endl;
252  if (simHits.isValid())
253  crossingSimHitIndexOffset_[tag.encode()] += simHits->size();
254  }
255  }
256 
257  // ------------ method called to produce the data ------------
259  const TrackerTopology* tTopo = &iSetup.getData(tTopoToken_);
260 
261  std::vector<edm::DetSet<PixelDigi> > theDigiVector;
262  std::vector<edm::DetSet<PixelDigiSimLink> > theDigiLinkVector;
263  std::vector<edm::DetSet<PixelSimHitExtraInfo> > theExtraSimHitInfoVector;
264 
265  if (firstFinalizeEvent_) {
266  _pixeldigialgo->init_DynIneffDB(iSetup);
267  firstFinalizeEvent_ = false;
268  }
269  _pixeldigialgo->calculateInstlumiFactor(PileupInfo_.get());
270 
271  if (_pixeldigialgo->killBadFEDChannels()) {
272  std::unique_ptr<PixelFEDChannelCollection> PixelFEDChannelCollection_ =
273  _pixeldigialgo->chooseScenario(PileupInfo_.get(), randomEngine_);
274  if (PixelFEDChannelCollection_ == nullptr) {
275  throw cms::Exception("NullPointerError") << "PixelFEDChannelCollection not set in chooseScenario function.\n";
276  }
277  iEvent.put(std::move(PixelFEDChannelCollection_));
278  }
279 
280  for (const auto& iu : pDD->detUnits()) {
281  if (iu->type().isTrackerPixel()) {
282  //
283 
284  edm::DetSet<PixelDigi> collector(iu->geographicalId().rawId());
285  edm::DetSet<PixelDigiSimLink> linkcollector(iu->geographicalId().rawId());
286  std::vector<PixelDigiAddTempInfo> tempcollector;
287  edm::DetSet<PixelSimHitExtraInfo> tempSHcollector(iu->geographicalId().rawId());
288 
289  _pixeldigialgo->digitize(dynamic_cast<const PixelGeomDetUnit*>(iu),
290  collector.data,
291  linkcollector.data,
292  tempcollector,
293  tTopo,
294  randomEngine_);
295 
296  // transformation of the tempcollector (October 15, 2021)
297  if (!tempcollector.empty()) {
298  std::vector<PixelDigiAddTempInfo>::const_iterator loopNewClass;
299  unsigned int channelPrevious2 = -1;
300  size_t hitFirstOne2 = -1;
301  for (loopNewClass = tempcollector.begin(); loopNewClass != tempcollector.end(); ++loopNewClass) {
302  // check if the new SimHit already exists in the class
303  // if yes : add only the Digi info to the existing entry
304  // if not : create a new entry
305  // PixelSimHitExtraInfo(
306  // size_t Hindex, Local3DPoint entryP , Local3DPoint exitP, uint32_t detID, std::vector<unsigned int> ch, std::vector<float> InitCharge)
307  // what about the duplicates : 2 SimHits associated to the same Digis ?
308  //
309  //
310 
311  bool checkTwoSimHits = false;
312  if (channelPrevious2 == loopNewClass->channel() && hitFirstOne2 != loopNewClass->hitIndex()) {
313  // case of one Digi associated to a second SimHit
314  checkTwoSimHits = true;
315  } else {
316  channelPrevious2 = loopNewClass->channel();
317  hitFirstOne2 = loopNewClass->hitIndex();
318  }
319 
320  bool checkInTheList = false;
321  if (!checkTwoSimHits) {
322  std::vector<PixelSimHitExtraInfo>::iterator loopTempSH;
323  for (loopTempSH = tempSHcollector.begin(); loopTempSH != tempSHcollector.end(); ++loopTempSH) {
324  if (loopNewClass->hitIndex() == loopTempSH->hitIndex()) {
325  checkInTheList = true;
326  loopTempSH->addDigiInfo(loopNewClass->channel());
327  }
328  }
329  if (!checkInTheList) {
330  PixelSimHitExtraInfo newSHEntry(loopNewClass->hitIndex(),
331  loopNewClass->entryPoint(),
332  loopNewClass->exitPoint(),
333  loopNewClass->channel());
334  tempSHcollector.push_back(newSHEntry);
335  }
336  }
337  }
338  }
339 
340  if (applyLateReweighting_) {
341  // if applyLateReweighting_ is true, the charge reweighting has to be applied on top of the digis
342  _pixeldigialgo->lateSignalReweight(
343  dynamic_cast<const PixelGeomDetUnit*>(iu), collector.data, tempSHcollector.data, tTopo, randomEngine_);
344  }
345 
346  if (!collector.data.empty()) {
347  theDigiVector.push_back(std::move(collector));
348  }
349  if (!linkcollector.data.empty()) {
350  theDigiLinkVector.push_back(std::move(linkcollector));
351  }
352  if (!tempSHcollector.data.empty()) {
353  theExtraSimHitInfoVector.push_back(std::move(tempSHcollector));
354  }
355  }
356  }
357  _pixeldigialgo->resetSimHitMaps();
358 
359  // Step C: create collection with the cache vector of DetSet
360  std::unique_ptr<edm::DetSetVector<PixelDigi> > output(new edm::DetSetVector<PixelDigi>(theDigiVector));
361  std::unique_ptr<edm::DetSetVector<PixelDigiSimLink> > outputlink(
362  new edm::DetSetVector<PixelDigiSimLink>(theDigiLinkVector));
363  std::unique_ptr<edm::DetSetVector<PixelSimHitExtraInfo> > outputExtraSim(
364  new edm::DetSetVector<PixelSimHitExtraInfo>(theExtraSimHitInfoVector));
365 
366  // Step D: write output to file
367  iEvent.put(std::move(output));
368  iEvent.put(std::move(outputlink));
370  iEvent.put(std::move(outputExtraSim));
371 
372  randomEngine_ = nullptr; // to prevent access outside event
373  }
374 } // namespace cms
iterator end()
Definition: DetSet.h:58
EDGetTokenT< ProductType > consumes(edm::InputTag const &tag)
void finalizeEvent(edm::Event &e, edm::EventSetup const &c) override
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
const edm::ESGetToken< TrackerTopology, TrackerTopologyRcd > tTopoToken_
const TrackerGeometry * pDD
ProductRegistryHelper::BranchAliasSetterT< ProductType > produces()
virtual GlobalVector inTesla(const GlobalPoint &gp) const =0
Field value ad specified global point, in Tesla.
const MagneticField * pSetup
const DetContainer & detUnits() const override
Returm a vector of all GeomDet.
assert(be >=bs)
virtual CLHEP::HepRandomEngine & getEngine(StreamID const &)=0
Use this engine in event methods.
std::unique_ptr< PileupMixingContent > PileupInfo_
unsigned int layer(const DetId &id) const
const std::string hitsProducer
int iEvent
Definition: GenABIO.cc:224
SiPixelDigitizer(const edm::ParameterSet &conf, edm::ProducesCollector, edm::ConsumesCollector &iC)
std::map< unsigned int, PixelGeomDetUnit const * > detectorUnits
void initializeEvent(edm::Event const &e, edm::EventSetup const &c) override
const edm::ESGetToken< TrackerGeometry, TrackerDigiGeometryRecord > pDDToken_
void accumulatePixelHits(edm::Handle< std::vector< PSimHit > >, size_t globalSimHitIndex, const unsigned int tofBin, edm::EventSetup const &c)
bool getData(T &iHolder) const
Definition: EventSetup.h:122
std::unique_ptr< SiPixelDigitizerAlgorithm > _pixeldigialgo
const bool store_SimHitEntryExitPoints_
void accumulate(edm::Event const &e, edm::EventSetup const &c) override
iterator begin()
Definition: DetSet.h:57
Namespace of DDCMS conversion namespace.
Log< level::Info, false > LogInfo
CLHEP::HepRandomEngine * randomEngine_
const edm::ESGetToken< MagneticField, IdealMagneticFieldRecord > pSetupToken_
bool empty() const
Definition: DetSet.h:62
HLT enums.
const vstring trackerContainers
bool isAvailable() const
Definition: Service.h:40
def move(src, dest)
Definition: eostools.py:511
bool isTrackerPixel(GeomDetEnumerators::SubDetector m)
std::map< std::string, size_t > crossingSimHitIndexOffset_
Offset to add to the index of each sim hit to account for which crossing it&#39;s in. ...
#define LogDebug(id)