CMS 3D CMS Logo

/afs/cern.ch/work/c/cnuttens/private/SiStripDev/DocumentationProduction/CMSSW_6_1_0/src/SimTracker/SiStripDigitizer/plugins/DigiSimLinkAlgorithm.cc

Go to the documentation of this file.
00001 // File: DigiSimLinkAlgorithm.cc
00002 // Description:  Steering class for digitization.
00003 
00004 #include <vector>
00005 #include <algorithm>
00006 #include <iostream>
00007 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 #include "DigiSimLinkAlgorithm.h"
00010 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
00011 #include "DataFormats/Common/interface/DetSetVector.h"
00012 #include "DataFormats/GeometrySurface/interface/BoundSurface.h"
00013 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
00014 #include "CLHEP/Random/RandFlat.h"
00015 
00016 #define CBOLTZ (1.38E-23)
00017 #define e_SI (1.6E-19)
00018 
00019 DigiSimLinkAlgorithm::DigiSimLinkAlgorithm(const edm::ParameterSet& conf, CLHEP::HepRandomEngine& eng):
00020   conf_(conf),rndEngine(eng){
00021   theThreshold              = conf_.getParameter<double>("NoiseSigmaThreshold");
00022   theFedAlgo                = conf_.getParameter<int>("FedAlgorithm");
00023   peakMode                  = conf_.getParameter<bool>("APVpeakmode");
00024   theElectronPerADC         = conf_.getParameter<double>( peakMode ? "electronPerAdcPeak" : "electronPerAdcDec" );
00025   noise                     = conf_.getParameter<bool>("Noise");
00026   zeroSuppression           = conf_.getParameter<bool>("ZeroSuppression");
00027   theTOFCutForPeak          = conf_.getParameter<double>("TOFCutForPeak");
00028   theTOFCutForDeconvolution = conf_.getParameter<double>("TOFCutForDeconvolution");
00029   cosmicShift               = conf_.getUntrackedParameter<double>("CosmicDelayShift");
00030   inefficiency              = conf_.getParameter<double>("Inefficiency");
00031   RealPedestals             = conf_.getParameter<bool>("RealPedestals"); 
00032   SingleStripNoise          = conf_.getParameter<bool>("SingleStripNoise");
00033   CommonModeNoise           = conf_.getParameter<bool>("CommonModeNoise");
00034   BaselineShift             = conf_.getParameter<bool>("BaselineShift");
00035   APVSaturationFromHIP      = conf_.getParameter<bool>("APVSaturationFromHIP");
00036   APVSaturationProb         = conf_.getParameter<double>("APVSaturationProb");
00037   cmnRMStib                 = conf_.getParameter<double>("cmnRMStib");
00038   cmnRMStob                 = conf_.getParameter<double>("cmnRMStob");
00039   cmnRMStid                 = conf_.getParameter<double>("cmnRMStid");
00040   cmnRMStec                 = conf_.getParameter<double>("cmnRMStec");
00041   pedOffset                 = (unsigned int)conf_.getParameter<double>("PedestalsOffset");
00042   if (peakMode) {
00043     tofCut=theTOFCutForPeak;
00044     LogDebug("StripDigiInfo")<<"APVs running in peak mode (poor time resolution)";
00045   } else {
00046     tofCut=theTOFCutForDeconvolution;
00047     LogDebug("StripDigiInfo")<<"APVs running in deconvolution mode (good time resolution)";
00048   };
00049   
00050   theSiHitDigitizer = new SiHitDigitizer(conf_,rndEngine);
00051   theDigiSimLinkPileUpSignals = new DigiSimLinkPileUpSignals();
00052   theSiNoiseAdder = new SiGaussianTailNoiseAdder(theThreshold,rndEngine);
00053   theSiDigitalConverter = new SiTrivialDigitalConverter(theElectronPerADC);
00054   theSiZeroSuppress = new SiStripFedZeroSuppression(theFedAlgo);
00055   theFlatDistribution = new CLHEP::RandFlat(rndEngine, 0., 1.);    
00056 
00057   
00058 }
00059 
00060 DigiSimLinkAlgorithm::~DigiSimLinkAlgorithm(){
00061   delete theSiHitDigitizer;
00062   delete theDigiSimLinkPileUpSignals;
00063   delete theSiNoiseAdder;
00064   delete theSiDigitalConverter;
00065   delete theSiZeroSuppress;
00066   delete theFlatDistribution;
00067   //delete particle;
00068   //delete pdt;
00069 }
00070 
00071 //  Run the algorithm for a given module
00072 //  ------------------------------------
00073 
00074 void DigiSimLinkAlgorithm::run(edm::DetSet<SiStripDigi>& outdigi,
00075                                edm::DetSet<SiStripRawDigi>& outrawdigi,
00076                                const std::vector<std::pair<const PSimHit*, int > > &input,
00077                                StripGeomDetUnit *det,
00078                                GlobalVector bfield,float langle, 
00079                                edm::ESHandle<SiStripGain> & gainHandle,
00080                                edm::ESHandle<SiStripThreshold> & thresholdHandle,
00081                                edm::ESHandle<SiStripNoises> & noiseHandle,
00082                                edm::ESHandle<SiStripPedestals> & pedestalHandle,
00083                                edm::ESHandle<SiStripBadStrip> & deadChannelHandle,
00084                                const TrackerTopology *tTopo) {  
00085   theDigiSimLinkPileUpSignals->reset();
00086   unsigned int detID = det->geographicalId().rawId();
00087   SiStripNoises::Range detNoiseRange = noiseHandle->getRange(detID);
00088   SiStripApvGain::Range detGainRange = gainHandle->getRange(detID);
00089   SiStripPedestals::Range detPedestalRange = pedestalHandle->getRange(detID);
00090   SiStripBadStrip::Range detBadStripRange = deadChannelHandle->getRange(detID);
00091   numStrips = (det->specificTopology()).nstrips();  
00092   
00093   //stroing the bad stip of the the module. the module is not removed but just signal put to 0
00094   std::vector<bool> badChannels;
00095   badChannels.clear();
00096   badChannels.insert(badChannels.begin(),numStrips,false);
00097   SiStripBadStrip::data fs;
00098   for(SiStripBadStrip::ContainerIterator it=detBadStripRange.first;it!=detBadStripRange.second;++it){
00099         fs=deadChannelHandle->decode(*it);
00100     for(int strip = fs.firstStrip; strip <fs.firstStrip+fs.range; ++strip )badChannels[strip] = true;
00101   }
00102 
00103      
00104   // local amplitude of detector channels (from processed PSimHit)
00105 //  locAmpl.clear();
00106   detAmpl.clear();
00107 //  locAmpl.insert(locAmpl.begin(),numStrips,0.);
00108   // total amplitude of detector channels
00109   detAmpl.insert(detAmpl.begin(),numStrips,0.);
00110 
00111   firstChannelWithSignal = numStrips;
00112   lastChannelWithSignal  = 0;
00113 
00114   // First: loop on the SimHits
00115   std::vector<std::pair<const PSimHit*, int > >::const_iterator simHitIter = input.begin();
00116   std::vector<std::pair<const PSimHit*, int > >::const_iterator simHitIterEnd = input.end();
00117   if(theFlatDistribution->fire()>inefficiency) {
00118     for (;simHitIter != simHitIterEnd; ++simHitIter) {
00119       locAmpl.clear();
00120       locAmpl.insert(locAmpl.begin(),numStrips,0.);
00121       // check TOF
00122       if ( std::fabs( ((*simHitIter).first)->tof() - cosmicShift - det->surface().toGlobal(((*simHitIter).first)->localPosition()).mag()/30.) < tofCut && ((*simHitIter).first)->energyLoss()>0) {
00123         localFirstChannel = numStrips;
00124         localLastChannel  = 0;
00125         // process the hit
00126         theSiHitDigitizer->processHit(((*simHitIter).first),*det,bfield,langle, locAmpl, localFirstChannel, localLastChannel, tTopo);
00127           
00128                   //APV Killer to simulate HIP effect
00129                   //------------------------------------------------------
00130                   
00131                   if(APVSaturationFromHIP&&!zeroSuppression){
00132                     int pdg_id = ((*simHitIter).first)->particleType();
00133                         particle = pdt->particle(pdg_id);
00134                         if(particle != NULL){
00135                                 float charge = particle->charge();
00136                                 bool isHadron = particle->isHadron();
00137                             if(charge!=0 && isHadron){
00138                                         if(theFlatDistribution->fire()<APVSaturationProb){
00139                                                 int FirstAPV = localFirstChannel/128;
00140                                                 int LastAPV = localLastChannel/128;
00141                                                 std::cout << "-------------------HIP--------------" << std::endl;
00142                                                 std::cout << "Killing APVs " << FirstAPV << " - " <<LastAPV << " " << detID <<std::endl;
00143                                                 for(int strip = FirstAPV*128; strip < LastAPV*128 +128; ++strip) badChannels[strip] = true; //doing like that I remove the signal information only after the 
00144                                                                                                                                                                                                                                         //stip that got the HIP but it remains the signal of the previous
00145                                                                                                                                                                                                                                         //one. I'll make a further loop to remove all signal                                                                                                                                                                                                            
00146                                                 
00147                                         }
00148                                 }
00149                         }
00150               }             
00151                 
00152                 
00153                 theDigiSimLinkPileUpSignals->add(locAmpl, localFirstChannel, localLastChannel, ((*simHitIter).first), (*simHitIter).second);
00154     
00155                 // sum signal on strips
00156         for (size_t iChannel=localFirstChannel; iChannel<localLastChannel; iChannel++) {
00157           if(locAmpl[iChannel]>0.) {
00158                     //if(!badChannels[iChannel]) detAmpl[iChannel]+=locAmpl[iChannel];
00159                         //locAmpl[iChannel]=0;
00160                         detAmpl[iChannel]+=locAmpl[iChannel];
00161            }
00162         }
00163         if(firstChannelWithSignal>localFirstChannel) firstChannelWithSignal=localFirstChannel;
00164         if(lastChannelWithSignal<localLastChannel) lastChannelWithSignal=localLastChannel;
00165       }
00166         }
00167   }
00168   
00169   //removing signal from the dead (and HIP effected) strips
00170   for(int strip =0; strip < numStrips; ++strip) if(badChannels[strip]) detAmpl[strip] =0;
00171   
00172   const DigiSimLinkPileUpSignals::HitToDigisMapType& theLink(theDigiSimLinkPileUpSignals->dumpLink());  
00173   const DigiSimLinkPileUpSignals::HitCounterToDigisMapType& theCounterLink(theDigiSimLinkPileUpSignals->dumpCounterLink());  
00174   
00175   if(zeroSuppression){
00176     if(noise){
00177           int RefStrip = int(numStrips/2.);
00178           while(RefStrip<numStrips&&badChannels[RefStrip]){ //if the refstrip is bad, I move up to when I don't find it
00179                 RefStrip++;
00180           }
00181           if(RefStrip<numStrips){
00182                 float noiseRMS = noiseHandle->getNoise(RefStrip,detNoiseRange);
00183                 float gainValue = gainHandle->getStripGain(RefStrip, detGainRange);
00184                 theSiNoiseAdder->addNoise(detAmpl,firstChannelWithSignal,lastChannelWithSignal,numStrips,noiseRMS*theElectronPerADC/gainValue);
00185           }
00186         }
00187     digis.clear();
00188     theSiZeroSuppress->suppress(theSiDigitalConverter->convert(detAmpl, gainHandle, detID), digis, detID,noiseHandle,thresholdHandle);
00189     push_link(digis, theLink, theCounterLink, detAmpl,detID);
00190     outdigi.data = digis;
00191   }
00192   
00193   
00194   if(!zeroSuppression){
00195     //if(noise){
00196       // the constant pedestal offset is needed because
00197       //   negative adc counts are not allowed in case
00198       //   Pedestal and CMN subtraction is performed.
00199       //   The pedestal value read from the conditions
00200       //   is pedValue and after the pedestal subtraction
00201       //   the baseline is zero. The Common Mode Noise
00202       //   is not subtracted from the negative adc counts
00203       //   channels. Adding pedOffset the baseline is set
00204       //   to pedOffset after pedestal subtraction and CMN
00205       //   is subtracted to all the channels since none of
00206       //   them has negative adc value. The pedOffset is
00207       //   treated as a constant component in the CMN
00208       //   estimation and subtracted as CMN.
00209       
00210          
00211                 //calculating the charge deposited on each APV and subtracting the shift
00212                 //------------------------------------------------------
00213                 if(BaselineShift){
00214                    theSiNoiseAdder->addBaselineShift(detAmpl, badChannels);
00215                 }
00216                 
00217                 //Adding the strip noise
00218                 //------------------------------------------------------                                                 
00219                 if(noise){
00220                     std::vector<float> noiseRMSv;
00221                         noiseRMSv.clear();
00222                     noiseRMSv.insert(noiseRMSv.begin(),numStrips,0.);
00223                         
00224                     if(SingleStripNoise){
00225                             for(int strip=0; strip< numStrips; ++strip){
00226                                         if(!badChannels[strip]) noiseRMSv[strip] = (noiseHandle->getNoise(strip,detNoiseRange))* theElectronPerADC;
00227                                 }
00228                         
00229                 } else {
00230                             int RefStrip = 0; //int(numStrips/2.);
00231                             while(RefStrip<numStrips&&badChannels[RefStrip]){ //if the refstrip is bad, I move up to when I don't find it
00232                                         RefStrip++;
00233                                 }
00234                                 if(RefStrip<numStrips){
00235                                         float noiseRMS = noiseHandle->getNoise(RefStrip,detNoiseRange) *theElectronPerADC;
00236                                         for(int strip=0; strip< numStrips; ++strip){
00237                                         if(!badChannels[strip]) noiseRMSv[strip] = noiseRMS;
00238                                         }
00239                                 }
00240                         }
00241                         
00242                         theSiNoiseAdder->addNoiseVR(detAmpl, noiseRMSv);
00243                 }                       
00244                 
00245                 //adding the CMN
00246                 //------------------------------------------------------
00247         if(CommonModeNoise){
00248                   float cmnRMS = 0.;
00249                   DetId  detId(detID);
00250                   uint32_t SubDet = detId.subdetId();
00251                   if(SubDet==3){
00252                     cmnRMS = cmnRMStib;
00253                   }else if(SubDet==4){
00254                     cmnRMS = cmnRMStid;
00255                   }else if(SubDet==5){
00256                     cmnRMS = cmnRMStob;
00257                   }else if(SubDet==6){
00258                     cmnRMS = cmnRMStec;
00259                   }
00260                   cmnRMS *= theElectronPerADC;
00261           theSiNoiseAdder->addCMNoise(detAmpl, cmnRMS, badChannels);
00262                 }
00263                 
00264                         
00265                 //Adding the pedestals
00266                 //------------------------------------------------------
00267                 
00268                 std::vector<float> vPeds;
00269                 vPeds.clear();
00270                 vPeds.insert(vPeds.begin(),numStrips,0.);
00271                 
00272                 if(RealPedestals){
00273                     for(int strip=0; strip< numStrips; ++strip){
00274                            if(!badChannels[strip]) vPeds[strip] = (pedestalHandle->getPed(strip,detPedestalRange)+pedOffset)* theElectronPerADC;
00275                     }
00276         } else {
00277                     for(int strip=0; strip< numStrips; ++strip){
00278                           if(!badChannels[strip]) vPeds[strip] = pedOffset* theElectronPerADC;
00279                         }
00280                 }
00281                 
00282                 theSiNoiseAdder->addPedestals(detAmpl, vPeds);  
00283                 
00284                  
00285         //if(!RealPedestals&&!CommonModeNoise&&!noise&&!BaselineShift&&!APVSaturationFromHIP){
00286     //  edm::LogWarning("DigiSimLinkAlgorithm")<<"You are running the digitizer without Noise generation and without applying Zero Suppression. ARE YOU SURE???";
00287     //}else{                                                     
00288     
00289         rawdigis.clear();
00290     rawdigis = theSiDigitalConverter->convertRaw(detAmpl, gainHandle, detID);
00291     push_link_raw(rawdigis, theLink, theCounterLink, detAmpl,detID);
00292     outrawdigi.data = rawdigis;
00293         
00294         //}
00295   }
00296 }
00297 
00298 void DigiSimLinkAlgorithm::push_link(const DigitalVecType &digis,
00299                                           const HitToDigisMapType& htd,
00300                                           const HitCounterToDigisMapType& hctd,
00301                                           const std::vector<double>& afterNoise,
00302                                           unsigned int detID) {
00303   link_coll.clear();  
00304   for ( DigitalVecType::const_iterator i=digis.begin(); i!=digis.end(); i++) {
00305     // Instead of checking the validity of the links against the digis,
00306     //  let's loop over digis and push the corresponding link
00307     HitToDigisMapType::const_iterator mi(htd.find(i->strip()));  
00308     if (mi == htd.end()) continue;
00309     HitCounterToDigisMapType::const_iterator cmi(hctd.find(i->strip()));  
00310     std::map<const PSimHit *, Amplitude> totalAmplitudePerSimHit;
00311     for (std::vector < std::pair < const PSimHit*, Amplitude > >::const_iterator simul = 
00312            (*mi).second.begin() ; simul != (*mi).second.end(); simul ++){
00313       totalAmplitudePerSimHit[(*simul).first] += (*simul).second;
00314     }
00315     
00316     //--- include the noise as well
00317     double totalAmplitude1 = afterNoise[(*mi).first];
00318     
00319     //--- digisimlink
00320     int sim_counter=0;
00321     for (std::map<const PSimHit *, Amplitude>::const_iterator iter = totalAmplitudePerSimHit.begin(); 
00322          iter != totalAmplitudePerSimHit.end(); iter++){
00323       float threshold = 0.;
00324       float fraction = (*iter).second/totalAmplitude1;
00325       if (fraction >= threshold) {
00326         // Noise fluctuation could make fraction>1. Unphysical, set it by hand = 1.
00327         if(fraction > 1.) fraction = 1.;
00328         for (std::vector<std::pair<const PSimHit*, int > >::const_iterator
00329                simcount = (*cmi).second.begin() ; simcount != (*cmi).second.end(); ++simcount){
00330           if((*iter).first == (*simcount).first) sim_counter = (*simcount).second;
00331         }
00332         link_coll.push_back(StripDigiSimLink( (*mi).first, //channel
00333                                               ((*iter).first)->trackId(), //simhit trackId
00334                                               sim_counter, //simhit counter
00335                                               ((*iter).first)->eventId(), //simhit eventId
00336                                               fraction)); //fraction 
00337       }
00338     }
00339   }
00340 }
00341 
00342 void DigiSimLinkAlgorithm::push_link_raw(const DigitalRawVecType &digis,
00343                                               const HitToDigisMapType& htd,
00344                                               const HitCounterToDigisMapType& hctd,
00345                                               const std::vector<double>& afterNoise,
00346                                               unsigned int detID) {
00347   link_coll.clear();  
00348   int nstrip = -1;
00349   for ( DigitalRawVecType::const_iterator i=digis.begin(); i!=digis.end(); i++) {
00350     nstrip++;
00351     // Instead of checking the validity of the links against the digis,
00352     //  let's loop over digis and push the corresponding link
00353     HitToDigisMapType::const_iterator mi(htd.find(nstrip));  
00354     HitCounterToDigisMapType::const_iterator cmi(hctd.find(nstrip));  
00355     if (mi == htd.end()) continue;
00356     std::map<const PSimHit *, Amplitude> totalAmplitudePerSimHit;
00357     for (std::vector < std::pair < const PSimHit*, Amplitude > >::const_iterator simul = 
00358            (*mi).second.begin() ; simul != (*mi).second.end(); simul ++){
00359       totalAmplitudePerSimHit[(*simul).first] += (*simul).second;
00360     }
00361     
00362     //--- include the noise as well
00363     double totalAmplitude1 = afterNoise[(*mi).first];
00364     
00365     //--- digisimlink
00366     int sim_counter_raw=0;
00367     for (std::map<const PSimHit *, Amplitude>::const_iterator iter = totalAmplitudePerSimHit.begin(); 
00368          iter != totalAmplitudePerSimHit.end(); iter++){
00369       float threshold = 0.;
00370       float fraction = (*iter).second/totalAmplitude1;
00371       if (fraction >= threshold) {
00372         //Noise fluctuation could make fraction>1. Unphysical, set it by hand.
00373         if(fraction >1.) fraction = 1.;
00374         //add counter information
00375         for (std::vector<std::pair<const PSimHit*, int > >::const_iterator
00376                simcount = (*cmi).second.begin() ; simcount != (*cmi).second.end(); ++simcount){
00377           if((*iter).first == (*simcount).first) sim_counter_raw = (*simcount).second;
00378         }
00379         link_coll.push_back(StripDigiSimLink( (*mi).first, //channel
00380                                               ((*iter).first)->trackId(), //simhit trackId
00381                                               sim_counter_raw, //simhit counter
00382                                               ((*iter).first)->eventId(), //simhit eventId
00383                                               fraction)); //fraction
00384       }
00385     }
00386   }
00387 }