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