CMS 3D CMS Logo

SiPixelDigitizerAlgorithm.cc
Go to the documentation of this file.
1 //class SiPixelDigitizerAlgorithm SimTracker/SiPixelDigitizer/src/SiPixelDigitizerAlgoithm.cc
2 
3 // Original Author Danek Kotlinski
4 // Ported in CMSSW by Michele Pioppi-INFN perugia
5 // Added DB capabilities by F.Blekman, Cornell University
6 // Created: Mon Sep 26 11:08:32 CEST 2005
7 // Add tof, change AddNoise to tracked. 4/06
8 // Change drift direction. 6/06 d.k.
9 // Add the statuis (non-rate dependent) inefficiency.
10 // -1 - no ineffciency
11 // 0 - static inefficency only
12 // 1,2 - low-lumi rate dependent inefficency added
13 // 10 - high-lumi inefficiency added
14 // Adopt the correct drift sign convetion from Morris Swartz. d.k. 8/06
15 // Add more complex misscalinbration, change kev/e to 3.61, diff=3.7,d.k.9/06
16 // Add the readout channel electronic noise. d.k. 3/07
17 // Lower the pixel noise from 500 to 175elec.
18 // Change the input threshold from noise units to electrons.
19 // Lower the amount of static dead pixels from 0.01 to 0.001.
20 // Modify to the new random number services. d.k. 5/07
21 // Protect against sigma=0 (delta tracks on the surface). d.k.5/07
22 // Change the TOF cut to lower and upper limit. d.k. 7/07
23 //
24 // July 2008: Split Lorentz Angle configuration in BPix/FPix (V. Cuplov)
25 // tanLorentzAngleperTesla_FPix=0.0912 and tanLorentzAngleperTesla_BPix=0.106
26 // Sept. 2008: Disable Pixel modules which are declared dead in the configuration python file. (V. Cuplov)
27 // Oct. 2008: Accessing/Reading the Lorentz angle from the DataBase instead of the cfg file. (V. Cuplov)
28 // Accessing dead modules from the DB. Implementation done and tested on a test.db
29 // Do not use this option for now. The PixelQuality Objects are not in the official DB yet.
30 // Feb. 2009: Split Fpix and Bpix threshold and use official numbers (V. Cuplov)
31 // ThresholdInElectrons_FPix = 2870 and ThresholdInElectrons_BPix = 3700
32 // update the electron to VCAL conversion using: VCAL_electrons = VCAL * 65.5 - 414
33 // Feb. 2009: Threshold gaussian smearing (V. Cuplov)
34 // March, 2009: changed DB access to *SimRcd objects (to de-couple the DB objects from reco chain) (F. Blekman)
35 // May, 2009: Pixel charge VCAL smearing. (V. Cuplov)
36 // November, 2009: new parameterization of the pixel response. (V. Cuplov)
37 // December, 2009: Fix issue with different compilers.
38 // October, 2010: Improvement: Removing single dead ROC (V. Cuplov)
39 // November, 2010: Bug fix in removing TBMB/A half-modules (V. Cuplov)
40 // February, 2011: Time improvement in DriftDirection() (J. Bashir Butt)
41 // June, 2011: Bug Fix for pixels on ROC edges in module_killing_DB() (J. Bashir Butt)
42 // February, 2018: Implement cluster charge reweighting (P. Schuetze, with code from A. Hazi)
43 #include <iostream>
44 #include <iomanip>
45 
47 
54 
55 #include <gsl/gsl_sf_erf.h>
57 #include "CLHEP/Random/RandGaussQ.h"
58 #include "CLHEP/Random/RandFlat.h"
59 #include "CLHEP/Random/RandGeneral.h"
60 
61 //#include "PixelIndices.h"
65 
71 
72 // Accessing dead pixel modules from the DB:
74 
76 
90 
97 
98 // Geometry
101 
103 
104 using namespace edm;
105 using namespace sipixelobjects;
106 
108  if (use_ineff_from_db_) { // load gain calibration service fromdb...
109  theSiPixelGainCalibrationService_->setESObjects(es);
110  }
111  if (use_deadmodule_DB_) {
112  SiPixelBadModule_ = &es.getData(SiPixelBadModuleToken_);
113  }
114  if (use_LorentzAngle_DB_) {
115  // Get Lorentz angle from DB record
116  SiPixelLorentzAngle_ = &es.getData(SiPixelLorentzAngleToken_);
117  }
118  //gets the map and geometry from the DB (to kill ROCs)
119  map_ = &es.getData(mapToken_);
120  geom_ = &es.getData(geomToken_);
121 
122  if (KillBadFEDChannels) {
123  scenarioProbability_ = &es.getData(scenarioProbabilityToken_);
124  quality_map = &es.getData(PixelFEDChannelCollectionMapToken_);
125 
126  SiPixelQualityProbabilities::probabilityMap m_probabilities = scenarioProbability_->getProbability_Map();
127  std::vector<std::string> allScenarios;
128 
129  std::transform(quality_map->begin(),
130  quality_map->end(),
131  std::back_inserter(allScenarios),
132  [](const PixelFEDChannelCollectionMap::value_type& pair) { return pair.first; });
133 
134  std::vector<std::string> allScenariosInProb;
135 
136  for (auto it = m_probabilities.begin(); it != m_probabilities.end(); ++it) {
137  //int PUbin = it->first;
138  for (const auto& entry : it->second) {
139  auto scenario = entry.first;
140  auto probability = entry.second;
141  if (probability != 0) {
142  if (std::find(allScenariosInProb.begin(), allScenariosInProb.end(), scenario) == allScenariosInProb.end()) {
143  allScenariosInProb.push_back(scenario);
144  }
145  } // if prob!=0
146  } // loop on the scenarios for that PU bin
147  } // loop on PU bins
148 
149  std::vector<std::string> notFound;
150  std::copy_if(allScenariosInProb.begin(),
151  allScenariosInProb.end(),
152  std::back_inserter(notFound),
153  [&allScenarios](const std::string& arg) {
154  return (std::find(allScenarios.begin(), allScenarios.end(), arg) == allScenarios.end());
155  });
156 
157  if (!notFound.empty()) {
158  for (const auto& entry : notFound) {
159  LogError("SiPixelFEDChannelContainer")
160  << "The requested scenario: " << entry << " is not found in the map!! \n";
161  }
162  throw cms::Exception("SiPixelDigitizerAlgorithm") << "Found: " << notFound.size()
163  << " missing scenario(s) in SiPixelStatusScenariosRcd while "
164  "present in SiPixelStatusScenarioProbabilityRcd \n";
165  }
166  }
167  LogInfo("PixelDigitizer ") << " PixelDigitizerAlgorithm init \n";
168  LogInfo("PixelDigitizer ") << " PixelDigitizerAlgorithm --> UseReweighting " << UseReweighting << "\n";
169  LogInfo("PixelDigitizer ") << " PixelDigitizerAlgorithm --> store_SimHitEntryExitPoints_ "
170  << store_SimHitEntryExitPoints_ << "\n";
171  LogInfo("PixelDigitizer ") << " PixelDigitizerAlgorithm --> makeDigiSimLinks_ " << makeDigiSimLinks_ << "\n";
172 
173  TheNewSiPixelChargeReweightingAlgorithmClass->init(es);
174 
175  int collectionIndex = 0; // I don't find what are the different collections here
176  int tofBin = 0;
177  for (int i1 = 1; i1 < 3; i1++) {
178  for (int i2 = 0; i2 < 2; i2++) {
179  if (i2 == 0) {
180  tofBin = PixelDigiSimLink::LowTof;
181  } else {
182  tofBin = PixelDigiSimLink::HighTof;
183  }
184  subDetTofBin theSubDetTofBin = std::make_pair(i1, tofBin);
185  SimHitCollMap[theSubDetTofBin] = collectionIndex;
186  collectionIndex++;
187  }
188  }
189 }
190 
191 //=========================================================================
192 
194  : mapToken_(iC.esConsumes()),
195  geomToken_(iC.esConsumes()),
196 
197  _signal(),
198  makeDigiSimLinks_(conf.getUntrackedParameter<bool>("makeDigiSimLinks", true)),
199  store_SimHitEntryExitPoints_(
200  conf.exists("store_SimHitEntryExitPoints") ? conf.getParameter<bool>("store_SimHitEntryExitPoints") : false),
201  use_ineff_from_db_(conf.getParameter<bool>("useDB")),
202  use_module_killing_(conf.getParameter<bool>("killModules")), // boolean to kill or not modules
203  use_deadmodule_DB_(conf.getParameter<bool>("DeadModules_DB")), // boolean to access dead modules from DB
204  use_LorentzAngle_DB_(conf.getParameter<bool>("LorentzAngle_DB")), // boolean to access Lorentz angle from DB
205 
206  DeadModules(use_deadmodule_DB_ ? Parameters()
207  : conf.getParameter<Parameters>("DeadModules")), // get dead module from cfg file
208 
209  TheNewSiPixelChargeReweightingAlgorithmClass(),
210 
211  // Common pixel parameters
212  // These are parameters which are not likely to be changed
213  GeVperElectron(3.61E-09), // 1 electron(3.61eV, 1keV(277e, mod 9/06 d.k.
214  Sigma0(0.00037), // Charge diffusion constant 7->3.7
215  Dist300(0.0300), // normalized to 300micron Silicon
216  alpha2Order(conf.getParameter<bool>("Alpha2Order")), // switch on/off of E.B effect
217  ClusterWidth(3.), // Charge integration spread on the collection plane
218 
219  // get external parameters:
220  // To account for upgrade geometries do not assume the number
221  // of layers or disks.
222  NumberOfBarrelLayers(conf.exists("NumPixelBarrel") ? conf.getParameter<int>("NumPixelBarrel") : 3),
223  NumberOfEndcapDisks(conf.exists("NumPixelEndcap") ? conf.getParameter<int>("NumPixelEndcap") : 2),
224 
225  // ADC calibration 1adc count(135e.
226  // Corresponds to 2adc/kev, 270[e/kev]/135[e/adc](2[adc/kev]
227  // Be carefull, this parameter is also used in SiPixelDet.cc to
228  // calculate the noise in adc counts from noise in electrons.
229  // Both defaults should be the same.
230  theElectronPerADC(conf.getParameter<double>("ElectronPerAdc")),
231 
232  // ADC saturation value, 255(8bit adc.
233  //theAdcFullScale(conf.getUntrackedParameter<int>("AdcFullScale",255)),
234  theAdcFullScale(conf.getParameter<int>("AdcFullScale")),
235  theAdcFullScLateCR(conf.getParameter<int>("AdcFullScLateCR")),
236 
237  // Noise in electrons:
238  // Pixel cell noise, relevant for generating noisy pixels
239  theNoiseInElectrons(conf.getParameter<double>("NoiseInElectrons")),
240 
241  // Fill readout noise, including all readout chain, relevant for smearing
242  //theReadoutNoise(conf.getUntrackedParameter<double>("ReadoutNoiseInElec",500.)),
243  theReadoutNoise(conf.getParameter<double>("ReadoutNoiseInElec")),
244 
245  // Pixel threshold in units of noise:
246  // thePixelThreshold(conf.getParameter<double>("ThresholdInNoiseUnits")),
247  // Pixel threshold in electron units.
248  theThresholdInE_FPix(conf.getParameter<double>("ThresholdInElectrons_FPix")),
249  theThresholdInE_BPix(conf.getParameter<double>("ThresholdInElectrons_BPix")),
250  theThresholdInE_BPix_L1(conf.exists("ThresholdInElectrons_BPix_L1")
251  ? conf.getParameter<double>("ThresholdInElectrons_BPix_L1")
252  : theThresholdInE_BPix),
253  theThresholdInE_BPix_L2(conf.exists("ThresholdInElectrons_BPix_L2")
254  ? conf.getParameter<double>("ThresholdInElectrons_BPix_L2")
255  : theThresholdInE_BPix),
256 
257  // Add threshold gaussian smearing:
258  theThresholdSmearing_FPix(conf.getParameter<double>("ThresholdSmearing_FPix")),
259  theThresholdSmearing_BPix(conf.getParameter<double>("ThresholdSmearing_BPix")),
260  theThresholdSmearing_BPix_L1(conf.exists("ThresholdSmearing_BPix_L1")
261  ? conf.getParameter<double>("ThresholdSmearing_BPix_L1")
262  : theThresholdSmearing_BPix),
263  theThresholdSmearing_BPix_L2(conf.exists("ThresholdSmearing_BPix_L2")
264  ? conf.getParameter<double>("ThresholdSmearing_BPix_L2")
265  : theThresholdSmearing_BPix),
266 
267  // electrons to VCAL conversion needed in misscalibrate()
268  electronsPerVCAL(conf.getParameter<double>("ElectronsPerVcal")),
269  electronsPerVCAL_Offset(conf.getParameter<double>("ElectronsPerVcal_Offset")),
270  electronsPerVCAL_L1(conf.exists("ElectronsPerVcal_L1") ? conf.getParameter<double>("ElectronsPerVcal_L1")
271  : electronsPerVCAL),
272  electronsPerVCAL_L1_Offset(conf.exists("ElectronsPerVcal_L1_Offset")
273  ? conf.getParameter<double>("ElectronsPerVcal_L1_Offset")
274  : electronsPerVCAL_Offset),
275 
276  //theTofCut 12.5, cut in particle TOD +/- 12.5ns
277  //theTofCut(conf.getUntrackedParameter<double>("TofCut",12.5)),
278  theTofLowerCut(conf.getParameter<double>("TofLowerCut")),
279  theTofUpperCut(conf.getParameter<double>("TofUpperCut")),
280 
281  // Get the Lorentz angle from the cfg file:
282  tanLorentzAnglePerTesla_FPix(use_LorentzAngle_DB_ ? 0.0
283  : conf.getParameter<double>("TanLorentzAnglePerTesla_FPix")),
284  tanLorentzAnglePerTesla_BPix(use_LorentzAngle_DB_ ? 0.0
285  : conf.getParameter<double>("TanLorentzAnglePerTesla_BPix")),
286 
287  // signal response new parameterization: split Fpix and BPix
288  FPix_p0(conf.getParameter<double>("FPix_SignalResponse_p0")),
289  FPix_p1(conf.getParameter<double>("FPix_SignalResponse_p1")),
290  FPix_p2(conf.getParameter<double>("FPix_SignalResponse_p2")),
291  FPix_p3(conf.getParameter<double>("FPix_SignalResponse_p3")),
292 
293  BPix_p0(conf.getParameter<double>("BPix_SignalResponse_p0")),
294  BPix_p1(conf.getParameter<double>("BPix_SignalResponse_p1")),
295  BPix_p2(conf.getParameter<double>("BPix_SignalResponse_p2")),
296  BPix_p3(conf.getParameter<double>("BPix_SignalResponse_p3")),
297 
298  // Add noise
299  addNoise(conf.getParameter<bool>("AddNoise")),
300 
301  // Smear the pixel charge with a gaussian which RMS is a function of the
302  // pixel charge (Danek's study)
303  addChargeVCALSmearing(conf.getParameter<bool>("ChargeVCALSmearing")),
304 
305  // Add noisy pixels
306  addNoisyPixels(conf.getParameter<bool>("AddNoisyPixels")),
307 
308  // Fluctuate charge in track subsegments
309  fluctuateCharge(conf.getUntrackedParameter<bool>("FluctuateCharge", true)),
310 
311  // Control the pixel inefficiency
312  AddPixelInefficiency(conf.getParameter<bool>("AddPixelInefficiency")),
313  KillBadFEDChannels(conf.getParameter<bool>("KillBadFEDChannels")),
314 
315  // Add threshold gaussian smearing:
316  addThresholdSmearing(conf.getParameter<bool>("AddThresholdSmearing")),
317 
318  // Get the constants for the miss-calibration studies
319  doMissCalibrate(conf.getParameter<bool>("MissCalibrate")), // Enable miss-calibration
320  doMissCalInLateCR(conf.getParameter<bool>("MissCalInLateCR")), // Enable miss-calibration
321  theGainSmearing(conf.getParameter<double>("GainSmearing")), // sigma of the gain smearing
322  theOffsetSmearing(conf.getParameter<double>("OffsetSmearing")), //sigma of the offset smearing
323 
324  // Add pixel radiation damage for upgrade studies
325  AddPixelAging(conf.getParameter<bool>("DoPixelAging")),
326  UseReweighting(conf.getParameter<bool>("UseReweighting")),
327 
328  // delta cutoff in MeV, has to be same as in OSCAR(0.030/cmsim=1.0 MeV
329  //tMax(0.030), // In MeV.
330  //tMax(conf.getUntrackedParameter<double>("deltaProductionCut",0.030)),
331  tMax(conf.getParameter<double>("deltaProductionCut")),
332 
333  fluctuate(fluctuateCharge ? new SiG4UniversalFluctuation() : nullptr),
334  theNoiser(addNoise ? new GaussianTailNoiseGenerator() : nullptr),
335  calmap((doMissCalibrate || doMissCalInLateCR) ? initCal() : std::map<int, CalParameters, std::less<int> >()),
336  theSiPixelGainCalibrationService_(use_ineff_from_db_ ? new SiPixelGainCalibrationOfflineSimService(conf, iC)
337  : nullptr),
338  pixelEfficiencies_(conf, AddPixelInefficiency, NumberOfBarrelLayers, NumberOfEndcapDisks),
339  pixelAging_(conf, AddPixelAging, NumberOfBarrelLayers, NumberOfEndcapDisks) {
340  if (use_deadmodule_DB_) {
341  //string to specify SiPixelQuality label
342  SiPixelBadModuleToken_ = iC.esConsumes(edm::ESInputTag("", conf.getParameter<std::string>("SiPixelQualityLabel")));
343  }
344  if (use_LorentzAngle_DB_) {
346  }
348  // TODO: in practice the bunchspacing is known at MixingModule
349  // construction time, and thus we could declare the consumption of
350  // the actual product. In principle, however, MixingModule is
351  // capable of updating (parts of) its configuration from the
352  // EventSetup, so if that capability is really needed we'd need to
353  // invent something new (similar to mayConsume in the ESProducer
354  // side). So for now, let's consume both payloads.
356  }
357  if (KillBadFEDChannels) {
360  }
361 
362  LogInfo("PixelDigitizer ") << "SiPixelDigitizerAlgorithm constructed"
363  << "Configuration parameters:"
364  << "Threshold/Gain = "
365  << "threshold in electron FPix = " << theThresholdInE_FPix
366  << "threshold in electron BPix = " << theThresholdInE_BPix
367  << "threshold in electron BPix Layer1 = " << theThresholdInE_BPix_L1
368  << "threshold in electron BPix Layer2 = " << theThresholdInE_BPix_L2 << " "
369  << theElectronPerADC << " " << theAdcFullScale << " The delta cut-off is set to " << tMax
370  << " pix-inefficiency " << AddPixelInefficiency;
371 
372  LogInfo("PixelDigitizer ") << " SiPixelDigitizerAlgorithm constructed with UseReweighting " << UseReweighting
373  << " and store_SimHitEntryExitPoints_ " << store_SimHitEntryExitPoints_ << " \n";
374 
375  TheNewSiPixelChargeReweightingAlgorithmClass = std::make_unique<SiPixelChargeReweightingAlgorithm>(conf, iC);
376 }
377 
378 std::map<int, SiPixelDigitizerAlgorithm::CalParameters, std::less<int> > SiPixelDigitizerAlgorithm::initCal() const {
379  std::map<int, SiPixelDigitizerAlgorithm::CalParameters, std::less<int> > calmap;
380  // Prepare for the analog amplitude miss-calibration
381  LogDebug("PixelDigitizer ") << " miss-calibrate the pixel amplitude \n";
382 
383  const bool ReadCalParameters = false;
384  if (ReadCalParameters) { // Read the calibration files from file
385  // read the calibration constants from a file (testing only)
386  std::ifstream in_file; // data file pointer
387  char filename[80] = "phCalibrationFit_C0.dat";
388 
389  in_file.open(filename, std::ios::in); // in C++
390  if (in_file.bad()) {
391  LogInfo("PixelDigitizer ") << " File not found \n ";
392  return calmap; // signal error
393  }
394  LogInfo("PixelDigitizer ") << " file opened : " << filename << "\n";
395 
396  char line[500];
397  for (int i = 0; i < 3; i++) {
398  in_file.getline(line, 500, '\n');
399  LogInfo("PixelDigitizer ") << line << "\n";
400  }
401 
402  LogInfo("PixelDigitizer ") << " test map"
403  << "\n";
404 
405  float par0, par1, par2, par3;
406  int colid, rowid;
408  // Read MC tracks
409  for (int i = 0; i < (52 * 80); i++) { // loop over tracks
410  in_file >> par0 >> par1 >> par2 >> par3 >> name >> colid >> rowid;
411  if (in_file.bad()) { // check for errors
412  LogError("PixelDigitizer") << "Cannot read data file for calmap"
413  << "\n";
414  return calmap;
415  }
416  if (in_file.eof() != 0) {
417  LogError("PixelDigitizer") << "calmap " << in_file.eof() << " " << in_file.gcount() << " " << in_file.fail()
418  << " " << in_file.good() << " end of file "
419  << "\n";
420  return calmap;
421  }
422 
423  LogDebug("PixelDigitizer ") << " line " << i << " " << par0 << " " << par1 << " " << par2 << " " << par3 << " "
424  << colid << " " << rowid << "\n";
425 
426  CalParameters onePix;
427  onePix.p0 = par0;
428  onePix.p1 = par1;
429  onePix.p2 = par2;
430  onePix.p3 = par3;
431 
432  // Convert ROC pixel index to channel
433  int chan = PixelIndices::pixelToChannelROC(rowid, colid);
434  calmap.insert(std::pair<int, CalParameters>(chan, onePix));
435 
436  // Testing the index conversion, can be skipped
437  std::pair<int, int> p = PixelIndices::channelToPixelROC(chan);
438  if (rowid != p.first)
439  LogInfo("PixelDigitizer ") << " wrong channel row " << rowid << " " << p.first << "\n";
440  if (colid != p.second)
441  LogInfo("PixelDigitizer ") << " wrong channel col " << colid << " " << p.second << "\n";
442 
443  } // pixel loop in a ROC
444 
445  LogInfo("PixelDigitizer ") << " map size " << calmap.size() << " max " << calmap.max_size() << " "
446  << calmap.empty() << "\n";
447 
448  // LogInfo("PixelDigitizer ") << " map size " << calmap.size() << "\n";
449  // map<int,CalParameters,std::less<int> >::iterator ix,it;
450  // map<int,CalParameters,std::less<int> >::const_iterator ip;
451  // for (ix = calmap.begin(); ix != calmap.end(); ++ix) {
452  // int i = (*ix).first;
453  // std::pair<int,int> p = channelToPixelROC(i);
454  // it = calmap.find(i);
455  // CalParameters y = (*it).second;
456  // CalParameters z = (*ix).second;
457  // LogInfo("PixelDigitizer ") << i <<" "<<p.first<<" "<<p.second<<" "<<y.p0<<" "<<z.p0<<" "<<calmap[i].p0<<"\n";
458 
459  // //int dummy=0;
460  // //cin>>dummy;
461  // }
462 
463  } // end if readparameters
464  return calmap;
465 } // end initCal()
466 
467 //=========================================================================
469  LogDebug("PixelDigitizer") << "SiPixelDigitizerAlgorithm deleted";
470 }
471 
472 // Read DynIneff Scale factors from Configuration
475  int NumberOfBarrelLayers,
476  int NumberOfEndcapDisks) {
477  // pixel inefficiency
478  // Don't use Hard coded values, read inefficiencies in from DB/python config or don't use any
479  int NumberOfTotLayers = NumberOfBarrelLayers + NumberOfEndcapDisks;
481  if (AddPixelInefficiency) {
482  FromConfig = conf.exists("thePixelColEfficiency_BPix1") && conf.exists("thePixelColEfficiency_BPix2") &&
483  conf.exists("thePixelColEfficiency_BPix3") && conf.exists("thePixelColEfficiency_FPix1") &&
484  conf.exists("thePixelColEfficiency_FPix2") && conf.exists("thePixelEfficiency_BPix1") &&
485  conf.exists("thePixelEfficiency_BPix2") && conf.exists("thePixelEfficiency_BPix3") &&
486  conf.exists("thePixelEfficiency_FPix1") && conf.exists("thePixelEfficiency_FPix2") &&
487  conf.exists("thePixelChipEfficiency_BPix1") && conf.exists("thePixelChipEfficiency_BPix2") &&
488  conf.exists("thePixelChipEfficiency_BPix3") && conf.exists("thePixelChipEfficiency_FPix1") &&
489  conf.exists("thePixelChipEfficiency_FPix2");
490  if (NumberOfBarrelLayers == 3)
491  FromConfig = FromConfig && conf.exists("theLadderEfficiency_BPix1") && conf.exists("theLadderEfficiency_BPix2") &&
492  conf.exists("theLadderEfficiency_BPix3") && conf.exists("theModuleEfficiency_BPix1") &&
493  conf.exists("theModuleEfficiency_BPix2") && conf.exists("theModuleEfficiency_BPix3") &&
494  conf.exists("thePUEfficiency_BPix1") && conf.exists("thePUEfficiency_BPix2") &&
495  conf.exists("thePUEfficiency_BPix3") && conf.exists("theInnerEfficiency_FPix1") &&
496  conf.exists("theInnerEfficiency_FPix2") && conf.exists("theOuterEfficiency_FPix1") &&
497  conf.exists("theOuterEfficiency_FPix2") && conf.exists("thePUEfficiency_FPix_Inner") &&
498  conf.exists("thePUEfficiency_FPix_Outer") && conf.exists("theInstLumiScaleFactor");
499  if (NumberOfBarrelLayers >= 4)
500  FromConfig = FromConfig && conf.exists("thePixelColEfficiency_BPix4") &&
501  conf.exists("thePixelEfficiency_BPix4") && conf.exists("thePixelChipEfficiency_BPix4");
502  if (NumberOfEndcapDisks >= 3)
503  FromConfig = FromConfig && conf.exists("thePixelColEfficiency_FPix3") &&
504  conf.exists("thePixelEfficiency_FPix3") && conf.exists("thePixelChipEfficiency_FPix3");
505  if (FromConfig) {
506  LogInfo("PixelDigitizer ") << "The PixelDigitizer inefficiency configuration is read from the config file.\n";
507  theInstLumiScaleFactor = conf.getParameter<double>("theInstLumiScaleFactor");
508  int i = 0;
509  thePixelColEfficiency[i++] = conf.getParameter<double>("thePixelColEfficiency_BPix1");
510  thePixelColEfficiency[i++] = conf.getParameter<double>("thePixelColEfficiency_BPix2");
511  thePixelColEfficiency[i++] = conf.getParameter<double>("thePixelColEfficiency_BPix3");
512  if (NumberOfBarrelLayers >= 4) {
513  thePixelColEfficiency[i++] = conf.getParameter<double>("thePixelColEfficiency_BPix4");
514  }
515  //
516  i = 0;
517  thePixelEfficiency[i++] = conf.getParameter<double>("thePixelEfficiency_BPix1");
518  thePixelEfficiency[i++] = conf.getParameter<double>("thePixelEfficiency_BPix2");
519  thePixelEfficiency[i++] = conf.getParameter<double>("thePixelEfficiency_BPix3");
520  if (NumberOfBarrelLayers >= 4) {
521  thePixelEfficiency[i++] = conf.getParameter<double>("thePixelEfficiency_BPix4");
522  }
523  //
524  i = 0;
525  thePixelChipEfficiency[i++] = conf.getParameter<double>("thePixelChipEfficiency_BPix1");
526  thePixelChipEfficiency[i++] = conf.getParameter<double>("thePixelChipEfficiency_BPix2");
527  thePixelChipEfficiency[i++] = conf.getParameter<double>("thePixelChipEfficiency_BPix3");
528  if (NumberOfBarrelLayers >= 4) {
529  thePixelChipEfficiency[i++] = conf.getParameter<double>("thePixelChipEfficiency_BPix4");
530  }
531  //
532  if (NumberOfBarrelLayers == 3) {
533  i = 0;
534  theLadderEfficiency_BPix[i++] = conf.getParameter<std::vector<double> >("theLadderEfficiency_BPix1");
535  theLadderEfficiency_BPix[i++] = conf.getParameter<std::vector<double> >("theLadderEfficiency_BPix2");
536  theLadderEfficiency_BPix[i++] = conf.getParameter<std::vector<double> >("theLadderEfficiency_BPix3");
537  if (((theLadderEfficiency_BPix[0].size() != 20) || (theLadderEfficiency_BPix[1].size() != 32) ||
538  (theLadderEfficiency_BPix[2].size() != 44)) &&
539  (NumberOfBarrelLayers == 3))
540  throw cms::Exception("Configuration") << "Wrong ladder number in efficiency config!";
541  //
542  i = 0;
543  theModuleEfficiency_BPix[i++] = conf.getParameter<std::vector<double> >("theModuleEfficiency_BPix1");
544  theModuleEfficiency_BPix[i++] = conf.getParameter<std::vector<double> >("theModuleEfficiency_BPix2");
545  theModuleEfficiency_BPix[i++] = conf.getParameter<std::vector<double> >("theModuleEfficiency_BPix3");
546  if (((theModuleEfficiency_BPix[0].size() != 4) || (theModuleEfficiency_BPix[1].size() != 4) ||
547  (theModuleEfficiency_BPix[2].size() != 4)) &&
548  (NumberOfBarrelLayers == 3))
549  throw cms::Exception("Configuration") << "Wrong module number in efficiency config!";
550  //
551  thePUEfficiency.push_back(conf.getParameter<std::vector<double> >("thePUEfficiency_BPix1"));
552  thePUEfficiency.push_back(conf.getParameter<std::vector<double> >("thePUEfficiency_BPix2"));
553  thePUEfficiency.push_back(conf.getParameter<std::vector<double> >("thePUEfficiency_BPix3"));
554  if (((thePUEfficiency[0].empty()) || (thePUEfficiency[1].empty()) || (thePUEfficiency[2].empty())) &&
555  (NumberOfBarrelLayers == 3))
556  throw cms::Exception("Configuration")
557  << "At least one PU efficiency (BPix) number is needed in efficiency config!";
558  }
559  // The next is needed for Phase2 Tracker studies
560  if (NumberOfBarrelLayers >= 5) {
561  if (NumberOfTotLayers > 20) {
562  throw cms::Exception("Configuration") << "SiPixelDigitizer was given more layers than it can handle";
563  }
564  // For Phase2 tracker layers just set the outermost BPix inefficiency to 99.9% THESE VALUES ARE HARDCODED ALSO ELSEWHERE IN THIS FILE
565  for (int j = 5; j <= NumberOfBarrelLayers; j++) {
566  thePixelColEfficiency[j - 1] = 0.999;
567  thePixelEfficiency[j - 1] = 0.999;
568  thePixelChipEfficiency[j - 1] = 0.999;
569  }
570  }
571  //
572  i = FPixIndex;
573  thePixelColEfficiency[i++] = conf.getParameter<double>("thePixelColEfficiency_FPix1");
574  thePixelColEfficiency[i++] = conf.getParameter<double>("thePixelColEfficiency_FPix2");
575  if (NumberOfEndcapDisks >= 3) {
576  thePixelColEfficiency[i++] = conf.getParameter<double>("thePixelColEfficiency_FPix3");
577  }
578  i = FPixIndex;
579  thePixelEfficiency[i++] = conf.getParameter<double>("thePixelEfficiency_FPix1");
580  thePixelEfficiency[i++] = conf.getParameter<double>("thePixelEfficiency_FPix2");
581  if (NumberOfEndcapDisks >= 3) {
582  thePixelEfficiency[i++] = conf.getParameter<double>("thePixelEfficiency_FPix3");
583  }
584  i = FPixIndex;
585  thePixelChipEfficiency[i++] = conf.getParameter<double>("thePixelChipEfficiency_FPix1");
586  thePixelChipEfficiency[i++] = conf.getParameter<double>("thePixelChipEfficiency_FPix2");
587  if (NumberOfEndcapDisks >= 3) {
588  thePixelChipEfficiency[i++] = conf.getParameter<double>("thePixelChipEfficiency_FPix3");
589  }
590  // The next is needed for Phase2 Tracker studies
591  if (NumberOfEndcapDisks >= 4) {
592  if (NumberOfTotLayers > 20) {
593  throw cms::Exception("Configuration") << "SiPixelDigitizer was given more layers than it can handle";
594  }
595  // For Phase2 tracker layers just set the extra FPix disk inefficiency to 99.9% THESE VALUES ARE HARDCODED ALSO ELSEWHERE IN THIS FILE
596  for (int j = 4 + FPixIndex; j <= NumberOfEndcapDisks + NumberOfBarrelLayers; j++) {
597  thePixelColEfficiency[j - 1] = 0.999;
598  thePixelEfficiency[j - 1] = 0.999;
599  thePixelChipEfficiency[j - 1] = 0.999;
600  }
601  }
602  //FPix Dynamic Inefficiency
603  if (NumberOfBarrelLayers == 3) {
604  i = FPixIndex;
605  theInnerEfficiency_FPix[i++] = conf.getParameter<double>("theInnerEfficiency_FPix1");
606  theInnerEfficiency_FPix[i++] = conf.getParameter<double>("theInnerEfficiency_FPix2");
607  i = FPixIndex;
608  theOuterEfficiency_FPix[i++] = conf.getParameter<double>("theOuterEfficiency_FPix1");
609  theOuterEfficiency_FPix[i++] = conf.getParameter<double>("theOuterEfficiency_FPix2");
610  thePUEfficiency.push_back(conf.getParameter<std::vector<double> >("thePUEfficiency_FPix_Inner"));
611  thePUEfficiency.push_back(conf.getParameter<std::vector<double> >("thePUEfficiency_FPix_Outer"));
612  if (((thePUEfficiency[3].empty()) || (thePUEfficiency[4].empty())) && (NumberOfEndcapDisks == 2))
613  throw cms::Exception("Configuration")
614  << "At least one (FPix) PU efficiency number is needed in efficiency config!";
615  pu_scale.resize(thePUEfficiency.size());
616  }
617  } else
618  LogInfo("PixelDigitizer ") << "The PixelDigitizer inefficiency configuration is read from the database.\n";
619  }
620  // the first "NumberOfBarrelLayers" settings [0],[1], ... , [NumberOfBarrelLayers-1] are for the barrel pixels
621  // the next "NumberOfEndcapDisks" settings [NumberOfBarrelLayers],[NumberOfBarrelLayers+1], ... [NumberOfEndcapDisks+NumberOfBarrelLayers-1]
622 }
623 
624 // Read DynIneff Scale factors from DB
626  LogDebug("PixelDigitizer ") << " In SiPixelDigitizerAlgorithm::init_DynIneffDB " << AddPixelInefficiency << " "
627  << pixelEfficiencies_.FromConfig << "\n";
631  }
632 }
633 
636  theInstLumiScaleFactor = SiPixelDynamicInefficiency->gettheInstLumiScaleFactor();
637  const std::map<uint32_t, double>& PixelGeomFactorsDBIn = SiPixelDynamicInefficiency->getPixelGeomFactors();
638  const std::map<uint32_t, double>& ColGeomFactorsDB = SiPixelDynamicInefficiency->getColGeomFactors();
639  const std::map<uint32_t, double>& ChipGeomFactorsDB = SiPixelDynamicInefficiency->getChipGeomFactors();
640  const std::map<uint32_t, std::vector<double> >& PUFactors = SiPixelDynamicInefficiency->getPUFactors();
641  std::vector<uint32_t> DetIdmasks = SiPixelDynamicInefficiency->getDetIdmasks();
642 
643  // Loop on all modules, initialize map for easy access
644  for (const auto& it_module : geom->detUnits()) {
645  if (dynamic_cast<PixelGeomDetUnit const*>(it_module) == nullptr)
646  continue;
647  const DetId detid = it_module->geographicalId();
648  uint32_t rawid = detid.rawId();
649  PixelGeomFactors[rawid] = 1;
650  ColGeomFactors[rawid] = 1;
651  ChipGeomFactors[rawid] = 1;
652  PixelGeomFactorsROCStdPixels[rawid] = std::vector<double>(16, 1);
653  PixelGeomFactorsROCBigPixels[rawid] = std::vector<double>(16, 1);
654  }
655 
656  // ROC level inefficiency for phase 1 (disentangle scale factors for big and std size pixels)
657  std::map<uint32_t, double> PixelGeomFactorsDB;
658 
659  LogDebug("PixelDigitizer ") << " Check PixelEfficiencies -- PixelGeomFactorsDBIn "
660  << "\n";
661  if (geom->isThere(GeomDetEnumerators::P1PXB) || geom->isThere(GeomDetEnumerators::P1PXEC)) {
662  for (auto db_factor : PixelGeomFactorsDBIn) {
663  LogDebug("PixelDigitizer ") << " db_factor " << db_factor.first << " " << db_factor.second << "\n";
664 
665  int shift = DetId(db_factor.first).subdetId() == static_cast<int>(PixelSubdetector::PixelBarrel) ? BPixRocIdShift
666  : FPixRocIdShift;
667  unsigned int rocMask = rocIdMaskBits << shift;
668  unsigned int rocId = (((db_factor.first) & rocMask) >> shift);
669  if (rocId != 0) {
670  rocId--;
671  unsigned int rawid = db_factor.first & (~rocMask);
672  const PixelGeomDetUnit* theGeomDet = dynamic_cast<const PixelGeomDetUnit*>(geom->idToDet(rawid));
673  PixelTopology const* topology = &(theGeomDet->specificTopology());
674  const int nPixelsInROC = topology->rowsperroc() * topology->colsperroc();
675  const int nBigPixelsInROC = 2 * topology->rowsperroc() + topology->colsperroc() - 2;
676  double factor = db_factor.second;
677  double badFraction = 1 - factor;
678  double bigPixelFraction = static_cast<double>(nBigPixelsInROC) / nPixelsInROC;
679  double stdPixelFraction = 1. - bigPixelFraction;
680 
681  double badFractionBig = std::min(bigPixelFraction, badFraction);
682  double badFractionStd = std::max(0., badFraction - badFractionBig);
683  double badFractionBigReNormalized = badFractionBig / bigPixelFraction;
684  double badFractionStdReNormalized = badFractionStd / stdPixelFraction;
685  PixelGeomFactorsROCStdPixels[rawid][rocId] *= (1. - badFractionStdReNormalized);
686  PixelGeomFactorsROCBigPixels[rawid][rocId] *= (1. - badFractionBigReNormalized);
687  } else {
688  PixelGeomFactorsDB[db_factor.first] = db_factor.second;
689  }
690  }
691  } // is Phase 1 geometry
692  else {
693  PixelGeomFactorsDB = PixelGeomFactorsDBIn;
694  }
695 
696  LogDebug("PixelDigitizer ")
697  << " Check PixelEfficiencies -- Loop on all modules and store module level geometrical scale factors "
698  << "\n";
699  // Loop on all modules, store module level geometrical scale factors
700  for (const auto& it_module : geom->detUnits()) {
701  if (dynamic_cast<PixelGeomDetUnit const*>(it_module) == nullptr)
702  continue;
703  const DetId detid = it_module->geographicalId();
704  uint32_t rawid = detid.rawId();
705  for (auto db_factor : PixelGeomFactorsDB) {
706  LogDebug("PixelDigitizer ") << " db_factor PixelGeomFactorsDB " << db_factor.first << " "
707  << db_factor.second << "\n";
708  if (matches(detid, DetId(db_factor.first), DetIdmasks))
709  PixelGeomFactors[rawid] *= db_factor.second;
710  }
711  for (auto db_factor : ColGeomFactorsDB) {
712  LogDebug("PixelDigitizer ") << " db_factor ColGeomFactorsDB " << db_factor.first << " " << db_factor.second
713  << "\n";
714  if (matches(detid, DetId(db_factor.first), DetIdmasks))
715  ColGeomFactors[rawid] *= db_factor.second;
716  }
717  for (auto db_factor : ChipGeomFactorsDB) {
718  LogDebug("PixelDigitizer ") << " db_factor ChipGeomFactorsDB " << db_factor.first << " "
719  << db_factor.second << "\n";
720  if (matches(detid, DetId(db_factor.first), DetIdmasks))
721  ChipGeomFactors[rawid] *= db_factor.second;
722  }
723  }
724 
725  // piluep scale factors are calculated once per event
726  // therefore vector index is stored in a map for each module that matches to a db_id
727  size_t i = 0;
728  LogDebug("PixelDigitizer ") << " Check PixelEfficiencies -- PUFactors "
729  << "\n";
730  for (const auto& factor : PUFactors) {
731  //
732  LogDebug("PixelDigitizer ") << " factor " << factor.first << " " << factor.second.size() << "\n";
733  for (size_t i = 0, n = factor.second.size(); i < n; i++) {
734  LogDebug("PixelDigitizer ") << " print factor.second for " << i << " " << factor.second[i] << "\n";
735  }
736  //
737  const DetId db_id = DetId(factor.first);
738  for (const auto& it_module : geom->detUnits()) {
739  if (dynamic_cast<PixelGeomDetUnit const*>(it_module) == nullptr)
740  continue;
741  const DetId detid = it_module->geographicalId();
742  if (!matches(detid, db_id, DetIdmasks))
743  continue;
744  if (iPU.count(detid.rawId())) {
745  throw cms::Exception("Database")
746  << "Multiple db_ids match to same module in SiPixelDynamicInefficiency DB Object";
747  } else {
748  iPU[detid.rawId()] = i;
749  }
750  }
751  thePUEfficiency.push_back(factor.second);
752  ++i;
753  }
754  pu_scale.resize(thePUEfficiency.size());
755 }
756 
758  const DetId& db_id,
759  const std::vector<uint32_t>& DetIdmasks) {
760  if (detid.subdetId() != db_id.subdetId())
761  return false;
762  for (size_t i = 0; i < DetIdmasks.size(); ++i) {
763  DetId maskid = DetId(DetIdmasks.at(i));
764  if (maskid.subdetId() != db_id.subdetId())
765  continue;
766  if ((detid.rawId() & maskid.rawId()) != (db_id.rawId() & maskid.rawId()) &&
767  (db_id.rawId() & maskid.rawId()) != DetId(db_id.det(), db_id.subdetId()).rawId())
768  return false;
769  }
770  return true;
771 }
772 
774  bool AddAging,
776  int NumberOfEndcapDisks) {
777  // pixel aging
778  // Don't use Hard coded values, read aging in from python or don't use any
779  if (AddAging) {
780  int NumberOfTotLayers = NumberOfBarrelLayers + NumberOfEndcapDisks;
781  FPixIndex = NumberOfBarrelLayers;
782 
783  int i = 0;
784  thePixelPseudoRadDamage[i++] = conf.getParameter<double>("thePixelPseudoRadDamage_BPix1");
785  thePixelPseudoRadDamage[i++] = conf.getParameter<double>("thePixelPseudoRadDamage_BPix2");
786  thePixelPseudoRadDamage[i++] = conf.getParameter<double>("thePixelPseudoRadDamage_BPix3");
787  thePixelPseudoRadDamage[i++] = conf.getParameter<double>("thePixelPseudoRadDamage_BPix4");
788 
789  // to be removed when Gaelle will have the phase2 digitizer
790  if (NumberOfBarrelLayers >= 5) {
791  if (NumberOfTotLayers > 20) {
792  throw cms::Exception("Configuration") << "SiPixelDigitizer was given more layers than it can handle";
793  }
794  // For Phase2 tracker layers just set the outermost BPix aging 0.
795  for (int j = 5; j <= NumberOfBarrelLayers; j++) {
796  thePixelPseudoRadDamage[j - 1] = 0.;
797  }
798  }
799  //
800  i = FPixIndex;
801  thePixelPseudoRadDamage[i++] = conf.getParameter<double>("thePixelPseudoRadDamage_FPix1");
802  thePixelPseudoRadDamage[i++] = conf.getParameter<double>("thePixelPseudoRadDamage_FPix2");
803  thePixelPseudoRadDamage[i++] = conf.getParameter<double>("thePixelPseudoRadDamage_FPix3");
804 
805  //To be removed when Phase2 digitizer will be available
806  if (NumberOfEndcapDisks >= 4) {
807  if (NumberOfTotLayers > 20) {
808  throw cms::Exception("Configuration") << "SiPixelDigitizer was given more layers than it can handle";
809  }
810  // For Phase2 tracker layers just set the extra FPix disk aging to 0. BE CAREFUL THESE VALUES ARE HARDCODED ALSO ELSEWHERE IN THIS FILE
811  for (int j = 4 + FPixIndex; j <= NumberOfEndcapDisks + NumberOfBarrelLayers; j++) {
812  thePixelPseudoRadDamage[j - 1] = 0.;
813  }
814  }
815  }
816  // the first "NumberOfBarrelLayers" settings [0],[1], ... , [NumberOfBarrelLayers-1] are for the barrel pixels
817  // the next "NumberOfEndcapDisks" settings [NumberOfBarrelLayers],[NumberOfBarrelLayers+1], ... [NumberOfEndcapDisks+NumberOfBarrelLayers-1]
818 }
819 
820 //=========================================================================
821 void SiPixelDigitizerAlgorithm::accumulateSimHits(std::vector<PSimHit>::const_iterator inputBegin,
822  std::vector<PSimHit>::const_iterator inputEnd,
823  const size_t inputBeginGlobalIndex,
824  const unsigned int tofBin,
825  const PixelGeomDetUnit* pixdet,
826  const GlobalVector& bfield,
827  const TrackerTopology* tTopo,
828  CLHEP::HepRandomEngine* engine) {
829  // produce SignalPoint's for all SimHit's in detector
830  // Loop over hits
831 
832  uint32_t detId = pixdet->geographicalId().rawId();
833  size_t simHitGlobalIndex = inputBeginGlobalIndex; // This needs to stored to create the digi-sim link later
834  for (std::vector<PSimHit>::const_iterator ssbegin = inputBegin; ssbegin != inputEnd; ++ssbegin, ++simHitGlobalIndex) {
835  // skip hits not in this detector.
836  if ((*ssbegin).detUnitId() != detId) {
837  continue;
838  }
839 
840 #ifdef TP_DEBUG
841  LogDebug("Pixel Digitizer") << (*ssbegin).particleType() << " " << (*ssbegin).pabs() << " "
842  << (*ssbegin).energyLoss() << " " << (*ssbegin).tof() << " " << (*ssbegin).trackId()
843  << " " << (*ssbegin).processType() << " " << (*ssbegin).detUnitId()
844  << (*ssbegin).entryPoint() << " " << (*ssbegin).exitPoint();
845 #endif
846 
847  std::vector<EnergyDepositUnit> ionization_points;
848  std::vector<SignalPoint> collection_points;
849 
850  // fill collection_points for this SimHit, indpendent of topology
851  // Check the TOF cut
852  if (((*ssbegin).tof() - pixdet->surface().toGlobal((*ssbegin).localPosition()).mag() / 30.) >= theTofLowerCut &&
853  ((*ssbegin).tof() - pixdet->surface().toGlobal((*ssbegin).localPosition()).mag() / 30.) <= theTofUpperCut) {
854  primary_ionization(*ssbegin, ionization_points, engine); // fills _ionization_points
855  drift(*ssbegin,
856  pixdet,
857  bfield,
858  tTopo,
859  ionization_points,
860  collection_points); // transforms _ionization_points to collection_points
861  // compute induced signal on readout elements and add to _signal
862  induce_signal(inputBegin,
863  inputEnd,
864  *ssbegin,
865  simHitGlobalIndex,
866  inputBeginGlobalIndex,
867  tofBin,
868  pixdet,
869  collection_points); // 1st 3 args needed only for SimHit<-->Digi link
870  } // end if
871  } // end for
872 }
873 
874 //============================================================================
876  //Instlumi scalefactor calculating for dynamic inefficiency
877 
878  if (puInfo) {
879  const std::vector<int>& bunchCrossing = puInfo->getMix_bunchCrossing();
880  const std::vector<float>& TrueInteractionList = puInfo->getMix_TrueInteractions();
881  //const int bunchSpacing = puInfo->getMix_bunchSpacing();
882 
883  int pui = 0, p = 0;
884  std::vector<int>::const_iterator pu;
885  std::vector<int>::const_iterator pu0 = bunchCrossing.end();
886 
887  for (pu = bunchCrossing.begin(); pu != bunchCrossing.end(); ++pu) {
888  if (*pu == 0) {
889  pu0 = pu;
890  p = pui;
891  }
892  pui++;
893  }
894  if (pu0 != bunchCrossing.end()) {
895  for (size_t i = 0, n = pixelEfficiencies_.thePUEfficiency.size(); i < n; i++) {
896  double instlumi = TrueInteractionList.at(p) * pixelEfficiencies_.theInstLumiScaleFactor;
897  double instlumi_pow = 1.;
899  for (size_t j = 0; j < pixelEfficiencies_.thePUEfficiency[i].size(); j++) {
901  instlumi_pow *= instlumi;
902  }
903  }
904  }
905  } else {
906  for (int i = 0, n = pixelEfficiencies_.thePUEfficiency.size(); i < n; i++) {
908  }
909  }
910 }
911 
912 //============================================================================
913 void SiPixelDigitizerAlgorithm::calculateInstlumiFactor(const std::vector<PileupSummaryInfo>& ps, int bunchSpacing) {
914  int p = -1;
915  for (unsigned int i = 0; i < ps.size(); i++)
916  if (ps[i].getBunchCrossing() == 0)
917  p = i;
918 
919  if (p >= 0) {
920  for (size_t i = 0, n = pixelEfficiencies_.thePUEfficiency.size(); i < n; i++) {
921  double instlumi = ps[p].getTrueNumInteractions() * pixelEfficiencies_.theInstLumiScaleFactor;
922  double instlumi_pow = 1.;
924  for (size_t j = 0; j < pixelEfficiencies_.thePUEfficiency[i].size(); j++) {
926  instlumi_pow *= instlumi;
927  }
928  }
929  } else {
930  for (int i = 0, n = pixelEfficiencies_.thePUEfficiency.size(); i < n; i++) {
932  }
933  }
934 }
935 
936 // ========== StuckTBMs
937 
939 
940 std::unique_ptr<PixelFEDChannelCollection> SiPixelDigitizerAlgorithm::chooseScenario(
941  const std::vector<PileupSummaryInfo>& ps, CLHEP::HepRandomEngine* engine) {
942  std::unique_ptr<PixelFEDChannelCollection> PixelFEDChannelCollection_ = nullptr;
944 
945  std::vector<int> bunchCrossing;
946  std::vector<float> TrueInteractionList;
947 
948  for (unsigned int i = 0; i < ps.size(); i++) {
949  bunchCrossing.push_back(ps[i].getBunchCrossing());
950  TrueInteractionList.push_back(ps[i].getTrueNumInteractions());
951  }
952 
953  int pui = 0, p = 0;
954  std::vector<int>::const_iterator pu;
955  std::vector<int>::const_iterator pu0 = bunchCrossing.end();
956 
957  for (pu = bunchCrossing.begin(); pu != bunchCrossing.end(); ++pu) {
958  if (*pu == 0) {
959  pu0 = pu;
960  p = pui;
961  }
962  pui++;
963  }
964 
965  if (pu0 != bunchCrossing.end()) {
966  unsigned int PUBin = TrueInteractionList.at(p); // case delta PU=1, fix me
967  const auto& theProbabilitiesPerScenario = scenarioProbability_->getProbabilities(PUBin);
968  std::vector<double> probabilities;
969  probabilities.reserve(theProbabilitiesPerScenario.size());
970  for (auto it = theProbabilitiesPerScenario.begin(); it != theProbabilitiesPerScenario.end(); it++) {
971  probabilities.push_back(it->second);
972  }
973 
974  CLHEP::RandGeneral randGeneral(*engine, &(probabilities.front()), probabilities.size());
975  double x = randGeneral.shoot();
976  unsigned int index = x * probabilities.size() - 1;
977  const std::string& scenario = theProbabilitiesPerScenario.at(index).first;
978 
979  PixelFEDChannelCollection_ = std::make_unique<PixelFEDChannelCollection>(quality_map->at(scenario));
981  std::make_unique<PixelFEDChannelCollection>(quality_map->at(scenario));
982  }
983 
984  return PixelFEDChannelCollection_;
985 }
986 
987 std::unique_ptr<PixelFEDChannelCollection> SiPixelDigitizerAlgorithm::chooseScenario(PileupMixingContent* puInfo,
988  CLHEP::HepRandomEngine* engine) {
989  //Determine scenario to use for the current event based on pileup information
990 
991  std::unique_ptr<PixelFEDChannelCollection> PixelFEDChannelCollection_ = nullptr;
993  if (puInfo) {
994  const std::vector<int>& bunchCrossing = puInfo->getMix_bunchCrossing();
995  const std::vector<float>& TrueInteractionList = puInfo->getMix_TrueInteractions();
996 
997  int pui = 0, p = 0;
998  std::vector<int>::const_iterator pu;
999  std::vector<int>::const_iterator pu0 = bunchCrossing.end();
1000 
1001  for (pu = bunchCrossing.begin(); pu != bunchCrossing.end(); ++pu) {
1002  if (*pu == 0) {
1003  pu0 = pu;
1004  p = pui;
1005  }
1006  pui++;
1007  }
1008 
1009  if (pu0 != bunchCrossing.end()) {
1010  unsigned int PUBin = TrueInteractionList.at(p); // case delta PU=1, fix me
1011  const auto& theProbabilitiesPerScenario = scenarioProbability_->getProbabilities(PUBin);
1012  std::vector<double> probabilities;
1013  probabilities.reserve(theProbabilitiesPerScenario.size());
1014  for (auto it = theProbabilitiesPerScenario.begin(); it != theProbabilitiesPerScenario.end(); it++) {
1015  probabilities.push_back(it->second);
1016  }
1017 
1018  CLHEP::RandGeneral randGeneral(*engine, &(probabilities.front()), probabilities.size());
1019  double x = randGeneral.shoot();
1020  unsigned int index = x * probabilities.size() - 1;
1021  const std::string& scenario = theProbabilitiesPerScenario.at(index).first;
1022 
1023  PixelFEDChannelCollection_ = std::make_unique<PixelFEDChannelCollection>(quality_map->at(scenario));
1025  std::make_unique<PixelFEDChannelCollection>(quality_map->at(scenario));
1026  }
1027  }
1028  return PixelFEDChannelCollection_;
1029 }
1030 
1031 //============================================================================
1032 void SiPixelDigitizerAlgorithm::setSimAccumulator(const std::map<uint32_t, std::map<int, int> >& signalMap) {
1033  for (const auto& det : signalMap) {
1034  auto& theSignal = _signal[det.first];
1035  for (const auto& chan : det.second) {
1036  theSignal[chan.first].set(chan.second *
1037  theElectronPerADC); // will get divided again by theElectronPerAdc in digitize...
1038  }
1039  }
1040 }
1041 
1042 //============================================================================
1044  std::vector<PixelDigi>& digis,
1045  std::vector<PixelDigiSimLink>& simlinks,
1046  std::vector<PixelDigiAddTempInfo>& newClass_Digi_extra,
1047  const TrackerTopology* tTopo,
1048  CLHEP::HepRandomEngine* engine) {
1049  // Pixel Efficiency moved from the constructor to this method because
1050  // the information of the det are not available in the constructor
1051  // Efficiency parameters. 0 - no inefficiency, 1-low lumi, 10-high lumi
1052 
1053  uint32_t detID = pixdet->geographicalId().rawId();
1054  const signal_map_type& theSignal = _signal[detID];
1055 
1056  // Noise already defined in electrons
1057  // thePixelThresholdInE = thePixelThreshold * theNoiseInElectrons ;
1058  // Find the threshold in noise units, needed for the noiser.
1059 
1060  float thePixelThresholdInE = 0.;
1061 
1062  if (theNoiseInElectrons > 0.) {
1063  if (pixdet->type().isTrackerPixel() && pixdet->type().isBarrel()) { // Barrel modules
1064  int lay = tTopo->layer(detID);
1065  if (addThresholdSmearing) {
1068  if (lay == 1) {
1069  thePixelThresholdInE = CLHEP::RandGaussQ::shoot(
1070  engine, theThresholdInE_BPix_L1, theThresholdSmearing_BPix_L1); // gaussian smearing
1071  } else if (lay == 2) {
1072  thePixelThresholdInE = CLHEP::RandGaussQ::shoot(
1073  engine, theThresholdInE_BPix_L2, theThresholdSmearing_BPix_L2); // gaussian smearing
1074  } else {
1075  thePixelThresholdInE =
1076  CLHEP::RandGaussQ::shoot(engine, theThresholdInE_BPix, theThresholdSmearing_BPix); // gaussian smearing
1077  }
1078  }
1079  } else {
1082  if (lay == 1) {
1083  thePixelThresholdInE = theThresholdInE_BPix_L1;
1084  } else if (lay == 2) {
1085  thePixelThresholdInE = theThresholdInE_BPix_L2;
1086  } else {
1087  thePixelThresholdInE = theThresholdInE_BPix; // no smearing
1088  }
1089  }
1090  }
1091  } else if (pixdet->type().isTrackerPixel()) { // Forward disks modules
1092  if (addThresholdSmearing) {
1093  thePixelThresholdInE =
1094  CLHEP::RandGaussQ::shoot(engine, theThresholdInE_FPix, theThresholdSmearing_FPix); // gaussian smearing
1095  } else {
1096  thePixelThresholdInE = theThresholdInE_FPix; // no smearing
1097  }
1098  } else {
1099  throw cms::Exception("NotAPixelGeomDetUnit") << "Not a pixel geomdet unit" << detID;
1100  }
1101  }
1102 
1103 #ifdef TP_DEBUG
1104  const PixelTopology* topol = &pixdet->specificTopology();
1105  int numColumns = topol->ncolumns(); // det module number of cols&rows
1106  int numRows = topol->nrows();
1107  // full detector thickness
1108  float moduleThickness = pixdet->specificSurface().bounds().thickness();
1109  LogDebug("PixelDigitizer") << " PixelDigitizer " << numColumns << " " << numRows << " " << moduleThickness;
1110 #endif
1111 
1112  if (addNoise)
1113  add_noise(pixdet, thePixelThresholdInE / theNoiseInElectrons, engine); // generate noise
1114 
1115  // Do only if needed
1116 
1117  if ((AddPixelInefficiency) && (!theSignal.empty()))
1118  pixel_inefficiency(pixelEfficiencies_, pixdet, tTopo, engine); // Kill some pixels
1119 
1120  if (use_ineff_from_db_ && (!theSignal.empty()))
1121  pixel_inefficiency_db(detID);
1122 
1123  if (use_module_killing_) {
1124  if (use_deadmodule_DB_) { // remove dead modules using DB
1125  module_killing_DB(detID);
1126  } else { // remove dead modules using the list in cfg file
1127  module_killing_conf(detID);
1128  }
1129  }
1130 
1131  make_digis(thePixelThresholdInE, detID, pixdet, digis, simlinks, newClass_Digi_extra, tTopo);
1132 
1133 #ifdef TP_DEBUG
1134  LogDebug("PixelDigitizer") << "[SiPixelDigitizerAlgorithm] converted " << digis.size() << " PixelDigis in DetUnit"
1135  << detID;
1136 #endif
1137 }
1138 
1139 //***********************************************************************/
1140 // Generate primary ionization along the track segment.
1141 // Divide the track into small sub-segments
1143  std::vector<EnergyDepositUnit>& ionization_points,
1144  CLHEP::HepRandomEngine* engine) const {
1145  // Straight line approximation for trajectory inside active media
1146 
1147  const float SegmentLength = 0.0010; //10microns in cm
1148  float energy;
1149 
1150  // Get the 3D segment direction vector
1151  LocalVector direction = hit.exitPoint() - hit.entryPoint();
1152 
1153  float eLoss = hit.energyLoss(); // Eloss in GeV
1154  float length = direction.mag(); // Track length in Silicon
1155 
1156  int NumberOfSegments = int(length / SegmentLength); // Number of segments
1157  if (NumberOfSegments < 1)
1158  NumberOfSegments = 1;
1159 
1160 #ifdef TP_DEBUG
1161  LogDebug("Pixel Digitizer") << " enter primary_ionzation " << NumberOfSegments
1162  << " shift = " << (hit.exitPoint().x() - hit.entryPoint().x()) << " "
1163  << (hit.exitPoint().y() - hit.entryPoint().y()) << " "
1164  << (hit.exitPoint().z() - hit.entryPoint().z()) << " " << hit.particleType() << " "
1165  << hit.pabs();
1166 #endif
1167 
1168  float* elossVector = new float[NumberOfSegments]; // Eloss vector
1169 
1170  if (fluctuateCharge) {
1171  //MP DA RIMUOVERE ASSOLUTAMENTE
1172  int pid = hit.particleType();
1173  //int pid=211; // assume it is a pion
1174 
1175  float momentum = hit.pabs();
1176  // Generate fluctuated charge points
1177  fluctuateEloss(pid, momentum, eLoss, length, NumberOfSegments, elossVector, engine);
1178  }
1179 
1180  ionization_points.resize(NumberOfSegments); // set size
1181 
1182  // loop over segments
1183  for (int i = 0; i != NumberOfSegments; i++) {
1184  // Divide the segment into equal length subsegments
1185  Local3DPoint point = hit.entryPoint() + float((i + 0.5) / NumberOfSegments) * direction;
1186 
1187  if (fluctuateCharge)
1188  energy = elossVector[i] / GeVperElectron; // Convert charge to elec.
1189  else
1190  energy = hit.energyLoss() / GeVperElectron / float(NumberOfSegments);
1191 
1192  EnergyDepositUnit edu(energy, point); //define position,energy point
1193  ionization_points[i] = edu; // save
1194 
1195 #ifdef TP_DEBUG
1196  LogDebug("Pixel Digitizer") << i << " " << ionization_points[i].x() << " " << ionization_points[i].y() << " "
1197  << ionization_points[i].z() << " " << ionization_points[i].energy();
1198 #endif
1199 
1200  } // end for loop
1201 
1202  delete[] elossVector;
1203 }
1204 //******************************************************************************
1205 
1206 // Fluctuate the charge comming from a small (10um) track segment.
1207 // Use the G4 routine. For mip pions for the moment.
1209  float particleMomentum,
1210  float eloss,
1211  float length,
1212  int NumberOfSegs,
1213  float elossVector[],
1214  CLHEP::HepRandomEngine* engine) const {
1215  // Get dedx for this track
1216  //float dedx;
1217  //if( length > 0.) dedx = eloss/length;
1218  //else dedx = eloss;
1219 
1220  double particleMass = 139.6; // Mass in MeV, Assume pion
1221  pid = std::abs(pid);
1222  if (pid != 211) { // Mass in MeV
1223  if (pid == 11)
1224  particleMass = 0.511;
1225  else if (pid == 13)
1226  particleMass = 105.7;
1227  else if (pid == 321)
1228  particleMass = 493.7;
1229  else if (pid == 2212)
1230  particleMass = 938.3;
1231  }
1232  // What is the track segment length.
1233  float segmentLength = length / NumberOfSegs;
1234 
1235  // Generate charge fluctuations.
1236  float de = 0.;
1237  float sum = 0.;
1238  double segmentEloss = (1000. * eloss) / NumberOfSegs; //eloss in MeV
1239  for (int i = 0; i < NumberOfSegs; i++) {
1240  // material,*, momentum,energy,*, *, mass
1241  //myglandz_(14.,segmentLength,2.,2.,dedx,de,0.14);
1242  // The G4 routine needs momentum in MeV, mass in Mev, delta-cut in MeV,
1243  // track segment length in mm, segment eloss in MeV
1244  // Returns fluctuated eloss in MeV
1245  double deltaCutoff = tMax; // the cutoff is sometimes redefined inside, so fix it.
1246  de = fluctuate->SampleFluctuations(double(particleMomentum * 1000.),
1247  particleMass,
1248  deltaCutoff,
1249  double(segmentLength * 10.),
1250  segmentEloss,
1251  engine) /
1252  1000.; //convert to GeV
1253  elossVector[i] = de;
1254  sum += de;
1255  }
1256 
1257  if (sum > 0.) { // If fluctuations give eloss>0.
1258  // Rescale to the same total eloss
1259  float ratio = eloss / sum;
1260 
1261  for (int ii = 0; ii < NumberOfSegs; ii++)
1262  elossVector[ii] = ratio * elossVector[ii];
1263  } else { // If fluctuations gives 0 eloss
1264  float averageEloss = eloss / NumberOfSegs;
1265  for (int ii = 0; ii < NumberOfSegs; ii++)
1266  elossVector[ii] = averageEloss;
1267  }
1268  return;
1269 }
1270 
1271 //*******************************************************************************
1272 // Drift the charge segments to the sensor surface (collection plane)
1273 // Include the effect of E-field and B-field
1275  const PixelGeomDetUnit* pixdet,
1276  const GlobalVector& bfield,
1277  const TrackerTopology* tTopo,
1278  const std::vector<EnergyDepositUnit>& ionization_points,
1279  std::vector<SignalPoint>& collection_points) const {
1280 #ifdef TP_DEBUG
1281  LogDebug("Pixel Digitizer") << " enter drift ";
1282 #endif
1283 
1284  collection_points.resize(ionization_points.size()); // set size
1285 
1286  LocalVector driftDir = DriftDirection(pixdet, bfield, hit.detUnitId()); // get the charge drift direction
1287  if (driftDir.z() == 0.) {
1288  LogWarning("Magnetic field") << " pxlx: drift in z is zero ";
1289  return;
1290  }
1291 
1292  // tangent of Lorentz angle
1293  //float TanLorenzAngleX = driftDir.x()/driftDir.z();
1294  //float TanLorenzAngleY = 0.; // force to 0, driftDir.y()/driftDir.z();
1295 
1296  float TanLorenzAngleX, TanLorenzAngleY, dir_z, CosLorenzAngleX, CosLorenzAngleY;
1297  if (alpha2Order) {
1298  TanLorenzAngleX = driftDir.x(); // tangen of Lorentz angle
1299  TanLorenzAngleY = driftDir.y();
1300  dir_z = driftDir.z(); // The z drift direction
1301  CosLorenzAngleX = 1. / sqrt(1. + TanLorenzAngleX * TanLorenzAngleX); //cosine
1302  CosLorenzAngleY = 1. / sqrt(1. + TanLorenzAngleY * TanLorenzAngleY); //cosine;
1303 
1304  } else {
1305  TanLorenzAngleX = driftDir.x();
1306  TanLorenzAngleY = 0.; // force to 0, driftDir.y()/driftDir.z();
1307  dir_z = driftDir.z(); // The z drift direction
1308  CosLorenzAngleX = 1. / sqrt(1. + TanLorenzAngleX * TanLorenzAngleX); //cosine to estimate the path length
1309  CosLorenzAngleY = 1.;
1310  }
1311 
1312  float moduleThickness = pixdet->specificSurface().bounds().thickness();
1313 #ifdef TP_DEBUG
1314  LogDebug("Pixel Digitizer") << " Lorentz Tan " << TanLorenzAngleX << " " << TanLorenzAngleY << " " << CosLorenzAngleX
1315  << " " << CosLorenzAngleY << " " << moduleThickness * TanLorenzAngleX << " " << driftDir;
1316 #endif
1317 
1318  float Sigma_x = 1.; // Charge spread
1319  float Sigma_y = 1.;
1320  float DriftDistance; // Distance between charge generation and collection
1321  float DriftLength; // Actual Drift Lentgh
1322  float Sigma;
1323 
1324  for (unsigned int i = 0; i != ionization_points.size(); i++) {
1325  float SegX, SegY, SegZ; // position
1326  SegX = ionization_points[i].x();
1327  SegY = ionization_points[i].y();
1328  SegZ = ionization_points[i].z();
1329 
1330  // Distance from the collection plane
1331  //DriftDistance = (moduleThickness/2. + SegZ); // Drift to -z
1332  // Include explixitely the E drift direction (for CMS dir_z=-1)
1333  DriftDistance = moduleThickness / 2. - (dir_z * SegZ); // Drift to -z
1334 
1335  if (DriftDistance <= 0.)
1336  LogDebug("PixelDigitizer ") << " <=0 " << DriftDistance << " " << i << " " << SegZ << " " << dir_z << " " << SegX
1337  << " " << SegY << " " << (moduleThickness / 2) << " " << ionization_points[i].energy()
1338  << " " << hit.particleType() << " " << hit.pabs() << " " << hit.energyLoss() << " "
1339  << hit.entryPoint() << " " << hit.exitPoint() << "\n";
1340 
1341  if (DriftDistance < 0.) {
1342  DriftDistance = 0.;
1343  } else if (DriftDistance > moduleThickness)
1344  DriftDistance = moduleThickness;
1345 
1346  // Assume full depletion now, partial depletion will come later.
1347  float XDriftDueToMagField = DriftDistance * TanLorenzAngleX;
1348  float YDriftDueToMagField = DriftDistance * TanLorenzAngleY;
1349 
1350  // Shift cloud center
1351  float CloudCenterX = SegX + XDriftDueToMagField;
1352  float CloudCenterY = SegY + YDriftDueToMagField;
1353 
1354  // Calculate how long is the charge drift path
1355  DriftLength = sqrt(DriftDistance * DriftDistance + XDriftDueToMagField * XDriftDueToMagField +
1356  YDriftDueToMagField * YDriftDueToMagField);
1357 
1358  // What is the charge diffusion after this path
1359  Sigma = sqrt(DriftLength / Dist300) * Sigma0;
1360 
1361  // Project the diffusion sigma on the collection plane
1362  Sigma_x = Sigma / CosLorenzAngleX;
1363  Sigma_y = Sigma / CosLorenzAngleY;
1364 
1365  // Insert a charge loss due to Rad Damage here
1366  float energyOnCollector = ionization_points[i].energy(); // The energy that reaches the collector
1367 
1368  // add pixel aging
1369  if (AddPixelAging) {
1370  float kValue = pixel_aging(pixelAging_, pixdet, tTopo);
1371  energyOnCollector *= exp(-1 * kValue * DriftDistance / moduleThickness);
1372  }
1373 
1374 #ifdef TP_DEBUG
1375  LogDebug("Pixel Digitizer") << " Dift DistanceZ= " << DriftDistance << " module thickness= " << moduleThickness
1376  << " Start Energy= " << ionization_points[i].energy()
1377  << " Energy after loss= " << energyOnCollector;
1378 #endif
1379  SignalPoint sp(CloudCenterX, CloudCenterY, Sigma_x, Sigma_y, hit.tof(), energyOnCollector);
1380 
1381  // Load the Charge distribution parameters
1382  collection_points[i] = (sp);
1383 
1384  } // loop over ionization points, i.
1385 
1386 } // end drift
1387 
1388 //*************************************************************************
1389 // Induce the signal on the collection plane of the active sensor area.
1390 void SiPixelDigitizerAlgorithm::induce_signal(std::vector<PSimHit>::const_iterator inputBegin,
1391  std::vector<PSimHit>::const_iterator inputEnd,
1392  const PSimHit& hit,
1393  const size_t hitIndex,
1394  const size_t FirstHitIndex,
1395  const unsigned int tofBin,
1396  const PixelGeomDetUnit* pixdet,
1397  const std::vector<SignalPoint>& collection_points) {
1398  // X - Rows, Left-Right, 160, (1.6cm) for barrel
1399  // Y - Columns, Down-Up, 416, (6.4cm)
1400 
1401  const PixelTopology* topol = &pixdet->specificTopology();
1402  uint32_t detID = pixdet->geographicalId().rawId();
1403  signal_map_type& theSignal = _signal[detID];
1404 
1405 #ifdef TP_DEBUG
1406  LogDebug("Pixel Digitizer") << " enter induce_signal, " << topol->pitch().first << " " << topol->pitch().second; //OK
1407 #endif
1408 
1409  // local map to store pixels hit by 1 Hit.
1410  typedef std::map<int, float, std::less<int> > hit_map_type;
1411  hit_map_type hit_signal;
1412 
1413  // map to store pixel integrals in the x and in the y directions
1414  std::map<int, float, std::less<int> > x, y;
1415 
1416  // Assign signals to readout channels and store sorted by channel number
1417 
1418  // Iterate over collection points on the collection plane
1419  for (std::vector<SignalPoint>::const_iterator i = collection_points.begin(); i != collection_points.end(); ++i) {
1420  float CloudCenterX = i->position().x(); // Charge position in x
1421  float CloudCenterY = i->position().y(); // in y
1422  float SigmaX = i->sigma_x(); // Charge spread in x
1423  float SigmaY = i->sigma_y(); // in y
1424  float Charge = i->amplitude(); // Charge amplitude
1425 
1426  if (SigmaX == 0 || SigmaY == 0) {
1427  LogDebug("Pixel Digitizer") << SigmaX << " " << SigmaY << " cloud " << i->position().x() << " "
1428  << i->position().y() << " " << i->sigma_x() << " " << i->sigma_y() << " "
1429  << i->amplitude() << "\n";
1430  }
1431 
1432 #ifdef TP_DEBUG
1433  LogDebug("Pixel Digitizer") << " cloud " << i->position().x() << " " << i->position().y() << " " << i->sigma_x()
1434  << " " << i->sigma_y() << " " << i->amplitude();
1435 #endif
1436 
1437  // Find the maximum cloud spread in 2D plane , assume 3*sigma
1438  float CloudRight = CloudCenterX + ClusterWidth * SigmaX;
1439  float CloudLeft = CloudCenterX - ClusterWidth * SigmaX;
1440  float CloudUp = CloudCenterY + ClusterWidth * SigmaY;
1441  float CloudDown = CloudCenterY - ClusterWidth * SigmaY;
1442 
1443  // Define 2D cloud limit points
1444  LocalPoint PointRightUp = LocalPoint(CloudRight, CloudUp);
1445  LocalPoint PointLeftDown = LocalPoint(CloudLeft, CloudDown);
1446 
1447  // This points can be located outside the sensor area.
1448  // The conversion to measurement point does not check for that
1449  // so the returned pixel index might be wrong (outside range).
1450  // We rely on the limits check below to fix this.
1451  // But remember whatever we do here THE CHARGE OUTSIDE THE ACTIVE
1452  // PIXEL AREA IS LOST, it should not be collected.
1453 
1454  // Convert the 2D points to pixel indices
1455  MeasurementPoint mp = topol->measurementPosition(PointRightUp); //OK
1456 
1457  int IPixRightUpX = int(floor(mp.x()));
1458  int IPixRightUpY = int(floor(mp.y()));
1459 
1460 #ifdef TP_DEBUG
1461  LogDebug("Pixel Digitizer") << " right-up " << PointRightUp << " " << mp.x() << " " << mp.y() << " " << IPixRightUpX
1462  << " " << IPixRightUpY;
1463 #endif
1464 
1465  mp = topol->measurementPosition(PointLeftDown); //OK
1466 
1467  int IPixLeftDownX = int(floor(mp.x()));
1468  int IPixLeftDownY = int(floor(mp.y()));
1469 
1470 #ifdef TP_DEBUG
1471  emd::LogDebug("Pixel Digitizer") << " left-down " << PointLeftDown << " " << mp.x() << " " << mp.y() << " "
1472  << IPixLeftDownX << " " << IPixLeftDownY;
1473 #endif
1474 
1475  // Check detector limits to correct for pixels outside range.
1476  int numColumns = topol->ncolumns(); // det module number of cols&rows
1477  int numRows = topol->nrows();
1478 
1479  IPixRightUpX = numRows > IPixRightUpX ? IPixRightUpX : numRows - 1;
1480  IPixRightUpY = numColumns > IPixRightUpY ? IPixRightUpY : numColumns - 1;
1481  IPixLeftDownX = 0 < IPixLeftDownX ? IPixLeftDownX : 0;
1482  IPixLeftDownY = 0 < IPixLeftDownY ? IPixLeftDownY : 0;
1483 
1484  x.clear(); // clear temporary integration array
1485  y.clear();
1486 
1487  // First integrate charge strips in x
1488  int ix; // TT for compatibility
1489  for (ix = IPixLeftDownX; ix <= IPixRightUpX; ix++) { // loop over x index
1490  float xUB, xLB, UpperBound, LowerBound;
1491 
1492  // Why is set to 0 if ix=0, does it meen that we accept charge
1493  // outside the sensor? CHeck How it was done in ORCA?
1494  //if(ix == 0) LowerBound = 0.;
1495  if (ix == 0 || SigmaX == 0.) // skip for surface segemnts
1496  LowerBound = 0.;
1497  else {
1498  mp = MeasurementPoint(float(ix), 0.0);
1499  xLB = topol->localPosition(mp).x();
1500  LowerBound = 1 - calcQ((xLB - CloudCenterX) / SigmaX);
1501  }
1502 
1503  if (ix == numRows - 1 || SigmaX == 0.)
1504  UpperBound = 1.;
1505  else {
1506  mp = MeasurementPoint(float(ix + 1), 0.0);
1507  xUB = topol->localPosition(mp).x();
1508  UpperBound = 1. - calcQ((xUB - CloudCenterX) / SigmaX);
1509  }
1510 
1511  float TotalIntegrationRange = UpperBound - LowerBound; // get strip
1512  x[ix] = TotalIntegrationRange; // save strip integral
1513  if (SigmaX == 0 || SigmaY == 0)
1514  LogDebug("Pixel Digitizer") << TotalIntegrationRange << " " << ix << "\n";
1515  }
1516 
1517  // Now integrate strips in y
1518  int iy; // TT for compatibility
1519  for (iy = IPixLeftDownY; iy <= IPixRightUpY; iy++) { //loope over y ind
1520  float yUB, yLB, UpperBound, LowerBound;
1521 
1522  if (iy == 0 || SigmaY == 0.)
1523  LowerBound = 0.;
1524  else {
1525  mp = MeasurementPoint(0.0, float(iy));
1526  yLB = topol->localPosition(mp).y();
1527  LowerBound = 1. - calcQ((yLB - CloudCenterY) / SigmaY);
1528  }
1529 
1530  if (iy == numColumns - 1 || SigmaY == 0.)
1531  UpperBound = 1.;
1532  else {
1533  mp = MeasurementPoint(0.0, float(iy + 1));
1534  yUB = topol->localPosition(mp).y();
1535  UpperBound = 1. - calcQ((yUB - CloudCenterY) / SigmaY);
1536  }
1537 
1538  float TotalIntegrationRange = UpperBound - LowerBound;
1539  y[iy] = TotalIntegrationRange; // save strip integral
1540  if (SigmaX == 0 || SigmaY == 0)
1541  LogDebug("Pixel Digitizer") << TotalIntegrationRange << " " << iy << "\n";
1542  }
1543 
1544  // Get the 2D charge integrals by folding x and y strips
1545  int chan;
1546  for (ix = IPixLeftDownX; ix <= IPixRightUpX; ix++) { // loop over x index
1547  for (iy = IPixLeftDownY; iy <= IPixRightUpY; iy++) { //loope over y ind
1548 
1549  float ChargeFraction = Charge * x[ix] * y[iy];
1550 
1551  if (ChargeFraction > 0.) {
1552  chan = PixelDigi::pixelToChannel(ix, iy); // Get index
1553  // Load the amplitude
1554  hit_signal[chan] += ChargeFraction;
1555  } // endif
1556 
1557 #ifdef TP_DEBUG
1558  mp = MeasurementPoint(float(ix), float(iy));
1559  LocalPoint lp = topol->localPosition(mp);
1560  chan = topol->channel(lp);
1561  LogDebug("Pixel Digitizer") << " pixel " << ix << " " << iy << " - "
1562  << " " << chan << " " << ChargeFraction << " " << mp.x() << " " << mp.y() << " "
1563  << lp.x() << " " << lp.y() << " " // givex edge position
1564  << chan; // edge belongs to previous ?
1565 #endif
1566 
1567  } // endfor iy
1568  } //endfor ix
1569 
1570  } // loop over charge distributions
1571 
1572  // Fill the global map with all hit pixels from this event
1573 
1574  bool reweighted = false;
1575  bool makeDSLinks = store_SimHitEntryExitPoints_ || makeDigiSimLinks_;
1576 
1577  size_t ReferenceIndex4CR = 0;
1578  if (UseReweighting) {
1579  if (hit.processType() == 0) {
1580  ReferenceIndex4CR = hitIndex;
1581  reweighted = TheNewSiPixelChargeReweightingAlgorithmClass->hitSignalReweight(
1582  hit, hit_signal, hitIndex, ReferenceIndex4CR, tofBin, topol, detID, theSignal, hit.processType(), makeDSLinks);
1583  } else {
1584  std::vector<PSimHit>::const_iterator crSimHit = inputBegin;
1585  ReferenceIndex4CR = FirstHitIndex;
1586  // if the first hit in the same detId is not associated to the same trackId, try to find a better match
1587  if ((*inputBegin).trackId() != hit.trackId()) {
1588  // loop over all the hit from the 1st in the same detId to the hit itself to find the primary particle of the same trackId
1589  uint32_t detId = pixdet->geographicalId().rawId();
1590  size_t localIndex = FirstHitIndex;
1591  for (std::vector<PSimHit>::const_iterator ssbegin = inputBegin; localIndex < hitIndex;
1592  ++ssbegin, ++localIndex) {
1593  if ((*ssbegin).detUnitId() != detId) {
1594  continue;
1595  }
1596  if ((*ssbegin).trackId() == hit.trackId() && (*ssbegin).processType() == 0) {
1597  crSimHit = ssbegin;
1598  ReferenceIndex4CR = localIndex;
1599  break;
1600  }
1601  }
1602  }
1603 
1604  reweighted = TheNewSiPixelChargeReweightingAlgorithmClass->hitSignalReweight((*crSimHit),
1605  hit_signal,
1606  hitIndex,
1607  ReferenceIndex4CR,
1608  tofBin,
1609  topol,
1610  detID,
1611  theSignal,
1612  hit.processType(),
1613  makeDSLinks);
1614  }
1615  }
1616  if (!reweighted) {
1617  for (hit_map_type::const_iterator im = hit_signal.begin(); im != hit_signal.end(); ++im) {
1618  int chan = (*im).first;
1619  if (ReferenceIndex4CR == 0) {
1620  // no determination has been done previously because !UseReweighting
1621  // we need to determine it now:
1622  if (hit.processType() == 0)
1623  ReferenceIndex4CR = hitIndex;
1624  else {
1625  ReferenceIndex4CR = FirstHitIndex;
1626  // if the first hit in the same detId is not associated to the same trackId, try to find a better match
1627  if ((*inputBegin).trackId() != hit.trackId()) {
1628  // loop on all the hit from the 1st of the collection to the hit itself to find the Primary particle of the same trackId
1629  uint32_t detId = pixdet->geographicalId().rawId();
1630  size_t localIndex = FirstHitIndex;
1631  for (std::vector<PSimHit>::const_iterator ssbegin = inputBegin; localIndex < hitIndex;
1632  ++ssbegin, ++localIndex) {
1633  if ((*ssbegin).detUnitId() != detId) {
1634  continue;
1635  }
1636  if ((*ssbegin).trackId() == hit.trackId() && (*ssbegin).processType() == 0) {
1637  ReferenceIndex4CR = localIndex;
1638  break;
1639  }
1640  }
1641  }
1642  }
1643  }
1644  theSignal[chan] += (makeDSLinks ? Amplitude((*im).second, &hit, hitIndex, ReferenceIndex4CR, tofBin, (*im).second)
1645  : Amplitude((*im).second, (*im).second));
1646 
1647 #ifdef TP_DEBUG
1648  std::pair<int, int> ip = PixelDigi::channelToPixel(chan);
1649  LogDebug("Pixel Digitizer") << " pixel " << ip.first << " " << ip.second << " " << theSignal[chan];
1650 #endif
1651  }
1652  }
1653 
1654 } // end induce_signal
1655 
1656 /***********************************************************************/
1657 
1658 void SiPixelDigitizerAlgorithm::fillSimHitMaps(std::vector<PSimHit> simHits, const unsigned int tofBin) {
1659  // store here the SimHit map for later
1660  int printnum = 0;
1661  for (std::vector<PSimHit>::const_iterator it = simHits.begin(), itEnd = simHits.end(); it != itEnd;
1662  ++it, ++printnum) {
1663  unsigned int detID = (*it).detUnitId();
1664  unsigned int subdetID = DetId(detID).subdetId();
1665  subDetTofBin theSubDetTofBin = std::make_pair(subdetID, tofBin);
1666  SimHitMap[SimHitCollMap[theSubDetTofBin]].push_back(*it);
1667  }
1668 }
1669 
1671 
1672 /***********************************************************************/
1673 
1674 // Build pixels, check threshold, add misscalibration, ...
1675 void SiPixelDigitizerAlgorithm::make_digis(float thePixelThresholdInE,
1676  uint32_t detID,
1677  const PixelGeomDetUnit* pixdet,
1678  std::vector<PixelDigi>& digis,
1679  std::vector<PixelDigiSimLink>& simlinks,
1680  std::vector<PixelDigiAddTempInfo>& newClass_Digi_extra,
1681  const TrackerTopology* tTopo) const {
1682 #ifdef TP_DEBUG
1683  LogDebug("Pixel Digitizer") << " make digis "
1684  << " "
1685  << " pixel threshold FPix" << theThresholdInE_FPix << " "
1686  << " pixel threshold BPix" << theThresholdInE_BPix << " "
1687  << " pixel threshold BPix Layer1" << theThresholdInE_BPix_L1 << " "
1688  << " pixel threshold BPix Layer2" << theThresholdInE_BPix_L2 << " "
1689  << " List pixels passing threshold ";
1690 #endif
1691 
1692  // Loop over hit pixels
1693 
1694  signalMaps::const_iterator it = _signal.find(detID);
1695  if (it == _signal.end()) {
1696  return;
1697  }
1698 
1699  const signal_map_type& theSignal = (*it).second;
1700 
1701  // unsigned long is enough to store SimTrack id and EncodedEventId
1702  using TrackEventId = std::pair<decltype(SimTrack().trackId()), decltype(EncodedEventId().rawId())>;
1703  std::map<TrackEventId, float> simi; // re-used
1704 
1705  for (signal_map_const_iterator i = theSignal.begin(); i != theSignal.end(); ++i) {
1706  float signalInElectrons = (*i).second; // signal in electrons
1707 
1708  // Do the miss calibration for calibration studies only.
1709  //if(doMissCalibrate) signalInElectrons = missCalibrate(signalInElectrons)
1710 
1711  // Do only for pixels above threshold
1712 
1713  if (signalInElectrons >= thePixelThresholdInE &&
1714  signalInElectrons > 0.) { // check threshold, always reject killed (0-charge) digis
1715 
1716  int chan = (*i).first; // channel number
1717  std::pair<int, int> ip = PixelDigi::channelToPixel(chan);
1718  int adc = 0; // ADC count as integer
1719 
1720  // Do the miss calibration for calibration studies only.
1721  if (doMissCalibrate) {
1722  int row = ip.first; // X in row
1723  int col = ip.second; // Y is in col
1724  adc = int(missCalibrate(detID, tTopo, pixdet, col, row, signalInElectrons)); //full misscalib.
1725  } else { // Just do a simple electron->adc conversion
1726  adc = int(signalInElectrons / theElectronPerADC); // calibrate gain
1727  }
1728  adc = std::min(adc, theAdcFullScale); // Check maximum value
1729 #ifdef TP_DEBUG
1730  LogDebug("Pixel Digitizer") << (*i).first << " " << (*i).second << " " << signalInElectrons << " " << adc
1731  << ip.first << " " << ip.second;
1732 #endif
1733 
1734  // Load digis
1735  digis.emplace_back(ip.first, ip.second, adc);
1736 
1737  if (makeDigiSimLinks_ && !(*i).second.hitInfos().empty()) {
1738  //digilink
1739  unsigned int il = 0;
1740  for (const auto& info : (*i).second.hitInfos()) {
1741  // note: according to C++ standard operator[] does
1742  // value-initializiation, which for float means initial value of 0
1743  simi[std::make_pair(info.trackId(), info.eventId().rawId())] += (*i).second.individualampl()[il];
1744  il++;
1745  }
1746 
1747  //sum the contribution of the same trackid
1748  for (const auto& info : (*i).second.hitInfos()) {
1749  // skip if track already processed
1750  auto found = simi.find(std::make_pair(info.trackId(), info.eventId().rawId()));
1751  if (found == simi.end())
1752  continue;
1753 
1754  float sum_samechannel = found->second;
1755  float fraction = sum_samechannel / (*i).second;
1756  if (fraction > 1.f)
1757  fraction = 1.f;
1758 
1759  // Approximation: pick hitIndex and tofBin only from the first SimHit
1760  simlinks.emplace_back((*i).first, info.trackId(), info.hitIndex(), info.tofBin(), info.eventId(), fraction);
1761  simi.erase(found);
1762  }
1763  simi.clear(); // although should be empty already
1764  }
1765 
1766  if (store_SimHitEntryExitPoints_ && !(*i).second.hitInfos().empty()) {
1767  // get info stored, like in simlinks...
1768  for (const auto& info : (*i).second.hitInfos()) {
1769  unsigned int CFPostoBeUsed = info.hitIndex4ChargeRew();
1770  // check if the association (chan, index) is already in the newClass_Digi_extra collection
1771  // if yes, don't push a duplicated entry ; if not, push a new entry
1772  std::vector<PixelDigiAddTempInfo>::iterator loopNewClass;
1773  bool already_present = false;
1774  for (loopNewClass = newClass_Digi_extra.begin(); loopNewClass != newClass_Digi_extra.end(); ++loopNewClass) {
1775  if (chan == (int)loopNewClass->channel() && CFPostoBeUsed == loopNewClass->hitIndex()) {
1776  already_present = true;
1777  loopNewClass->addCharge(info.getAmpl());
1778  }
1779  }
1780  if (!already_present) {
1781  unsigned int tofBin = info.tofBin();
1782  // then inspired by https://github.com/cms-sw/cmssw/blob/master/SimTracker/TrackerHitAssociation/src/TrackerHitAssociator.cc#L566 :
1783  subDetTofBin theSubDetTofBin = std::make_pair(DetId(detID).subdetId(), tofBin);
1784  auto it = SimHitCollMap.find(theSubDetTofBin);
1785  if (it != SimHitCollMap.end()) {
1786  auto it2 = SimHitMap.find((it->second));
1787 
1788  if (it2 != SimHitMap.end()) {
1789  const PSimHit& theSimHit = (it2->second)[CFPostoBeUsed];
1790  newClass_Digi_extra.emplace_back(chan,
1791  info.hitIndex4ChargeRew(),
1792  theSimHit.entryPoint(),
1793  theSimHit.exitPoint(),
1794  theSimHit.processType(),
1795  theSimHit.trackId(),
1796  detID,
1797  info.getAmpl());
1798  }
1799  }
1800  }
1801  } // end for
1802  } // end if store_SimHitEntryExitPoints_
1803  }
1804  }
1805 }
1806 
1807 /***********************************************************************/
1808 
1809 // Add electronic noise to pixel charge
1811  float thePixelThreshold,
1812  CLHEP::HepRandomEngine* engine) {
1813 #ifdef TP_DEBUG
1814  LogDebug("Pixel Digitizer") << " enter add_noise " << theNoiseInElectrons;
1815 #endif
1816 
1817  uint32_t detID = pixdet->geographicalId().rawId();
1818  signal_map_type& theSignal = _signal[detID];
1819 
1820  // First add noise to hit pixels
1821  float theSmearedChargeRMS = 0.0;
1822 
1823  for (signal_map_iterator i = theSignal.begin(); i != theSignal.end(); i++) {
1824  if (addChargeVCALSmearing) {
1825  if ((*i).second < 3000) {
1826  theSmearedChargeRMS = 543.6 - (*i).second * 0.093;
1827  } else if ((*i).second < 6000) {
1828  theSmearedChargeRMS = 307.6 - (*i).second * 0.01;
1829  } else {
1830  theSmearedChargeRMS = -432.4 + (*i).second * 0.123;
1831  }
1832 
1833  // Noise from Vcal smearing:
1834  float noise_ChargeVCALSmearing = theSmearedChargeRMS * CLHEP::RandGaussQ::shoot(engine, 0., 1.);
1835  // Noise from full readout:
1836  float noise = CLHEP::RandGaussQ::shoot(engine, 0., theReadoutNoise);
1837 
1838  if (((*i).second + Amplitude(noise + noise_ChargeVCALSmearing, -1.)) < 0.) {
1839  (*i).second.set(0);
1840  } else {
1841  (*i).second += Amplitude(noise + noise_ChargeVCALSmearing, -1.);
1842  }
1843 
1844  } // End if addChargeVCalSmearing
1845  else {
1846  // Noise: ONLY full READOUT Noise.
1847  // Use here the FULL readout noise, including TBM,ALT,AOH,OPT-REC.
1848  float noise = CLHEP::RandGaussQ::shoot(engine, 0., theReadoutNoise);
1849 
1850  if (((*i).second + Amplitude(noise, -1.)) < 0.) {
1851  (*i).second.set(0);
1852  } else {
1853  (*i).second += Amplitude(noise, -1.);
1854  }
1855  } // end if only Noise from full readout
1856  }
1857 
1858  if (!addNoisyPixels) // Option to skip noise in non-hit pixels
1859  return;
1860 
1861  const PixelTopology* topol = &pixdet->specificTopology();
1862  int numColumns = topol->ncolumns(); // det module number of cols&rows
1863  int numRows = topol->nrows();
1864 
1865  // Add noise on non-hit pixels
1866  // Use here the pixel noise
1867  int numberOfPixels = (numRows * numColumns);
1868  std::map<int, float, std::less<int> > otherPixels;
1869  std::map<int, float, std::less<int> >::iterator mapI;
1870 
1871  theNoiser->generate(numberOfPixels,
1872  thePixelThreshold, //thr. in un. of nois
1873  theNoiseInElectrons, // noise in elec.
1874  otherPixels,
1875  engine);
1876 
1877 #ifdef TP_DEBUG
1878  LogDebug("Pixel Digitizer") << " Add noisy pixels " << numRows << " " << numColumns << " " << theNoiseInElectrons
1879  << " " << theThresholdInE_FPix << theThresholdInE_BPix << " " << numberOfPixels << " "
1880  << otherPixels.size();
1881 #endif
1882 
1883  // Add noisy pixels
1884  for (mapI = otherPixels.begin(); mapI != otherPixels.end(); mapI++) {
1885  int iy = ((*mapI).first) / numRows;
1886  int ix = ((*mapI).first) - (iy * numRows);
1887 
1888  // Keep for a while for testing.
1889  if (iy < 0 || iy > (numColumns - 1))
1890  LogWarning("Pixel Geometry") << " error in iy " << iy;
1891  if (ix < 0 || ix > (numRows - 1))
1892  LogWarning("Pixel Geometry") << " error in ix " << ix;
1893 
1894  int chan = PixelDigi::pixelToChannel(ix, iy);
1895 
1896 #ifdef TP_DEBUG
1897  LogDebug("Pixel Digitizer") << " Storing noise = " << (*mapI).first << " " << (*mapI).second << " " << ix << " "
1898  << iy << " " << chan;
1899 #endif
1900 
1901  if (theSignal[chan] == 0) {
1902  // float noise = float( (*mapI).second );
1903  int noise = int((*mapI).second);
1904  theSignal[chan] = Amplitude(noise, -1.);
1905  }
1906  }
1907 }
1908 
1909 /***********************************************************************/
1910 
1911 // Simulate the readout inefficiencies.
1912 // Delete a selected number of single pixels, dcols and rocs.
1914  const PixelGeomDetUnit* pixdet,
1915  const TrackerTopology* tTopo,
1916  CLHEP::HepRandomEngine* engine) {
1917  uint32_t detID = pixdet->geographicalId().rawId();
1918  signal_map_type& theSignal = _signal[detID];
1919  const PixelTopology* topol = &pixdet->specificTopology();
1920  int numColumns = topol->ncolumns(); // det module number of cols&rows
1921  int numRows = topol->nrows();
1924  // Predefined efficiencies
1925  double pixelEfficiency = 1.0;
1926  double columnEfficiency = 1.0;
1927  double chipEfficiency = 1.0;
1928  std::vector<double> pixelEfficiencyROCStdPixels(16, 1);
1929  std::vector<double> pixelEfficiencyROCBigPixels(16, 1);
1930 
1931  auto pIndexConverter = PixelIndices(numColumns, numRows);
1932 
1933  std::vector<int> badRocsFromFEDChannels(16, 0);
1934  if (eff.PixelFEDChannelCollection_ != nullptr) {
1936 
1937  if (it != eff.PixelFEDChannelCollection_->end()) {
1938  const std::vector<CablingPathToDetUnit>& path = map_->pathToDetUnit(detID);
1939  for (const auto& ch : *it) {
1940  for (unsigned int i_roc = ch.roc_first; i_roc <= ch.roc_last; ++i_roc) {
1941  for (const auto p : path) {
1942  const PixelROC* myroc = map_->findItem(p);
1943  if (myroc->idInDetUnit() == static_cast<unsigned int>(i_roc)) {
1944  LocalPixel::RocRowCol local = {39, 25}; //corresponding to center of ROC row,col
1945  GlobalPixel global = myroc->toGlobal(LocalPixel(local));
1946  int chipIndex(0), colROC(0), rowROC(0);
1947  pIndexConverter.transformToROC(global.col, global.row, chipIndex, colROC, rowROC);
1948  badRocsFromFEDChannels.at(chipIndex) = 1;
1949  }
1950  }
1951  }
1952  } // loop over channels
1953  } // detID in PixelFEDChannelCollection_
1954  } // has PixelFEDChannelCollection_
1955 
1956  if (eff.FromConfig) {
1957  // setup the chip indices conversion
1959  pixdet->subDetector() == GeomDetEnumerators::SubDetector::P1PXB) { // barrel layers
1960  int layerIndex = tTopo->layer(detID);
1961  pixelEfficiency = eff.thePixelEfficiency[layerIndex - 1];
1962  columnEfficiency = eff.thePixelColEfficiency[layerIndex - 1];
1963  chipEfficiency = eff.thePixelChipEfficiency[layerIndex - 1];
1964  LogDebug("Pixel Digitizer") << "Using BPix columnEfficiency = " << columnEfficiency
1965  << " for layer = " << layerIndex << "\n";
1966  // This should never happen, but only check if it is not an upgrade geometry
1967  if (NumberOfBarrelLayers == 3) {
1968  if (numColumns > 416)
1969  LogWarning("Pixel Geometry") << " wrong columns in barrel " << numColumns;
1970  if (numRows > 160)
1971  LogWarning("Pixel Geometry") << " wrong rows in barrel " << numRows;
1972 
1973  int ladder = tTopo->pxbLadder(detID);
1974  int module = tTopo->pxbModule(detID);
1975  if (module <= 4)
1976  module = 5 - module;
1977  else
1978  module -= 4;
1979 
1980  columnEfficiency *= eff.theLadderEfficiency_BPix[layerIndex - 1][ladder - 1] *
1981  eff.theModuleEfficiency_BPix[layerIndex - 1][module - 1] * eff.pu_scale[layerIndex - 1];
1982  }
1985  pixdet->subDetector() == GeomDetEnumerators::SubDetector::P2PXEC) { // forward disks
1986 
1987  unsigned int diskIndex =
1988  tTopo->layer(detID) + eff.FPixIndex; // Use diskIndex-1 later to stay consistent with BPix
1989  unsigned int panelIndex = tTopo->pxfPanel(detID);
1990  unsigned int moduleIndex = tTopo->pxfModule(detID);
1991  //if (eff.FPixIndex>diskIndex-1){throw cms::Exception("Configuration") <<"SiPixelDigitizer is using the wrong efficiency value. index = "
1992  // <<diskIndex-1<<" , MinIndex = "<<eff.FPixIndex<<" ... "<<tTopo->pxfDisk(detID);}
1993  pixelEfficiency = eff.thePixelEfficiency[diskIndex - 1];
1994  columnEfficiency = eff.thePixelColEfficiency[diskIndex - 1];
1995  chipEfficiency = eff.thePixelChipEfficiency[diskIndex - 1];
1996  LogDebug("Pixel Digitizer") << "Using FPix columnEfficiency = " << columnEfficiency
1997  << " for Disk = " << tTopo->pxfDisk(detID) << "\n";
1998  // Sometimes the forward pixels have wrong size,
1999  // this crashes the index conversion, so exit, but only check if it is not an upgrade geometry
2000  if (NumberOfBarrelLayers ==
2001  3) { // whether it is the present or the phase 1 detector can be checked using GeomDetEnumerators::SubDetector
2002  if (numColumns > 260 || numRows > 160) {
2003  if (numColumns > 260)
2004  LogWarning("Pixel Geometry") << " wrong columns in endcaps " << numColumns;
2005  if (numRows > 160)
2006  LogWarning("Pixel Geometry") << " wrong rows in endcaps " << numRows;
2007  return;
2008  }
2009  if ((panelIndex == 1 && (moduleIndex == 1 || moduleIndex == 2)) ||
2010  (panelIndex == 2 && moduleIndex == 1)) { //inner modules
2011  columnEfficiency *= eff.theInnerEfficiency_FPix[diskIndex - 1] * eff.pu_scale[3];
2012  } else { //outer modules
2013  columnEfficiency *= eff.theOuterEfficiency_FPix[diskIndex - 1] * eff.pu_scale[4];
2014  }
2015  } // current detector, forward
2016  } else if (pixdet->subDetector() == GeomDetEnumerators::SubDetector::P2OTB ||
2018  // If phase 2 outer tracker, hardcoded values as they have been so far
2019  pixelEfficiency = 0.999;
2020  columnEfficiency = 0.999;
2021  chipEfficiency = 0.999;
2022  } // if barrel/forward
2023  } else { // Load precomputed factors from Database
2024  pixelEfficiency = eff.PixelGeomFactors.at(detID);
2025  columnEfficiency = eff.ColGeomFactors.at(detID) * eff.pu_scale[eff.iPU.at(detID)];
2026  chipEfficiency = eff.ChipGeomFactors.at(detID);
2027  if (isPhase1) {
2028  for (unsigned int i_roc = 0; i_roc < eff.PixelGeomFactorsROCStdPixels.at(detID).size(); ++i_roc) {
2029  pixelEfficiencyROCStdPixels[i_roc] = eff.PixelGeomFactorsROCStdPixels.at(detID).at(i_roc);
2030  pixelEfficiencyROCBigPixels[i_roc] = eff.PixelGeomFactorsROCBigPixels.at(detID).at(i_roc);
2031  }
2032  } // is Phase 1
2033  }
2034 
2035 #ifdef TP_DEBUG
2036  LogDebug("Pixel Digitizer") << " enter pixel_inefficiency " << pixelEfficiency << " " << columnEfficiency << " "
2037  << chipEfficiency;
2038 #endif
2039 
2040  // Initilize the index converter
2041  //PixelIndices indexConverter(numColumns,numRows);
2042 
2043  int chipIndex = 0;
2044  int rowROC = 0;
2045  int colROC = 0;
2046  std::map<int, int, std::less<int> > chips, columns, pixelStd, pixelBig;
2047  std::map<int, int, std::less<int> >::iterator iter;
2048 
2049  // Find out the number of columns and rocs hits
2050  // Loop over hit pixels, amplitude in electrons, channel = coded row,col
2051  for (signal_map_const_iterator i = theSignal.begin(); i != theSignal.end(); ++i) {
2052  int chan = i->first;
2053  std::pair<int, int> ip = PixelDigi::channelToPixel(chan);
2054  int row = ip.first; // X in row
2055  int col = ip.second; // Y is in col
2056  //transform to ROC index coordinates
2057  pIndexConverter.transformToROC(col, row, chipIndex, colROC, rowROC);
2058  int dColInChip = pIndexConverter.DColumn(colROC); // get ROC dcol from ROC col
2059  //dcol in mod
2060  int dColInDet = pIndexConverter.DColumnInModule(dColInChip, chipIndex);
2061 
2062  chips[chipIndex]++;
2063  columns[dColInDet]++;
2064  if (isPhase1) {
2065  if (topol->isItBigPixelInX(row) || topol->isItBigPixelInY(col))
2066  pixelBig[chipIndex]++;
2067  else
2068  pixelStd[chipIndex]++;
2069  }
2070  }
2071 
2072  // Delete some ROC hits.
2073  for (iter = chips.begin(); iter != chips.end(); iter++) {
2074  //float rand = RandFlat::shoot();
2075  float rand = CLHEP::RandFlat::shoot(engine);
2076  if (rand > chipEfficiency)
2077  chips[iter->first] = 0;
2078  }
2079 
2080  // Delete some Dcol hits.
2081  for (iter = columns.begin(); iter != columns.end(); iter++) {
2082  //float rand = RandFlat::shoot();
2083  float rand = CLHEP::RandFlat::shoot(engine);
2084  if (rand > columnEfficiency)
2085  columns[iter->first] = 0;
2086  }
2087 
2088  // Delete some pixel hits based on DCDC issue damage.
2089  if (isPhase1) {
2090  for (iter = pixelStd.begin(); iter != pixelStd.end(); iter++) {
2091  float rand = CLHEP::RandFlat::shoot(engine);
2092  if (rand > pixelEfficiencyROCStdPixels[iter->first])
2093  pixelStd[iter->first] = 0;
2094  }
2095 
2096  for (iter = pixelBig.begin(); iter != pixelBig.end(); iter++) {
2097  float rand = CLHEP::RandFlat::shoot(engine);
2098  if (rand > pixelEfficiencyROCBigPixels[iter->first])
2099  pixelBig[iter->first] = 0;
2100  }
2101  }
2102 
2103  // Now loop again over pixels to kill some of them.
2104  // Loop over hit pixels, amplitude in electrons, channel = coded row,col
2105  for (signal_map_iterator i = theSignal.begin(); i != theSignal.end(); ++i) {
2106  // int chan = i->first;
2107  std::pair<int, int> ip = PixelDigi::channelToPixel(i->first); //get pixel pos
2108  int row = ip.first; // X in row
2109  int col = ip.second; // Y is in col
2110  //transform to ROC index coordinates
2111  pIndexConverter.transformToROC(col, row, chipIndex, colROC, rowROC);
2112  int dColInChip = pIndexConverter.DColumn(colROC); //get ROC dcol from ROC col
2113  //dcol in mod
2114  int dColInDet = pIndexConverter.DColumnInModule(dColInChip, chipIndex);
2115 
2116  //float rand = RandFlat::shoot();
2117  float rand = CLHEP::RandFlat::shoot(engine);
2118  if (chips[chipIndex] == 0 || columns[dColInDet] == 0 || rand > pixelEfficiency ||
2119  (pixelStd.count(chipIndex) && pixelStd[chipIndex] == 0) ||
2120  (pixelBig.count(chipIndex) && pixelBig[chipIndex] == 0)) {
2121  // make pixel amplitude =0, pixel will be lost at clusterization
2122  i->second.set(0.); // reset amplitude,
2123  } // end if
2124  if (isPhase1) {
2125  if ((pixelStd.count(chipIndex) && pixelStd[chipIndex] == 0) ||
2126  (pixelBig.count(chipIndex) && pixelBig[chipIndex] == 0) || (badRocsFromFEDChannels.at(chipIndex) == 1)) {
2127  //============================================================
2128  // make pixel amplitude =0, pixel will be lost at clusterization
2129  i->second.set(0.); // reset amplitude,
2130  } // end if
2131  } // is Phase 1
2132  if (KillBadFEDChannels && badRocsFromFEDChannels.at(chipIndex) == 1) {
2133  i->second.set(0.);
2134  }
2135  } // end pixel loop
2136 } // end pixel_indefficiency
2137 
2138 //***************************************************************************************
2139 // Simulate pixel aging with an exponential function
2140 //**************************************************************************************
2141 
2143  const PixelGeomDetUnit* pixdet,
2144  const TrackerTopology* tTopo) const {
2145  uint32_t detID = pixdet->geographicalId().rawId();
2146 
2147  // Predefined damage parameter (no aging)
2148  float pseudoRadDamage = 0.0f;
2149 
2150  // setup the chip indices conversion
2152  pixdet->subDetector() == GeomDetEnumerators::SubDetector::P1PXB) { // barrel layers
2153  int layerIndex = tTopo->layer(detID);
2154 
2155  pseudoRadDamage = aging.thePixelPseudoRadDamage[layerIndex - 1];
2156 
2157  LogDebug("Pixel Digitizer") << "pixel_aging: "
2158  << "\n";
2159  LogDebug("Pixel Digitizer") << "Subid " << pixdet->subDetector() << " layerIndex " << layerIndex << " ladder "
2160  << tTopo->pxbLadder(detID) << " module " << tTopo->pxbModule(detID) << "\n";
2161 
2164  pixdet->subDetector() == GeomDetEnumerators::SubDetector::P2PXEC) { // forward disks
2165  unsigned int diskIndex =
2166  tTopo->layer(detID) + aging.FPixIndex; // Use diskIndex-1 later to stay consistent with BPix
2167 
2168  pseudoRadDamage = aging.thePixelPseudoRadDamage[diskIndex - 1];
2169 
2170  LogDebug("Pixel Digitizer") << "pixel_aging: "
2171  << "\n";
2172  LogDebug("Pixel Digitizer") << "Subid " << pixdet->subDetector() << " diskIndex " << diskIndex << "\n";
2173  } else if (pixdet->subDetector() == GeomDetEnumerators::SubDetector::P2OTB ||
2175  // if phase 2 OT hardcoded value as it has always been
2176  pseudoRadDamage = 0.f;
2177  } // if barrel/forward
2178 
2179  LogDebug("Pixel Digitizer") << " pseudoRadDamage " << pseudoRadDamage << "\n";
2180  LogDebug("Pixel Digitizer") << " end pixel_aging "
2181  << "\n";
2182 
2183  return pseudoRadDamage;
2184 #ifdef TP_DEBUG
2185  LogDebug("Pixel Digitizer") << " enter pixel_aging " << pseudoRadDamage;
2186 #endif
2187 }
2188 
2189 //***********************************************************************
2190 
2191 // Fluctuate the gain and offset for the amplitude calibration
2192 // Use gaussian smearing.
2193 //float SiPixelDigitizerAlgorithm::missCalibrate(const float amp) const {
2194 //float gain = RandGaussQ::shoot(1.,theGainSmearing);
2195 //float offset = RandGaussQ::shoot(0.,theOffsetSmearing);
2196 //float newAmp = amp * gain + offset;
2197 // More complex misscalibration
2199  const TrackerTopology* tTopo,
2200  const PixelGeomDetUnit* pixdet,
2201  int col,
2202  int row,
2203  const float signalInElectrons) const {
2204  // Central values
2205  //const float p0=0.00352, p1=0.868, p2=112., p3=113.; // pix(0,0,0)
2206  // const float p0=0.00382, p1=0.886, p2=112.7, p3=113.0; // average roc=0
2207  //const float p0=0.00492, p1=1.998, p2=90.6, p3=134.1; // average roc=6
2208  // Smeared (rms)
2209  //const float s0=0.00020, s1=0.051, s2=5.4, s3=4.4; // average roc=0
2210  //const float s0=0.00015, s1=0.043, s2=3.2, s3=3.1; // col average roc=0
2211 
2212  // Make 2 sets of parameters for Fpix and BPIx:
2213 
2214  float p0 = 0.0f;
2215  float p1 = 0.0f;
2216  float p2 = 0.0f;
2217  float p3 = 0.0f;
2218 
2219  if (pixdet->type().isTrackerPixel() && pixdet->type().isBarrel()) { // barrel layers
2220  p0 = BPix_p0;
2221  p1 = BPix_p1;
2222  p2 = BPix_p2;
2223  p3 = BPix_p3;
2224  } else if (pixdet->type().isTrackerPixel()) { // forward disks
2225  p0 = FPix_p0;
2226  p1 = FPix_p1;
2227  p2 = FPix_p2;
2228  p3 = FPix_p3;
2229  } else {
2230  throw cms::Exception("NotAPixelGeomDetUnit") << "Not a pixel geomdet unit" << detID;
2231  }
2232 
2233  float newAmp = 0.f; //Modified signal
2234 
2235  // Convert electrons to VCAL units
2236  float signal = (signalInElectrons - electronsPerVCAL_Offset) / electronsPerVCAL;
2237 
2238  // New gains/offsets are needed for phase1 L1
2239  int layer = 0;
2240  if (DetId(detID).subdetId() == 1)
2241  layer = tTopo->pxbLayer(detID);
2242  if (layer == 1)
2243  signal = (signalInElectrons - electronsPerVCAL_L1_Offset) / electronsPerVCAL_L1;
2244 
2245  // Simulate the analog response with fixed parametrization
2246  newAmp = p3 + p2 * tanh(p0 * signal - p1);
2247 
2248  // Use the pixel-by-pixel calibrations
2249  //transform to ROC index coordinates
2250  //int chipIndex=0, colROC=0, rowROC=0;
2251  //std::unique_ptr<PixelIndices> pIndexConverter(new PixelIndices(numColumns,numRows));
2252  //pIndexConverter->transformToROC(col,row,chipIndex,colROC,rowROC);
2253 
2254  // Use calibration from a file
2255  //int chanROC = PixelIndices::pixelToChannelROC(rowROC,colROC); // use ROC coordinates
2256  //float pp0=0, pp1=0,pp2=0,pp3=0;
2257  //map<int,CalParameters,std::less<int> >::const_iterator it=calmap.find(chanROC);
2258  //CalParameters y = (*it).second;
2259  //pp0 = y.p0;
2260  //pp1 = y.p1;
2261  //pp2 = y.p2;
2262  //pp3 = y.p3;
2263 
2264  //
2265  // Use random smearing
2266  // Randomize the pixel response
2267  //float pp0 = RandGaussQ::shoot(p0,s0);
2268  //float pp1 = RandGaussQ::shoot(p1,s1);
2269  //float pp2 = RandGaussQ::shoot(p2,s2);
2270  //float pp3 = RandGaussQ::shoot(p3,s3);
2271 
2272  //newAmp = pp3 + pp2 * tanh(pp0*signal - pp1); // Final signal
2273 
2274  LogDebug("Pixel Digitizer") << " misscalibrate " << col << " " << row
2275  << " "
2276  // <<chipIndex<<" " <<colROC<<" " <<rowROC<<" "
2277  << signalInElectrons << " " << signal << " " << newAmp << " "
2278  << (signalInElectrons / theElectronPerADC) << "\n";
2279 
2280  return newAmp;
2281 }
2282 //******************************************************************************
2283 
2284 // Set the drift direction accoring to the Bfield in local det-unit frame
2285 // Works for both barrel and forward pixels.
2286 // Replace the sign convention to fit M.Swartz's formulaes.
2287 // Configurations for barrel and foward pixels possess different tanLorentzAngleperTesla
2288 // parameter value
2289 
2291  const GlobalVector& bfield,
2292  const DetId& detId) const {
2293  Frame detFrame(pixdet->surface().position(), pixdet->surface().rotation());
2294  LocalVector Bfield = detFrame.toLocal(bfield);
2295 
2296  float alpha2_FPix;
2297  float alpha2_BPix;
2298  float alpha2;
2299 
2300  //float dir_x = -tanLorentzAnglePerTesla * Bfield.y();
2301  //float dir_y = +tanLorentzAnglePerTesla * Bfield.x();
2302  //float dir_z = -1.; // E field always in z direction, so electrons go to -z
2303  // The dir_z has to be +/- 1. !
2304  // LocalVector theDriftDirection = LocalVector(dir_x,dir_y,dir_z);
2305 
2306  float dir_x = 0.0f;
2307  float dir_y = 0.0f;
2308  float dir_z = 0.0f;
2309  float scale = 0.0f;
2310 
2311  uint32_t detID = pixdet->geographicalId().rawId();
2312 
2313  // Read Lorentz angle from cfg file:**************************************************************
2314 
2315  if (!use_LorentzAngle_DB_) {
2316  if (alpha2Order) {
2319  } else {
2320  alpha2_FPix = 0.0f;
2321  alpha2_BPix = 0.0f;
2322  }
2323 
2324  if (pixdet->type().isTrackerPixel() && pixdet->type().isBarrel()) { // barrel layers
2325  dir_x = -(tanLorentzAnglePerTesla_BPix * Bfield.y() + alpha2_BPix * Bfield.z() * Bfield.x());
2326  dir_y = +(tanLorentzAnglePerTesla_BPix * Bfield.x() - alpha2_BPix * Bfield.z() * Bfield.y());
2327  dir_z = -(1 + alpha2_BPix * Bfield.z() * Bfield.z());
2328  scale = -dir_z;
2329  } else if (pixdet->type().isTrackerPixel()) { // forward disks
2330  dir_x = -(tanLorentzAnglePerTesla_FPix * Bfield.y() + alpha2_FPix * Bfield.z() * Bfield.x());
2331  dir_y = +(tanLorentzAnglePerTesla_FPix * Bfield.x() - alpha2_FPix * Bfield.z() * Bfield.y());
2332  dir_z = -(1 + alpha2_FPix * Bfield.z() * Bfield.z());
2333  scale = -dir_z;
2334  } else {
2335  throw cms::Exception("NotAPixelGeomDetUnit") << "Not a pixel geomdet unit" << detID;
2336  }
2337  } // end: Read LA from cfg file.
2338 
2339  //Read Lorentz angle from DB:********************************************************************
2340  if (use_LorentzAngle_DB_) {
2341  float lorentzAngle = SiPixelLorentzAngle_->getLorentzAngle(detId);
2342  alpha2 = lorentzAngle * lorentzAngle;
2343  dir_x = -(lorentzAngle * Bfield.y() + alpha2 * Bfield.z() * Bfield.x());
2344  dir_y = +(lorentzAngle * Bfield.x() - alpha2 * Bfield.z() * Bfield.y());
2345  dir_z = -(1 + alpha2 * Bfield.z() * Bfield.z());
2346  scale = -dir_z;
2347  } // end: Read LA from DataBase.
2348 
2349  LocalVector theDriftDirection = LocalVector(dir_x / scale, dir_y / scale, dir_z / scale);
2350 
2351 #ifdef TP_DEBUG
2352  LogDebug("Pixel Digitizer") << " The drift direction in local coordinate is " << theDriftDirection;
2353 #endif
2354 
2355  return theDriftDirection;
2356 }
2357 
2358 //****************************************************************************************************
2359 
2361  signal_map_type& theSignal = _signal[detID];
2362 
2363  // Loop over hit pixels, amplitude in electrons, channel = coded row,col
2364  for (signal_map_iterator i = theSignal.begin(); i != theSignal.end(); ++i) {
2365  // int chan = i->first;
2366  std::pair<int, int> ip = PixelDigi::channelToPixel(i->first); //get pixel pos
2367  int row = ip.first; // X in row
2368  int col = ip.second; // Y is in col
2369  //transform to ROC index coordinates
2370  if (theSiPixelGainCalibrationService_->isDead(detID, col, row)) {
2371  LogDebug("Pixel Digitizer") << "now in isdead check, row " << detID << " " << col << "," << row << "\n";
2372  // make pixel amplitude =0, pixel will be lost at clusterization
2373  i->second.set(0.); // reset amplitude,
2374  } // end if
2375  } // end pixel loop
2376 } // end pixel_indefficiency
2377 
2378 //****************************************************************************************************
2379 
2381  bool isbad = false;
2382 
2383  Parameters::const_iterator itDeadModules = DeadModules.begin();
2384 
2385  int detid = detID;
2386  for (; itDeadModules != DeadModules.end(); ++itDeadModules) {
2387  int Dead_detID = itDeadModules->getParameter<int>("Dead_detID");
2388  if (detid == Dead_detID) {
2389  isbad = true;
2390  break;
2391  }
2392  }
2393 
2394  if (!isbad)
2395  return;
2396 
2397  signal_map_type& theSignal = _signal[detID];
2398 
2399  std::string Module = itDeadModules->getParameter<std::string>("Module");
2400 
2401  if (Module == "whole") {
2402  for (signal_map_iterator i = theSignal.begin(); i != theSignal.end(); ++i) {
2403  i->second.set(0.); // reset amplitude
2404  }
2405  }
2406 
2407  for (signal_map_iterator i = theSignal.begin(); i != theSignal.end(); ++i) {
2408  std::pair<int, int> ip = PixelDigi::channelToPixel(i->first); //get pixel pos
2409 
2410  if (Module == "tbmA" && ip.first >= 80 && ip.first <= 159) {
2411  i->second.set(0.);
2412  }
2413 
2414  if (Module == "tbmB" && ip.first <= 79) {
2415  i->second.set(0.);
2416  }
2417  }
2418 }
2419 //****************************************************************************************************
2421  // Not SLHC safe for now
2422 
2423  bool isbad = false;
2424 
2425  std::vector<SiPixelQuality::disabledModuleType> disabledModules = SiPixelBadModule_->getBadComponentList();
2426 
2428 
2429  for (size_t id = 0; id < disabledModules.size(); id++) {
2430  if (detID == disabledModules[id].DetID) {
2431  isbad = true;
2432  badmodule = disabledModules[id];
2433  break;
2434  }
2435  }
2436 
2437  if (!isbad)
2438  return;
2439 
2440  signal_map_type& theSignal = _signal[detID];
2441 
2442  LogDebug("Pixel Digitizer") << "Hit in: " << detID << " errorType " << badmodule.errorType << " BadRocs=" << std::hex
2443  << SiPixelBadModule_->getBadRocs(detID) << std::dec << " "
2444  << "\n";
2445  if (badmodule.errorType == 0) { // this is a whole dead module.
2446 
2447  for (signal_map_iterator i = theSignal.begin(); i != theSignal.end(); ++i) {
2448  i->second.set(0.); // reset amplitude
2449  }
2450  } else { // all other module types: half-modules and single ROCs.
2451  // Get Bad ROC position:
2452  //follow the example of getBadRocPositions in CondFormats/SiPixelObjects/src/SiPixelQuality.cc
2453  std::vector<GlobalPixel> badrocpositions(0);
2454  for (unsigned int j = 0; j < 16; j++) {
2455  if (SiPixelBadModule_->IsRocBad(detID, j) == true) {
2456  std::vector<CablingPathToDetUnit> path = map_->pathToDetUnit(detID);
2457  typedef std::vector<CablingPathToDetUnit>::const_iterator IT;
2458  for (IT it = path.begin(); it != path.end(); ++it) {
2459  const PixelROC* myroc = map_->findItem(*it);
2460  if (myroc->idInDetUnit() == j) {
2461  LocalPixel::RocRowCol local = {39, 25}; //corresponding to center of ROC row, col
2462  GlobalPixel global = myroc->toGlobal(LocalPixel(local));
2463  badrocpositions.push_back(global);
2464  break;
2465  }
2466  }
2467  }
2468  } // end of getBadRocPositions
2469 
2470  for (signal_map_iterator i = theSignal.begin(); i != theSignal.end(); ++i) {
2471  std::pair<int, int> ip = PixelDigi::channelToPixel(i->first); //get pixel pos
2472 
2473  for (std::vector<GlobalPixel>::const_iterator it = badrocpositions.begin(); it != badrocpositions.end(); ++it) {
2474  if (it->row >= 80 && ip.first >= 80) {
2475  if ((std::abs(ip.second - it->col) < 26)) {
2476  i->second.set(0.);
2477  } else if (it->row == 120 && ip.second - it->col == 26) {
2478  i->second.set(0.);
2479  } else if (it->row == 119 && it->col - ip.second == 26) {
2480  i->second.set(0.);
2481  }
2482  } else if (it->row < 80 && ip.first < 80) {
2483  if ((std::abs(ip.second - it->col) < 26)) {
2484  i->second.set(0.);
2485  } else if (it->row == 40 && ip.second - it->col == 26) {
2486  i->second.set(0.);
2487  } else if (it->row == 39 && it->col - ip.second == 26) {
2488  i->second.set(0.);
2489  }
2490  }
2491  }
2492  }
2493  }
2494 }
2495 
2496 /******************************************************************/
2497 
2499  std::vector<PixelDigi>& digis,
2500  std::vector<PixelSimHitExtraInfo>& newClass_Sim_extra,
2501  const TrackerTopology* tTopo,
2502  CLHEP::HepRandomEngine* engine) {
2503  // Function to apply the Charge Reweighting on top of digi in case of PU from mixing library
2504  // for time dependent MC
2505  std::vector<PixelDigi> New_digis;
2506  uint32_t detID = pixdet->geographicalId().rawId();
2507 
2508  if (UseReweighting) {
2509  LogError("PixelDigitizer ") << " ******************************** \n";
2510  LogError("PixelDigitizer ") << " ******************************** \n";
2511  LogError("PixelDigitizer ") << " ***** INCONSISTENCY !!! ***** \n";
2512  LogError("PixelDigitizer ")
2513  << " applyLateReweighting_ and UseReweighting can not be true at the same time for PU ! \n";
2514  LogError("PixelDigitizer ") << " ---> DO NOT APPLY CHARGE REWEIGHTING TWICE !!! \n";
2515  LogError("PixelDigitizer ") << " ******************************** \n";
2516  LogError("PixelDigitizer ") << " ******************************** \n";
2517  return;
2518  }
2519 
2520  float thePixelThresholdInE = 0.;
2521  if (theNoiseInElectrons > 0.) {
2522  if (pixdet->type().isTrackerPixel() && pixdet->type().isBarrel()) { // Barrel modules
2523  int lay = tTopo->layer(detID);
2524  if (addThresholdSmearing) {
2527  if (lay == 1) {
2528  thePixelThresholdInE = CLHEP::RandGaussQ::shoot(
2529  engine, theThresholdInE_BPix_L1, theThresholdSmearing_BPix_L1); // gaussian smearing
2530  } else if (lay == 2) {
2531  thePixelThresholdInE = CLHEP::RandGaussQ::shoot(
2532  engine, theThresholdInE_BPix_L2, theThresholdSmearing_BPix_L2); // gaussian smearing
2533  } else {
2534  thePixelThresholdInE =
2535  CLHEP::RandGaussQ::shoot(engine, theThresholdInE_BPix, theThresholdSmearing_BPix); // gaussian smearing
2536  }
2537  }
2538  } else {
2541  if (lay == 1) {
2542  thePixelThresholdInE = theThresholdInE_BPix_L1;
2543  } else if (lay == 2) {
2544  thePixelThresholdInE = theThresholdInE_BPix_L2;
2545  } else {
2546  thePixelThresholdInE = theThresholdInE_BPix; // no smearing
2547  }
2548  }
2549  }
2550 
2551  } else if (pixdet->type().isTrackerPixel()) { // Forward disks modules
2552 
2553  if (addThresholdSmearing) {
2554  thePixelThresholdInE =
2555  CLHEP::RandGaussQ::shoot(engine, theThresholdInE_FPix, theThresholdSmearing_FPix); // gaussian smearing
2556  } else {
2557  thePixelThresholdInE = theThresholdInE_FPix; // no smearing
2558  }
2559 
2560  } else {
2561  throw cms::Exception("NotAPixelGeomDetUnit") << "Not a pixel geomdet unit" << detID;
2562  }
2563  }
2564 
2565  // loop on the SimHit extra info class
2566  // apply the reweighting for that SimHit on a cluster way
2567  bool reweighted = false;
2568  std::vector<PixelSimHitExtraInfo>::iterator loopTempSH;
2569  for (loopTempSH = newClass_Sim_extra.begin(); loopTempSH != newClass_Sim_extra.end(); ++loopTempSH) {
2570  signal_map_type theDigiSignal;
2571  PixelSimHitExtraInfo TheNewInfo = *loopTempSH;
2572  reweighted = TheNewSiPixelChargeReweightingAlgorithmClass->lateSignalReweight(
2573  pixdet, digis, TheNewInfo, theDigiSignal, tTopo, engine);
2574  if (!reweighted) {
2575  // loop on the non-reweighthed digis associated to the considered SimHit
2576  std::vector<PixelDigi>::const_iterator loopDigi;
2577  for (loopDigi = digis.begin(); loopDigi != digis.end(); ++loopDigi) {
2578  unsigned int chan = loopDigi->channel();
2579  // check if that digi is related to the SimHit
2580  if (loopTempSH->isInTheList(chan)) {
2581  float corresponding_charge = loopDigi->adc();
2582  theDigiSignal[chan] += Amplitude(corresponding_charge, corresponding_charge);
2583  }
2584  }
2585  }
2586 
2587  // transform theDigiSignal into digis
2588  int Thresh_inADC = int(thePixelThresholdInE / theElectronPerADC);
2589  for (signal_map_const_iterator i = theDigiSignal.begin(); i != theDigiSignal.end(); ++i) {
2590  float signalInADC = (*i).second; // signal in ADC
2591  if (signalInADC > 0.) {
2592  if (signalInADC >= Thresh_inADC) {
2593  int chan = (*i).first; // channel number
2594  std::pair<int, int> ip = PixelDigi::channelToPixel(chan);
2595  int adc = int(signalInADC);
2596  // add MissCalibration
2597  if (doMissCalInLateCR) {
2598  int row = ip.first;
2599  int col = ip.second;
2600  adc =
2601  int(missCalibrate(detID, tTopo, pixdet, col, row, signalInADC * theElectronPerADC)); //full misscalib.
2602  }
2603 
2604  if (adc > theAdcFullScLateCR)
2605  adc = theAdcFullScLateCR; // Check maximum value
2606 
2607 #ifdef TP_DEBUG
2608  LogDebug("Pixel Digitizer") << (*i).first << " " << (*i).second << " " << signalInADC << " " << adc
2609  << ip.first << " " << ip.second;
2610 #endif
2611 
2612  // Load digis
2613  New_digis.emplace_back(ip.first, ip.second, adc);
2614  }
2615  }
2616  } // end loop on theDigiSignal
2617  theDigiSignal.clear();
2618  }
2619  digis.clear();
2620  digis = New_digis;
2621 }
void init(const edm::EventSetup &es)
size
Write out results.
static std::pair< int, int > channelToPixelROC(const int chan)
Definition: PixelIndices.h:236
void fillSimHitMaps(std::vector< PSimHit > simHits, const unsigned int tofBin)
ESGetTokenH3DDVariant esConsumes(std::string const &Record, edm::ConsumesCollector &)
Definition: DeDxTools.cc:283
T getParameter(std::string const &) const
Definition: ParameterSet.h:303
void pixel_inefficiency_db(uint32_t detID)
unsigned int pxbLayer(const DetId &id) const
signal_map_type::const_iterator signal_map_const_iterator
static const TGPicture * info(bool iBackgroundIsBlack)
Local3DVector LocalVector
Definition: LocalVector.h:12
Point3DBase< Scalar, LocalTag > LocalPoint
Definition: Definitions.h:30
std::map< unsigned int, probabilityVec > probabilityMap
void tanh(data_T data[CONFIG_T::n_in], res_T res[CONFIG_T::n_in])
const std::unique_ptr< SiPixelGainCalibrationOfflineSimService > theSiPixelGainCalibrationService_
bool IsRocBad(const uint32_t &detid, const short &rocNb) const
static std::pair< int, int > channelToPixel(int ch)
Definition: PixelDigi.h:69
const std::map< unsigned int, double > & getPixelGeomFactors() const
virtual LocalPoint localPosition(const MeasurementPoint &) const =0
virtual int ncolumns() const =0
T z() const
Definition: PV3DBase.h:61
const std::unique_ptr< SiG4UniversalFluctuation > fluctuate
PixelEfficiencies(const edm::ParameterSet &conf, bool AddPixelInefficiency, int NumberOfBarrelLayers, int NumberOfEndcapDisks)
unsigned int pxfModule(const DetId &id) const
const GeomDetType & type() const override
virtual int rowsperroc() const =0
bool exists(std::string const &parameterName) const
checks if a parameter exists
const std::map< unsigned int, double > & getColGeomFactors() const
virtual int nrows() const =0
edm::ESGetToken< SiPixelQualityProbabilities, SiPixelStatusScenarioProbabilityRcd > scenarioProbabilityToken_
Local3DPoint exitPoint() const
Exit point in the local Det frame.
Definition: PSimHit.h:46
std::unique_ptr< PixelFEDChannelCollection > PixelFEDChannelCollection_
std::vector< std::vector< double > > thePUEfficiency
std::vector< sipixelobjects::CablingPathToDetUnit > pathToDetUnit(uint32_t rawDetId) const final
const std::vector< int > & getMix_bunchCrossing() const
void make_digis(float thePixelThresholdInE, uint32_t detID, const PixelGeomDetUnit *pixdet, std::vector< PixelDigi > &digis, std::vector< PixelDigiSimLink > &simlinks, std::vector< PixelDigiAddTempInfo > &newClass_Digi_extra, const TrackerTopology *tTopo) const
float pixel_aging(const PixelAging &aging, const PixelGeomDetUnit *pixdet, const TrackerTopology *tTopo) const
T x() const
Definition: PV2DBase.h:43
unsigned int pxbLadder(const DetId &id) const
Log< level::Error, false > LogError
void drift(const PSimHit &hit, const PixelGeomDetUnit *pixdet, const GlobalVector &bfield, const TrackerTopology *tTopo, const std::vector< EnergyDepositUnit > &ionization_points, std::vector< SignalPoint > &collection_points) const
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
constexpr Detector det() const
get the detector field from this detid
Definition: DetId.h:46
A arg
Definition: Factorize.h:31
scenario
Definition: constants.h:173
identify pixel inside single ROC
Definition: LocalPixel.h:7
const SiPixelDynamicInefficiency * SiPixelDynamicInefficiency_
unsigned int layer(const DetId &id) const
std::unique_ptr< SiPixelChargeReweightingAlgorithm > TheNewSiPixelChargeReweightingAlgorithmClass
bool isTrackerPixel() const
Definition: GeomDetType.cc:15
constexpr std::array< uint8_t, layerIndexSize > layer
static int pixelToChannel(int row, int col)
Definition: PixelDigi.h:75
global coordinates (row and column in DetUnit, as in PixelDigi)
Definition: GlobalPixel.h:6
T y() const
Definition: PV2DBase.h:44
virtual float thickness() const =0
void induce_signal(std::vector< PSimHit >::const_iterator inputBegin, std::vector< PSimHit >::const_iterator inputEnd, const PSimHit &hit, const size_t hitIndex, const size_t FirstHitIndex, const unsigned int tofBin, const PixelGeomDetUnit *pixdet, const std::vector< SignalPoint > &collection_points)
T x() const
Definition: PV3DBase.h:59
T y() const
Definition: PV3DBase.h:60
const std::map< unsigned int, std::vector< double > > & getPUFactors() const
Measurement2DPoint MeasurementPoint
Measurement points are two-dimensional by default.
LocalVector DriftDirection(const PixelGeomDetUnit *pixdet, const GlobalVector &bfield, const DetId &detId) const
edm::ESGetToken< SiPixelQuality, SiPixelQualityRcd > SiPixelBadModuleToken_
const std::vector< disabledModuleType > getBadComponentList() const
SiPixelDigitizerAlgorithm(const edm::ParameterSet &conf, edm::ConsumesCollector iC)
const PixelFEDChannelCollectionMap * quality_map
const std::vector< uint32_t > getDetIdmasks() const
std::pair< unsigned int, unsigned int > subDetTofBin
void digitize(const PixelGeomDetUnit *pixdet, std::vector< PixelDigi > &digis, std::vector< PixelDigiSimLink > &simlinks, std::vector< PixelDigiAddTempInfo > &newClass_Digi_extra, const TrackerTopology *tTopo, CLHEP::HepRandomEngine *)
std::map< uint32_t, std::vector< double > > PixelGeomFactorsROCBigPixels
virtual bool isItBigPixelInX(int ixbin) const =0
virtual int colsperroc() const =0
void primary_ionization(const PSimHit &hit, std::vector< EnergyDepositUnit > &ionization_points, CLHEP::HepRandomEngine *) const
GlobalPixel toGlobal(const LocalPixel &loc) const
Definition: PixelROC.h:55
T sqrt(T t)
Definition: SSEVec.h:19
probabilityVec getProbabilities(const unsigned int puBin) const
static int pixelToChannelROC(const int rowROC, const int colROC)
Definition: PixelIndices.h:233
virtual bool isItBigPixelInY(int iybin) const =0
unsigned short processType() const
Definition: PSimHit.h:120
constexpr float Bfield
Definition: Config.h:88
const std::map< unsigned int, double > & getChipGeomFactors() const
T mag() const
Definition: PV3DBase.h:64
unsigned int pxfDisk(const DetId &id) const
const sipixelobjects::PixelROC * findItem(const sipixelobjects::CablingPathToDetUnit &path) const final
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
const SiPixelLorentzAngle * SiPixelLorentzAngle_
Local3DPoint entryPoint() const
Entry point in the local Det frame.
Definition: PSimHit.h:43
virtual int channel(const LocalPoint &p) const =0
double f[11][100]
constexpr int subdetId() const
get the contents of the subdetector field (not cast into any detector&#39;s numbering enum) ...
Definition: DetId.h:48
virtual MeasurementPoint measurementPosition(const LocalPoint &) const =0
bool getData(T &iHolder) const
Definition: EventSetup.h:122
float missCalibrate(uint32_t detID, const TrackerTopology *tTopo, const PixelGeomDetUnit *pixdet, int col, int row, float amp) const
unsigned int trackId() const
Definition: PSimHit.h:106
std::vector< LinkConnSpec >::const_iterator IT
void init_from_db(const TrackerGeometry *, const SiPixelDynamicInefficiency *)
edm::ESGetToken< SiPixelLorentzAngle, SiPixelLorentzAngleSimRcd > SiPixelLorentzAngleToken_
signal_map_type::iterator signal_map_iterator
void init_DynIneffDB(const edm::EventSetup &)
DetId geographicalId() const
The label of this GeomDet.
Definition: GeomDet.h:64
std::unique_ptr< PixelFEDChannelCollection > chooseScenario(PileupMixingContent *puInfo, CLHEP::HepRandomEngine *)
ii
Definition: cuy.py:589
void setSimAccumulator(const std::map< uint32_t, std::map< int, int > > &signalMap)
edm::ESGetToken< PixelFEDChannelCollectionMap, SiPixelFEDChannelContainerESProducerRcd > PixelFEDChannelCollectionMapToken_
const std::map< int, CalParameters, std::less< int > > calmap
GlobalPoint toGlobal(const Point2DBase< Scalar, LocalTag > lp) const
Definition: Surface.h:79
unsigned int pxfPanel(const DetId &id) const
Log< level::Info, false > LogInfo
boost::transform_iterator< IterHelp, const_IdIter > const_iterator
const std::unique_ptr< GaussianTailNoiseGenerator > theNoiser
Definition: DetId.h:17
std::map< int, Amplitude, std::less< int > > signal_map_type
const SiPixelQuality * SiPixelBadModule_
const SiPixelFedCablingMap * map_
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())
bool isBarrel() const
Definition: GeomDetType.cc:9
const PositionType & position() const
std::map< uint32_t, std::vector< double > > PixelGeomFactorsROCStdPixels
const std::vector< float > & getMix_TrueInteractions() const
constexpr uint32_t rawId() const
get the raw id
Definition: DetId.h:57
void calculateInstlumiFactor(PileupMixingContent *puInfo)
void accumulateSimHits(const std::vector< PSimHit >::const_iterator inputBegin, const std::vector< PSimHit >::const_iterator inputEnd, const size_t inputBeginGlobalIndex, const unsigned int tofBin, const PixelGeomDetUnit *pixdet, const GlobalVector &bfield, const TrackerTopology *tTopo, CLHEP::HepRandomEngine *)
row and collumn in ROC representation
Definition: LocalPixel.h:13
virtual SubDetector subDetector() const
Which subdetector.
Definition: GeomDet.cc:38
static const GlobalPoint notFound(0, 0, 0)
chan
lumi = TPaveText(lowX+0.38, lowY+0.061, lowX+0.45, lowY+0.161, "NDC") lumi.SetBorderSize( 0 ) lumi...
const SiPixelQualityProbabilities * scenarioProbability_
void fluctuateEloss(int particleId, float momentum, float eloss, float length, int NumberOfSegments, float elossVector[], CLHEP::HepRandomEngine *) const
bool matches(const DetId &, const DetId &, const std::vector< uint32_t > &)
void lateSignalReweight(const PixelGeomDetUnit *pixdet, std::vector< PixelDigi > &digis, std::vector< PixelSimHitExtraInfo > &newClass_Sim_extra, const TrackerTopology *tTopo, CLHEP::HepRandomEngine *engine)
std::vector< edm::ParameterSet > Parameters
HLT enums.
virtual const PixelTopology & specificTopology() const
Returns a reference to the pixel proxy topology.
EcalLogicID subdetID(EcalSubdetector)
col
Definition: cuy.py:1009
short getBadRocs(const uint32_t &detid) const
static unsigned int const shift
edm::ESGetToken< SiPixelDynamicInefficiency, SiPixelDynamicInefficiencyRcd > SiPixelDynamicInefficiencyToken_
const RotationType & rotation() const
std::map< int, CalParameters, std::less< int > > initCal() const
virtual std::pair< float, float > pitch() const =0
PixelAging(const edm::ParameterSet &conf, bool AddPixelAging, int NumberOfBarrelLayers, int NumberOfEndcapDisks)
unsigned int pxbModule(const DetId &id) const
Log< level::Warning, false > LogWarning
const Plane & specificSurface() const
Same as surface(), kept for backward compatibility.
Definition: GeomDet.h:40
float getLorentzAngle(const uint32_t &) const
unsigned int idInDetUnit() const
id of this ROC in DetUnit etermined by token path
Definition: PixelROC.h:37
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
Definition: invegas.h:5
Definition: aging.py:1
uint16_t *__restrict__ uint16_t const *__restrict__ adc
void add_noise(const PixelGeomDetUnit *pixdet, float thePixelThreshold, CLHEP::HepRandomEngine *)
#define LogDebug(id)
void pixel_inefficiency(const PixelEfficiencies &eff, const PixelGeomDetUnit *pixdet, const TrackerTopology *tTopo, CLHEP::HepRandomEngine *)
const Bounds & bounds() const
Definition: Surface.h:87
unsigned transform(const HcalDetId &id, unsigned transformCode)