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