CMS 3D CMS Logo

Public Member Functions | Private Member Functions | Private Attributes

CSCWireElectronicsSim Class Reference

#include <CSCWireElectronicsSim.h>

Inheritance diagram for CSCWireElectronicsSim:
CSCBaseElectronicsSim

List of all members.

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 timeOfFlightCalibration (int wireGroup) const

Private Attributes

float theFraction
float theWireNoise
float theWireThreshold

Detailed Description

Model the readout electronics chain for EMU CSC wires

Author:
Rick Wilkinson

Definition at line 21 of file CSCWireElectronicsSim.h.


Constructor & Destructor Documentation

CSCWireElectronicsSim::CSCWireElectronicsSim ( const edm::ParameterSet p)

configurable parameters

Definition at line 13 of file CSCWireElectronicsSim.cc.

References CSCBaseElectronicsSim::fillAmpResponse().


Member Function Documentation

float CSCWireElectronicsSim::calculateAmpResponse ( float  t) const [private, virtual]

Implements CSCBaseElectronicsSim.

Definition at line 160 of file CSCWireElectronicsSim.cc.

References funct::exp(), lumiNorm::norm, p1, and funct::pow().

                                                               {
  static const float fC_by_ns = 1000000;
  static const float resistor = 20000;
  static const float amplifier_pole               = 1/7.5;
  static const float fastest_chamber_exp_risetime = 10.;
  static const float p0=amplifier_pole;
  static const float p1=1/fastest_chamber_exp_risetime;

  static const float dp = p0 - p1;

  // ENABLE DISC:

  static const float norm = -12 * resistor * p1 * pow(p0/dp, 4) / fC_by_ns;

  float enable_disc_volts = norm*(  exp(-p0*t) *(1          +
                                                 t*dp       +
                                                 pow(t*dp,2)/2 +
                                                 pow(t*dp,3)/6  )
                                    - exp(-p1*t) );
  static const float collectionFraction = 0.12;
  static const float igain = 1./0.005; // volts per fC
  return enable_disc_volts * igain * collectionFraction;
}                                                                               
virtual int CSCWireElectronicsSim::channelIndex ( int  channel) const [inline, private, virtual]

we code strip indices from 1-80, and wire indices start at 100

Reimplemented from CSCBaseElectronicsSim.

Definition at line 43 of file CSCWireElectronicsSim.h.

Referenced by fillDigis().

{return channel+100;}
void CSCWireElectronicsSim::fillDigis ( CSCWireDigiCollection digis)

Definition at line 35 of file CSCWireElectronicsSim.cc.

References CSCBaseElectronicsSim::addLinks(), CSCChamberSpecs::chamberType(), channelIndex(), CSCBaseElectronicsSim::doNoise_, CSCAnalogSignal::getBinValue(), CSCAnalogSignal::getSize(), i, CSCBaseElectronicsSim::layerId(), LogTrace, CSCBaseElectronicsSim::theBunchSpacing, CSCBaseElectronicsSim::theBunchTimingOffsets, theFraction, CSCBaseElectronicsSim::theOffsetOfBxZero, CSCBaseElectronicsSim::theRandGaussQ, CSCBaseElectronicsSim::theSamplingTime, CSCBaseElectronicsSim::theSignalMap, CSCBaseElectronicsSim::theSignalStartTime, CSCBaseElectronicsSim::theSpecs, CSCBaseElectronicsSim::theTimingCalibrationError, theWireNoise, theWireThreshold, crabWrap::threshold, and timeOfFlightCalibration().

