#include <SimMuon/CSCDigitizer/src/CSCWireElectronicsSim.h>
Public Member Functions | |
CSCWireElectronicsSim (const edm::ParameterSet &p) | |
configurable parameters | |
void | fillDigis (CSCWireDigiCollection &digis) |
void | setFraction (float newFraction) |
Private Member Functions | |
float | calculateAmpResponse (float t) const |
virtual int | channelIndex (int channel) const |
we code strip indices from 1-80, and wire indices start at 100 | |
virtual void | initParameters () |
initialization for each layer | |
virtual int | readoutElement (int element) const |
virtual float | signalDelay (int element, float pos) const |
how long, in ns, it takes a signal at pos to propagate to the readout edge. | |
virtual float | timeOfFlightCalibration (int wireGroup) const |
Private Attributes | |
float | theFraction |
float | theTimingCalibrationError |
float | theWireNoise |
float | theWireThreshold |
Definition at line 21 of file CSCWireElectronicsSim.h.
CSCWireElectronicsSim::CSCWireElectronicsSim | ( | const edm::ParameterSet & | p | ) |
configurable parameters
Definition at line 12 of file CSCWireElectronicsSim.cc.
References CSCBaseElectronicsSim::fillAmpResponse().
00013 : CSCBaseElectronicsSim(p), 00014 theFraction(0.5), 00015 theWireNoise(0.0), 00016 theWireThreshold(0.), 00017 theTimingCalibrationError(p.getParameter<double>("wireTimingError")) 00018 { 00019 fillAmpResponse(); 00020 }
float CSCWireElectronicsSim::calculateAmpResponse | ( | float | t | ) | const [private, virtual] |
Implements CSCBaseElectronicsSim.
Definition at line 150 of file CSCWireElectronicsSim.cc.
References funct::exp(), norm, p1, and funct::pow().
00150 { 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 // ENABLE DISC: 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; // volts per fC 00171 return enable_disc_volts * igain * collectionFraction; 00172 }
we code strip indices from 1-80, and wire indices start at 100
Reimplemented from CSCBaseElectronicsSim.
Definition at line 44 of file CSCWireElectronicsSim.h.
Referenced by fillDigis().
void CSCWireElectronicsSim::fillDigis | ( | CSCWireDigiCollection & | digis | ) |
Definition at line 36 of file CSCWireElectronicsSim.cc.
References CSCBaseElectronicsSim::addLinks(), CSCChamberSpecs::chamberType(), channelIndex(), CSCBaseElectronicsSim::doNoise_, CSCAnalogSignal::getBinValue(), CSCAnalogSignal::getSize(), i, CSCBaseElectronicsSim::layerId(), LogTrace, signal, CSCBaseElectronicsSim::theBunchSpacing, CSCBaseElectronicsSim::theBunchTimingOffsets, theFraction, CSCBaseElectronicsSim::theOffsetOfBxZero, CSCBaseElectronicsSim::theRandGaussQ, CSCBaseElectronicsSim::theSamplingTime, CSCBaseElectronicsSim::theSignalMap, CSCBaseElectronicsSim::theSignalStartTime, CSCBaseElectronicsSim::theSpecs, theTimingCalibrationError, theWireNoise, theWireThreshold, dimuonsSequences_cff::threshold, and timeOfFlightCalibration().
Referenced by CSCDigitizer::doAction().
00036 { 00037 00038 if(theSignalMap.empty()) { 00039 return; 00040 } 00041 00042 // Loop over analog signals, run the fractional discriminator on each one, 00043 // and save the DIGI in the layer. 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; // and this will remain if too early or late (<bx-6 or >bx+9) 00055 00056 // the way we handle noise in this chamber is by randomly varying 00057 // the threshold 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 // jackpot. Now define this signal as everything up until 00067 // the signal goes below zero. 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 // in this loop, find the max charge and the 'fifth' electron arrival 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 // Note that CSCAnalogSignal::superimpose does not reset theTimeOffset to the earliest 00099 // of the two signal's time offsets. If it did then we could handle signals from any 00100 // time range e.g. form pileup events many bx's from the signal bx (bx=0). 00101 // But then we would be wastefully storing signals over times which we can never 00102 // see in the real detector, because only hits within a few bx's of bx=0 are read out. 00103 // Instead, the working time range for wire hits is always started from 00104 // theSignalStartTime, set as a parameter in the config file. 00105 // On the other hand, if any of the overlapped CSCAnalogSignals happens to have 00106 // a timeOffset earlier than theSignalStartTime (which is currently set to -100 ns) 00107 // then we're in trouble. For pileup events this would mean events from collisions 00108 // earlier than 4 bx before the signal bx. 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 // Wire digi as of Oct-2006 adapted to real data: time word has 16 bits with set bit 00123 // flagging appropriate bunch crossing, and bx 0 corresponding to the 7th bit, 'bit 6': 00124 00125 // 1st bit set (bit 0) <-> bx -6 00126 // 2nd 1 <-> bx -5 00127 // ... ... .... 00128 // 7th 6 <-> bx 0 00129 // 8th 7 <-> bx +1 00130 // ... ... .... 00131 // 16th 15 <-> bx +9 00132 00133 // skip over all the time bins used for this digi 00134 ibin = lastbin; 00135 } // if over threshold 00136 } // loop over time bins in signal 00137 00138 // Only create a wire digi if there is a wire hit within [-6 bx, +9 bx] 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 } // loop over wire signals 00147 }
void CSCWireElectronicsSim::initParameters | ( | ) | [private, virtual] |
initialization for each layer
Implements CSCBaseElectronicsSim.
Definition at line 23 of file CSCWireElectronicsSim.cc.
References e_SI, CSCLayer::geometry(), CSCBaseElectronicsSim::nElements, CSCLayerGeometry::numberOfWireGroups(), funct::pow(), CSCBaseElectronicsSim::theLayer, CSCBaseElectronicsSim::theLayerGeometry, CSCBaseElectronicsSim::theShapingTime, CSCBaseElectronicsSim::theSpecs, theWireNoise, theWireThreshold, and CSCChamberSpecs::wireNoise().
00023 { 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 }
Implements CSCBaseElectronicsSim.
Definition at line 32 of file CSCWireElectronicsSim.cc.
References CSCBaseElectronicsSim::theLayerGeometry, and CSCLayerGeometry::wireGroup().
00032 { 00033 return theLayerGeometry->wireGroup(element); 00034 }
void CSCWireElectronicsSim::setFraction | ( | float | newFraction | ) | [inline] |
Definition at line 27 of file CSCWireElectronicsSim.h.
References theFraction.
00027 {theFraction = newFraction;};
float CSCWireElectronicsSim::signalDelay | ( | int | element, | |
float | pos | |||
) | const [private, virtual] |
how long, in ns, it takes a signal at pos to propagate to the readout edge.
This may be negative, since the timing may be calibrated to the center of the detector
Implements CSCBaseElectronicsSim.
Definition at line 175 of file CSCWireElectronicsSim.cc.
00175 { 00176 // readout is on right edge of chamber, signal speed is c 00177 // zero calibrated to chamber center 00178 // pos is assumed to be in wire coordinates, not local 00179 float distance = -1. * pos; // in cm 00180 float speed = c_light / cm; 00181 float delay = distance / speed; 00182 return delay; 00183 }
float CSCWireElectronicsSim::timeOfFlightCalibration | ( | int | wireGroup | ) | const [private, virtual] |
Definition at line 185 of file CSCWireElectronicsSim.cc.
References CSCLayer::centerOfWireGroup(), LogTrace, PV3DBase< T, PVType, FrameType >::mag(), CSCLayerGeometry::numberOfWireGroups(), CSCBaseElectronicsSim::theLayer, and CSCBaseElectronicsSim::theLayerGeometry.
Referenced by fillDigis().
00185 { 00186 // calibration is done for groups of 8 wire groups, facetiously 00187 // called wireGroupGroups 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; // Units of c_light: mm/ns 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 }
float CSCWireElectronicsSim::theFraction [private] |
Definition at line 49 of file CSCWireElectronicsSim.h.
Referenced by fillDigis(), and setFraction().
float CSCWireElectronicsSim::theTimingCalibrationError [private] |
float CSCWireElectronicsSim::theWireNoise [private] |
Definition at line 50 of file CSCWireElectronicsSim.h.
Referenced by fillDigis(), and initParameters().
float CSCWireElectronicsSim::theWireThreshold [private] |
Definition at line 51 of file CSCWireElectronicsSim.h.
Referenced by fillDigis(), and initParameters().