CMS 3D CMS Logo

SiStripDigitizerAlgorithm.cc
Go to the documentation of this file.
1 // File: SiStripDigitizerAlgorithm.cc
2 // Description: Steering class for digitization.
3 // Modified 15/May/2013 mark.grimes@bristol.ac.uk - Modified so that the digi-sim link has the correct
4 // index for the sim hits stored. It was previously always set to zero (I won't mention that it was
5 // me who originally wrote that).
6 // Modified on Feb 11, 2015: prolay.kumar.mal@cern.ch & Jean-Laurent.Agram@cern.ch
7 // Added/Modified the individual strip noise in zero suppression
8 // mode from the conditions DB; previously, the digitizer used to
9 // consider the noise value for individual strips inside a module from
10 // the central strip noise value.
12 #include <vector>
13 #include <algorithm>
14 #include <iostream>
31 #include "CLHEP/Random/RandFlat.h"
32 
33 #include <cstring>
34 #include <sstream>
35 
36 #include <boost/algorithm/string.hpp>
37 
39  : theThreshold(conf.getParameter<double>("NoiseSigmaThreshold")),
40  cmnRMStib(conf.getParameter<double>("cmnRMStib")),
41  cmnRMStob(conf.getParameter<double>("cmnRMStob")),
42  cmnRMStid(conf.getParameter<double>("cmnRMStid")),
43  cmnRMStec(conf.getParameter<double>("cmnRMStec")),
44  APVSaturationProbScaling_(conf.getParameter<double>("APVSaturationProbScaling")),
45  makeDigiSimLinks_(conf.getUntrackedParameter<bool>("makeDigiSimLinks", false)),
46  peakMode(conf.getParameter<bool>("APVpeakmode")),
47  noise(conf.getParameter<bool>("Noise")),
48  RealPedestals(conf.getParameter<bool>("RealPedestals")),
49  SingleStripNoise(conf.getParameter<bool>("SingleStripNoise")),
50  CommonModeNoise(conf.getParameter<bool>("CommonModeNoise")),
51  BaselineShift(conf.getParameter<bool>("BaselineShift")),
52  APVSaturationFromHIP(conf.getParameter<bool>("APVSaturationFromHIP")),
53  theFedAlgo(conf.getParameter<int>("FedAlgorithm")),
54  zeroSuppression(conf.getParameter<bool>("ZeroSuppression")),
55  theElectronPerADC(conf.getParameter<double>(peakMode ? "electronPerAdcPeak" : "electronPerAdcDec")),
56  theTOFCutForPeak(conf.getParameter<double>("TOFCutForPeak")),
57  theTOFCutForDeconvolution(conf.getParameter<double>("TOFCutForDeconvolution")),
58  tofCut(peakMode ? theTOFCutForPeak : theTOFCutForDeconvolution),
59  cosmicShift(conf.getUntrackedParameter<double>("CosmicDelayShift")),
60  inefficiency(conf.getParameter<double>("Inefficiency")),
61  pedOffset((unsigned int)conf.getParameter<double>("PedestalsOffset")),
62  PreMixing_(conf.getParameter<bool>("PreMixingMode")),
63  deadChannelToken_(iC.esConsumes()),
64  pdtToken_(iC.esConsumes()),
65  lorentzAngleToken_(iC.esConsumes(edm::ESInputTag("", conf.getParameter<std::string>("LorentzAngle")))),
66  theSiHitDigitizer(new SiHitDigitizer(conf)),
67  theSiPileUpSignals(new SiPileUpSignals()),
68  theSiNoiseAdder(new SiGaussianTailNoiseAdder(theThreshold)),
69  theSiDigitalConverter(new SiTrivialDigitalConverter(theElectronPerADC, PreMixing_)),
70  theSiZeroSuppress(new SiStripFedZeroSuppression(theFedAlgo, &iC)),
71  APVProbabilityFile(conf.getParameter<edm::FileInPath>("APVProbabilityFile")),
72  includeAPVSimulation_(conf.getParameter<bool>("includeAPVSimulation")),
73  apv_maxResponse_(conf.getParameter<double>("apv_maxResponse")),
74  apv_rate_(conf.getParameter<double>("apv_rate")),
75  apv_mVPerQ_(conf.getParameter<double>("apv_mVPerQ")),
76  apv_fCPerElectron_(conf.getParameter<double>("apvfCPerElectron")) {
77  if (peakMode) {
78  LogDebug("StripDigiInfo") << "APVs running in peak mode (poor time resolution)";
79  } else {
80  LogDebug("StripDigiInfo") << "APVs running in deconvolution mode (good time resolution)";
81  };
82  if (SingleStripNoise)
83  LogDebug("SiStripDigitizerAlgorithm") << " SingleStripNoise: ON";
84  else
85  LogDebug("SiStripDigitizerAlgorithm") << " SingleStripNoise: OFF";
86  if (CommonModeNoise)
87  LogDebug("SiStripDigitizerAlgorithm") << " CommonModeNoise: ON";
88  else
89  LogDebug("SiStripDigitizerAlgorithm") << " CommonModeNoise: OFF";
91  throw cms::Exception("PreMixing does not work with HIP loss simulation yet");
94  APVProbaFile.open((APVProbabilityFile.fullPath()).c_str());
95  if (APVProbaFile.is_open()) {
96  while (getline(APVProbaFile, line)) {
97  std::vector<std::string> strs;
98  boost::split(strs, line, boost::is_any_of(" "));
99  if (strs.size() == 2) {
100  mapOfAPVprobabilities[std::stoi(strs.at(0))] = std::stof(strs.at(1));
101  }
102  }
103  APVProbaFile.close();
104  } else
105  throw cms::Exception("MissingInput") << "It seems that the APV probability list is missing\n";
106  }
107 }
108 
110 
112  auto const& deadChannel = iSetup.getData(deadChannelToken_);
113 
114  unsigned int detId = det->geographicalId().rawId();
115  int numStrips = (det->specificTopology()).nstrips();
116 
117  SiStripBadStrip::Range detBadStripRange = deadChannel.getRange(detId);
118  //storing the bad strip of the the module. the module is not removed but just signal put to 0
119  std::vector<bool>& badChannels = allBadChannels[detId];
120  badChannels.clear();
121  badChannels.insert(badChannels.begin(), numStrips, false);
122  for (SiStripBadStrip::ContainerIterator it = detBadStripRange.first; it != detBadStripRange.second; ++it) {
123  SiStripBadStrip::data fs = deadChannel.decode(*it);
124  for (int strip = fs.firstStrip; strip < fs.firstStrip + fs.range; ++strip) {
125  badChannels[strip] = true;
126  }
127  }
128  firstChannelsWithSignal[detId] = numStrips;
129  lastChannelsWithSignal[detId] = 0;
130 
131  // if(APVSaturationFromHIP){
132  // std::bitset<6> &bs=SiStripTrackerAffectedAPVMap[detId];
133  // if(bs.any())theAffectedAPVvector.push_back(std::make_pair(detId,bs));
134  //}
135 }
136 
138  theSiPileUpSignals->reset();
139  // This should be clear by after all calls to digitize(), but I might as well make sure
140  associationInfoForDetId_.clear();
141 
142  APVSaturationProb_ = APVSaturationProbScaling_; // reset probability
144  FirstLumiCalc_ = true;
145  FirstDigitize_ = true;
146 
147  nTruePU_ = 0;
148 
149  //get gain noise pedestal lorentzAngle from ES handle
152 }
153 
154 // Run the algorithm for a given module
155 // ------------------------------------
156 
157 void SiStripDigitizerAlgorithm::accumulateSimHits(std::vector<PSimHit>::const_iterator inputBegin,
158  std::vector<PSimHit>::const_iterator inputEnd,
159  size_t inputBeginGlobalIndex,
160  unsigned int tofBin,
161  const StripGeomDetUnit* det,
162  const GlobalVector& bfield,
163  const TrackerTopology* tTopo,
164  CLHEP::HepRandomEngine* engine) {
165  // produce SignalPoints for all SimHits in detector
166  unsigned int detID = det->geographicalId().rawId();
167  int numStrips = (det->specificTopology()).nstrips();
168 
169  size_t thisFirstChannelWithSignal = numStrips;
170  size_t thisLastChannelWithSignal = 0;
171 
172  float langle = (lorentzAngleHandle.isValid()) ? lorentzAngleHandle->getLorentzAngle(detID) : 0.;
173 
174  std::vector<float> locAmpl(numStrips, 0.);
175 
176  // Loop over hits
177 
178  uint32_t detId = det->geographicalId().rawId();
179  // First: loop on the SimHits
180  if (CLHEP::RandFlat::shoot(engine) > inefficiency) {
181  AssociationInfoForChannel* pDetIDAssociationInfo; // I only need this if makeDigiSimLinks_ is true...
182  if (makeDigiSimLinks_)
183  pDetIDAssociationInfo = &(associationInfoForDetId_[detId]); // ...so only search the map if that is the case
184  std::vector<float>
185  previousLocalAmplitude; // Only used if makeDigiSimLinks_ is true. Needed to work out the change in amplitude.
186 
187  size_t simHitGlobalIndex = inputBeginGlobalIndex; // This needs to stored to create the digi-sim link later
188  for (std::vector<PSimHit>::const_iterator simHitIter = inputBegin; simHitIter != inputEnd;
189  ++simHitIter, ++simHitGlobalIndex) {
190  // skip hits not in this detector.
191  if ((*simHitIter).detUnitId() != detId) {
192  continue;
193  }
194  // check TOF
195  if (std::fabs(simHitIter->tof() - cosmicShift -
196  det->surface().toGlobal(simHitIter->localPosition()).mag() / 30.) < tofCut &&
197  simHitIter->energyLoss() > 0) {
198  if (makeDigiSimLinks_)
199  previousLocalAmplitude = locAmpl; // Not needed except to make the sim link association.
200  size_t localFirstChannel = numStrips;
201  size_t localLastChannel = 0;
202  // process the hit
203  theSiHitDigitizer->processHit(
204  &*simHitIter, *det, bfield, langle, locAmpl, localFirstChannel, localLastChannel, tTopo, engine);
205 
206  if (thisFirstChannelWithSignal > localFirstChannel)
207  thisFirstChannelWithSignal = localFirstChannel;
208  if (thisLastChannelWithSignal < localLastChannel)
209  thisLastChannelWithSignal = localLastChannel;
210 
211  if (makeDigiSimLinks_) { // No need to do any of this if truth association was turned off in the configuration
212  for (size_t stripIndex = 0; stripIndex < locAmpl.size(); ++stripIndex) {
213  // Work out the amplitude from this SimHit from the difference of what it was before and what it is now
214  float signalFromThisSimHit = locAmpl[stripIndex] - previousLocalAmplitude[stripIndex];
215  if (signalFromThisSimHit != 0) { // If this SimHit had any contribution I need to record it.
216  auto& associationVector = (*pDetIDAssociationInfo)[stripIndex];
217  bool addNewEntry = true;
218  // Make sure the hit isn't in already. I've seen this a few times, it always seems to happen in pairs so I think
219  // it's something to do with the stereo strips.
220  for (auto& associationInfo : associationVector) {
221  if (associationInfo.trackID == simHitIter->trackId() &&
222  associationInfo.eventID == simHitIter->eventId()) {
223  // The hit is already in, so add this second contribution and move on
224  associationInfo.contributionToADC += signalFromThisSimHit;
225  addNewEntry = false;
226  break;
227  }
228  } // end of loop over associationVector
229  // If the hit wasn't already in create a new association info structure.
230  if (addNewEntry)
231  associationVector.push_back(AssociationInfo{
232  simHitIter->trackId(), simHitIter->eventId(), signalFromThisSimHit, simHitGlobalIndex, tofBin});
233  } // end of "if( signalFromThisSimHit!=0 )"
234  } // end of loop over locAmpl strips
235  } // end of "if( makeDigiSimLinks_ )"
236  } // end of TOF check
237  } // end for
238  }
239  theSiPileUpSignals->add(detID, locAmpl, thisFirstChannelWithSignal, thisLastChannelWithSignal);
240 
241  if (firstChannelsWithSignal[detID] > thisFirstChannelWithSignal)
242  firstChannelsWithSignal[detID] = thisFirstChannelWithSignal;
243  if (lastChannelsWithSignal[detID] < thisLastChannelWithSignal)
244  lastChannelsWithSignal[detID] = thisLastChannelWithSignal;
245 }
246 
247 //============================================================================
249  //Instlumi scalefactor calculating for dynamic inefficiency
250 
251  if (puInfo && FirstLumiCalc_) {
252  const std::vector<int>& bunchCrossing = puInfo->getMix_bunchCrossing();
253  const std::vector<float>& TrueInteractionList = puInfo->getMix_TrueInteractions();
254  const int bunchSpacing = puInfo->getMix_bunchSpacing();
255 
256  double RevFreq = 11245.;
257  double minBXsec = 70.0E-27; // use 70mb as an approximation
258  double Bunch = 2100.; // 2016 value
259  if (bunchSpacing == 50)
260  Bunch = Bunch / 2.;
261 
262  int pui = 0, p = 0;
263  std::vector<int>::const_iterator pu;
264  std::vector<int>::const_iterator pu0 = bunchCrossing.end();
265 
266  for (pu = bunchCrossing.begin(); pu != bunchCrossing.end(); ++pu) {
267  if (*pu == 0) {
268  pu0 = pu;
269  p = pui;
270  }
271  pui++;
272  }
273  if (pu0 != bunchCrossing.end()) { // found the in-time interaction
274  nTruePU_ = TrueInteractionList.at(p);
275  double instLumi = Bunch * nTruePU_ * RevFreq / minBXsec;
276  APVSaturationProb_ = instLumi / 6.0E33;
277  }
278  FirstLumiCalc_ = false;
279  }
280 }
281 
282 //============================================================================
283 
285  edm::DetSet<SiStripRawDigi>& outrawdigi,
286  edm::DetSet<SiStripRawDigi>& outStripAmplitudes,
287  edm::DetSet<SiStripRawDigi>& outStripAmplitudesPostAPV,
288  edm::DetSet<SiStripRawDigi>& outStripAPVBaselines,
290  const StripGeomDetUnit* det,
291  const SiStripGain& gain,
293  const SiStripNoises& noiseObj,
294  const SiStripPedestals& pedestal,
295  bool simulateAPVInThisEvent,
296  const SiStripApvSimulationParameters* apvSimulationParameters,
297  std::vector<std::pair<int, std::bitset<6>>>& theAffectedAPVvector,
298  CLHEP::HepRandomEngine* engine,
299  const TrackerTopology* tTopo) {
300  unsigned int detID = det->geographicalId().rawId();
301  int numStrips = (det->specificTopology()).nstrips();
302 
303  DetId detId(detID);
304  uint32_t SubDet = detId.subdetId();
305 
306  const SiPileUpSignals::SignalMapType* theSignal(theSiPileUpSignals->getSignal(detID));
307 
308  std::vector<float> detAmpl(numStrips, 0.);
309  if (theSignal) {
310  for (const auto& amp : *theSignal) {
311  detAmpl[amp.first] = amp.second;
312  }
313  }
314 
315  //removing signal from the dead (and HIP effected) strips
316  std::vector<bool>& badChannels = allBadChannels[detID];
317  for (int strip = 0; strip < numStrips; ++strip) {
318  if (badChannels[strip]) {
319  detAmpl[strip] = 0.;
320  }
321  }
322 
323  if (includeAPVSimulation_ && simulateAPVInThisEvent) {
324  // Get index in apv baseline distributions corresponding to z of detSet and PU
325  const StripTopology* topol = dynamic_cast<const StripTopology*>(&(det->specificTopology()));
326  LocalPoint localPos = topol->localPosition(0);
327  GlobalPoint globalPos = det->surface().toGlobal(Local3DPoint(localPos.x(), localPos.y(), localPos.z()));
328  float detSet_z = fabs(globalPos.z());
329  float detSet_r = globalPos.perp();
330 
331  // Store SCD, before APV sim
332  outStripAmplitudes.reserve(numStrips);
333  for (int strip = 0; strip < numStrips; ++strip) {
334  outStripAmplitudes.emplace_back(SiStripRawDigi(detAmpl[strip] / theElectronPerADC));
335  }
336 
337  // Simulate APV response for each strip
338  for (int strip = 0; strip < numStrips; ++strip) {
339  if (detAmpl[strip] > 0) {
340  // Convert charge from electrons to fC
341  double stripCharge = detAmpl[strip] * apv_fCPerElectron_;
342 
343  // Get APV baseline
344  double baselineV = 0;
346  baselineV = apvSimulationParameters->sampleTIB(tTopo->tibLayer(detId), detSet_z, nTruePU_, engine);
347  } else if (SubDet == SiStripSubdetector::TOB) {
348  baselineV = apvSimulationParameters->sampleTOB(tTopo->tobLayer(detId), detSet_z, nTruePU_, engine);
349  } else if (SubDet == SiStripSubdetector::TID) {
350  baselineV = apvSimulationParameters->sampleTID(tTopo->tidWheel(detId), detSet_r, nTruePU_, engine);
351  } else if (SubDet == SiStripSubdetector::TEC) {
352  baselineV = apvSimulationParameters->sampleTEC(tTopo->tecWheel(detId), detSet_r, nTruePU_, engine);
353  }
354  // Store APV baseline for this strip
355  outStripAPVBaselines.emplace_back(SiStripRawDigi(baselineV));
356 
357  // Fitted parameters from G Hall/M Raymond
358  double maxResponse = apv_maxResponse_;
359  double rate = apv_rate_;
360 
361  double outputChargeInADC = 0;
362  if (baselineV < apv_maxResponse_) {
363  // Convert V0 into baseline charge
364  double baselineQ = -1.0 * rate * log(2 * maxResponse / (baselineV + maxResponse) - 1);
365 
366  // Add charge deposited in this BX
367  double newStripCharge = baselineQ + stripCharge;
368 
369  // Apply APV response
370  double signalV = 2 * maxResponse / (1 + exp(-1.0 * newStripCharge / rate)) - maxResponse;
371  double gain = signalV - baselineV;
372 
373  // Convert gain (mV) to charge (assuming linear region of APV) and then to electrons
374  double outputCharge = gain / apv_mVPerQ_;
375  outputChargeInADC = outputCharge / apv_fCPerElectron_;
376  }
377 
378  // Output charge back to original container
379  detAmpl[strip] = outputChargeInADC;
380  }
381  }
382 
383  // Store SCD, after APV sim
384  outStripAmplitudesPostAPV.reserve(numStrips);
385  for (int strip = 0; strip < numStrips; ++strip)
386  outStripAmplitudesPostAPV.emplace_back(SiStripRawDigi(detAmpl[strip] / theElectronPerADC));
387  }
388 
389  if (APVSaturationFromHIP) {
390  //Implementation of the proper charge scaling function. Need consider resaturation effect:
391  //The probability map gives the probability that at least one HIP happened during the last N bunch crossings (cfr APV recovery time).
392  //The impact on the charge depends on the clostest HIP occurance (in terms of bunch crossing).
393  //The function discribing the APV recovery is therefore the weighted average function which takes into account all possibilities of HIP occurances across the last bx's.
394 
395  // do this step here because we now have access to luminosity information
396  if (FirstDigitize_) {
397  for (std::map<int, float>::iterator iter = mapOfAPVprobabilities.begin(); iter != mapOfAPVprobabilities.end();
398  ++iter) {
399  std::bitset<6> bs;
400  for (int Napv = 0; Napv < 6; Napv++) {
401  float cursor = CLHEP::RandFlat::shoot(engine);
402  bs[Napv] = cursor < iter->second * APVSaturationProb_
403  ? true
404  : false; //APVSaturationProb has been scaled by PU luminosity
405  }
406  SiStripTrackerAffectedAPVMap[iter->first] = bs;
407  }
408 
410  bool HasAtleastOneAffectedAPV = false;
411  while (!HasAtleastOneAffectedAPV) {
412  for (int bx = floor(300.0 / 25.0); bx > 0; bx--) { //Reminder: make these numbers not hard coded!!
413  float temp = CLHEP::RandFlat::shoot(engine) < 0.5 ? 1 : 0;
414  if (temp == 1 && bx < NumberOfBxBetweenHIPandEvent) {
416  HasAtleastOneAffectedAPV = true;
417  }
418  }
419  }
420 
421  FirstDigitize_ = false;
422  }
423 
424  std::bitset<6>& bs = SiStripTrackerAffectedAPVMap[detID];
425 
426  if (bs.any()) {
427  // store this information so it can be saved to the event later
428  theAffectedAPVvector.push_back(std::make_pair(detID, bs));
429 
430  if (!PreMixing_) {
431  // Here below is the scaling function which describes the evolution of the baseline (i.e. how the charge is suppressed).
432  // This must be replaced as soon as we have a proper modeling of the baseline evolution from VR runs
433  float Shift =
434  1 - NumberOfBxBetweenHIPandEvent / floor(300.0 / 25.0); //Reminder: make these numbers not hardcoded!!
435  float randomX = CLHEP::RandFlat::shoot(engine);
436  float scalingValue = (randomX - Shift) * 10.0 / 7.0 - 3.0 / 7.0;
437 
438  for (int strip = 0; strip < numStrips; ++strip) {
439  if (!badChannels[strip] && bs[strip / 128] == 1) {
440  detAmpl[strip] *= scalingValue > 0 ? scalingValue : 0.0;
441  }
442  }
443  }
444  }
445  }
446 
447  SiStripNoises::Range detNoiseRange = noiseObj.getRange(detID);
448  SiStripApvGain::Range detGainRange = gain.getRange(detID);
449  SiStripPedestals::Range detPedestalRange = pedestal.getRange(detID);
450 
451  // -----------------------------------------------------------
452 
453  auto& firstChannelWithSignal = firstChannelsWithSignal[detID];
454  auto& lastChannelWithSignal = lastChannelsWithSignal[detID];
455  auto iAssociationInfoByChannel =
456  associationInfoForDetId_.find(detID); // Use an iterator so that I can easily remove it once finished
457 
458  if (zeroSuppression) {
459  //Adding the strip noise
460  //------------------------------------------------------
461  if (noise) {
462  if (SingleStripNoise) {
463  // std::cout<<"In SSN, detId="<<detID<<std::endl;
464  std::vector<float> noiseRMSv;
465  noiseRMSv.clear();
466  noiseRMSv.insert(noiseRMSv.begin(), numStrips, 0.);
467  for (int strip = 0; strip < numStrips; ++strip) {
468  if (!badChannels[strip]) {
469  float gainValue = gain.getStripGain(strip, detGainRange);
470  noiseRMSv[strip] = (noiseObj.getNoise(strip, detNoiseRange)) * theElectronPerADC / gainValue;
471  //std::cout<<"<SiStripDigitizerAlgorithm::digitize>: gainValue: "<<gainValue<<"\tnoiseRMSv["<<strip<<"]: "<<noiseRMSv[strip]<<std::endl;
472  }
473  }
474  theSiNoiseAdder->addNoiseVR(detAmpl, noiseRMSv, engine);
475  } else {
476  int RefStrip = int(numStrips / 2.);
477  while (RefStrip < numStrips &&
478  badChannels[RefStrip]) { //if the refstrip is bad, I move up to when I don't find it
479  RefStrip++;
480  }
481  if (RefStrip < numStrips) {
482  float RefgainValue = gain.getStripGain(RefStrip, detGainRange);
483  float RefnoiseRMS = noiseObj.getNoise(RefStrip, detNoiseRange) * theElectronPerADC / RefgainValue;
484 
485  theSiNoiseAdder->addNoise(
486  detAmpl, firstChannelWithSignal, lastChannelWithSignal, numStrips, RefnoiseRMS, engine);
487  //std::cout<<"<SiStripDigitizerAlgorithm::digitize>: RefgainValue: "<<RefgainValue<<"\tRefnoiseRMS: "<<RefnoiseRMS<<std::endl;
488  }
489  }
490  } //if noise
491 
492  DigitalVecType digis;
493  theSiZeroSuppress->suppress(
494  theSiDigitalConverter->convert(detAmpl, &gain, detID), digis, detID, noiseObj, threshold);
495  // Now do the association to truth. Note that if truth association was turned off in the configuration this map
496  // will be empty and the iterator will always equal associationInfoForDetId_.end().
497  if (iAssociationInfoByChannel !=
498  associationInfoForDetId_.end()) { // make sure the readings for this DetID aren't completely from noise
499  for (const auto& iDigi : digis) {
500  auto& associationInfoByChannel = iAssociationInfoByChannel->second;
501  const std::vector<AssociationInfo>& associationInfo = associationInfoByChannel[iDigi.channel()];
502 
503  // Need to find the total from all sim hits, because this might not be the same as the total
504  // digitised due to noise or whatever.
505  float totalSimADC = 0;
506  for (const auto& iAssociationInfo : associationInfo)
507  totalSimADC += iAssociationInfo.contributionToADC;
508  // Now I know that I can loop again and create the links
509  for (const auto& iAssociationInfo : associationInfo) {
510  // Note simHitGlobalIndex used to have +1 because TrackerHitAssociator (the only place I can find this value being used)
511  // expected counting to start at 1, not 0. Now changed.
512  outLink.push_back(StripDigiSimLink(iDigi.channel(),
513  iAssociationInfo.trackID,
514  iAssociationInfo.simHitGlobalIndex,
515  iAssociationInfo.tofBin,
516  iAssociationInfo.eventID,
517  iAssociationInfo.contributionToADC / totalSimADC));
518  } // end of loop over associationInfo
519  } // end of loop over the digis
520  } // end of check that iAssociationInfoByChannel is a valid iterator
521  outdigi.data = digis;
522  } //if zeroSuppression
523 
524  if (!zeroSuppression) {
525  //if(noise){
526  // the constant pedestal offset is needed because
527  // negative adc counts are not allowed in case
528  // Pedestal and CMN subtraction is performed.
529  // The pedestal value read from the conditions
530  // is pedValue and after the pedestal subtraction
531  // the baseline is zero. The Common Mode Noise
532  // is not subtracted from the negative adc counts
533  // channels. Adding pedOffset the baseline is set
534  // to pedOffset after pedestal subtraction and CMN
535  // is subtracted to all the channels since none of
536  // them has negative adc value. The pedOffset is
537  // treated as a constant component in the CMN
538  // estimation and subtracted as CMN.
539 
540  //calculating the charge deposited on each APV and subtracting the shift
541  //------------------------------------------------------
542  if (BaselineShift) {
543  theSiNoiseAdder->addBaselineShift(detAmpl, badChannels);
544  }
545 
546  //Adding the strip noise
547  //------------------------------------------------------
548  if (noise) {
549  std::vector<float> noiseRMSv;
550  noiseRMSv.clear();
551  noiseRMSv.insert(noiseRMSv.begin(), numStrips, 0.);
552 
553  if (SingleStripNoise) {
554  for (int strip = 0; strip < numStrips; ++strip) {
555  if (!badChannels[strip])
556  noiseRMSv[strip] = (noiseObj.getNoise(strip, detNoiseRange)) * theElectronPerADC;
557  }
558 
559  } else {
560  int RefStrip = 0; //int(numStrips/2.);
561  while (RefStrip < numStrips &&
562  badChannels[RefStrip]) { //if the refstrip is bad, I move up to when I don't find it
563  RefStrip++;
564  }
565  if (RefStrip < numStrips) {
566  float noiseRMS = noiseObj.getNoise(RefStrip, detNoiseRange) * theElectronPerADC;
567  for (int strip = 0; strip < numStrips; ++strip) {
568  if (!badChannels[strip])
569  noiseRMSv[strip] = noiseRMS;
570  }
571  }
572  }
573 
574  theSiNoiseAdder->addNoiseVR(detAmpl, noiseRMSv, engine);
575  }
576 
577  //adding the CMN
578  //------------------------------------------------------
579  if (CommonModeNoise) {
580  float cmnRMS = 0.;
581  DetId detId(detID);
582  switch (detId.subdetId()) {
584  cmnRMS = cmnRMStib;
585  break;
587  cmnRMS = cmnRMStid;
588  break;
590  cmnRMS = cmnRMStob;
591  break;
593  cmnRMS = cmnRMStec;
594  break;
595  }
596  cmnRMS *= theElectronPerADC;
597  theSiNoiseAdder->addCMNoise(detAmpl, cmnRMS, badChannels, engine);
598  }
599 
600  //Adding the pedestals
601  //------------------------------------------------------
602 
603  std::vector<float> vPeds;
604  vPeds.clear();
605  vPeds.insert(vPeds.begin(), numStrips, 0.);
606 
607  if (RealPedestals) {
608  for (int strip = 0; strip < numStrips; ++strip) {
609  if (!badChannels[strip])
610  vPeds[strip] = (pedestal.getPed(strip, detPedestalRange) + pedOffset) * theElectronPerADC;
611  }
612  } else {
613  for (int strip = 0; strip < numStrips; ++strip) {
614  if (!badChannels[strip])
615  vPeds[strip] = pedOffset * theElectronPerADC;
616  }
617  }
618 
619  theSiNoiseAdder->addPedestals(detAmpl, vPeds);
620 
621  //if(!RealPedestals&&!CommonModeNoise&&!noise&&!BaselineShift&&!APVSaturationFromHIP){
622 
623  // edm::LogWarning("SiStripDigitizer")<<"You are running the digitizer without Noise generation and without applying Zero Suppression. ARE YOU SURE???";
624  //}else{
625 
626  DigitalRawVecType rawdigis = theSiDigitalConverter->convertRaw(detAmpl, &gain, detID);
627 
628  // Now do the association to truth. Note that if truth association was turned off in the configuration this map
629  // will be empty and the iterator will always equal associationInfoForDetId_.end().
630  if (iAssociationInfoByChannel !=
631  associationInfoForDetId_.end()) { // make sure the readings for this DetID aren't completely from noise
632  // N.B. For the raw digis the channel is inferred from the position in the vector.
633  // I'VE NOT TESTED THIS YET!!!!!
634  // ToDo Test this properly.
635  for (size_t channel = 0; channel < rawdigis.size(); ++channel) {
636  auto& associationInfoByChannel = iAssociationInfoByChannel->second;
637  const auto iAssociationInfo = associationInfoByChannel.find(channel);
638  if (iAssociationInfo == associationInfoByChannel.end())
639  continue; // Skip if there is no sim information for this channel (i.e. it's all noise)
640  const std::vector<AssociationInfo>& associationInfo = iAssociationInfo->second;
641 
642  // Need to find the total from all sim hits, because this might not be the same as the total
643  // digitised due to noise or whatever.
644  float totalSimADC = 0;
645  for (const auto& iAssociationInfo : associationInfo)
646  totalSimADC += iAssociationInfo.contributionToADC;
647  // Now I know that I can loop again and create the links
648  for (const auto& iAssociationInfo : associationInfo) {
649  // Note simHitGlobalIndex used to have +1 because TrackerHitAssociator (the only place I can find this value being used)
650  // expected counting to start at 1, not 0. Now changed.
651  outLink.push_back(StripDigiSimLink(channel,
652  iAssociationInfo.trackID,
653  iAssociationInfo.simHitGlobalIndex,
654  iAssociationInfo.tofBin,
655  iAssociationInfo.eventID,
656  iAssociationInfo.contributionToADC / totalSimADC));
657  } // end of loop over associationInfo
658  } // end of loop over the digis
659  } // end of check that iAssociationInfoByChannel is a valid iterator
660 
661  outrawdigi.data = rawdigis;
662 
663  //}
664  }
665 
666  // Now that I've finished with this entry in the map of associations, I can remove it.
667  // Note that there might not be an association if the ADC reading is from noise in which
668  // case associationIsValid will be false.
669  if (iAssociationInfoByChannel != associationInfoForDetId_.end())
670  associationInfoForDetId_.erase(iAssociationInfoByChannel);
671 }
const edm::ESGetToken< HepPDT::ParticleDataTable, PDTRecord > pdtToken_
const std::unique_ptr< SiPileUpSignals > theSiPileUpSignals
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
unsigned int tobLayer(const DetId &id) const
edm::ESHandle< SiStripLorentzAngle > lorentzAngleHandle
T perp() const
Definition: PV3DBase.h:69
void push_back(const T &t)
Definition: DetSet.h:66
float sampleTOB(layerid layer, float z, float pu, CLHEP::HepRandomEngine *engine) const
std::string fullPath() const
Definition: FileInPath.cc:161
const int & getMix_bunchSpacing() const
std::map< int, float > mapOfAPVprobabilities
AssociationInfoForDetId associationInfoForDetId_
Structure that holds the information on the SimTrack contributions. Only filled if makeDigiSimLinks_ ...
T z() const
Definition: PV3DBase.h:61
SiDigitalConverter::DigitalRawVecType DigitalRawVecType
SiDigitalConverter::DigitalVecType DigitalVecType
std::vector< unsigned int >::const_iterator ContainerIterator
unsigned int tidWheel(const DetId &id) const
unsigned int tecWheel(const DetId &id) const
void initializeEvent(const edm::EventSetup &iSetup)
float sampleTIB(layerid layer, float z, float pu, CLHEP::HepRandomEngine *engine) const
const std::vector< int > & getMix_bunchCrossing() const
std::pair< ContainerIterator, ContainerIterator > Range
void initializeDetUnit(StripGeomDetUnit const *det, const edm::EventSetup &iSetup)
const edm::ESGetToken< SiStripBadStrip, SiStripBadChannelRcd > deadChannelToken_
const std::unique_ptr< const SiGaussianTailNoiseAdder > theSiNoiseAdder
const std::unique_ptr< SiHitDigitizer > theSiHitDigitizer
std::map< unsigned int, size_t > firstChannelsWithSignal
std::map< int, Amplitude > SignalMapType
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
void reserve(size_t s)
Definition: DetSet.h:65
static float getNoise(uint16_t strip, const Range &range)
Definition: SiStripNoises.h:73
const std::unique_ptr< SiTrivialDigitalConverter > theSiDigitalConverter
const std::unique_ptr< SiStripFedZeroSuppression > theSiZeroSuppress
decltype(auto) emplace_back(Args &&... args)
Definition: DetSet.h:68
virtual const StripTopology & specificTopology() const
Returns a reference to the strip proxy topology.
std::pair< ContainerIterator, ContainerIterator > Range
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:48
bool getData(T &iHolder) const
Definition: EventSetup.h:122
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:64
void calculateInstlumiScale(PileupMixingContent *puInfo)
std::map< unsigned int, std::vector< bool > > allBadChannels
ESHandle< T > getHandle(const ESGetToken< T, R > &iToken) const
Definition: EventSetup.h:151
bool isValid() const
Definition: ESHandle.h:44
GlobalPoint toGlobal(const Point2DBase< Scalar, LocalTag > lp) const
Definition: Surface.h:79
void setParticleDataTable(const ParticleDataTable *pardt)
Definition: DetId.h:17
float getLorentzAngle(const uint32_t &) const
float sampleTID(layerid wheel, float r, float pu, CLHEP::HepRandomEngine *engine) const
const Plane & surface() const
The nominal surface of the GeomDet.
Definition: GeomDet.h:37
T mag() const
The vector magnitude. Equivalent to sqrt(vec.mag2())
const std::vector< float > & getMix_TrueInteractions() const
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
const edm::ESGetToken< SiStripLorentzAngle, SiStripLorentzAngleSimRcd > lorentzAngleToken_
std::map< int, std::vector< AssociationInfo > > AssociationInfoForChannel
SiStripDigitizerAlgorithm(const edm::ParameterSet &conf, edm::ConsumesCollector iC)
RealPedestals
NOTE : turning Noise ON/OFF will make a big change Parameters valid only if Noise = True and ZeroSupp...
const Range getRange(const uint32_t detID) const
double rate(double x)
Definition: Constants.cc:3
collection_type data
Definition: DetSet.h:80
HLT enums.
std::pair< ContainerIterator, ContainerIterator > Range
std::map< unsigned int, size_t > lastChannelsWithSignal
void accumulateSimHits(const std::vector< PSimHit >::const_iterator inputBegin, const std::vector< PSimHit >::const_iterator inputEnd, size_t inputBeginGlobalIndex, unsigned int tofBin, const StripGeomDetUnit *stripdet, const GlobalVector &bfield, const TrackerTopology *tTopo, CLHEP::HepRandomEngine *)
virtual LocalPoint localPosition(float strip) const =0
unsigned int tibLayer(const DetId &id) const
std::map< int, std::bitset< 6 > > SiStripTrackerAffectedAPVMap
std::pair< ContainerIterator, ContainerIterator > Range
Definition: SiStripNoises.h:47
A Digi for the silicon strip detector, containing only adc information, and suitable for storing raw ...
float sampleTEC(layerid wheel, float r, float pu, CLHEP::HepRandomEngine *engine) const
#define LogDebug(id)
void digitize(edm::DetSet< SiStripDigi > &outDigis, edm::DetSet< SiStripRawDigi > &outRawDigis, edm::DetSet< SiStripRawDigi > &outStripAmplitudes, edm::DetSet< SiStripRawDigi > &outStripAmplitudesPostAPV, edm::DetSet< SiStripRawDigi > &outStripAPVBaselines, edm::DetSet< StripDigiSimLink > &outLink, const StripGeomDetUnit *stripdet, const SiStripGain &, const SiStripThreshold &, const SiStripNoises &, const SiStripPedestals &, bool simulateAPVInThisEvent, const SiStripApvSimulationParameters *, std::vector< std::pair< int, std::bitset< 6 >>> &theAffectedAPVvector, CLHEP::HepRandomEngine *, const TrackerTopology *tTopo)
Point3DBase< float, LocalTag > Local3DPoint
Definition: LocalPoint.h:9