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
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
00063
00064
00065 float averageDistance = theLayer->surface().position().mag();
00066 theAverageTimeOfFlight = averageDistance * cm / c_light;
00067 int chamberType = theSpecs->chamberType();
00068 theTimingOffset = theShapingTime + theAverageTimeOfFlight
00069 + theBunchTimingOffsets[chamberType];
00070
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
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
00116
00117 std::list<int> comparatorsWithSignal;
00118 CSCSignalMap::iterator signalMapItr;
00119 for(signalMapItr = theSignalMap.begin();
00120 signalMapItr != theSignalMap.end(); ++signalMapItr) {
00121
00122
00123 comparatorsWithSignal.push_back( ((*signalMapItr).first-1)/2 );
00124 }
00125
00126 comparatorsWithSignal.unique();
00127 for(std::list<int>::iterator listItr = comparatorsWithSignal.begin();
00128 listItr != comparatorsWithSignal.end(); ++listItr) {
00129 int iComparator = *listItr;
00130
00131
00132
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
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
00150
00151
00152
00153
00154
00155
00156 const CSCAnalogSignal * mainSignal = 0;
00157
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
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
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 int timeWord = 0;
00200 if ( (bxFloat>= 0) && (bxFloat<16) )
00201 timeWord = (1 << static_cast<int>(bxFloat) );
00202
00203 CSCComparatorDigi newDigi(strip, output, timeWord);
00204 result.push_back(newDigi);
00205 }
00206
00207
00208 time += theComparatorDeadTime;
00209
00210 float resetThreshold = 1;
00211 while(time < theSignalStopTime
00212 && mainSignal->getValue(time) > resetThreshold) {
00213 time += theComparatorSamplingTime;
00214 }
00215
00216 }
00217 }
00218 }
00219
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
00237 result.sort();
00238 result.unique();
00239 return result;
00240 }
00241
00242
00243 std::list<int>
00244 CSCStripElectronicsSim::getKeyStripsFromMC() const
00245 {
00246
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
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
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
00287 if(remainder < window && cfeb != 0)
00288 {
00289 cfebsToRead.push_back(cfeb-1);
00290 }
00291
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
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
00333 if(!comparatorOutputs.empty())
00334 {
00335 CSCComparatorDigiCollection::Range range(comparatorOutputs.begin(),
00336 comparatorOutputs.end());
00337 comparators.put(range, layerId());
00338 }
00339
00340
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
00365
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
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
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
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
00420
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
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
00456 std::list<int> chamberKeyStrips;
00457 for(CSCComparatorDigiCollection::DigiRangeIterator comparatorItr = comparators.begin();
00458 comparatorItr != comparators.end(); ++comparatorItr)
00459 {
00460
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
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