CMS 3D CMS Logo

CSCStripElectronicsSim.cc

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

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