Referenced by CSCDigitizer::doAction().

                                                                   {

  if(theSignalMap.empty()) {
    return;
  }

  // Loop over analog signals, run the fractional discriminator on each one,
  // and save the DIGI in the layer.
  for(CSCSignalMap::iterator mapI = theSignalMap.begin(),
      lastSignal = theSignalMap.end();
      mapI != lastSignal; ++mapI) 
  {
    int wireGroup = (*mapI).first;
    const CSCAnalogSignal & signal = (*mapI).second;
    LogTrace("CSCWireElectronicsSim") << "CSCWireElectronicsSim: dump of wire signal follows... " 
       <<  signal;
    int signalSize = signal.getSize();

    int timeWord = 0; // and this will remain if too early or late (<bx-6 or >bx+9)

    // the way we handle noise in this chamber is by randomly varying
    // the threshold
    float threshold = theWireThreshold;
    if (doNoise_) {
       threshold += theRandGaussQ->fire() * theWireNoise;
    }
    for(int ibin = 0; ibin < signalSize; ++ibin)
    {
      if(signal.getBinValue(ibin) > threshold) 
      {
        // jackpot.  Now define this signal as everything up until
        // the signal goes below zero.
        int lastbin = signalSize;
        int i;
        for(i = ibin; i < signalSize; ++i) {
          if(signal.getBinValue(i) < 0.) {
            lastbin = i;
            break;
          }
        }

        float qMax = 0.0;
        // in this loop, find the max charge and the 'fifth' electron arrival
        for ( i = ibin; i < lastbin; ++i)
        {
          float next_charge = signal.getBinValue(i);
          if(next_charge > qMax) {
            qMax = next_charge;
          }
        }
     
        int bin_firing_FD = 0;
        for ( i = ibin; i < lastbin; ++i)
        {
          if( signal.getBinValue(i) >= qMax * theFraction )
          {
             bin_firing_FD = i;
             //@@ Long-standing but unlikely minor bug, I (Tim) think - following 'break' was missing...
             //@@ ... So if both ibins 0 and 1 could fire FD, we'd flag the firing bin as 1 not 0
             //@@ (since the above test was restricted to bin_firing_FD==0 too).
             break;
          }
        } 

        float tofOffset = timeOfFlightCalibration(wireGroup);
        int chamberType = theSpecs->chamberType();

        // Note that CSCAnalogSignal::superimpose does not reset theTimeOffset to the earliest
        // of the two signal's time offsets. If it did then we could handle signals from any
        // time range e.g. form pileup events many bx's from the signal bx (bx=0).
        // But then we would be wastefully storing signals over times which we can never
        // see in the real detector, because only hits within a few bx's of bx=0 are read out.
        // Instead, the working time range for wire hits is always started from
        // theSignalStartTime, set as a parameter in the config file.
        // On the other hand, if any of the overlapped CSCAnalogSignals happens to have
        // a timeOffset earlier than theSignalStartTime (which is currently set to -100 ns)
        // then we're in trouble. For pileup events this would mean events from collisions
        // earlier than 4 bx before the signal bx.

        float fdTime = theSignalStartTime + theSamplingTime*bin_firing_FD;
        if(doNoise_) {
          fdTime += theTimingCalibrationError[chamberType] * theRandGaussQ->fire();
        }

        float bxFloat = (fdTime - tofOffset- theBunchTimingOffsets[chamberType]) / theBunchSpacing
                           + theOffsetOfBxZero;
        int bxInt = static_cast<int>(bxFloat);
        if(bxFloat >= 0 && bxFloat < 16)
        {
           timeWord |= (1 << bxInt );
           // discriminator stays high for 35 ns
           if(bxFloat-bxInt > 0.6) 
           {
             timeWord |= (1 << (bxInt+1) );
           }
        }

        // Wire digi as of Oct-2006 adapted to real data: time word has 16 bits with set bit
        // flagging appropriate bunch crossing, and bx 0 corresponding to the 7th bit, 'bit 6':
  
        //      1st bit set (bit 0) <-> bx -6
        //      2nd              1  <-> bx -5
        //      ...           ...       ....
        //      7th              6  <-> bx  0
        //      8th              7  <-> bx +1
        //      ...           ...       ....
        //     16th             15  <-> bx +9

        // skip over all the time bins used for this digi
        ibin = lastbin;
      } // if over threshold
    } // loop over time bins in signal

    // Only create a wire digi if there is a wire hit within [-6 bx, +9 bx]
    if(timeWord != 0)
    {
      CSCWireDigi newDigi(wireGroup, timeWord);
      LogTrace("CSCWireElectronicsSim") << newDigi;
      digis.insertDigi(layerId(), newDigi);
      addLinks(channelIndex(wireGroup));
    }
  } // loop over wire signals   
}
void CSCWireElectronicsSim::initParameters ( ) [private, virtual]
int CSCWireElectronicsSim::readoutElement ( int  element) const [private, virtual]
void CSCWireElectronicsSim::setFraction ( float  newFraction) [inline]

Definition at line 27 of file CSCWireElectronicsSim.h.

References theFraction.

{theFraction = newFraction;};
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().

                                                                        {
  // calibration is done for groups of 8 wire groups, facetiously
  // called wireGroupGroups
  int middleWireGroup = wireGroup - wireGroup%8 + 4;
  int numberOfWireGroups = theLayerGeometry->numberOfWireGroups();
  if(middleWireGroup > numberOfWireGroups) 
     middleWireGroup = numberOfWireGroups;

  GlobalPoint centerOfGroupGroup = theLayer->centerOfWireGroup(middleWireGroup);
  float averageDist = centerOfGroupGroup.mag();
  float averageTOF  = averageDist * cm / c_light; // Units of c_light: mm/ns

  LogTrace("CSCWireElectronicsSim") << "CSCWireElectronicsSim: TofCalib  wg = " << wireGroup << 
       " mid wg = " << middleWireGroup << 
       " av dist = " << averageDist << 
      " av tof = " << averageTOF;
  
  return averageTOF;
}

Member Data Documentation

Definition at line 48 of file CSCWireElectronicsSim.h.

Referenced by fillDigis(), and setFraction().

Definition at line 49 of file CSCWireElectronicsSim.h.

Referenced by fillDigis(), and initParameters().

Definition at line 50 of file CSCWireElectronicsSim.h.

Referenced by fillDigis(), and initParameters().