Go to the documentation of this file.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/GlobalPhysicalConstants.h"
00009 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00010 #include <iostream>
00011
00012
00013 CSCWireElectronicsSim::CSCWireElectronicsSim(const edm::ParameterSet & p)
00014 : CSCBaseElectronicsSim(p),
00015 theFraction(0.5),
00016 theWireNoise(0.0),
00017 theWireThreshold(0.)
00018 {
00019 fillAmpResponse();
00020 }
00021
00022
00023 void CSCWireElectronicsSim::initParameters() {
00024 nElements = theLayerGeometry->numberOfWireGroups();
00025 theWireNoise = theSpecs->wireNoise(theShapingTime)
00026 * e_SI * pow(10.0,15);
00027 theWireThreshold = theWireNoise * 8;
00028 }
00029
00030
00031 int CSCWireElectronicsSim::readoutElement(int element) const {
00032 return theLayerGeometry->wireGroup(element);
00033 }
00034
00035 void CSCWireElectronicsSim::fillDigis(CSCWireDigiCollection & digis) {
00036
00037 if(theSignalMap.empty()) {
00038 return;
00039 }
00040
00041
00042
00043 for(CSCSignalMap::iterator mapI = theSignalMap.begin(),
00044 lastSignal = theSignalMap.end();
00045 mapI != lastSignal; ++mapI)
00046 {
00047 int wireGroup = (*mapI).first;
00048 const CSCAnalogSignal & signal = (*mapI).second;
00049 LogTrace("CSCWireElectronicsSim") << "CSCWireElectronicsSim: dump of wire signal follows... "
00050 << signal;
00051 int signalSize = signal.getSize();
00052
00053 int timeWord = 0;
00054
00055
00056
00057 float threshold = theWireThreshold;
00058 if (doNoise_) {
00059 threshold += theRandGaussQ->fire() * theWireNoise;
00060 }
00061 for(int ibin = 0; ibin < signalSize; ++ibin)
00062 {
00063 if(signal.getBinValue(ibin) > threshold)
00064 {
00065
00066
00067 int lastbin = signalSize;
00068 int i;
00069 for(i = ibin; i < signalSize; ++i) {
00070 if(signal.getBinValue(i) < 0.) {
00071 lastbin = i;
00072 break;
00073 }
00074 }
00075
00076 float qMax = 0.0;
00077
00078 for ( i = ibin; i < lastbin; ++i)
00079 {
00080 float next_charge = signal.getBinValue(i);
00081 if(next_charge > qMax) {
00082 qMax = next_charge;
00083 }
00084 }
00085
00086 int bin_firing_FD = 0;
00087 for ( i = ibin; i < lastbin; ++i)
00088 {
00089 if( signal.getBinValue(i) >= qMax * theFraction )
00090 {
00091 bin_firing_FD = i;
00092
00093
00094
00095 break;
00096 }
00097 }
00098
00099 float tofOffset = timeOfFlightCalibration(wireGroup);
00100 int chamberType = theSpecs->chamberType();
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 float fdTime = theSignalStartTime + theSamplingTime*bin_firing_FD;
00115 if(doNoise_) {
00116 fdTime += theTimingCalibrationError[chamberType] * theRandGaussQ->fire();
00117 }
00118
00119 float bxFloat = (fdTime - tofOffset- theBunchTimingOffsets[chamberType]) / theBunchSpacing
00120 + theOffsetOfBxZero;
00121 int bxInt = static_cast<int>(bxFloat);
00122 if(bxFloat >= 0 && bxFloat < 16)
00123 {
00124 timeWord |= (1 << bxInt );
00125
00126 if(bxFloat-bxInt > 0.6)
00127 {
00128 timeWord |= (1 << (bxInt+1) );
00129 }
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 ibin = lastbin;
00145 }
00146 }
00147
00148
00149 if(timeWord != 0)
00150 {
00151 CSCWireDigi newDigi(wireGroup, timeWord);
00152 LogTrace("CSCWireElectronicsSim") << newDigi;
00153 digis.insertDigi(layerId(), newDigi);
00154 addLinks(channelIndex(wireGroup));
00155 }
00156 }
00157 }
00158
00159
00160 float CSCWireElectronicsSim::calculateAmpResponse(float t) const {
00161 static const float fC_by_ns = 1000000;
00162 static const float resistor = 20000;
00163 static const float amplifier_pole = 1/7.5;
00164 static const float fastest_chamber_exp_risetime = 10.;
00165 static const float p0=amplifier_pole;
00166 static const float p1=1/fastest_chamber_exp_risetime;
00167
00168 static const float dp = p0 - p1;
00169
00170
00171
00172 static const float norm = -12 * resistor * p1 * pow(p0/dp, 4) / fC_by_ns;
00173
00174 float enable_disc_volts = norm*( exp(-p0*t) *(1 +
00175 t*dp +
00176 pow(t*dp,2)/2 +
00177 pow(t*dp,3)/6 )
00178 - exp(-p1*t) );
00179 static const float collectionFraction = 0.12;
00180 static const float igain = 1./0.005;
00181 return enable_disc_volts * igain * collectionFraction;
00182 }
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