CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/SimTracker/SiStripDigitizer/plugins/SiStripDigitizerAlgorithm.cc

Go to the documentation of this file.
00001 // File: SiStripDigitizerAlgorithm.cc
00002 // Description:  Steering class for digitization.
00003 
00004 // Modified 15/May/2013 mark.grimes@bristol.ac.uk - Modified so that the digi-sim link has the correct
00005 // index for the sim hits stored. It was previously always set to zero (I won't mention that it was
00006 // me who originally wrote that).
00007 
00008 #include <vector>
00009 #include <algorithm>
00010 #include <iostream>
00011 #include "FWCore/Framework/interface/EventSetup.h"
00012 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00013 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00014 #include "SiStripDigitizerAlgorithm.h"
00015 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
00016 #include "SimDataFormats/TrackerDigiSimLink/interface/StripDigiSimLink.h"
00017 #include "DataFormats/Common/interface/DetSetVector.h"
00018 #include "DataFormats/GeometrySurface/interface/BoundSurface.h"
00019 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
00020 #include "CalibTracker/Records/interface/SiStripDependentRecords.h"
00021 #include "CondFormats/SiStripObjects/interface/SiStripLorentzAngle.h"
00022 #include "CondFormats/DataRecord/interface/SiStripCondDataRecords.h"
00023 #include "CondFormats/SiStripObjects/interface/SiStripNoises.h"
00024 #include "CondFormats/SiStripObjects/interface/SiStripThreshold.h"
00025 #include "CondFormats/SiStripObjects/interface/SiStripPedestals.h"
00026 #include "CondFormats/SiStripObjects/interface/SiStripBadStrip.h"
00027 #include "CLHEP/Random/RandFlat.h"
00028 
00029 SiStripDigitizerAlgorithm::SiStripDigitizerAlgorithm(const edm::ParameterSet& conf, CLHEP::HepRandomEngine& eng):
00030   lorentzAngleName(conf.getParameter<std::string>("LorentzAngle")),
00031   theThreshold(conf.getParameter<double>("NoiseSigmaThreshold")),
00032   cmnRMStib(conf.getParameter<double>("cmnRMStib")),
00033   cmnRMStob(conf.getParameter<double>("cmnRMStob")),
00034   cmnRMStid(conf.getParameter<double>("cmnRMStid")),
00035   cmnRMStec(conf.getParameter<double>("cmnRMStec")),
00036   APVSaturationProb(conf.getParameter<double>("APVSaturationProb")),
00037   makeDigiSimLinks_(conf.getUntrackedParameter<bool>("makeDigiSimLinks", false)),
00038   peakMode(conf.getParameter<bool>("APVpeakmode")),
00039   noise(conf.getParameter<bool>("Noise")),
00040   RealPedestals(conf.getParameter<bool>("RealPedestals")), 
00041   SingleStripNoise(conf.getParameter<bool>("SingleStripNoise")),
00042   CommonModeNoise(conf.getParameter<bool>("CommonModeNoise")),
00043   BaselineShift(conf.getParameter<bool>("BaselineShift")),
00044   APVSaturationFromHIP(conf.getParameter<bool>("APVSaturationFromHIP")),
00045   theFedAlgo(conf.getParameter<int>("FedAlgorithm")),
00046   zeroSuppression(conf.getParameter<bool>("ZeroSuppression")),
00047   theElectronPerADC(conf.getParameter<double>( peakMode ? "electronPerAdcPeak" : "electronPerAdcDec" )),
00048   theTOFCutForPeak(conf.getParameter<double>("TOFCutForPeak")),
00049   theTOFCutForDeconvolution(conf.getParameter<double>("TOFCutForDeconvolution")),
00050   tofCut(peakMode ? theTOFCutForPeak : theTOFCutForDeconvolution),
00051   cosmicShift(conf.getUntrackedParameter<double>("CosmicDelayShift")),
00052   inefficiency(conf.getParameter<double>("Inefficiency")),
00053   pedOffset((unsigned int)conf.getParameter<double>("PedestalsOffset")),
00054   theSiHitDigitizer(new SiHitDigitizer(conf, eng)),
00055   theSiPileUpSignals(new SiPileUpSignals()),
00056   theSiNoiseAdder(new SiGaussianTailNoiseAdder(theThreshold, eng)),
00057   theSiDigitalConverter(new SiTrivialDigitalConverter(theElectronPerADC)),
00058   theSiZeroSuppress(new SiStripFedZeroSuppression(theFedAlgo)),
00059   theFlatDistribution(new CLHEP::RandFlat(eng, 0., 1.)) {
00060 
00061   if (peakMode) {
00062     LogDebug("StripDigiInfo")<<"APVs running in peak mode (poor time resolution)";
00063   } else {
00064     LogDebug("StripDigiInfo")<<"APVs running in deconvolution mode (good time resolution)";
00065   };
00066 }
00067 
00068 SiStripDigitizerAlgorithm::~SiStripDigitizerAlgorithm(){
00069 }
00070 
00071 void
00072 SiStripDigitizerAlgorithm::initializeDetUnit(StripGeomDetUnit* det, const edm::EventSetup& iSetup) {
00073   edm::ESHandle<SiStripBadStrip> deadChannelHandle;
00074   iSetup.get<SiStripBadChannelRcd>().get(deadChannelHandle);
00075 
00076   unsigned int detId = det->geographicalId().rawId();
00077   int numStrips = (det->specificTopology()).nstrips();  
00078 
00079   SiStripBadStrip::Range detBadStripRange = deadChannelHandle->getRange(detId);
00080   //storing the bad strip of the the module. the module is not removed but just signal put to 0
00081   std::vector<bool>& badChannels = allBadChannels[detId];
00082   badChannels.clear();
00083   badChannels.insert(badChannels.begin(), numStrips, false);
00084   for(SiStripBadStrip::ContainerIterator it = detBadStripRange.first; it != detBadStripRange.second; ++it) {
00085     SiStripBadStrip::data fs = deadChannelHandle->decode(*it);
00086     for(int strip = fs.firstStrip; strip < fs.firstStrip + fs.range; ++strip) badChannels[strip] = true;
00087   }
00088   firstChannelsWithSignal[detId] = numStrips;
00089   lastChannelsWithSignal[detId]= 0;
00090 }
00091 
00092 void
00093 SiStripDigitizerAlgorithm::initializeEvent(const edm::EventSetup& iSetup) {
00094   theSiPileUpSignals->reset();
00095   // This should be clear by after all calls to digitize(), but I might as well make sure
00096   associationInfoForDetId_.clear();
00097 
00098   //get gain noise pedestal lorentzAngle from ES handle
00099   edm::ESHandle<ParticleDataTable> pdt;
00100   iSetup.getData(pdt);
00101   setParticleDataTable(&*pdt);
00102   iSetup.get<SiStripLorentzAngleSimRcd>().get(lorentzAngleName,lorentzAngleHandle);
00103 }
00104 
00105 //  Run the algorithm for a given module
00106 //  ------------------------------------
00107 
00108 void
00109 SiStripDigitizerAlgorithm::accumulateSimHits(std::vector<PSimHit>::const_iterator inputBegin,
00110                                              std::vector<PSimHit>::const_iterator inputEnd,
00111                                              size_t inputBeginGlobalIndex,
00112                                              const StripGeomDetUnit* det,
00113                                              const GlobalVector& bfield,
00114                                              const TrackerTopology *tTopo) {
00115   // produce SignalPoints for all SimHits in detector
00116   unsigned int detID = det->geographicalId().rawId();
00117   int numStrips = (det->specificTopology()).nstrips();  
00118 
00119   std::vector<bool>& badChannels = allBadChannels[detID];
00120   size_t thisFirstChannelWithSignal = numStrips;
00121   size_t thisLastChannelWithSignal = numStrips;
00122 
00123   float langle = (lorentzAngleHandle.isValid()) ? lorentzAngleHandle->getLorentzAngle(detID) : 0.;
00124 
00125   std::vector<float> locAmpl(numStrips, 0.);
00126 
00127   // Loop over hits
00128 
00129   uint32_t detId = det->geographicalId().rawId();
00130   // First: loop on the SimHits
00131   if(theFlatDistribution->fire()>inefficiency) {
00132     AssociationInfoForChannel* pDetIDAssociationInfo; // I only need this if makeDigiSimLinks_ is true...
00133     if( makeDigiSimLinks_ ) pDetIDAssociationInfo=&(associationInfoForDetId_[detId]); // ...so only search the map if that is the case
00134     std::vector<float> previousLocalAmplitude; // Only used if makeDigiSimLinks_ is true. Needed to work out the change in amplitude.
00135 
00136     size_t simHitGlobalIndex=inputBeginGlobalIndex; // This needs to stored to create the digi-sim link later
00137     for (std::vector<PSimHit>::const_iterator simHitIter = inputBegin; simHitIter != inputEnd; ++simHitIter, ++simHitGlobalIndex ) {
00138       // skip hits not in this detector.
00139       if((*simHitIter).detUnitId() != detId) {
00140         continue;
00141       }
00142       // check TOF
00143       if (std::fabs(simHitIter->tof() - cosmicShift - det->surface().toGlobal(simHitIter->localPosition()).mag()/30.) < tofCut && simHitIter->energyLoss()>0) {
00144         if( makeDigiSimLinks_ ) previousLocalAmplitude=locAmpl; // Not needed except to make the sim link association.
00145         size_t localFirstChannel = numStrips;
00146         size_t localLastChannel  = 0;
00147         // process the hit
00148         theSiHitDigitizer->processHit(&*simHitIter, *det, bfield, langle, locAmpl, localFirstChannel, localLastChannel, tTopo);
00149           
00150                   //APV Killer to simulate HIP effect
00151                   //------------------------------------------------------
00152                   
00153                   if(APVSaturationFromHIP&&!zeroSuppression){
00154                     int pdg_id = simHitIter->particleType();
00155                         particle = pdt->particle(pdg_id);
00156                         if(particle != NULL){
00157                                 float charge = particle->charge();
00158                                 bool isHadron = particle->isHadron();
00159                             if(charge!=0 && isHadron){
00160                                         if(theFlatDistribution->fire()<APVSaturationProb){
00161                                                 int FirstAPV = localFirstChannel/128;
00162                                                 int LastAPV = localLastChannel/128;
00163                                                 std::cout << "-------------------HIP--------------" << std::endl;
00164                                                 std::cout << "Killing APVs " << FirstAPV << " - " <<LastAPV << " " << detID <<std::endl;
00165                                                 for(int strip = FirstAPV*128; strip < LastAPV*128 +128; ++strip) {
00166                                                         badChannels[strip] = true;
00167                                                 }
00168                                                 //doing like that I remove the signal information only after the 
00169                                                 //stip that got the HIP but it remains the signal of the previous
00170                                                 //one. I'll make a further loop to remove all signal
00171                                         }
00172                                 }
00173                         }
00174               }             
00175                 
00176     
00177         if(thisFirstChannelWithSignal > localFirstChannel) thisFirstChannelWithSignal = localFirstChannel;
00178         if(thisLastChannelWithSignal < localLastChannel) thisLastChannelWithSignal = localLastChannel;
00179 
00180         if( makeDigiSimLinks_ ) { // No need to do any of this if truth association was turned off in the configuration
00181           for( size_t stripIndex=0; stripIndex<locAmpl.size(); ++stripIndex ) {
00182             // Work out the amplitude from this SimHit from the difference of what it was before and what it is now
00183             float signalFromThisSimHit=locAmpl[stripIndex]-previousLocalAmplitude[stripIndex];
00184             if( signalFromThisSimHit!=0 ) { // If this SimHit had any contribution I need to record it.
00185               auto& associationVector=(*pDetIDAssociationInfo)[stripIndex];
00186               bool addNewEntry=true;
00187               // Make sure the hit isn't in already. I've seen this a few times, it always seems to happen in pairs so I think
00188               // it's something to do with the stereo strips.
00189               for( auto& associationInfo : associationVector ) {
00190                 if( associationInfo.trackID==simHitIter->trackId() && associationInfo.eventID==simHitIter->eventId() ) {
00191                   // The hit is already in, so add this second contribution and move on
00192                   associationInfo.contributionToADC+=signalFromThisSimHit;
00193                   addNewEntry=false;
00194                   break;
00195                 }
00196               } // end of loop over associationVector
00197               // If the hit wasn't already in create a new association info structure.
00198               if( addNewEntry ) associationVector.push_back( AssociationInfo{ simHitIter->trackId(), simHitIter->eventId(), signalFromThisSimHit, simHitGlobalIndex } );
00199             } // end of "if( signalFromThisSimHit!=0 )"
00200           } // end of loop over locAmpl strips
00201         } // end of "if( makeDigiSimLinks_ )"
00202       } // end of TOF check
00203     } // end for
00204   }
00205   theSiPileUpSignals->add(detID, locAmpl, thisFirstChannelWithSignal, thisLastChannelWithSignal);
00206 
00207   if(firstChannelsWithSignal[detID] > thisFirstChannelWithSignal) firstChannelsWithSignal[detID] = thisFirstChannelWithSignal;
00208   if(lastChannelsWithSignal[detID] < thisLastChannelWithSignal) lastChannelsWithSignal[detID] = thisLastChannelWithSignal;
00209 }
00210 
00211 void
00212 SiStripDigitizerAlgorithm::digitize(
00213                            edm::DetSet<SiStripDigi>& outdigi,
00214                            edm::DetSet<SiStripRawDigi>& outrawdigi,
00215                            edm::DetSet<StripDigiSimLink>& outLink,
00216                            const StripGeomDetUnit *det,
00217                            edm::ESHandle<SiStripGain> & gainHandle,
00218                            edm::ESHandle<SiStripThreshold> & thresholdHandle,
00219                            edm::ESHandle<SiStripNoises> & noiseHandle,
00220                            edm::ESHandle<SiStripPedestals> & pedestalHandle) {
00221   unsigned int detID = det->geographicalId().rawId();
00222   int numStrips = (det->specificTopology()).nstrips();  
00223 
00224   const SiPileUpSignals::SignalMapType* theSignal(theSiPileUpSignals->getSignal(detID));  
00225 
00226   std::vector<float> detAmpl(numStrips, 0.);
00227   if(theSignal) {
00228     for(const auto& amp : *theSignal) {
00229       detAmpl[amp.first] = amp.second;
00230     }
00231   }
00232 
00233   //removing signal from the dead (and HIP effected) strips
00234   std::vector<bool>& badChannels = allBadChannels[detID];
00235   for(int strip =0; strip < numStrips; ++strip) if(badChannels[strip]) detAmpl[strip] = 0.;
00236 
00237   SiStripNoises::Range detNoiseRange = noiseHandle->getRange(detID);
00238   SiStripApvGain::Range detGainRange = gainHandle->getRange(detID);
00239   SiStripPedestals::Range detPedestalRange = pedestalHandle->getRange(detID);
00240 
00241 // -----------------------------------------------------------
00242 
00243   auto& firstChannelWithSignal = firstChannelsWithSignal[detID];
00244   auto& lastChannelWithSignal = lastChannelsWithSignal[detID];
00245   auto iAssociationInfoByChannel=associationInfoForDetId_.find(detID); // Use an iterator so that I can easily remove it once finished
00246 
00247   if(zeroSuppression){
00248     if(noise){
00249           int RefStrip = int(numStrips/2.);
00250           while(RefStrip<numStrips&&badChannels[RefStrip]){ //if the refstrip is bad, I move up to when I don't find it
00251                 RefStrip++;
00252           }
00253           if(RefStrip<numStrips){
00254                 float noiseRMS = noiseHandle->getNoise(RefStrip,detNoiseRange);
00255                 float gainValue = gainHandle->getStripGain(RefStrip, detGainRange);
00256                 theSiNoiseAdder->addNoise(detAmpl,firstChannelWithSignal,lastChannelWithSignal,numStrips,noiseRMS*theElectronPerADC/gainValue);
00257           }
00258         }
00259     DigitalVecType digis;
00260     theSiZeroSuppress->suppress(theSiDigitalConverter->convert(detAmpl, gainHandle, detID), digis, detID,noiseHandle,thresholdHandle);
00261     // Now do the association to truth. Note that if truth association was turned off in the configuration this map
00262     // will be empty and the iterator will always equal associationInfoForDetId_.end().
00263     if( iAssociationInfoByChannel!=associationInfoForDetId_.end() ) { // make sure the readings for this DetID aren't completely from noise
00264       for( const auto& iDigi : digis ) {
00265         auto& associationInfoByChannel=iAssociationInfoByChannel->second;
00266         const std::vector<AssociationInfo>& associationInfo=associationInfoByChannel[iDigi.channel()];
00267 
00268         // Need to find the total from all sim hits, because this might not be the same as the total
00269         // digitised due to noise or whatever.
00270         float totalSimADC=0;
00271         for( const auto& iAssociationInfo : associationInfo ) totalSimADC+=iAssociationInfo.contributionToADC;
00272         // Now I know that I can loop again and create the links
00273         for( const auto& iAssociationInfo : associationInfo ) {
00274           // Note simHitGlobalIndex has +1 because TrackerHitAssociator (the only place I can find this value being used)
00275           // expects counting to start at 1, not 0.
00276           outLink.push_back( StripDigiSimLink( iDigi.channel(), iAssociationInfo.trackID, iAssociationInfo.simHitGlobalIndex+1, iAssociationInfo.eventID, iAssociationInfo.contributionToADC/totalSimADC ) );
00277         } // end of loop over associationInfo
00278       } // end of loop over the digis
00279     } // end of check that iAssociationInfoByChannel is a valid iterator
00280     outdigi.data = digis;
00281   }
00282   
00283   
00284   if(!zeroSuppression){
00285     //if(noise){
00286       // the constant pedestal offset is needed because
00287       //   negative adc counts are not allowed in case
00288       //   Pedestal and CMN subtraction is performed.
00289       //   The pedestal value read from the conditions
00290       //   is pedValue and after the pedestal subtraction
00291       //   the baseline is zero. The Common Mode Noise
00292       //   is not subtracted from the negative adc counts
00293       //   channels. Adding pedOffset the baseline is set
00294       //   to pedOffset after pedestal subtraction and CMN
00295       //   is subtracted to all the channels since none of
00296       //   them has negative adc value. The pedOffset is
00297       //   treated as a constant component in the CMN
00298       //   estimation and subtracted as CMN.
00299       
00300          
00301                 //calculating the charge deposited on each APV and subtracting the shift
00302                 //------------------------------------------------------
00303                 if(BaselineShift){
00304                    theSiNoiseAdder->addBaselineShift(detAmpl, badChannels);
00305                 }
00306                 
00307                 //Adding the strip noise
00308                 //------------------------------------------------------                                                 
00309                 if(noise){
00310                     std::vector<float> noiseRMSv;
00311                         noiseRMSv.clear();
00312                     noiseRMSv.insert(noiseRMSv.begin(),numStrips,0.);
00313                         
00314                     if(SingleStripNoise){
00315                             for(int strip=0; strip< numStrips; ++strip){
00316                                         if(!badChannels[strip]) noiseRMSv[strip] = (noiseHandle->getNoise(strip,detNoiseRange))* theElectronPerADC;
00317                                 }
00318                         
00319                 } else {
00320                             int RefStrip = 0; //int(numStrips/2.);
00321                             while(RefStrip<numStrips&&badChannels[RefStrip]){ //if the refstrip is bad, I move up to when I don't find it
00322                                         RefStrip++;
00323                                 }
00324                                 if(RefStrip<numStrips){
00325                                         float noiseRMS = noiseHandle->getNoise(RefStrip,detNoiseRange) *theElectronPerADC;
00326                                         for(int strip=0; strip< numStrips; ++strip){
00327                                         if(!badChannels[strip]) noiseRMSv[strip] = noiseRMS;
00328                                         }
00329                                 }
00330                         }
00331                         
00332                         theSiNoiseAdder->addNoiseVR(detAmpl, noiseRMSv);
00333                 }                       
00334                 
00335                 //adding the CMN
00336                 //------------------------------------------------------
00337         if(CommonModeNoise){
00338                   float cmnRMS = 0.;
00339                   DetId  detId(detID);
00340                   uint32_t SubDet = detId.subdetId();
00341                   if(SubDet==3){
00342                     cmnRMS = cmnRMStib;
00343                   }else if(SubDet==4){
00344                     cmnRMS = cmnRMStid;
00345                   }else if(SubDet==5){
00346                     cmnRMS = cmnRMStob;
00347                   }else if(SubDet==6){
00348                     cmnRMS = cmnRMStec;
00349                   }
00350                   cmnRMS *= theElectronPerADC;
00351           theSiNoiseAdder->addCMNoise(detAmpl, cmnRMS, badChannels);
00352                 }
00353                 
00354                         
00355                 //Adding the pedestals
00356                 //------------------------------------------------------
00357                 
00358                 std::vector<float> vPeds;
00359                 vPeds.clear();
00360                 vPeds.insert(vPeds.begin(),numStrips,0.);
00361                 
00362                 if(RealPedestals){
00363                     for(int strip=0; strip< numStrips; ++strip){
00364                            if(!badChannels[strip]) vPeds[strip] = (pedestalHandle->getPed(strip,detPedestalRange)+pedOffset)* theElectronPerADC;
00365                     }
00366         } else {
00367                     for(int strip=0; strip< numStrips; ++strip){
00368                           if(!badChannels[strip]) vPeds[strip] = pedOffset* theElectronPerADC;
00369                         }
00370                 }
00371                 
00372                 theSiNoiseAdder->addPedestals(detAmpl, vPeds);  
00373                 
00374                  
00375         //if(!RealPedestals&&!CommonModeNoise&&!noise&&!BaselineShift&&!APVSaturationFromHIP){
00376     //  edm::LogWarning("SiStripDigitizer")<<"You are running the digitizer without Noise generation and without applying Zero Suppression. ARE YOU SURE???";
00377     //}else{                                                     
00378     
00379     DigitalRawVecType rawdigis = theSiDigitalConverter->convertRaw(detAmpl, gainHandle, detID);
00380 
00381     // Now do the association to truth. Note that if truth association was turned off in the configuration this map
00382     // will be empty and the iterator will always equal associationInfoForDetId_.end().
00383     if( iAssociationInfoByChannel!=associationInfoForDetId_.end() ) { // make sure the readings for this DetID aren't completely from noise
00384       // N.B. For the raw digis the channel is inferred from the position in the vector.
00385       // I'VE NOT TESTED THIS YET!!!!!
00386       // ToDo Test this properly.
00387       for( size_t channel=0; channel<rawdigis.size(); ++channel ) {
00388         auto& associationInfoByChannel=iAssociationInfoByChannel->second;
00389         const auto iAssociationInfo=associationInfoByChannel.find(channel);
00390         if( iAssociationInfo==associationInfoByChannel.end() ) continue; // Skip if there is no sim information for this channel (i.e. it's all noise)
00391         const std::vector<AssociationInfo>& associationInfo=iAssociationInfo->second;
00392 
00393         // Need to find the total from all sim hits, because this might not be the same as the total
00394         // digitised due to noise or whatever.
00395         float totalSimADC=0;
00396         for( const auto& iAssociationInfo : associationInfo ) totalSimADC+=iAssociationInfo.contributionToADC;
00397         // Now I know that I can loop again and create the links
00398         for( const auto& iAssociationInfo : associationInfo ) {
00399           // Note simHitGlobalIndex has +1 because TrackerHitAssociator (the only place I can find this value being used)
00400           // expects counting to start at 1, not 0.
00401           outLink.push_back( StripDigiSimLink( channel, iAssociationInfo.trackID, iAssociationInfo.simHitGlobalIndex+1, iAssociationInfo.eventID, iAssociationInfo.contributionToADC/totalSimADC ) );
00402         } // end of loop over associationInfo
00403       } // end of loop over the digis
00404     } // end of check that iAssociationInfoByChannel is a valid iterator
00405 
00406     outrawdigi.data = rawdigis;
00407         
00408         //}
00409   }
00410 
00411   // Now that I've finished with this entry in the map of associations, I can remove it.
00412   // Note that there might not be an association if the ADC reading is from noise in which
00413   // case associationIsValid will be false.
00414   if( iAssociationInfoByChannel!=associationInfoForDetId_.end() ) associationInfoForDetId_.erase(iAssociationInfoByChannel);
00415 }