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