CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
CSCWireElectronicsSim.cc
Go to the documentation of this file.
8 #include "CLHEP/Units/GlobalPhysicalConstants.h"
9 #include "CLHEP/Units/GlobalSystemOfUnits.h"
10 #include <iostream>
11 
12 
15  theFraction(0.5),
16  theWireNoise(0.0),
17  theWireThreshold(0.)
18 {
20 }
21 
22 
26  * e_SI * pow(10.0,15);
28 }
29 
30 
31 int CSCWireElectronicsSim::readoutElement(int element) const {
32  return theLayerGeometry->wireGroup(element);
33 }
34 
36 
37  if(theSignalMap.empty()) {
38  return;
39  }
40 
41  // Loop over analog signals, run the fractional discriminator on each one,
42  // and save the DIGI in the layer.
43  for(CSCSignalMap::iterator mapI = theSignalMap.begin(),
44  lastSignal = theSignalMap.end();
45  mapI != lastSignal; ++mapI)
46  {
47  int wireGroup = (*mapI).first;
48  const CSCAnalogSignal & signal = (*mapI).second;
49  LogTrace("CSCWireElectronicsSim") << "CSCWireElectronicsSim: dump of wire signal follows... "
50  << signal;
51  int signalSize = signal.getSize();
52 
53  int timeWord = 0; // and this will remain if too early or late (<bx-6 or >bx+9)
54 
55  // the way we handle noise in this chamber is by randomly varying
56  // the threshold
58  if (doNoise_) {
59  threshold += theRandGaussQ->fire() * theWireNoise;
60  }
61  for(int ibin = 0; ibin < signalSize; ++ibin)
62  {
63  if(signal.getBinValue(ibin) > threshold)
64  {
65  // jackpot. Now define this signal as everything up until
66  // the signal goes below zero.
67  int lastbin = signalSize;
68  int i;
69  for(i = ibin; i < signalSize; ++i) {
70  if(signal.getBinValue(i) < 0.) {
71  lastbin = i;
72  break;
73  }
74  }
75 
76  float qMax = 0.0;
77  // in this loop, find the max charge and the 'fifth' electron arrival
78  for ( i = ibin; i < lastbin; ++i)
79  {
80  float next_charge = signal.getBinValue(i);
81  if(next_charge > qMax) {
82  qMax = next_charge;
83  }
84  }
85 
86  int bin_firing_FD = 0;
87  for ( i = ibin; i < lastbin; ++i)
88  {
89  if( signal.getBinValue(i) >= qMax * theFraction )
90  {
91  bin_firing_FD = i;
92  //@@ Long-standing but unlikely minor bug, I (Tim) think - following 'break' was missing...
93  //@@ ... So if both ibins 0 and 1 could fire FD, we'd flag the firing bin as 1 not 0
94  //@@ (since the above test was restricted to bin_firing_FD==0 too).
95  break;
96  }
97  }
98 
99  float tofOffset = timeOfFlightCalibration(wireGroup);
100  int chamberType = theSpecs->chamberType();
101 
102  // Note that CSCAnalogSignal::superimpose does not reset theTimeOffset to the earliest
103  // of the two signal's time offsets. If it did then we could handle signals from any
104  // time range e.g. form pileup events many bx's from the signal bx (bx=0).
105  // But then we would be wastefully storing signals over times which we can never
106  // see in the real detector, because only hits within a few bx's of bx=0 are read out.
107  // Instead, the working time range for wire hits is always started from
108  // theSignalStartTime, set as a parameter in the config file.
109  // On the other hand, if any of the overlapped CSCAnalogSignals happens to have
110  // a timeOffset earlier than theSignalStartTime (which is currently set to -100 ns)
111  // then we're in trouble. For pileup events this would mean events from collisions
112  // earlier than 4 bx before the signal bx.
113 
114  float fdTime = theSignalStartTime + theSamplingTime*bin_firing_FD;
115  if(doNoise_) {
116  fdTime += theTimingCalibrationError[chamberType] * theRandGaussQ->fire();
117  }
118 
119  float bxFloat = (fdTime - tofOffset- theBunchTimingOffsets[chamberType]) / theBunchSpacing
121  int bxInt = static_cast<int>(bxFloat);
122  if(bxFloat >= 0 && bxFloat < 16)
123  {
124  timeWord |= (1 << bxInt );
125  // discriminator stays high for 35 ns
126  if(bxFloat-bxInt > 0.6)
127  {
128  timeWord |= (1 << (bxInt+1) );
129  }
130  }
131 
132  // Wire digi as of Oct-2006 adapted to real data: time word has 16 bits with set bit
133  // flagging appropriate bunch crossing, and bx 0 corresponding to the 7th bit, 'bit 6':
134 
135  // 1st bit set (bit 0) <-> bx -6
136  // 2nd 1 <-> bx -5
137  // ... ... ....
138  // 7th 6 <-> bx 0
139  // 8th 7 <-> bx +1
140  // ... ... ....
141  // 16th 15 <-> bx +9
142 
143  // skip over all the time bins used for this digi
144  ibin = lastbin;
145  } // if over threshold
146  } // loop over time bins in signal
147 
148  // Only create a wire digi if there is a wire hit within [-6 bx, +9 bx]
149  if(timeWord != 0)
150  {
151  CSCWireDigi newDigi(wireGroup, timeWord);
152  LogTrace("CSCWireElectronicsSim") << newDigi;
153  digis.insertDigi(layerId(), newDigi);
154  addLinks(channelIndex(wireGroup));
155  }
156  } // loop over wire signals
157 }
158 
159 
161  static const float fC_by_ns = 1000000;
162  static const float resistor = 20000;
163  static const float amplifier_pole = 1/7.5;
164  static const float fastest_chamber_exp_risetime = 10.;
165  static const float p0=amplifier_pole;
166  static const float p1=1/fastest_chamber_exp_risetime;
167 
168  static const float dp = p0 - p1;
169 
170  // ENABLE DISC:
171 
172  static const float norm = -12 * resistor * p1 * pow(p0/dp, 4) / fC_by_ns;
173 
174  float enable_disc_volts = norm*( exp(-p0*t) *(1 +
175  t*dp +
176  pow(t*dp,2)/2 +
177  pow(t*dp,3)/6 )
178  - exp(-p1*t) );
179  static const float collectionFraction = 0.12;
180  static const float igain = 1./0.005; // volts per fC
181  return enable_disc_volts * igain * collectionFraction;
182 }
183 
184 
186  // calibration is done for groups of 8 wire groups, facetiously
187  // called wireGroupGroups
188  int middleWireGroup = wireGroup - wireGroup%8 + 4;
189  int numberOfWireGroups = theLayerGeometry->numberOfWireGroups();
190  if(middleWireGroup > numberOfWireGroups)
191  middleWireGroup = numberOfWireGroups;
192 
193  GlobalPoint centerOfGroupGroup = theLayer->centerOfWireGroup(middleWireGroup);
194  float averageDist = centerOfGroupGroup.mag();
195  float averageTOF = averageDist * cm / c_light; // Units of c_light: mm/ns
196 
197  LogTrace("CSCWireElectronicsSim") << "CSCWireElectronicsSim: TofCalib wg = " << wireGroup <<
198  " mid wg = " << middleWireGroup <<
199  " av dist = " << averageDist <<
200  " av tof = " << averageTOF;
201 
202  return averageTOF;
203 }
204 
std::vector< double > theBunchTimingOffsets
int i
Definition: DBlmapReader.cc:9
const CSCChamberSpecs * theSpecs
const CSCLayerGeometry * theLayerGeometry
float getBinValue(int i) const
float calculateAmpResponse(float t) const
virtual int channelIndex(int channel) const
we code strip indices from 1-80, and wire indices start at 100
CSCWireElectronicsSim(const edm::ParameterSet &p)
configurable parameters
int numberOfWireGroups() const
CLHEP::RandGaussQ * theRandGaussQ
int wireGroup(int wire) const
#define e_SI
T mag() const
Definition: PV3DBase.h:66
float wireNoise(float timeInterval) const
virtual void initParameters()
initialization for each layer
int getSize() const
#define LogTrace(id)
GlobalPoint centerOfWireGroup(int wireGroup) const
Definition: CSCLayer.cc:10
virtual void addLinks(int channelIndex)
virtual int readoutElement(int element) const
int chamberType() const
void fillDigis(CSCWireDigiCollection &digis)
CSCDetId layerId() const
the CSCDetId corresponding to the current layer
double p1[4]
Definition: TauolaWrapper.h:89
virtual float timeOfFlightCalibration(int wireGroup) const
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40
std::vector< double > theTimingCalibrationError