00001 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00002 #include "SimMuon/CSCDigitizer/src/CSCWireElectronicsSim.h"
00003 #include "SimMuon/CSCDigitizer/src/CSCAnalogSignal.h"
00004 #include "DataFormats/CSCDigi/interface/CSCWireDigi.h"
00005 #include "Geometry/CSCGeometry/interface/CSCLayer.h"
00006 #include "Geometry/CSCGeometry/interface/CSCLayerGeometry.h"
00007 #include "Geometry/CSCGeometry/interface/CSCChamberSpecs.h"
00008 #include "CLHEP/Units/PhysicalConstants.h"
00009 #include <iostream>
00010
00011
00012 CSCWireElectronicsSim::CSCWireElectronicsSim(const edm::ParameterSet & p)
00013 : CSCBaseElectronicsSim(p),
00014 theFraction(0.5),
00015 theWireNoise(0.0),
00016 theWireThreshold(0.),
00017 theTimingCalibrationError(p.getParameter<double>("wireTimingError"))
00018 {
00019 fillAmpResponse();
00020 }
00021
00022
00023 void CSCWireElectronicsSim::initParameters() {
00024 theLayerGeometry = theLayer->geometry();
00025 nElements = theLayerGeometry->numberOfWireGroups();
00026 theWireNoise = theSpecs->wireNoise(theShapingTime)
00027 * e_SI * pow(10.0,15);
00028 theWireThreshold = theWireNoise * 8;
00029 }
00030
00031
00032 int CSCWireElectronicsSim::readoutElement(int element) const {
00033 return theLayerGeometry->wireGroup(element);
00034 }
00035
00036 void CSCWireElectronicsSim::fillDigis(CSCWireDigiCollection & digis) {
00037
00038 if(theSignalMap.empty()) {
00039 return;
00040 }
00041
00042
00043
00044 for(CSCSignalMap::iterator mapI = theSignalMap.begin(),
00045 lastSignal = theSignalMap.end();
00046 mapI != lastSignal; ++mapI)
00047 {
00048 int wireGroup = (*mapI).first;
00049 const CSCAnalogSignal & signal = (*mapI).second;
00050 LogTrace("CSCWireElectronicsSim") << "CSCWireElectronicsSim: dump of wire signal follows... "
00051 << signal;
00052 int signalSize = signal.getSize();
00053
00054 int timeWord = 0;
00055
00056
00057
00058 float threshold = theWireThreshold;
00059 if (doNoise_) {
00060 threshold += theRandGaussQ->fire() * theWireNoise;
00061 }
00062 for(int ibin = 0; ibin < signalSize; ++ibin)
00063 {
00064 if(signal.getBinValue(ibin) > threshold)
00065 {
00066
00067
00068 int lastbin = signalSize;
00069 int i;
00070 for(i = ibin; i < signalSize; ++i) {
00071 if(signal.getBinValue(i) < 0.) {
00072 lastbin = i;
00073 break;
00074 }
00075 }
00076
00077 float qMax = 0.0;
00078
00079 for ( i = ibin; i < lastbin; ++i)
00080 {
00081 float next_charge = signal.getBinValue(i);
00082 if(next_charge > qMax) {
00083 qMax = next_charge;
00084 }
00085 }
00086
00087 int bin_firing_FD = 0;
00088 for ( i = ibin; i < lastbin; ++i)
00089 {
00090 if( bin_firing_FD == 0 && signal.getBinValue(i) >= qMax * theFraction )
00091 {
00092 bin_firing_FD = i;
00093 }
00094 }
00095 float tofOffset = timeOfFlightCalibration(wireGroup);
00096 int chamberType = theSpecs->chamberType();
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 float fdTime = theSignalStartTime + theSamplingTime*bin_firing_FD;
00111 if(doNoise_) {
00112 fdTime += theTimingCalibrationError * theRandGaussQ->fire();
00113 }
00114
00115 float bxFloat = (fdTime - tofOffset- theBunchTimingOffsets[chamberType]) / theBunchSpacing
00116 + theOffsetOfBxZero;
00117 if(bxFloat >= 0 && bxFloat < 16)
00118 {
00119 timeWord |= (1 << static_cast<int>(bxFloat) );
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 ibin = lastbin;
00135 }
00136 }
00137
00138
00139 if(timeWord != 0)
00140 {
00141 CSCWireDigi newDigi(wireGroup, timeWord);
00142 LogTrace("CSCWireElectronicsSim") << newDigi;
00143 digis.insertDigi(layerId(), newDigi);
00144 addLinks(channelIndex(wireGroup));
00145 }
00146 }
00147 }
00148
00149
00150 float CSCWireElectronicsSim::calculateAmpResponse(float t) const {
00151 static const float fC_by_ns = 1000000;
00152 static const float resistor = 20000;
00153 static const float amplifier_pole = 1/7.5;
00154 static const float fastest_chamber_exp_risetime = 10.;
00155 static const float p0=amplifier_pole;
00156 static const float p1=1/fastest_chamber_exp_risetime;
00157
00158 static const float dp = p0 - p1;
00159
00160
00161
00162 static const float norm = -12 * resistor * p1 * pow(p0/dp, 4) / fC_by_ns;
00163
00164 float enable_disc_volts = norm*( exp(-p0*t) *(1 +
00165 t*dp +
00166 pow(t*dp,2)/2 +
00167 pow(t*dp,3)/6 )
00168 - exp(-p1*t) );
00169 static const float collectionFraction = 0.12;
00170 static const float igain = 1./0.005;
00171 return enable_disc_volts * igain * collectionFraction;
00172 }
00173
00174
00175 float CSCWireElectronicsSim::signalDelay(int element, float pos) const {
00176
00177
00178
00179 float distance = -1. * pos;
00180 float speed = c_light / cm;
00181 float delay = distance / speed;
00182 return delay;
00183 }
00184
00185 float CSCWireElectronicsSim::timeOfFlightCalibration(int wireGroup) const {
00186
00187
00188 int middleWireGroup = wireGroup - wireGroup%8 + 4;
00189 int numberOfWireGroups = theLayerGeometry->numberOfWireGroups();
00190 if(middleWireGroup > numberOfWireGroups)
00191 middleWireGroup = numberOfWireGroups;
00192
00193 GlobalPoint centerOfGroupGroup = theLayer->centerOfWireGroup(middleWireGroup);
00194 float averageDist = centerOfGroupGroup.mag();
00195 float averageTOF = averageDist * cm / c_light;
00196
00197 LogTrace("CSCWireElectronicsSim") << "CSCWireElectronicsSim: TofCalib wg = " << wireGroup <<
00198 " mid wg = " << middleWireGroup <<
00199 " av dist = " << averageDist <<
00200 " av tof = " << averageTOF;
00201
00202 return averageTOF;
00203 }
00204