CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/src/SimMuon/CSCDigitizer/src/CSCStripElectronicsSim.cc

Go to the documentation of this file.
00001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00002 #include "SimMuon/CSCDigitizer/src/CSCStripElectronicsSim.h"
00003 #include "SimMuon/CSCDigitizer/src/CSCAnalogSignal.h"
00004 #include "SimMuon/CSCDigitizer/src/CSCCrosstalkGenerator.h"
00005 #include "SimMuon/CSCDigitizer/src/CSCStripConditions.h"
00006 #include "DataFormats/CSCDigi/interface/CSCComparatorDigi.h"
00007 #include "DataFormats/CSCDigi/interface/CSCStripDigi.h"
00008 #include "Geometry/CSCGeometry/interface/CSCLayer.h"
00009 #include "Geometry/CSCGeometry/interface/CSCChamberSpecs.h"
00010 #include "Geometry/CSCGeometry/interface/CSCLayerGeometry.h"
00011 #include "SimMuon/CSCDigitizer/src/CSCDetectorHit.h"
00012 #include "CLHEP/Units/GlobalPhysicalConstants.h"
00013 #include "CLHEP/Units/GlobalSystemOfUnits.h"  
00014 #include "boost/bind.hpp"  
00015 #include <list>
00016 #include <cassert>
00017 
00018 // This is CSCStripElectronicsSim.cc
00019 
00020 CSCStripElectronicsSim::CSCStripElectronicsSim(const edm::ParameterSet & p)
00021 : CSCBaseElectronicsSim(p),
00022   theAmpResponse(theShapingTime, CSCStripAmpResponse::RADICAL),
00023   theComparatorThreshold(20.),
00024   theComparatorNoise(0.),
00025   theComparatorRMSOffset(2.),
00026   theComparatorSaturation(1057.),
00027   theComparatorWait(50.),
00028   theComparatorDeadTime(100.),
00029   theDaqDeadTime(200.),
00030   theTimingOffset(0.),
00031   nScaBins_(p.getParameter<int>("nScaBins")),
00032   doSuppression_(p.getParameter<bool>("doSuppression")),
00033   doCrosstalk_(p.getParameter<bool>("doCrosstalk")),
00034   theStripConditions(0),
00035   theCrosstalkGenerator(0),
00036   theComparatorClockJump(2),
00037   sca_time_bin_size(50.),
00038   sca_peak_bin(p.getParameter<int>("scaPeakBin")),
00039   theComparatorTimeBinOffset(p.getParameter<double>("comparatorTimeBinOffset")),
00040   theComparatorTimeOffset(p.getParameter<double>("comparatorTimeOffset")),
00041   theComparatorSamplingTime(p.getParameter<double>("comparatorSamplingTime")),
00042   theSCATimingOffsets(p.getParameter<std::vector<double> >("scaTimingOffsets"))
00043 {
00044 
00045   if(doCrosstalk_) {
00046     theCrosstalkGenerator = new CSCCrosstalkGenerator();
00047   }
00048 
00049   fillAmpResponse();
00050 }
00051 
00052 
00053 CSCStripElectronicsSim::~CSCStripElectronicsSim() {
00054   if(doCrosstalk_) {
00055     delete theCrosstalkGenerator;
00056   }
00057 }
00058 
00059 void CSCStripElectronicsSim::initParameters() {
00060   nElements = theLayerGeometry->numberOfStrips();
00061   theComparatorThreshold = 20.;
00062   //selfTest();
00063 
00064   //calculate the offset to the peak
00065   float averageDistance = theLayer->surface().position().mag();
00066   theAverageTimeOfFlight = averageDistance * cm / c_light; // Units of c_light: mm/ns
00067   int chamberType = theSpecs->chamberType();
00068   theTimingOffset = theShapingTime + theAverageTimeOfFlight
00069          + theBunchTimingOffsets[chamberType];
00070 //TODO make sure config gets overridden
00071   theSignalStartTime = theTimingOffset
00072                      - (sca_peak_bin-1) * sca_time_bin_size;
00073   theSignalStopTime = theSignalStartTime + nScaBins_*sca_time_bin_size;
00074   theNumberOfSamples = nScaBins_*static_cast<int>(sca_time_bin_size/theSamplingTime);
00075 
00076 }  
00077 
00078 
00079 int CSCStripElectronicsSim::readoutElement(int strip) const {
00080   return theLayerGeometry->channel(strip);
00081 }
00082 
00083 
00084 float CSCStripElectronicsSim::calculateAmpResponse(float t) const
00085 {
00086   return theAmpResponse.calculateAmpResponse(t);
00087 }
00088 
00089 
00090 CSCAnalogSignal CSCStripElectronicsSim::makeNoiseSignal(int element) {
00091   std::vector<float> noiseBins(nScaBins_);
00092   CSCAnalogSignal tmpSignal(element, sca_time_bin_size, noiseBins);
00093   if(doNoise_) {
00094     theStripConditions->noisify(layerId(), tmpSignal);
00095   }
00096   // now rebin it
00097   std::vector<float> binValues(theNumberOfSamples);
00098   for(int ibin=0; ibin < theNumberOfSamples; ++ibin) {
00099      binValues[ibin] = tmpSignal.getValue(ibin*theSamplingTime);
00100   }
00101   CSCAnalogSignal finalSignal(element, theSamplingTime, binValues, 0., theSignalStartTime);
00102   return finalSignal;
00103 }
00104 
00105 
00106 float CSCStripElectronicsSim::comparatorReading(const CSCAnalogSignal & signal,
00107                                                   float time) const {
00108    return std::min(signal.getValue(time), theComparatorSaturation)
00109        +  theComparatorRMSOffset* theRandGaussQ->fire();  
00110 }
00111 
00112 
00113 void
00114 CSCStripElectronicsSim::runComparator(std::vector<CSCComparatorDigi> & result) {
00115   // first, make a list of all the comparators we actually
00116   // need to run
00117   std::list<int> comparatorsWithSignal;
00118   CSCSignalMap::iterator signalMapItr;
00119   for(signalMapItr = theSignalMap.begin();
00120       signalMapItr != theSignalMap.end(); ++signalMapItr) {
00121     // Elements in signal map count from 1
00122     // 1,2->0,  3,4->1,  5,6->2, ...
00123         comparatorsWithSignal.push_back( ((*signalMapItr).first-1)/2 );
00124   }
00125   // no need to sort
00126   comparatorsWithSignal.unique();
00127   for(std::list<int>::iterator listItr = comparatorsWithSignal.begin();
00128       listItr != comparatorsWithSignal.end(); ++listItr) {
00129     int iComparator = *listItr;
00130     // find signal1 and signal2
00131     // iComparator counts from 0
00132     // icomp =0->1,2,  =1->3,4,  =2->5,6, ...
00133     const CSCAnalogSignal & signal1 = find(readoutElement(iComparator*2 + 1));
00134     const CSCAnalogSignal & signal2 = find(readoutElement(iComparator*2 + 2));
00135     for(float time = theSignalStartTime +theComparatorTimeOffset; 
00136         time < theSignalStopTime-theComparatorWait; 
00137         time += theComparatorSamplingTime) 
00138     {
00139       if(comparatorReading(signal1, time) > theComparatorThreshold
00140       || comparatorReading(signal2, time) > theComparatorThreshold) {
00141          // wait a bit, so we can run the comparator at the signal peak
00142         float comparatorTime = time;
00143         time += theComparatorWait;
00144                   
00145         float height1 = comparatorReading(signal1, time);
00146         float height2 = comparatorReading(signal2, time);
00147         int output = 0; 
00148         int strip = 0;
00149          // distrip logic; comparator output is for pairs of strips:
00150          // hit  bin  dec
00151          // x--- 100   4
00152          // -x-- 101   5
00153          // --x- 110   6
00154          // ---x 111   7
00155          // just to prevent a copy
00156          const CSCAnalogSignal * mainSignal = 0;
00157          // pick the higher of the two strips in the pair
00158          if(height1 > height2) {
00159            mainSignal = &signal1;
00160            float leftStrip = 0.;
00161            if(iComparator > 0)  {
00162              leftStrip = comparatorReading(find(readoutElement(iComparator*2)), time); 
00163            }
00164            // if this strip is higher than either of its neighbors, make a comparator digi
00165            if(leftStrip < height1 && height1 > theComparatorThreshold) {
00166              output = (leftStrip < height2);
00167              strip = iComparator*2 + 1;
00168            }
00169          } else {
00170            mainSignal = &signal2;
00171            float rightStrip = 0.;
00172            if(iComparator*2+3 <= nElements) {
00173              rightStrip = comparatorReading(find(readoutElement(iComparator*2+3)), time);
00174            }
00175            if(rightStrip < height2 && height2 > theComparatorThreshold) {
00176              output = (height1 < rightStrip);
00177              strip = iComparator*2 + 2;
00178            }
00179          }
00180          if(strip != 0) {
00181 
00182            float bxFloat = (comparatorTime-theTimingOffset)/theBunchSpacing
00183                            + theComparatorTimeBinOffset + theOffsetOfBxZero;
00184 
00185 
00186       // Comparator digi as of Nov-2006 adapted to real data: time word has 16 bits with set bit
00187       // flagging appropriate bunch crossing, and bx 0 corresponding to 9th bit i.e.
00188 
00189       //      1st bit set (bit 0) <-> bx -9
00190       //      2nd              1  <-> bx -8
00191       //      ...           ...       ....
00192       //      8th              9  <-> bx  0
00193       //      9th             10  <-> bx +1
00194       //      ...           ...       ....
00195       //     16th             15  <-> bx +6
00196 
00197       // Parameter theOffsetOfBxZero = 9 @@WARNING! This offset may be changed (hardware)!
00198 
00199            int timeWord = 0; // and this will remain if too early or late
00200            if ( (bxFloat>= 0) && (bxFloat<16) ) 
00201                timeWord = (1 << static_cast<int>(bxFloat) ); // set appropriate bit
00202 
00203            CSCComparatorDigi newDigi(strip, output, timeWord);
00204            result.push_back(newDigi);
00205          }
00206 
00207          // wait for the comparator to reset
00208          time += theComparatorDeadTime;
00209          // really should be zero, but strip signal doesn't go negative yet
00210          float resetThreshold = 1;
00211          while(time < theSignalStopTime
00212             && mainSignal->getValue(time) > resetThreshold) {
00213            time += theComparatorSamplingTime;
00214          }
00215 
00216        } // if over threshold
00217     } // loop over time samples
00218   }  // loop over comparators  
00219   // sort by time
00220   sort(result.begin(), result.end());
00221 }
00222 
00223 
00224 std::list<int> 
00225 CSCStripElectronicsSim::getKeyStrips(const std::vector<CSCComparatorDigi> & comparators) const
00226 {
00227   std::list<int> result;
00228   for(std::vector<CSCComparatorDigi>::const_iterator compItr = comparators.begin();
00229       compItr != comparators.end(); ++compItr)
00230   {
00231     if(std::abs(compItr->getTimeBin()-theOffsetOfBxZero) <= 2)
00232     {
00233       result.push_back(compItr->getStrip());
00234     }
00235   }
00236   // need sort for unique to work.
00237   result.sort();
00238   result.unique();
00239   return result;
00240 }
00241 
00242 
00243 std::list<int>
00244 CSCStripElectronicsSim::getKeyStripsFromMC() const
00245 {
00246   // assumes the detector hit map is filled
00247   std::list<int> result;
00248   transform(theDetectorHitMap.begin(), theDetectorHitMap.end(), 
00249             back_inserter(result), boost::bind(&DetectorHitMap::value_type::first,_1));
00250   result.sort();
00251   result.unique();
00252   return result;
00253 }
00254 
00255 
00256 std::list<int> 
00257 CSCStripElectronicsSim::channelsToRead(const std::list<int> & keyStrips, int window) const
00258 {
00259   std::list<int> result;
00260   std::list<int>::const_iterator keyStripItr = keyStrips.begin();
00261   if(doSuppression_)
00262   {
00263     for( ; keyStripItr != keyStrips.end(); ++keyStripItr)
00264     { 
00265       // pick the five strips around the comparator
00266       for(int istrip = (*keyStripItr)-window; istrip <= (*keyStripItr)+window; ++istrip)
00267       {
00268         if(istrip>0 && istrip<= nElements)
00269         {
00270           result.push_back(readoutElement(istrip));
00271         }
00272       }
00273     }
00274     result.sort();
00275     result.unique();
00276   }
00277   else 
00278   {
00279     // read the whole CFEB, 16 strips
00280     std::list<int> cfebsToRead;
00281     for( ; keyStripItr != keyStrips.end(); ++keyStripItr)
00282     {
00283       int cfeb = (readoutElement(*keyStripItr)-1)/16;
00284       cfebsToRead.push_back(cfeb);
00285       int remainder = (readoutElement(*keyStripItr)-1)%16;
00286       // if we're within 3 strips of an edge, take neighboring CFEB, too
00287       if(remainder < window && cfeb != 0)
00288       {
00289         cfebsToRead.push_back(cfeb-1);
00290       }
00291       // the 'readouElement' makes it so that ME1/1 has just one CFEB
00292       int maxCFEBs = readoutElement(nElements)/16 - 1;
00293       if(remainder >= 16-window && cfeb != maxCFEBs)
00294       {
00295         cfebsToRead.push_back(cfeb+1);
00296       }
00297     }
00298     cfebsToRead.sort();
00299     cfebsToRead.unique();
00300 
00301     // now convert the CFEBS to strips
00302     for(std::list<int>::const_iterator cfebItr = cfebsToRead.begin();
00303         cfebItr != cfebsToRead.end(); ++cfebItr)
00304     {
00305       for(int i = 1; i <= 16; ++i)
00306       {
00307         result.push_back((*cfebItr)*16 + i);
00308       }
00309     }
00310   }
00311   return result;
00312 }
00313        
00314 
00315    
00316 
00317 bool SortSignalsByTotal(const CSCAnalogSignal & s1,
00318                         const CSCAnalogSignal & s2) {
00319   return ( s1.getTotal() > s2.getTotal() );
00320 }
00321 
00322 
00323 void CSCStripElectronicsSim::fillDigis(CSCStripDigiCollection & digis, 
00324                                        CSCComparatorDigiCollection & comparators)
00325 {
00326   if(doCrosstalk_) {
00327     addCrosstalk();
00328   } 
00329 
00330   std::vector<CSCComparatorDigi> comparatorOutputs;
00331   runComparator(comparatorOutputs);
00332   // copy these to the result
00333   if(!comparatorOutputs.empty())
00334   {
00335     CSCComparatorDigiCollection::Range range(comparatorOutputs.begin(), 
00336                                              comparatorOutputs.end());
00337     comparators.put(range, layerId());
00338   }
00339 
00340   //std::list<int> keyStrips = getKeyStrips(comparatorOutputs);
00341   std::list<int> keyStrips = getKeyStripsFromMC();
00342   fillStripDigis(keyStrips, digis);
00343 }
00344 
00345 
00346 void CSCStripElectronicsSim::fillStripDigis(const std::list<int> & keyStrips,
00347   CSCStripDigiCollection & digis)
00348 {
00349   std::list<int> stripsToDo = channelsToRead(keyStrips, 3);
00350   std::vector<CSCStripDigi> stripDigis;
00351   stripDigis.reserve(stripsToDo.size());
00352   for(std::list<int>::const_iterator stripItr = stripsToDo.begin();
00353       stripItr != stripsToDo.end(); ++stripItr)
00354   {
00355     createDigi( *stripItr, find(*stripItr), stripDigis);
00356   }
00357 
00358   CSCStripDigiCollection::Range stripRange(stripDigis.begin(), stripDigis.end());
00359   digis.put(stripRange, layerId());
00360 }
00361 
00362  
00363 void CSCStripElectronicsSim::addCrosstalk() {
00364   // this is needed so we can add a noise signal to the map
00365   // without messing up any iterators
00366   std::vector<CSCAnalogSignal> realSignals;
00367   realSignals.reserve(theSignalMap.size());
00368   CSCSignalMap::iterator mapI = theSignalMap.begin(), mapEnd = theSignalMap.end();
00369   for( ; mapI != mapEnd; ++mapI) {
00370     realSignals.push_back((*mapI).second);
00371   }
00372   sort(realSignals.begin(), realSignals.end(), SortSignalsByTotal);
00373   std::vector<CSCAnalogSignal>::iterator realSignalItr = realSignals.begin(),
00374                                          realSignalsEnd = realSignals.end();
00375   for( ; realSignalItr != realSignalsEnd;  ++realSignalItr)
00376   {
00377     int thisStrip = (*realSignalItr).getElement();
00378     // add it to each neighbor
00379     if(thisStrip > 1) {
00380       int otherStrip = thisStrip - 1;
00381       addCrosstalk(*realSignalItr, thisStrip, otherStrip);
00382     }
00383     if(thisStrip < nElements) {
00384       int otherStrip = thisStrip + 1;
00385       addCrosstalk(*realSignalItr, thisStrip, otherStrip);
00386     }
00387   }
00388 }
00389 
00390 
00391 void CSCStripElectronicsSim::addCrosstalk(const CSCAnalogSignal & signal,
00392        int thisStrip, int otherStrip)
00393 {
00394   float capacitiveCrosstalk, resistiveCrosstalk;
00395   bool leftRight = (otherStrip > thisStrip);
00396   theStripConditions->crosstalk(layerId(), thisStrip, 
00397                                 theLayerGeometry->length(), leftRight,
00398                                 capacitiveCrosstalk, resistiveCrosstalk);
00399   theCrosstalkGenerator->setParameters(capacitiveCrosstalk, 0., resistiveCrosstalk);
00400   CSCAnalogSignal crosstalkSignal( theCrosstalkGenerator->getCrosstalk(signal) );
00401   find(readoutElement(otherStrip)).superimpose(crosstalkSignal);
00402 
00403   // Now subtract the crosstalk signal from the original signal
00404   crosstalkSignal *= -1.;
00405   find(thisStrip).superimpose(crosstalkSignal);
00406 
00407 }
00408 
00409 
00410 void CSCStripElectronicsSim::createDigi(int channel, const CSCAnalogSignal & signal, std::vector<CSCStripDigi> & result)
00411 {
00412   // fill in the sca information
00413   std::vector<int> scaCounts(nScaBins_);
00414 
00415   float pedestal = theStripConditions->pedestal(layerId(), channel);
00416   float gain = theStripConditions->smearedGain(layerId(), channel);
00417   int chamberType = theSpecs->chamberType();
00418   float timeSmearing = theRandGaussQ->fire() * theTimingCalibrationError[chamberType];
00419   // undo the correction for TOF, instead, using some nominal
00420   // value from ME2/1
00421   float t0 = theSignalStartTime+theSCATimingOffsets[chamberType] + timeSmearing
00422            + 29. - theAverageTimeOfFlight;
00423   for(int scaBin = 0; scaBin < nScaBins_; ++scaBin) {
00424     float t = t0 + scaBin*sca_time_bin_size;
00425     scaCounts[scaBin] = static_cast< int >
00426       ( pedestal + signal.getValue(t) * gain );
00427   }
00428   CSCStripDigi newDigi(channel, scaCounts);
00429 
00430   // do saturation of 12-bit ADC
00431   doSaturation(newDigi);
00432 
00433   result.push_back(newDigi);
00434   addLinks(channelIndex(channel));
00435   LogTrace("CSCStripElectronicsSim") << newDigi;
00436 }
00437 
00438 
00439 void CSCStripElectronicsSim::doSaturation(CSCStripDigi & digi)
00440 {
00441   std::vector<int> scaCounts(digi.getADCCounts());
00442   for(unsigned scaBin = 0; scaBin < scaCounts.size(); ++scaBin) {
00443     scaCounts[scaBin] = std::min(scaCounts[scaBin], 4095);
00444   }
00445   digi.setADCCounts(scaCounts);
00446 }
00447 
00448 
00449 void CSCStripElectronicsSim::fillMissingLayer(const CSCLayer * layer,
00450   const CSCComparatorDigiCollection & comparators, CSCStripDigiCollection & digis)
00451 {
00452   theSignalMap.clear();
00453   setLayer(layer);
00454   CSCDetId chamberId(theLayerId.chamberId());
00455   // find all comparator key strips in this chamber
00456   std::list<int> chamberKeyStrips;
00457   for(CSCComparatorDigiCollection::DigiRangeIterator comparatorItr = comparators.begin();
00458       comparatorItr != comparators.end(); ++comparatorItr)
00459   {
00460     // could be more efficient
00461     if(CSCDetId((*comparatorItr).first).chamberId() == chamberId)
00462     {
00463       std::vector<CSCComparatorDigi> layerComparators((*comparatorItr).second.first, (*comparatorItr).second.second);
00464       std::list<int> layerKeyStrips = getKeyStrips(layerComparators);
00465       chamberKeyStrips.insert(chamberKeyStrips.end(), layerKeyStrips.begin(), layerKeyStrips.end());
00466     }
00467   }
00468   chamberKeyStrips.sort();
00469   chamberKeyStrips.unique();
00470   fillStripDigis(chamberKeyStrips, digis);
00471 }
00472     
00473 
00474 void CSCStripElectronicsSim::selfTest() const
00475 {
00476   // make sure the zero suppression algorithms work
00477   std::list<int> keyStrips, stripsRead;
00478   // 
00479   bool isGanged = (readoutElement(nElements) == 16);
00480   keyStrips.push_back(readoutElement(19));
00481   keyStrips.push_back(readoutElement(30));
00482   keyStrips.push_back(readoutElement(32)); 
00483   stripsRead = channelsToRead(keyStrips, 3);
00484   if(doSuppression_)
00485   {
00486     unsigned int expectedSize = isGanged ? 10 : 12;
00487     assert(stripsRead.size() == expectedSize);
00488     assert(stripsRead.front() == readoutElement(17));
00489   }
00490   else 
00491   {
00492     unsigned int expectedSize = isGanged ? 16 : 48;
00493     assert(stripsRead.size() == expectedSize);
00494     assert(stripsRead.front() == 1);
00495   }
00496 }
00497 
00498 
00499