CMS 3D CMS Logo

SiPixelDigitizerAlgorithm.cc

Go to the documentation of this file.
00001 //class SiPixelDigitizerAlgorithm SimTracker/SiPixelDigitizer/src/SiPixelDigitizerAlgoithm.cc
00002 
00003 // Original Author Danek Kotlinski
00004 // Ported in CMSSW by  Michele Pioppi-INFN perugia
00005 // Added DB capabilities by F.Blekman, Cornell University
00006 //         Created:  Mon Sep 26 11:08:32 CEST 2005
00007 // Add tof, change AddNoise to tracked. 4/06
00008 // Change drift direction. 6/06 d.k.
00009 // Add the statuis (non-rate dependent) inefficiency.
00010 //     -1 - no ineffciency
00011 //      0 - static inefficency only
00012 //    1,2 - low-lumi rate dependent inefficency added
00013 //     10 - high-lumi inefficiency added
00014 // Adopt the correct drift sign convetion from Morris Swartz. d.k. 8/06
00015 // Add more complex misscalinbration, change kev/e to 3.61, diff=3.7,d.k.9/06
00016 // Add the readout channel electronic noise. d.k. 3/07
00017 // Lower the pixel noise from 500 to 175elec.
00018 // Change the input threshold from noise units to electrons.
00019 // Lower the amount of static dead pixels from 0.01 to 0.001.
00020 // Modify to the new random number services. d.k. 5/07
00021 // Protect against sigma=0 (delta tracks on the surface). d.k.5/07
00022 // Change the TOF cut to lower and upper limit. d.k. 7/07
00023 // Split Lorentz Angle configuration in BPix/FPix: V. Cuplov, Rice University 7/08
00024 // tanLorentzAngleperTesla_FPix=0.0912 and tanLorentzAngleperTesla_BPix=0.106
00025 // Disable Pixel modules which are declared dead in the configuration python file. (sept 2008)
00026 // Accessing/Reading the Lorentz angle from the DataBase instead of the cfg file. (oct 2008)
00027 // Accessing dead modules from the DB. Implementation done and tested on a test.db
00028 // Do not use this option for now. The PixelQuality Objects are not in the official DB yet.
00029 // Accessing dead modules via DB is tested using GlobalTag STARTUP_30X (jan 2009). Ok
00030 // Split Fpix and Bpix threshold and use official numbers (fev 2009)
00031 // ThresholdInElectrons_FPix = 2870 and ThresholdInElectrons_BPix = 3700
00032 // update the electron to VCAL conversion using: VCAL_electrons = VCAL * 65.5 - 414
00033 // Threshold gaussian smearing: (fev. 2009)
00034 // Fpix: Mean=2870 and RMS=200 
00035 // Bpix: Mean=3700 and RMS=410
00036  
00037 
00038 #include <vector>
00039 #include <iostream>
00040 
00041 #include "DataFormats/SiPixelDigi/interface/PixelDigi.h"
00042 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
00043 #include "SimTracker/SiPixelDigitizer/interface/SiPixelDigitizerAlgorithm.h"
00044 
00045 #include <gsl/gsl_sf_erf.h>
00046 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00047 #include "CLHEP/Random/RandGaussQ.h"
00048 #include "CLHEP/Random/RandFlat.h"
00049 
00050 
00051 //#include "SimTracker/SiPixelDigitizer/interface/PixelIndices.h"
00052 #include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
00053 #include "DataFormats/SiPixelDetId/interface/PXBDetId.h"
00054 
00055 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00056 #include "FWCore/ServiceRegistry/interface/Service.h"
00057 #include "FWCore/Utilities/interface/Exception.h"
00058 #include "CondTools/SiPixel/interface/SiPixelGainCalibrationOfflineService.h"
00059  
00060 // Accessing Lorentz Angle from the DB:
00061 #include "CalibTracker/SiPixelLorentzAngle/test/SiPixelLorentzAngleReader.h"
00062 
00063 // Accessing dead pixel modules from the DB:
00064 //#include "CondTools/SiPixel/test/SiPixelBadModuleReader.h"
00065 //#include "DataFormats/DetId/interface/DetId.h"
00066 
00067 using namespace std;
00068 using namespace edm;
00069 
00070 #define TP_DEBUG // protect all LogDebug with ifdef. Takes too much CPU
00071 
00072 void SiPixelDigitizerAlgorithm::init(const edm::EventSetup& es){
00073   if(use_ineff_from_db_){// load gain calibration service fromdb...
00074     theSiPixelGainCalibrationService_= new SiPixelGainCalibrationOfflineService(conf_);
00075     theSiPixelGainCalibrationService_->setESObjects( es );
00076   }
00077 
00078   fillDeadModules(es); // gets the dead module from config file or DB.
00079   fillLorentzAngle(es); // gets the Lorentz angle from the config file or DB.  
00080 }
00081 
00082 //=========================================================================
00083 
00084 void SiPixelDigitizerAlgorithm::fillDeadModules(const edm::EventSetup& es){
00085   if(!use_deadmodule_DB_){
00086     DeadModules = conf_.getParameter<Parameters>("DeadModules"); // get dead module from cfg file
00087   }
00088   //  else{  // Get dead module from DB record 
00089     // ESHandle was defined in the header file   edm::ESHandle<SiPixelQuality> SiPixelBadModule_;
00090   //    es.get<SiPixelQualityRcd>().get(SiPixelBadModule_);
00091   //  }
00092 }
00093 
00094 void SiPixelDigitizerAlgorithm::fillLorentzAngle(const edm::EventSetup& es){
00095   if(!use_LorentzAngle_DB_){
00096     // Get the Lorentz angle from the cfg file:
00097     tanLorentzAnglePerTesla_FPix=conf_.getParameter<double>("TanLorentzAnglePerTesla_FPix");
00098     tanLorentzAnglePerTesla_BPix=conf_.getParameter<double>("TanLorentzAnglePerTesla_BPix");
00099   } 
00100   else {
00101     // Get Lorentz angle from DB record 
00102     // ESHandle was defined in the header file edm::ESHandle<SiPixelLorentzAngle> SiPixelLorentzAngle_;
00103     es.get<SiPixelLorentzAngleRcd>().get(SiPixelLorentzAngle_);
00104   }
00105 }
00106 //=========================================================================
00107 
00108 SiPixelDigitizerAlgorithm::SiPixelDigitizerAlgorithm(const edm::ParameterSet& conf) :
00109   conf_(conf) , fluctuate(0), theNoiser(0), pIndexConverter(0),
00110   use_ineff_from_db_(conf_.getParameter<bool>("useDB")),
00111   use_module_killing_(conf_.getParameter<bool>("killModules")), // boolean to kill or not modules
00112   use_deadmodule_DB_(conf_.getParameter<bool>("DeadModules_DB")), // boolean to access dead modules from DB
00113   use_LorentzAngle_DB_(conf_.getParameter<bool>("LorentzAngle_DB")), // boolean to access Lorentz angle from DB 
00114   theSiPixelGainCalibrationService_(0)
00115 {
00116   using std::cout;
00117   using std::endl;
00118 
00119   // Common pixel parameters
00120   // These are parameters which are not likely to be changed
00121   NumberOfSegments = 20; // Default number of track segment divisions
00122   ClusterWidth = 3.;     // Charge integration spread on the collection plane
00123   GeVperElectron = 3.61E-09; // 1 electron =3.61eV, 1keV=277e, mod 9/06 d.k.
00124   Sigma0 = 0.00037;           // Charge diffusion constant 7->3.7 
00125   Dist300 = 0.0300;          //   normalized to 300micron Silicon
00126 
00127   alpha2Order = conf_.getParameter<bool>("Alpha2Order");   // switch on/off of E.B effect   
00128 
00129   // get external parameters:
00130   // ADC calibration 1adc count = 135e.
00131   // Corresponds to 2adc/kev, 270[e/kev]/135[e/adc]=2[adc/kev]
00132   // Be carefull, this parameter is also used in SiPixelDet.cc to 
00133   // calculate the noise in adc counts from noise in electrons.
00134   // Both defaults should be the same.
00135   theElectronPerADC=conf_.getParameter<double>("ElectronPerAdc");
00136 
00137   // ADC saturation value, 255=8bit adc.
00138   //theAdcFullScale=conf_.getUntrackedParameter<int>("AdcFullScale",255);
00139   theAdcFullScale=conf_.getParameter<int>("AdcFullScale");
00140 
00141   // Pixel threshold in units of noise:
00142   // thePixelThreshold=conf_.getParameter<double>("ThresholdInNoiseUnits");
00143   // Pixel threshold in electron units.
00144   theThresholdInE_FPix=conf_.getParameter<double>("ThresholdInElectrons_FPix");
00145   theThresholdInE_BPix=conf_.getParameter<double>("ThresholdInElectrons_BPix");
00146 
00147   // Add threshold gaussian smearing:
00148   addThresholdSmearing = conf_.getParameter<bool>("AddThresholdSmearing");
00149   theThresholdSmearing_FPix = conf_.getParameter<double>("ThresholdSmearing_FPix");
00150   theThresholdSmearing_BPix = conf_.getParameter<double>("ThresholdSmearing_BPix");
00151 
00152   // electrons to VCAL conversion needed in misscalibrate()
00153   electronsPerVCAL = conf_.getParameter<double>("ElectronsPerVcal");
00154   electronsPerVCAL_Offset = conf_.getParameter<double>("ElectronsPerVcal_Offset");
00155 
00156   // Add noise   
00157   addNoise=conf_.getParameter<bool>("AddNoise");
00158   // Add noisy pixels 
00159   addNoisyPixels=conf_.getParameter<bool>("AddNoisyPixels");
00160   // Noise in electrons:
00161   // Pixel cell noise, relevant for generating noisy pixels 
00162   theNoiseInElectrons=conf_.getParameter<double>("NoiseInElectrons");
00163   // Fill readout noise, including all readout chain, relevant for smearing
00164   //theReadoutNoise=conf_.getUntrackedParameter<double>("ReadoutNoiseInElec",500.);
00165   theReadoutNoise=conf_.getParameter<double>("ReadoutNoiseInElec");
00166 
00167   //theTofCut 12.5, cut in particle TOD +/- 12.5ns
00168   //theTofCut=conf_.getUntrackedParameter<double>("TofCut",12.5);
00169   theTofLowerCut=conf_.getParameter<double>("TofLowerCut");
00170   theTofUpperCut=conf_.getParameter<double>("TofUpperCut");
00171   
00172   // Fluctuate charge in track subsegments
00173   fluctuateCharge=conf_.getUntrackedParameter<bool>("FluctuateCharge",true);
00174 
00175   // delta cutoff in MeV, has to be same as in OSCAR=0.030/cmsim=1.0 MeV
00176   //tMax = 0.030; // In MeV.  
00177   //tMax =conf_.getUntrackedParameter<double>("DeltaProductionCut",0.030);  
00178   tMax =conf_.getParameter<double>("DeltaProductionCut");  
00179  
00180   // Control the pixel inefficiency
00181   thePixelLuminosity=conf_.getParameter<int>("AddPixelInefficiency");
00182 
00183   // Get the constants for the miss-calibration studies
00184   doMissCalibrate=conf_.getParameter<bool>("MissCalibrate"); // Enable miss-calibration
00185   theGainSmearing=conf_.getParameter<double>("GainSmearing"); // sigma of the gain smearing
00186   theOffsetSmearing=conf_.getParameter<double>("OffsetSmearing"); //sigma of the offset smearing
00187 
00188 
00189   //pixel inefficiency
00190   // the first 3 settings [0],[1],[2] are for the barrel pixels
00191   // the next  3 settings [3],[4],[5] are for the endcaps (undecided how)  
00192 
00193   if (thePixelLuminosity==-1) {  // No inefficiency, all 100% efficient
00194     pixelInefficiency=false;
00195     for (int i=0; i<6;i++) {
00196       thePixelEfficiency[i]     = 1.;  // pixels = 100%
00197       thePixelColEfficiency[i]  = 1.;  // columns = 100%
00198       thePixelChipEfficiency[i] = 1.; // chips = 100%
00199     }
00200     
00201     // include only the static (non rate depedent) efficiency 
00202     // Usefull for very low rates (luminosity)
00203   } else if (thePixelLuminosity==0) { // static effciency
00204     pixelInefficiency=true;
00205     // Default efficiencies 
00206     for (int i=0; i<6;i++) {
00207       if(i<3) {  // For the barrel
00208         // Assume 1% inefficiency for single pixels, 
00209         // this is given by faulty bump-bonding and seus.  
00210         thePixelEfficiency[i]     = 1.-0.001;  // pixels = 99.9%
00211         // For columns make 0.1% default.
00212         thePixelColEfficiency[i]  = 1.-0.001;  // columns = 99.9%
00213         // A flat 0.1% inefficiency due to lost rocs
00214         thePixelChipEfficiency[i] = 1.-0.001; // chips = 99.9%
00215       } else { // For the endcaps
00216         // Assume 1% inefficiency for single pixels, 
00217         // this is given by faulty bump-bonding and seus.  
00218         thePixelEfficiency[i]     = 1.-0.001;  // pixels = 99.9%
00219         // For columns make 0.1% default.
00220         thePixelColEfficiency[i]  = 1.-0.001;  // columns = 99.9%
00221         // A flat 0.1% inefficiency due to lost rocs
00222         thePixelChipEfficiency[i] = 1.-0.001; // chips = 99.9%
00223       }
00224     }
00225     
00226     // Include also luminosity rate dependent inefficieny
00227   } else if (thePixelLuminosity>0) { // Include effciency
00228     pixelInefficiency=true;
00229     // Default efficiencies 
00230     for (int i=0; i<6;i++) {
00231       if(i<3) { // For the barrel
00232         // Assume 1% inefficiency for single pixels, 
00233         // this is given by faulty bump-bonding and seus.  
00234         thePixelEfficiency[i]     = 1.-0.01;  // pixels = 99%
00235         // For columns make 1% default.
00236         thePixelColEfficiency[i]  = 1.-0.01;  // columns = 99%
00237         // A flat 0.25% inefficiency due to lost data packets from TBM
00238         thePixelChipEfficiency[i] = 1.-0.0025; // chips = 99.75%
00239       } else { // For the endcaps
00240         // Assume 1% inefficiency for single pixels, 
00241         // this is given by faulty bump-bonding and seus.  
00242         thePixelEfficiency[i]     = 1.-0.01;  // pixels = 99%
00243         // For columns make 1% default.
00244         thePixelColEfficiency[i]  = 1.-0.01;  // columns = 99%
00245         // A flat 0.25% inefficiency due to lost data packets from TBM
00246         thePixelChipEfficiency[i] = 1.-0.0025; // chips = 99.75%
00247       }
00248     }
00249    
00250     // Special cases ( High-lumi for 4cm layer) where the readout losses are higher
00251     if(thePixelLuminosity==10) { // For high luminosity, bar layer 1
00252       thePixelColEfficiency[0] = 1.-0.034; // 3.4% for r=4 only
00253       thePixelEfficiency[0]    = 1.-0.015; // 1.5% for r=4
00254     }
00255     
00256   } // end the pixel inefficiency part
00257 
00258   // Init the random number services  
00259     if(addNoise || thePixelLuminosity || fluctuateCharge || addThresholdSmearing ) {
00260     edm::Service<edm::RandomNumberGenerator> rng;
00261     if ( ! rng.isAvailable()) {
00262       throw cms::Exception("Configuration")
00263         << "SiPixelDigitizer requires the RandomNumberGeneratorService\n"
00264         "which is not present in the configuration file.  You must add the service\n"
00265         "in the configuration file or remove the modules that require it.";
00266     }
00267  
00268     CLHEP::HepRandomEngine& engine = rng->getEngine();
00269     // Fillipo has: rndEngine = &(rng->getEngine()); LETS SEE IF BOTH WORK
00270 
00271     // engine MUST be a reference here, if a pointer is used the
00272     // distribution will destroy the engine in its destructor, a major
00273     // problem because the service owns the engine and will destroy it
00274     gaussDistribution_ = new CLHEP::RandGaussQ(engine, 0., theReadoutNoise);
00275     flatDistribution_ = new CLHEP::RandFlat(engine, 0., 1.);
00276 
00277     if(addNoise) { 
00278       theNoiser = new GaussianTailNoiseGenerator(engine);
00279     }
00280 
00281     if(fluctuateCharge) {
00282       fluctuate = new SiG4UniversalFluctuation(engine);
00283     }
00284 
00285     // Threshold smearing with gaussian distribution:
00286     if(addThresholdSmearing) {
00287       smearedThreshold_FPix_ = new CLHEP::RandGaussQ(engine, theThresholdInE_FPix , theThresholdSmearing_FPix);
00288       smearedThreshold_BPix_ = new CLHEP::RandGaussQ(engine, theThresholdInE_BPix , theThresholdSmearing_BPix);
00289     }
00290 
00291     } //end Init the random number services
00292 
00293   // Prepare for the analog amplitude miss-calibration
00294   if(doMissCalibrate) {
00295     LogDebug ("PixelDigitizer ") 
00296       << " miss-calibrate the pixel amplitude "; 
00297     
00298     const bool ReadCalParameters = false;
00299     if(ReadCalParameters) {   // Read the calibration files from file
00300       // read the calibration constants from a file (testing only)
00301       ifstream in_file;  // data file pointer
00302       char filename[80] = "phCalibrationFit_C0.dat";
00303       
00304       in_file.open(filename, ios::in ); // in C++
00305       if (in_file.bad()) {
00306         cout << " File not found " << endl;
00307         return; // signal error
00308       }
00309       cout << " file opened : " << filename << endl;
00310       
00311       char line[500];
00312       for (int i = 0; i < 3; i++) {
00313         in_file.getline(line, 500,'\n');
00314         cout<<line<<endl;
00315       }
00316       
00317       cout << " test map" << endl;
00318       
00319       float par0,par1,par2,par3;
00320       int colid,rowid;
00321       string name;
00322       // Read MC tracks
00323       for(int i=0;i<(52*80);i++)  { // loop over tracks    
00324         in_file >> par0 >> par1 >> par2 >> par3 >> name >> colid
00325                 >> rowid;
00326         if (in_file.bad()) { // check for errors
00327           cerr << "Cannot read data file" << endl;
00328           return;
00329         }
00330         if ( in_file.eof() != 0 ) {
00331           cerr << in_file.eof() << " " << in_file.gcount() << " "
00332                << in_file.fail() << " " << in_file.good() << " end of file "
00333                << endl;
00334           return;
00335         }
00336         
00337         //cout << " line " << i << " " <<par0<<" "<<par1<<" "<<par2<<" "<<par3<<" "
00338         //   <<colid<<" "<<rowid<<endl;
00339         
00340         CalParameters onePix;
00341         onePix.p0=par0;
00342         onePix.p1=par1;
00343         onePix.p2=par2;
00344         onePix.p3=par3;
00345         
00346         // Convert ROC pixel index to channel 
00347         int chan = PixelIndices::pixelToChannelROC(rowid,colid);
00348         calmap.insert(pair<int,CalParameters>(chan,onePix));
00349         
00350         // Testing the index conversion, can be skipped 
00351         pair<int,int> p = PixelIndices::channelToPixelROC(chan);
00352         if(rowid!=p.first) cout<<" wrong channel row "<<rowid<<" "<<p.first<<endl;
00353         if(colid!=p.second) cout<<" wrong channel col "<<colid<<" "<<p.second<<endl;
00354               
00355       } // pixel loop in a ROC
00356  
00357       cout << " map size  " << calmap.size() <<" max "<<calmap.max_size() << " "
00358            <<calmap.empty()<< endl;
00359       
00360 //     cout << " map size  " << calmap.size()  << endl;
00361 //     map<int,CalParameters,less<int> >::iterator ix,it;
00362 //     map<int,CalParameters,less<int> >::const_iterator ip;
00363 //     for (ix = calmap.begin(); ix != calmap.end(); ++ix) {
00364 //       int i = (*ix).first;
00365 //       pair<int,int> p = channelToPixelROC(i);
00366 //       it  = calmap.find(i);
00367 //       CalParameters y  = (*it).second;
00368 //       CalParameters z = (*ix).second;
00369 //       cout << i <<" "<<p.first<<" "<<p.second<<" "<<y.p0<<" "<<z.p0<<" "<<calmap[i].p0<<endl; 
00370       
00371 //       //int dummy=0;
00372 //       //cin>>dummy;
00373 //     }
00374 
00375     } // end if readparameters
00376   } // end if missCalibration 
00377 
00378   LogInfo ("PixelDigitizer ") <<"SiPixelDigitizerAlgorithm constructed"
00379                               <<"Configuration parameters:" 
00380                               << "Threshold/Gain = "  
00381                               << "threshold in electron FPix = " 
00382                               << theThresholdInE_FPix
00383                               << "threshold in electron BPix = " 
00384                               << theThresholdInE_BPix 
00385                               <<" " << theElectronPerADC << " " << theAdcFullScale 
00386                               << " The delta cut-off is set to " << tMax
00387                               << " pix-inefficiency "<<thePixelLuminosity;
00388 
00389 
00390 }
00391 //=========================================================================
00392 SiPixelDigitizerAlgorithm::~SiPixelDigitizerAlgorithm() {
00393 
00394   LogDebug ("PixelDigitizer")<<"SiPixelDigitizerAlgorithm deleted";
00395   
00396   // Destructor
00397   delete gaussDistribution_;
00398   delete flatDistribution_;
00399   delete theSiPixelGainCalibrationService_;
00400 
00401   // Threshold gaussian smearing:
00402   if(addThresholdSmearing) {
00403     delete smearedThreshold_FPix_;
00404     delete smearedThreshold_BPix_;
00405   }
00406 
00407   if(addNoise) delete theNoiser;
00408   if(fluctuateCharge) delete fluctuate;
00409   
00410 }
00411 
00412 //=========================================================================
00413 edm::DetSet<PixelDigi>::collection_type 
00414 SiPixelDigitizerAlgorithm::run(
00415                                const std::vector<PSimHit> &input,
00416                                PixelGeomDetUnit *pixdet,
00417                                GlobalVector bfield) {
00418   
00419   _detp = pixdet; //cache the PixGeomDetUnit
00420   _PixelHits=input; //cache the SimHit
00421   _bfield=bfield; //cache the drift direction
00422 
00423   // Pixel Efficiency moved from the constructor to the method run because
00424   // the information of the det are not available in the constructor
00425   // Effciency parameters. 0 - no inefficiency, 1-low lumi, 10-high lumi
00426   
00427   detID= _detp->geographicalId().rawId();
00428   
00429   _signal.clear();
00430   
00431   // initalization  of pixeldigisimlinks
00432   link_coll.clear();
00433   
00434   //Digitization of the SimHits of a given pixdet
00435   vector<PixelDigi> collector =digitize(pixdet);
00436 
00437   // edm::DetSet<PixelDigi> collector;
00438   
00439 #ifdef TP_DEBUG
00440   LogDebug ("PixelDigitizer") << "[SiPixelDigitizerAlgorithm] converted " << collector.size() << " PixelDigis in DetUnit" << detID; 
00441 #endif
00442   
00443   return collector;
00444 }
00445 
00446 //============================================================================
00447 vector<PixelDigi> SiPixelDigitizerAlgorithm::digitize(PixelGeomDetUnit *det){
00448   
00449   if( _PixelHits.size() > 0 || addNoisyPixels) {
00450     
00451     topol=&det->specificTopology(); // cache topology
00452     numColumns = topol->ncolumns();  // det module number of cols&rows
00453     numRows = topol->nrows();
00454     
00455     // full detector thickness
00456     moduleThickness = det->specificSurface().bounds().thickness(); 
00457     
00458     // The index converter is only needed when inefficiencies or misscalibration
00459     // are simulated.
00460     if((pixelInefficiency>0) || doMissCalibrate ) {  // Init pixel indices
00461       pIndexConverter = new PixelIndices(numColumns,numRows);
00462     }
00463     
00464     // Noise already defined in electrons
00465     //thePixelThresholdInE = thePixelThreshold * theNoiseInElectrons ; 
00466     // Find the threshold in noise units, needed for the noiser.
00467 
00468   unsigned int Sub_detid=DetId(detID).subdetId();
00469     
00470   if(theNoiseInElectrons>0.){
00471     if(Sub_detid == PixelSubdetector::PixelBarrel){ // Barrel modules
00472       if(addThresholdSmearing) { 
00473         thePixelThresholdInE = smearedThreshold_BPix_->fire(); // gaussian smearing 
00474       } else {
00475         thePixelThresholdInE = theThresholdInE_BPix; // no smearing
00476       }
00477       
00478       thePixelThreshold = thePixelThresholdInE/theNoiseInElectrons; 
00479       
00480       //      std::cout << "digitize(): theNoiseInElectrons>0 and BPix: threshold in electrons is: " << thePixelThresholdInE << std::endl;
00481       
00482     } else { // Forward disks modules 
00483       if(addThresholdSmearing) {
00484         thePixelThresholdInE = smearedThreshold_FPix_->fire(); // gaussian smearing
00485       } else {
00486         thePixelThresholdInE = theThresholdInE_FPix; // no smearing
00487       }
00488       
00489       thePixelThreshold = thePixelThresholdInE/theNoiseInElectrons;
00490       
00491       //      std::cout << "digitize(): theNoiseInElectrons>0 and FPix: threshold in electrons is: " << thePixelThresholdInE << std::endl;
00492     }
00493   } else {
00494     thePixelThreshold = 0.;
00495   }
00496   
00497 #ifdef TP_DEBUG
00498     LogDebug ("PixelDigitizer") 
00499       << " PixelDigitizer "  
00500       << numColumns << " " << numRows << " " << moduleThickness;
00501 #endif
00502 
00503     // produce SignalPoint's for all SimHit's in detector
00504     // Loop over hits
00505  
00506     vector<PSimHit>::const_iterator ssbegin; 
00507     for (ssbegin= _PixelHits.begin();ssbegin !=_PixelHits.end(); ++ssbegin) {
00508       
00509 #ifdef TP_DEBUG
00510       LogDebug ("Pixel Digitizer") 
00511         << (*ssbegin).particleType() << " " << (*ssbegin).pabs() << " " 
00512         << (*ssbegin).energyLoss() << " " << (*ssbegin).tof() << " " 
00513         << (*ssbegin).trackId() << " " << (*ssbegin).processType() << " " 
00514         << (*ssbegin).detUnitId()  
00515         << (*ssbegin).entryPoint() << " " << (*ssbegin).exitPoint() ; 
00516 #endif      
00517       
00518       _collection_points.clear();  // Clear the container
00519       // fill _collection_points for this SimHit, indpendent of topology
00520       // Check the TOF cut
00521       //if (std::abs( (*ssbegin).tof() )<theTofCut){ // old cut
00522       if ( ((*ssbegin).tof() >= theTofLowerCut) && ((*ssbegin).tof() <= theTofUpperCut) ) {
00523         primary_ionization(*ssbegin); // fills _ionization_points       
00524         drift(*ssbegin);  // transforms _ionization_points to _collection_points        
00525         // compute induced signal on readout elements and add to _signal
00526         induce_signal(*ssbegin); // *ihit needed only for SimHit<-->Digi link
00527       } //  end if 
00528     } // end for 
00529 
00530     //    if(use_module_killing_ && use_deadmodule_DB_) // remove dead modules using DB
00531     //      module_killing_DB();
00532 
00533     if(use_module_killing_ && !use_deadmodule_DB_) // remove dead modules using the list in cfg file
00534       module_killing_conf();
00535   
00536     if(addNoise) add_noise();  // generate noise
00537     // Do only if needed 
00538 
00539     if((pixelInefficiency>0) && (_signal.size()>0)) 
00540       pixel_inefficiency(); // Kill some pixels
00541 
00542     if(use_ineff_from_db_ && (_signal.size()>0))
00543       pixel_inefficiency_db();
00544 
00545     delete pIndexConverter;
00546 
00547   }
00548 
00549   make_digis();
00550   return internal_coll;
00551 }
00552 
00553 //***********************************************************************/
00554 // Generate primary ionization along the track segment. 
00555 // Divide the track into small sub-segments  
00556 void SiPixelDigitizerAlgorithm::primary_ionization(const PSimHit& hit) {
00557 
00558 // Straight line approximation for trajectory inside active media
00559 
00560   const float SegmentLength = 0.0010; //10microns in cm
00561   float energy;
00562   
00563   // Get the 3D segment direction vector 
00564   LocalVector direction = hit.exitPoint() - hit.entryPoint(); 
00565   
00566   float eLoss = hit.energyLoss();  // Eloss in GeV
00567   float length = direction.mag();  // Track length in Silicon
00568   
00569   NumberOfSegments = int ( length / SegmentLength); // Number of segments
00570   if(NumberOfSegments < 1) NumberOfSegments = 1;
00571   
00572 #ifdef TP_DEBUG
00573   LogDebug ("Pixel Digitizer") 
00574     << " enter primary_ionzation " << NumberOfSegments 
00575     << " shift = " 
00576     << (hit.exitPoint().x()-hit.entryPoint().x()) << " " 
00577     << (hit.exitPoint().y()-hit.entryPoint().y()) << " " 
00578     << (hit.exitPoint().z()-hit.entryPoint().z()) << " "
00579     << hit.particleType() <<" "<< hit.pabs() ; 
00580 #endif  
00581 
00582   float* elossVector = new float[NumberOfSegments];  // Eloss vector
00583 
00584   if( fluctuateCharge ) {
00585     //MP DA RIMUOVERE ASSOLUTAMENTE
00586     int pid = hit.particleType();
00587     //int pid=211;  // assume it is a pion
00588   
00589     float momentum = hit.pabs();
00590     // Generate fluctuated charge points
00591     fluctuateEloss(pid, momentum, eLoss, length, NumberOfSegments, 
00592                    elossVector);
00593   }
00594   
00595   _ionization_points.resize( NumberOfSegments); // set size
00596 
00597   // loop over segments
00598   for ( int i = 0; i != NumberOfSegments; i++) {
00599     // Divide the segment into equal length subsegments 
00600     Local3DPoint point = hit.entryPoint() + 
00601       float((i+0.5)/NumberOfSegments) * direction;
00602 
00603     if( fluctuateCharge ) 
00604       energy = elossVector[i]/GeVperElectron; // Convert charge to elec.
00605     else
00606       energy = hit.energyLoss()/GeVperElectron/float(NumberOfSegments);
00607     
00608     EnergyDepositUnit edu( energy, point); //define position,energy point
00609     _ionization_points[i] = edu; // save
00610     
00611 #ifdef TP_DEBUG
00612     LogDebug ("Pixel Digitizer") 
00613       << i << " " << _ionization_points[i].x() << " " 
00614       << _ionization_points[i].y() << " " 
00615       << _ionization_points[i].z() << " " 
00616       << _ionization_points[i].energy();
00617 #endif
00618     
00619   }  // end for loop 
00620 
00621   delete[] elossVector;
00622 
00623 }
00624 //****************************************************************************** 
00625 
00626 // Fluctuate the charge comming from a small (10um) track segment.
00627 // Use the G4 routine. For mip pions for the moment.  
00628 void SiPixelDigitizerAlgorithm::fluctuateEloss(int pid, float particleMomentum, 
00629                                       float eloss, float length, 
00630                                       int NumberOfSegs,float elossVector[]) {
00631 
00632   // Get dedx for this track
00633   float dedx;
00634   if( length > 0.) dedx = eloss/length;
00635   else dedx = eloss;
00636 
00637   double particleMass = 139.6; // Mass in MeV, Assume pion
00638   pid = abs(pid);
00639   if(pid!=211) {       // Mass in MeV
00640     if(pid==11)        particleMass = 0.511;        
00641     else if(pid==13)   particleMass = 105.7;
00642     else if(pid==321)  particleMass = 493.7;
00643     else if(pid==2212) particleMass = 938.3;
00644   }
00645   // What is the track segment length.
00646   float segmentLength = length/NumberOfSegs;
00647 
00648   // Generate charge fluctuations.
00649   float de=0.;
00650   float sum=0.;
00651   double segmentEloss = (1000.*eloss)/NumberOfSegs; //eloss in MeV
00652   for (int i=0;i<NumberOfSegs;i++) {
00653     //       material,*,   momentum,energy,*, *,  mass
00654     //myglandz_(14.,segmentLength,2.,2.,dedx,de,0.14);
00655     // The G4 routine needs momentum in MeV, mass in Mev, delta-cut in MeV,
00656     // track segment length in mm, segment eloss in MeV 
00657     // Returns fluctuated eloss in MeV
00658     double deltaCutoff = tMax; // the cutoff is sometimes redefined inside, so fix it.
00659     de = fluctuate->SampleFluctuations(double(particleMomentum*1000.),
00660                                       particleMass, deltaCutoff, 
00661                                       double(segmentLength*10.),
00662                                       segmentEloss )/1000.; //convert to GeV
00663    
00664     elossVector[i]=de;
00665     sum +=de;
00666   }
00667   
00668   if(sum>0.) {  // If fluctuations give eloss>0.
00669     // Rescale to the same total eloss
00670     float ratio = eloss/sum;
00671    
00672     for (int ii=0;ii<NumberOfSegs;ii++) elossVector[ii]= ratio*elossVector[ii];
00673   } else {  // If fluctuations gives 0 eloss
00674     float averageEloss = eloss/NumberOfSegs;
00675     for (int ii=0;ii<NumberOfSegs;ii++) elossVector[ii]= averageEloss; 
00676   }
00677   return;
00678 }
00679 
00680 //*******************************************************************************
00681 // Drift the charge segments to the sensor surface (collection plane)
00682 // Include the effect of E-field and B-field 
00683 void SiPixelDigitizerAlgorithm::drift(const PSimHit& hit){
00684 
00685 
00686 #ifdef TP_DEBUG
00687   LogDebug ("Pixel Digitizer") << " enter drift " ;
00688 #endif
00689 
00690   _collection_points.resize( _ionization_points.size()); // set size
00691   
00692   LocalVector driftDir=DriftDirection();  // get the charge drift direction
00693   if(driftDir.z() ==0.) {
00694     LogWarning("Magnetic field") << " pxlx: drift in z is zero ";
00695     return;
00696   }  
00697 
00698   // tangent of Lorentz angle
00699   //float TanLorenzAngleX = driftDir.x()/driftDir.z(); 
00700   //float TanLorenzAngleY = 0.; // force to 0, driftDir.y()/driftDir.z();
00701 
00702   float TanLorenzAngleX, TanLorenzAngleY,dir_z, CosLorenzAngleX,
00703     CosLorenzAngleY;
00704   if ( alpha2Order) {
00705     
00706     TanLorenzAngleX = driftDir.x(); // tangen of Lorentz angle
00707     TanLorenzAngleY = driftDir.y();
00708     dir_z = driftDir.z(); // The z drift direction
00709     CosLorenzAngleX = 1./sqrt(1.+TanLorenzAngleX*TanLorenzAngleX); //cosine
00710     CosLorenzAngleY = 1./sqrt(1.+TanLorenzAngleY*TanLorenzAngleY); //cosine;
00711     
00712   } else{
00713     
00714     TanLorenzAngleX = driftDir.x();
00715     TanLorenzAngleY = 0.; // force to 0, driftDir.y()/driftDir.z();
00716     dir_z = driftDir.z(); // The z drift direction
00717     CosLorenzAngleX = 1./sqrt(1.+TanLorenzAngleX*TanLorenzAngleX); //cosine to estimate the path length
00718     CosLorenzAngleY = 1.;
00719   }
00720   
00721   
00722 #ifdef TP_DEBUG
00723   LogDebug ("Pixel Digitizer") 
00724     << " Lorentz Tan " << TanLorenzAngleX << " " << TanLorenzAngleY <<" "
00725     << CosLorenzAngleX << " " << CosLorenzAngleY << " "
00726     << moduleThickness*TanLorenzAngleX << " " << driftDir;
00727 #endif  
00728   
00729   float Sigma_x = 1.;  // Charge spread 
00730   float Sigma_y = 1.;
00731   float DriftDistance; // Distance between charge generation and collection 
00732   float DriftLength;   // Actual Drift Lentgh
00733   float Sigma;
00734   
00735   
00736   for (unsigned int i = 0; i != _ionization_points.size(); i++) {
00737     
00738     float SegX, SegY, SegZ; // position
00739     SegX = _ionization_points[i].x();
00740     SegY = _ionization_points[i].y();
00741     SegZ = _ionization_points[i].z();
00742     
00743     // Distance from the collection plane
00744     //DriftDistance = (moduleThickness/2. + SegZ); // Drift to -z 
00745     // Include explixitely the E drift direction (for CMS dir_z=-1)
00746     DriftDistance = moduleThickness/2. - (dir_z * SegZ); // Drift to -z 
00747     
00748     //if( DriftDistance <= 0.) 
00749     //cout<<" <=0 "<<DriftDistance<<" "<<i<<" "<<SegZ<<" "<<dir_z<<" "
00750     //  <<SegX<<" "<<SegY<<" "<<(moduleThickness/2)<<" "
00751     //  <<_ionization_points[i].energy()<<" "
00752     //  <<hit.particleType()<<" "<<hit.pabs()<<" "<<hit.energyLoss()<<" "
00753     //  <<hit.entryPoint()<<" "<<hit.exitPoint()
00754     //  <<endl;
00755 
00756     if( DriftDistance < 0.) {
00757       DriftDistance = 0.;
00758     } else if ( DriftDistance > moduleThickness )
00759       DriftDistance = moduleThickness;
00760     
00761     // Assume full depletion now, partial depletion will come later.
00762     float XDriftDueToMagField = DriftDistance * TanLorenzAngleX;
00763     float YDriftDueToMagField = DriftDistance * TanLorenzAngleY;
00764     
00765     // Shift cloud center
00766     float CloudCenterX = SegX + XDriftDueToMagField;
00767     float CloudCenterY = SegY + YDriftDueToMagField;
00768 
00769     // Calculate how long is the charge drift path
00770     DriftLength = sqrt( DriftDistance*DriftDistance + 
00771                         XDriftDueToMagField*XDriftDueToMagField +
00772                         YDriftDueToMagField*YDriftDueToMagField );
00773 
00774     // What is the charge diffusion after this path
00775     Sigma = sqrt(DriftLength/Dist300) * Sigma0;
00776 
00777     // Project the diffusion sigma on the collection plane
00778     Sigma_x = Sigma / CosLorenzAngleX ;
00779     Sigma_y = Sigma / CosLorenzAngleY ;
00780 
00781     SignalPoint sp( CloudCenterX, CloudCenterY,
00782      Sigma_x, Sigma_y, hit.tof(), _ionization_points[i].energy() );
00783 
00784     // Load the Charge distribution parameters
00785     _collection_points[i] = (sp);
00786 
00787   } // loop over ionization points, i.
00788  
00789 } // end drift
00790 
00791 //*************************************************************************
00792 // Induce the signal on the collection plane of the active sensor area.
00793 void SiPixelDigitizerAlgorithm::induce_signal( const PSimHit& hit) {
00794 
00795   // X  - Rows, Left-Right, 160, (1.6cm)   for barrel
00796   // Y  - Columns, Down-Up, 416, (6.4cm)
00797 
00798 #ifdef TP_DEBUG
00799     LogDebug ("Pixel Digitizer") 
00800       << " enter induce_signal, " 
00801       << topol->pitch().first << " " << topol->pitch().second; //OK
00802 #endif
00803 
00804    // local map to store pixels hit by 1 Hit.      
00805    typedef map< int, float, less<int> > hit_map_type;
00806    hit_map_type hit_signal;
00807 
00808    // map to store pixel integrals in the x and in the y directions
00809    map<int, float, less<int> > x,y; 
00810    
00811    // Assign signals to readout channels and store sorted by channel number
00812    
00813    // Iterate over collection points on the collection plane
00814    for ( vector<SignalPoint>::const_iterator i=_collection_points.begin();
00815          i != _collection_points.end(); i++) {
00816      
00817      float CloudCenterX = i->position().x(); // Charge position in x
00818      float CloudCenterY = i->position().y(); //                 in y
00819      float SigmaX = i->sigma_x();            // Charge spread in x
00820      float SigmaY = i->sigma_y();            //               in y
00821      float Charge = i->amplitude();          // Charge amplitude
00822 
00823 
00824      //if(SigmaX==0 || SigmaY==0) {
00825      //cout<<SigmaX<<" "<<SigmaY
00826      //   << " cloud " << i->position().x() << " " << i->position().y() << " " 
00827      //   << i->sigma_x() << " " << i->sigma_y() << " " << i->amplitude()<<endl;
00828      //}
00829 
00830 #ifdef TP_DEBUG
00831        LogDebug ("Pixel Digitizer") 
00832          << " cloud " << i->position().x() << " " << i->position().y() << " " 
00833          << i->sigma_x() << " " << i->sigma_y() << " " << i->amplitude();
00834 #endif      
00835      
00836      // Find the maximum cloud spread in 2D plane , assume 3*sigma
00837      float CloudRight = CloudCenterX + ClusterWidth*SigmaX;
00838      float CloudLeft  = CloudCenterX - ClusterWidth*SigmaX;
00839      float CloudUp    = CloudCenterY + ClusterWidth*SigmaY;
00840      float CloudDown  = CloudCenterY - ClusterWidth*SigmaY;
00841      
00842      // Define 2D cloud limit points
00843      LocalPoint PointRightUp  = LocalPoint(CloudRight,CloudUp);
00844      LocalPoint PointLeftDown = LocalPoint(CloudLeft,CloudDown);
00845      
00846      // This points can be located outside the sensor area.
00847      // The conversion to measurement point does not check for that
00848      // so the returned pixel index might be wrong (outside range).
00849      // We rely on the limits check below to fix this.
00850      // But remember whatever we do here THE CHARGE OUTSIDE THE ACTIVE
00851      // PIXEL ARE IS LOST, it should not be collected.
00852 
00853      // Convert the 2D points to pixel indices
00854      MeasurementPoint mp = topol->measurementPosition(PointRightUp ); //OK
00855      
00856      int IPixRightUpX = int( floor( mp.x()));
00857      int IPixRightUpY = int( floor( mp.y()));
00858      
00859 #ifdef TP_DEBUG
00860      LogDebug ("Pixel Digitizer") << " right-up " << PointRightUp << " " 
00861                                   << mp.x() << " " << mp.y() << " "
00862                                   << IPixRightUpX << " " << IPixRightUpY ;
00863 #endif
00864  
00865      mp = topol->measurementPosition(PointLeftDown ); //OK
00866     
00867      int IPixLeftDownX = int( floor( mp.x()));
00868      int IPixLeftDownY = int( floor( mp.y()));
00869      
00870 #ifdef TP_DEBUG
00871      LogDebug ("Pixel Digitizer") << " left-down " << PointLeftDown << " " 
00872                                   << mp.x() << " " << mp.y() << " "
00873                                   << IPixLeftDownX << " " << IPixLeftDownY ;
00874 #endif
00875 
00876      // Check detector limits to correct for pixels outside range.
00877      IPixRightUpX = numRows>IPixRightUpX ? IPixRightUpX : numRows-1 ;
00878      IPixRightUpY = numColumns>IPixRightUpY ? IPixRightUpY : numColumns-1 ;
00879      IPixLeftDownX = 0<IPixLeftDownX ? IPixLeftDownX : 0 ;
00880      IPixLeftDownY = 0<IPixLeftDownY ? IPixLeftDownY : 0 ;
00881      
00882      x.clear(); // clear temporary integration array
00883      y.clear();
00884 
00885      // First integrate cahrge strips in x
00886      int ix; // TT for compatibility
00887      for (ix=IPixLeftDownX; ix<=IPixRightUpX; ix++) {  // loop over x index
00888        float xUB, xLB, UpperBound, LowerBound;
00889       
00890        // Why is set to 0 if ix=0, does it meen that we accept charge 
00891        // outside the sensor? CHeck How it was done in ORCA? 
00892        //if (ix == 0) LowerBound = 0.;
00893        if (ix == 0 || SigmaX==0. )  // skip for surface segemnts 
00894          LowerBound = 0.;
00895        else {
00896          mp = MeasurementPoint( float(ix), 0.0);
00897          xLB = topol->localPosition(mp).x();
00898          gsl_sf_result result;
00899          int status = gsl_sf_erf_Q_e( (xLB-CloudCenterX)/SigmaX, &result);
00900          if (status != 0)  
00901            LogWarning ("Integration")<<"could not compute gaussian probability";
00902          LowerBound = 1-result.val;
00903        }
00904      
00905        if (ix == numRows-1 || SigmaX==0. ) 
00906          UpperBound = 1.;
00907        else {
00908          mp = MeasurementPoint( float(ix+1), 0.0);
00909          xUB = topol->localPosition(mp).x();
00910          gsl_sf_result result;
00911          int status = gsl_sf_erf_Q_e( (xUB-CloudCenterX)/SigmaX, &result);
00912          if (status != 0)  
00913            LogWarning ("Integration")<<"could not compute gaussian probability";
00914          UpperBound = 1. - result.val;
00915        }
00916        
00917        float   TotalIntegrationRange = UpperBound - LowerBound; // get strip
00918        x[ix] = TotalIntegrationRange; // save strip integral 
00919        //if(SigmaX==0 || SigmaY==0) 
00920        //cout<<TotalIntegrationRange<<" "<<ix<<endl;
00921 
00922      }
00923 
00924     // Now integarte strips in y
00925     int iy; // TT for compatibility
00926     for (iy=IPixLeftDownY; iy<=IPixRightUpY; iy++) { //loope over y ind  
00927       float yUB, yLB, UpperBound, LowerBound;
00928 
00929       if (iy == 0 || SigmaY==0.) 
00930         LowerBound = 0.;
00931       else {
00932         mp = MeasurementPoint( 0.0, float(iy) );
00933         yLB = topol->localPosition(mp).y();
00934         gsl_sf_result result;
00935         int status = gsl_sf_erf_Q_e( (yLB-CloudCenterY)/SigmaY, &result);
00936         if (status != 0)  
00937           LogWarning ("Integration")<<"could not compute gaussian probability";
00938         LowerBound = 1. - result.val;
00939       }
00940 
00941       if (iy == numColumns-1 || SigmaY==0. ) 
00942         UpperBound = 1.;
00943       else {
00944         mp = MeasurementPoint( 0.0, float(iy+1) );
00945         yUB = topol->localPosition(mp).y();
00946         gsl_sf_result result;
00947         int status = gsl_sf_erf_Q_e( (yUB-CloudCenterY)/SigmaY, &result);
00948         if (status != 0)  
00949           LogWarning ("Integration")<<"could not compute gaussian probability";
00950         UpperBound = 1. - result.val;
00951       }
00952 
00953       float   TotalIntegrationRange = UpperBound - LowerBound;
00954       y[iy] = TotalIntegrationRange; // save strip integral
00955       //if(SigmaX==0 || SigmaY==0) 
00956       //cout<<TotalIntegrationRange<<" "<<iy<<endl;
00957     }       
00958 
00959     // Get the 2D charge integrals by folding x and y strips
00960     int chan;
00961     for (ix=IPixLeftDownX; ix<=IPixRightUpX; ix++) {  // loop over x index
00962       for (iy=IPixLeftDownY; iy<=IPixRightUpY; iy++) { //loope over y ind  
00963         
00964         float ChargeFraction = Charge*x[ix]*y[iy];
00965 
00966         if( ChargeFraction > 0. ) {
00967           chan = PixelDigi::pixelToChannel( ix, iy);  // Get index 
00968           // Load the amplitude                                          
00969           hit_signal[chan] += ChargeFraction;
00970         } // endif
00971 
00972         
00973         mp = MeasurementPoint( float(ix), float(iy) );
00974         LocalPoint lp = topol->localPosition(mp);
00975         chan = topol->channel(lp);
00976 
00977 #ifdef TP_DEBUG
00978         LogDebug ("Pixel Digitizer") 
00979           << " pixel " << ix << " " << iy << " - "<<" "
00980           << chan << " " << ChargeFraction<<" "
00981           << mp.x() << " " << mp.y() <<" "
00982           << lp.x() << " " << lp.y() << " "  // givex edge position
00983           << chan; // edge belongs to previous ?
00984 #endif
00985 
00986       } // endfor iy
00987     } //endfor ix
00988    
00989 
00990     // Test conversions (THIS IS FOR TESTING ONLY) comment-out.
00991     //     mp = topol->measurementPosition( i->position() ); //OK
00992     //     LocalPoint lp = topol->localPosition(mp);     //OK
00993     //     pair<float,float> p = topol->pixel( i->position() );  //OK
00994     //     chan = PixelDigi::pixelToChannel( int(p.first), int(p.second));
00995     //     pair<int,int> ip = PixelDigi::channelToPixel(chan);
00996     //     MeasurementPoint mp1 = MeasurementPoint( float(ip.first),
00997     //                                       float(ip.second) );
00998     //     LogDebug ("Pixel Digitizer") << " Test "<< mp.x() << " " << mp.y() 
00999     //                           << " "<< lp.x() << " " << lp.y() << " "<<" "
01000     //                           <<p.first <<" "<<p.second<<" "<<chan<< " "
01001     //                           <<" " << ip.first << " " << ip.second << " "
01002     //                           << mp1.x() << " " << mp1.y() << " " //OK
01003     //                           << topol->localPosition(mp1).x() << " "  //OK
01004     //                           << topol->localPosition(mp1).y() << " "
01005     //                           << topol->channel( i->position() ); //OK
01006     
01007     
01008   } // loop over charge distributions
01009    
01010   // Fill the global map with all hit pixels from this event
01011    
01012   for ( hit_map_type::const_iterator im = hit_signal.begin();
01013         im != hit_signal.end(); im++) {
01014     _signal[(*im).first] += Amplitude( (*im).second, &hit, (*im).second);
01015     
01016     int chan =  (*im).first; 
01017     pair<int,int> ip = PixelDigi::channelToPixel(chan);
01018 
01019 #ifdef TP_DEBUG
01020     LogDebug ("Pixel Digitizer") 
01021       << " pixel " << ip.first << " " << ip.second << " "
01022       << _signal[(*im).first];    
01023 #endif
01024   }
01025 
01026 } // end induce_signal
01027 
01028 /***********************************************************************/
01029 
01030 // Build pixels, check threshold, add misscalibration, ... 
01031 void SiPixelDigitizerAlgorithm::make_digis() {
01032   internal_coll.reserve(50); internal_coll.clear();
01033 
01034 #ifdef TP_DEBUG
01035   LogDebug ("Pixel Digitizer") << " make digis "<<" "
01036                                << " pixel threshold FPix" << theThresholdInE_FPix << " " 
01037                                << " pixel threshold BPix" << theThresholdInE_BPix << " "
01038                                << " List pixels passing threshold ";
01039 #endif  
01040   
01041 
01042   //  std::cout << "make_digis(): we enter the make_digis.... " << std::endl;
01043 
01044   // Loop over hit pixels
01045 
01046   for ( signal_map_iterator i = _signal.begin(); i != _signal.end(); i++) {
01047     
01048     float signalInElectrons = (*i).second ;   // signal in electrons
01049     // Do the miss calibration for calibration studies only.
01050     //if(doMissCalibrate) signalInElectrons = missCalibrate(signalInElectrons)
01051 
01052     // Do only for pixels above threshold
01053 
01054     //    std::cout << "make_digis(): signalInElectrons is " << signalInElectrons << std::endl;
01055 
01056     if ( signalInElectrons >= thePixelThresholdInE) { // check threshold
01057       
01058       //      unsigned int Sub_detid=DetId(detID).subdetId();
01059       //      std::cout << "make_digis(): For (Sub_detid, detID) = (" << Sub_detid << ", "<< detID << ") " << "thePixelThresholdInE vaut " << thePixelThresholdInE << std::endl;
01060 
01061       int chan =  (*i).first;  // channel number
01062       pair<int,int> ip = PixelDigi::channelToPixel(chan);
01063       int adc=0;  // ADC count as integer
01064 
01065       // Do the miss calibration for calibration studies only.
01066       if(doMissCalibrate) {
01067         int row = ip.first;  // X in row
01068         int col = ip.second; // Y is in col
01069         adc = int(missCalibrate(col,row,signalInElectrons)); //full misscalib.
01070       } else { // Just do a simple electron->adc conversion
01071         adc = int( signalInElectrons / theElectronPerADC ); // calibrate gain
01072       }
01073       adc = min(adc, theAdcFullScale); // Check maximum value
01074       
01075 #ifdef TP_DEBUG
01076       LogDebug ("Pixel Digitizer") 
01077         << (*i).first << " " << (*i).second << " " << signalInElectrons 
01078         << " " << adc << ip.first << " " << ip.second ;
01079 #endif
01080            
01081       // Load digis
01082       internal_coll.push_back( PixelDigi( ip.first, ip.second, adc));
01083   
01084       //digilink     
01085       if((*i).second.hits().size()>0){
01086         simi.clear();
01087         unsigned int il=0;
01088         for( vector<const PSimHit*>::const_iterator ihit = (*i).second.hits().begin();
01089              ihit != (*i).second.hits().end(); ihit++) {
01090           simi[(**ihit).trackId()].push_back((*i).second.individualampl()[il]);
01091           il++;
01092         }
01093         
01094         //sum the contribution of the same trackid 
01095         for( simlink_map::iterator simiiter=simi.begin();
01096              simiiter!=simi.end();
01097              simiiter++){
01098           
01099           float sum_samechannel=0;
01100           for (unsigned int iii=0;iii<(*simiiter).second.size();iii++){
01101             sum_samechannel+=(*simiiter).second[iii];
01102           }
01103           float fraction=sum_samechannel/(*i).second;
01104           if (fraction>1.) fraction=1.;
01105           link_coll.push_back(PixelDigiSimLink((*i).first,(*simiiter).first,((*i).second.hits().front())->eventId(),fraction));
01106         }
01107         
01108       }
01109     }
01110     
01111   }
01112 }
01113 
01114 /***********************************************************************/
01115 
01116 //  Add electronic noise to pixel charge
01117 void SiPixelDigitizerAlgorithm::add_noise() {
01118 
01119 #ifdef TP_DEBUG
01120   LogDebug ("Pixel Digitizer") << " enter add_noise " << theNoiseInElectrons;
01121 #endif
01122  
01123   // First add noise to hit pixels
01124   // Use here the FULL readout noise, including TBM,ALT,AOH,OPT-REC.
01125   for ( signal_map_iterator i = _signal.begin(); i != _signal.end(); i++) {
01126     //float noise  = RandGaussQ::shoot(0.,theReadoutNoise);
01127     float noise  = gaussDistribution_->fire() ;
01128     (*i).second += Amplitude( noise,0,-1.);  
01129   }
01130   
01131   if(!addNoisyPixels)  // Option to skip noise in non-hit pixels
01132     return;
01133 
01134   // Add noise on non-hit pixels
01135   // Use here the pixel noise 
01136   int numberOfPixels = (numRows * numColumns);
01137   map<int,float, less<int> > otherPixels;
01138   map<int,float, less<int> >::iterator mapI;
01139 
01140   //  unsigned int Sub_detid=DetId(detID).subdetId();
01141   //  std::cout << "add_noise: " << "Subdetid = " << Sub_detid << " and detID " << detID << " the threshold is " << thePixelThreshold << " and the threshold in electrons = " << thePixelThresholdInE << std::endl;
01142 
01143 
01144   theNoiser->generate(numberOfPixels, 
01145                       thePixelThreshold, //thr. in un. of nois
01146                       theNoiseInElectrons, // noise in elec. 
01147                       otherPixels );
01148 
01149 #ifdef TP_DEBUG
01150   LogDebug ("Pixel Digitizer") 
01151     <<  " Add noisy pixels " << numRows << " " 
01152     << numColumns << " " << theNoiseInElectrons << " " 
01153     << theThresholdInE_FPix << theThresholdInE_BPix <<" "<< numberOfPixels<<" " 
01154     << otherPixels.size() ;
01155 #endif
01156   
01157   // Add noisy pixels
01158   for (mapI = otherPixels.begin(); mapI!= otherPixels.end(); mapI++) {
01159     int iy = ((*mapI).first) / numRows;
01160     int ix = ((*mapI).first) - (iy*numRows);
01161 
01162     // Keep for a while for testing.
01163     if( iy < 0 || iy > (numColumns-1) ) 
01164       LogWarning ("Pixel Geometry") << " error in iy " << iy ;
01165     if( ix < 0 || ix > (numRows-1) )
01166       LogWarning ("Pixel Geometry")  << " error in ix " << ix ;
01167 
01168     int chan = PixelDigi::pixelToChannel(ix, iy);
01169 
01170 #ifdef TP_DEBUG
01171     LogDebug ("Pixel Digitizer")
01172       <<" Storing noise = " << (*mapI).first << " " << (*mapI).second 
01173       << " " << ix << " " << iy << " " << chan ;
01174 #endif
01175  
01176     if(_signal[chan] == 0){
01177       //      float noise = float( (*mapI).second );
01178       int noise=int( (*mapI).second );
01179       _signal[chan] = Amplitude (noise, 0,-1.);
01180     }
01181   }
01182   
01183 } 
01184 
01185 /***********************************************************************/
01186 
01187 // Simulate the readout inefficiencies. 
01188 // Delete a selected number of single pixels, dcols and rocs.
01189 void SiPixelDigitizerAlgorithm::pixel_inefficiency() {
01190 
01191 
01192   // Predefined efficiencies
01193   float pixelEfficiency  = 1.0;
01194   float columnEfficiency = 1.0;
01195   float chipEfficiency   = 1.0;
01196 
01197   // setup the chip indices conversion
01198   unsigned int Subid=DetId(detID).subdetId();
01199   if    (Subid==  PixelSubdetector::PixelBarrel){// barrel layers
01200     int layerIndex=PXBDetId(detID).layer();
01201     pixelEfficiency  = thePixelEfficiency[layerIndex-1];
01202     columnEfficiency = thePixelColEfficiency[layerIndex-1];
01203     chipEfficiency   = thePixelChipEfficiency[layerIndex-1];
01204  
01205     // This should never happen
01206     if(numColumns>416)  LogWarning ("Pixel Geometry") <<" wrong columns in barrel "<<numColumns;
01207     if(numRows>160)  LogWarning ("Pixel Geometry") <<" wrong rows in barrel "<<numRows;
01208     
01209   } else {                // forward disks
01210    
01211     // For endcaps take same for each endcap
01212     pixelEfficiency  = thePixelEfficiency[3];
01213     columnEfficiency = thePixelColEfficiency[3];
01214     chipEfficiency   = thePixelChipEfficiency[3];
01215  
01216     // Sometimes the forward pixels have wrong size, 
01217     // this crashes the index conversion, so exit.
01218     if(numColumns>260 || numRows>160) {
01219       if(numColumns>260)  LogWarning ("Pixel Geometry") <<" wrong columns in endcaps "<<numColumns;
01220       if(numRows>160)  LogWarning ("Pixel Geometry") <<" wrong rows in endcaps "<<numRows;
01221       return;
01222     }
01223   } // if barrel/forward
01224 
01225 #ifdef TP_DEBUG
01226   LogDebug ("Pixel Digitizer") << " enter pixel_inefficiency " << pixelEfficiency << " " 
01227                                << columnEfficiency << " " << chipEfficiency;
01228 #endif
01229   
01230   // Initilize the index converter
01231   //PixelIndices indexConverter(numColumns,numRows);
01232   int chipIndex,rowROC,colROC;
01233   map<int, int, less<int> >chips, columns;
01234   map<int, int, less<int> >::iterator iter;
01235   
01236   // Find out the number of columns and rocs hits
01237   // Loop over hit pixels, amplitude in electrons, channel = coded row,col
01238   for (signal_map_iterator i = _signal.begin();i != _signal.end();i++) {
01239     
01240     int chan = i->first;
01241     pair<int,int> ip = PixelDigi::channelToPixel(chan);
01242     int row = ip.first;  // X in row
01243     int col = ip.second; // Y is in col
01244     //transform to ROC index coordinates   
01245     pIndexConverter->transformToROC(col,row,chipIndex,colROC,rowROC);
01246     int dColInChip = pIndexConverter->DColumn(colROC); // get ROC dcol from ROC col 
01247     //dcol in mod
01248     int dColInDet = pIndexConverter->DColumnInModule(dColInChip,chipIndex); 
01249       
01250     chips[chipIndex]++;
01251     columns[dColInDet]++;
01252   }
01253   
01254   // Delete some ROC hits.
01255   for ( iter = chips.begin(); iter != chips.end() ; iter++ ) {
01256     //float rand  = RandFlat::shoot();
01257     float rand  = flatDistribution_->fire();
01258     if( rand > chipEfficiency ) chips[iter->first]=0;
01259   }
01260 
01261   // Delete some Dcol hits.
01262   for ( iter = columns.begin(); iter != columns.end() ; iter++ ) {
01263     //float rand  = RandFlat::shoot();
01264     float rand  = flatDistribution_->fire();
01265     if( rand > columnEfficiency ) columns[iter->first]=0;
01266   }
01267   
01268   // Now loop again over pixels to kill some of them.
01269   // Loop over hit pixels, amplitude in electrons, channel = coded row,col
01270   for(signal_map_iterator i = _signal.begin();i != _signal.end(); i++) {    
01271 
01272     //    int chan = i->first;
01273     pair<int,int> ip = PixelDigi::channelToPixel(i->first);//get pixel pos
01274     int row = ip.first;  // X in row
01275     int col = ip.second; // Y is in col
01276     //transform to ROC index coordinates   
01277     pIndexConverter->transformToROC(col,row,chipIndex,colROC,rowROC);
01278     int dColInChip = pIndexConverter->DColumn(colROC); //get ROC dcol from ROC col 
01279     //dcol in mod
01280     int dColInDet = pIndexConverter->DColumnInModule(dColInChip,chipIndex); 
01281 
01282 
01283     //float rand  = RandFlat::shoot();
01284     float rand  = flatDistribution_->fire();
01285     if( chips[chipIndex]==0 || columns[dColInDet]==0 
01286         || rand>pixelEfficiency ) {
01287       // make pixel amplitude =0, pixel will be lost at clusterization    
01288       i->second.set(0.); // reset amplitude, 
01289     } // end if
01290 
01291   } // end pixel loop
01292   
01293 } // end pixel_indefficiency
01294 
01295 //***********************************************************************
01296 
01297 // Fluctuate the gain and offset for the amplitude calibration
01298 // Use gaussian smearing.
01299 //float SiPixelDigitizerAlgorithm::missCalibrate(const float amp) const {
01300   //float gain  = RandGaussQ::shoot(1.,theGainSmearing);
01301   //float offset  = RandGaussQ::shoot(0.,theOffsetSmearing);
01302   //float newAmp = amp * gain + offset;
01303   // More complex misscalibration 
01304 float SiPixelDigitizerAlgorithm::missCalibrate(int col,int row,
01305                                  const float signalInElectrons) const {
01306 
01307   // Central values
01308   //const float p0=0.00352, p1=0.868, p2=112., p3=113.; // pix(0,0,0)
01309   const float p0=0.00382, p1=0.886, p2=112.7, p3=113.0; // average roc=0
01310   //const float p0=0.00492, p1=1.998, p2=90.6, p3=134.1; // average roc=6
01311   // Smeared (rms)
01312   //const float s0=0.00020, s1=0.051, s2=5.4, s3=4.4; // average roc=0
01313   //const float s0=0.00015, s1=0.043, s2=3.2, s3=3.1; // col average roc=0
01314 
01315   //  const float electronsPerVCAL = 65.5; // our present VCAL calibration (feb 2009)
01316   //  const float electronsPerVCAL_Offset = -414.0; // our present VCAL calibration (feb 2009)
01317   float newAmp = 0.; //Modified signal
01318 
01319   // Convert electrons to VCAL units
01320   float signal = (signalInElectrons-electronsPerVCAL_Offset)/electronsPerVCAL;
01321 
01322   //  std::cout << "electronsPerVCAL = " << electronsPerVCAL << " and electronsPerVCAL_Offset = " << electronsPerVCAL_Offset << std::endl;
01323 
01324   //
01325   // Simulate the analog response with fixed parametrization
01326   newAmp = p3 + p2 * tanh(p0*signal - p1);
01327   
01328   //
01329   // Use the pixel-by-pixel calibrations
01330   //transform to ROC index coordinates
01331   //int chipIndex=0, colROC=0, rowROC=0;
01332   //pIndexConverter->transformToROC(col,row,chipIndex,colROC,rowROC);
01333 
01334   // Use calibration from a file
01335   //int chanROC = PixelIndices::pixelToChannelROC(rowROC,colROC); // use ROC coordinates
01336   //float pp0=0, pp1=0,pp2=0,pp3=0;
01337   //map<int,CalParameters,less<int> >::const_iterator it=calmap.find(chanROC);
01338   //CalParameters y  = (*it).second;
01339   //pp0 = y.p0;
01340   //pp1 = y.p1;
01341   //pp2 = y.p2;
01342   //pp3 = y.p3;
01343 
01344   //
01345   // Use random smearing 
01346   // Randomize the pixel response
01347   //float pp0  = RandGaussQ::shoot(p0,s0);
01348   //float pp1  = RandGaussQ::shoot(p1,s1);
01349   //float pp2  = RandGaussQ::shoot(p2,s2);
01350   //float pp3  = RandGaussQ::shoot(p3,s3);
01351 
01352   //newAmp = pp3 + pp2 * tanh(pp0*signal - pp1); // Final signal
01353 
01354   //cout<<" misscalibrate "<<col<<" "<<row<<" "<<chipIndex<<" "<<colROC<<" "
01355   //  <<rowROC<<" "<<signalInElectrons<<" "<<signal<<" "<<newAmp<<" "
01356   //  <<(signalInElectrons/theElectronPerADC)<<endl;
01357 
01358   return newAmp;
01359 }  
01360 //******************************************************************************
01361 
01362 // Set the drift direction accoring to the Bfield in local det-unit frame
01363 // Works for both barrel and forward pixels.
01364 // Replace the sign convention to fit M.Swartz's formulaes.
01365 // Configurations for barrel and foward pixels possess different tanLorentzAngleperTesla 
01366 // parameter value
01367 
01368 LocalVector SiPixelDigitizerAlgorithm::DriftDirection(){
01369   Frame detFrame(_detp->surface().position(),_detp->surface().rotation());
01370   LocalVector Bfield=detFrame.toLocal(_bfield);
01371   
01372   float alpha2_FPix;
01373   float alpha2_BPix;
01374   float alpha2;
01375 
01376   //float dir_x = -tanLorentzAnglePerTesla * Bfield.y();
01377   //float dir_y = +tanLorentzAnglePerTesla * Bfield.x();
01378   //float dir_z = -1.; // E field always in z direction, so electrons go to -z
01379   // The dir_z has to be +/- 1. !
01380   // LocalVector theDriftDirection = LocalVector(dir_x,dir_y,dir_z);
01381 
01382   float dir_x = 0.0;
01383   float dir_y = 0.0;
01384   float dir_z = 0.0;
01385   float scale = 0.0;
01386   
01387   unsigned int Sub_detid=DetId(detID).subdetId();
01388 
01389   // Read Lorentz angle from cfg file:**************************************************************
01390   
01391   if(!use_LorentzAngle_DB_){ 
01392     
01393     if ( alpha2Order) {
01394       alpha2_FPix = tanLorentzAnglePerTesla_FPix*tanLorentzAnglePerTesla_FPix;
01395       alpha2_BPix = tanLorentzAnglePerTesla_BPix*tanLorentzAnglePerTesla_BPix;
01396     }else {
01397       alpha2_FPix = 0.0;
01398       alpha2_BPix = 0.0;
01399     }
01400     
01401     if (Sub_detid == PixelSubdetector::PixelBarrel){// barrel layers
01402       dir_x = -( tanLorentzAnglePerTesla_BPix * Bfield.y() + alpha2_BPix* Bfield.z()* Bfield.x() );
01403       dir_y = +( tanLorentzAnglePerTesla_BPix * Bfield.x() - alpha2_BPix* Bfield.z()* Bfield.y() );
01404       dir_z = -(1 + alpha2_BPix* Bfield.z()*Bfield.z() );
01405       scale = (1 + alpha2_BPix* Bfield.z()*Bfield.z() );
01406       
01407     } else {// forward disks
01408       dir_x = -( tanLorentzAnglePerTesla_FPix * Bfield.y() + alpha2_FPix* Bfield.z()* Bfield.x() );
01409       dir_y = +( tanLorentzAnglePerTesla_FPix * Bfield.x() - alpha2_FPix* Bfield.z()* Bfield.y() );
01410       dir_z = -(1 + alpha2_FPix* Bfield.z()*Bfield.z() );
01411       scale = (1 + alpha2_FPix* Bfield.z()*Bfield.z() );
01412     }
01413     } // end: Read LA from cfg file.
01414   
01415   //Read Lorentz angle from DB:********************************************************************
01416   if(use_LorentzAngle_DB_){ 
01417     std::map<unsigned int,float> detid_la= SiPixelLorentzAngle_->getLorentzAngles();
01418     std::map<unsigned int,float>::const_iterator it;
01419     
01420     
01421     for (it=detid_la.begin();it!=detid_la.end();it++)
01422     {
01423       if (detID==it->first) {
01424         if (alpha2Order) {
01425           alpha2 = it->second * it->second;
01426         }  
01427         else {
01428           alpha2 = 0.0;
01429         } 
01430         //      std::cout << "detID is: " << it->first << "The LA per tesla is: " << it->second << std::endl;
01431         dir_x = -( it->second * Bfield.y() + alpha2 * Bfield.z()* Bfield.x() );
01432         dir_y = +( it->second * Bfield.x() - alpha2 * Bfield.z()* Bfield.y() );
01433         dir_z = -(1 + alpha2 * Bfield.z()*Bfield.z() );
01434         scale = (1 + alpha2 * Bfield.z()*Bfield.z() );
01435       }
01436     } 
01437   }// end: Read LA from DataBase.
01438   
01439   LocalVector theDriftDirection = LocalVector(dir_x/scale, dir_y/scale, dir_z/scale );  
01440   
01441 #ifdef TP_DEBUG
01442   LogDebug ("Pixel Digitizer") << " The drift direction in local coordinate is "   
01443                                << theDriftDirection ;
01444 #endif
01445   
01446   return theDriftDirection;
01447 }
01448 
01449 //****************************************************************************************************
01450 
01451 void SiPixelDigitizerAlgorithm::pixel_inefficiency_db(void){
01452   if(!use_ineff_from_db_)
01453     return;
01454   
01455   // Loop over hit pixels, amplitude in electrons, channel = coded row,col
01456   for(signal_map_iterator i = _signal.begin();i != _signal.end(); i++) {    
01457     
01458     //    int chan = i->first;
01459     pair<int,int> ip = PixelDigi::channelToPixel(i->first);//get pixel pos
01460     int row = ip.first;  // X in row
01461     int col = ip.second; // Y is in col
01462     uint32_t detid = detID;
01463     //transform to ROC index coordinates   
01464     if(theSiPixelGainCalibrationService_->isDead(detid, col, row)){
01465       //      std::cout << "now in isdead check, row " << detid << " " << col << "," << row << std::endl;
01466       // make pixel amplitude =0, pixel will be lost at clusterization    
01467       i->second.set(0.); // reset amplitude, 
01468     } // end if
01469   } // end pixel loop
01470 } // end pixel_indefficiency
01471 
01472 
01473 //****************************************************************************************************
01474 
01475 void SiPixelDigitizerAlgorithm::module_killing_conf(void){
01476   if(!use_module_killing_)
01477     return;
01478   
01479   bool isbad=false;
01480   int detid = detID;
01481   
01482   Parameters::iterator itDeadModules=DeadModules.begin();
01483   
01484   for(; itDeadModules != DeadModules.end(); ++itDeadModules){
01485     int Dead_detID = itDeadModules->getParameter<int>("Dead_detID"); 
01486     if(detid==Dead_detID){
01487       isbad=true;
01488       break;
01489     }
01490   }
01491   
01492   if(!isbad)
01493     return;
01494   
01495   std::string Module = itDeadModules->getParameter<std::string>("Module");
01496   
01497   if(Module=="whole"){
01498     for(signal_map_iterator i = _signal.begin();i != _signal.end(); i++) {    
01499       i->second.set(0.); // reset amplitude
01500       //      std::cout << "whole dead module is removed " << detid << std::endl;
01501     }
01502   }
01503   
01504   for(signal_map_iterator i = _signal.begin();i != _signal.end(); i++) {    
01505     pair<int,int> ip = PixelDigi::channelToPixel(i->first);//get pixel pos
01506     
01507     if(Module=="tbmA" && ip.first>=80 && ip.first<=159){
01508       i->second.set(0.);
01509       //      std::cout << "tbmA dead module is removed " << detid << std::endl;
01510     }
01511     
01512     if( Module=="tbmB" && ip.first<=79){
01513       i->second.set(0.);
01514       //      std::cout << "tbmB dead module is removed " << detid << std::endl;
01515 
01516     }
01517 
01518   }
01519 }
01520 
01521 
01522 //****************************************************************************************************
01523   /*
01524 void SiPixelDigitizerAlgorithm::module_killing_DB(void){
01525   if(!use_module_killing_)
01526     return;
01527   
01528   bool isbad=false;
01529   uint32_t detid = detID;
01530   
01531   std::vector<SiPixelQuality::disabledModuleType>disabledModules = SiPixelBadModule_->getBadComponentList();
01532   for (size_t id=0;id<disabledModules.size();id++)
01533     {
01534       SiPixelQuality::disabledModuleType badmodule = disabledModules[id];
01535       
01536       if(detid==badmodule.DetID){
01537         isbad=true;
01538         //std::cout << "Dead module from DB is: " << detid << std::endl;
01539         break;
01540       }
01541     }
01542   
01543   if(!isbad)
01544     return;
01545   
01546   SiPixelQuality::disabledModuleType badmodule;
01547   
01548   if(badmodule.errorType == 0){
01549     std::cout << "bad module error type is " << badmodule.errorType <<std::endl;
01550     for(signal_map_iterator i = _signal.begin();i != _signal.end(); i++) {    
01551       i->second.set(0.); // reset amplitude
01552     }
01553   }
01554   
01555   
01556   for(signal_map_iterator i = _signal.begin();i != _signal.end(); i++) {    
01557     pair<int,int> ip = PixelDigi::channelToPixel(i->first);//get pixel pos
01558     
01559     if(badmodule.errorType == 1 &&  ip.first>=80 && ip.first<=159){
01560       i->second.set(0.);
01561     }
01562     
01563     if( badmodule.errorType == 2 && ip.first<=79){
01564       i->second.set(0.);
01565     }
01566   } 
01567 }
01568   */

Generated on Tue Jun 9 17:47:53 2009 for CMSSW by  doxygen 1.5.4