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