CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2/src/RecoLocalMuon/CSCRecHitD/src/CSCMake2DRecHit.cc

Go to the documentation of this file.
00001 // This is CSCMake2DRecHit
00002  
00003 #include <RecoLocalMuon/CSCRecHitD/src/CSCMake2DRecHit.h>
00004 #include <RecoLocalMuon/CSCRecHitD/src/CSCXonStrip_MatchGatti.h>
00005 #include <RecoLocalMuon/CSCRecHitD/src/CSCStripHit.h>
00006 #include <RecoLocalMuon/CSCRecHitD/src/CSCWireHit.h>
00007 #include <RecoLocalMuon/CSCRecHitD/src/CSCRecoConditions.h>
00008  
00009 #include <DataFormats/CSCRecHit/interface/CSCRecHit2D.h>
00010 #include <DataFormats/MuonDetId/interface/CSCDetId.h>
00011 
00012 #include <Geometry/CSCGeometry/interface/CSCLayer.h>
00013 #include <Geometry/CSCGeometry/interface/CSCChamberSpecs.h>
00014 #include <Geometry/CSCGeometry/interface/CSCLayerGeometry.h>
00015 
00016 #include <FWCore/MessageLogger/interface/MessageLogger.h>
00017 #include <FWCore/Utilities/interface/Exception.h>
00018 
00019 #include <iostream>
00020 #include <algorithm>
00021 #include <cmath>
00022 #include <string>
00023 
00024 
00025 CSCMake2DRecHit::CSCMake2DRecHit(const edm::ParameterSet& ps):
00026   peakTimeFinder_( new CSCFindPeakTime( ps ) ){
00027     
00028   useCalib            = ps.getParameter<bool>("CSCUseCalibrations");
00029   stripWireDeltaTime  = ps.getParameter<int>("CSCstripWireDeltaTime"); //@@ Non-standard  CSC*s*trip...
00030   useTimingCorrections= ps.getParameter<bool>("CSCUseTimingCorrections");
00031   useGasGainCorrections = ps.getParameter<bool>("CSCUseGasGainCorrections");
00032 
00033   xMatchGatti_        = new CSCXonStrip_MatchGatti( ps );
00034 
00035 }   
00036 
00037 
00038 CSCMake2DRecHit::~CSCMake2DRecHit() {
00039   delete xMatchGatti_;
00040 }
00041 
00042 
00043 CSCRecHit2D CSCMake2DRecHit::hitFromStripAndWire(const CSCDetId& id, const CSCLayer* layer,
00044                                                  const CSCWireHit& wHit, const CSCStripHit& sHit)
00045 {
00046   // Cache layer info for ease of access
00047   layer_        = layer;
00048   layergeom_    = layer_->geometry();
00049   specs_        = layer->chamber()->specs();
00050   id_           = id;
00051   
00052   const float sqrt_12 = 3.4641;
00053   
00054   float tpeak = -99.;
00055   
00056   CSCRecHit2D::ADCContainer adcMap;
00057   CSCRecHit2D::ChannelContainer wgroups;
00058   
00059   // Find wire hit position and wire properties
00060   wgroups = wHit.wgroups();
00061 
00062   int wg_left = wgroups[0];;
00063   int wg_right = wgroups[wgroups.size()-1];
00064   
00065   int Nwires1 = layergeom_->numberOfWiresPerGroup( wg_left );
00066   int Nwires2 = layergeom_->numberOfWiresPerGroup( wg_right );
00067 
00068   float Mwire1 = layergeom_->middleWireOfGroup( wg_left );
00069   float Mwire2 = layergeom_->middleWireOfGroup( wg_right );
00070   
00071   int centerWire_left = (int) (Mwire1 - Nwires1 / 2. + 0.5);
00072   int centerWire_right = (int) (Mwire2 + Nwires2 / 2.);
00073   
00074   float centerWire = (centerWire_left + centerWire_right) / 2.;
00075 
00076   //---- WGs around dead HV segment regions may need special treatment...
00077   //---- This is not addressed here.
00078     
00079   float sigmaWire = 0.;
00080   if(wHit.deadWG()>0 || wgroups.size()>2){
00081     //---- worst possible case; take most conservative approach
00082     for(unsigned int iWG=0;iWG<wgroups.size();iWG++){
00083       sigmaWire+=layergeom_->yResolution( wgroups[iWG] );
00084     }
00085   }
00086   else if(2==wgroups.size()){
00087     //---- 2 WGs - get the larger error (overestimation if a single track is passing
00088     //---- between the WGs; underestimation if there are two separate signal sources)
00089     if(layergeom_->yResolution( wgroups[0] ) > layergeom_->yResolution( wgroups[1] )){
00090       sigmaWire  = layergeom_->yResolution( wgroups[0]);
00091     }    
00092     else{
00093       sigmaWire  = layergeom_->yResolution( wgroups[1]);
00094     }
00095   }  
00096   else if(1==wgroups.size()){
00097     //---- simple - just 1 WG
00098     sigmaWire  = layergeom_->yResolution( wgroups[0]);
00099   }
00100   
00101   // Find strips position and properties
00102   
00103   CSCRecHit2D::ChannelContainer strips = sHit.strips();
00104   int tmax = sHit.tmax();
00105   int nStrip = strips.size();
00106   int idCenterStrip = nStrip/2;
00107   int centerStrip = strips[idCenterStrip];
00108   
00109   // Retrieve strip pulseheights from the CSCStripHit
00110   const std::vector<float>& adc    = sHit.s_adc();
00111   const std::vector<float>& adcRaw = sHit.s_adcRaw();
00112 
00113   std::vector<float> adc2;
00114   std::vector<float> adc2Raw;
00115 
00116   LogTrace("CSCMake2DRecHit") << "[CSCMake2DRecHit] dump of adc values to be added to rechit follows...";
00117 
00118   for ( int iStrip = 0; iStrip < nStrip; ++iStrip) {
00119 
00120     adc2.clear();
00121     adc2Raw.clear();
00122     adc2.reserve(4);
00123     adc2Raw.reserve(4);
00124     for ( int t = 0; t < 4; ++t ){
00125       adc2.push_back(adc[t+iStrip*4]);
00126       adc2Raw.push_back(adcRaw[t+iStrip*4]);
00127     }
00128     //After CMSSW_5_0: ADC value is pedestal-subtracted and electronics-gain corrected
00129     adcMap.put( strips[iStrip], adc2.begin(), adc2.end() ); 
00130     // Up to CMSSW_5_0, Rechit takes _raw_ adc values
00131     // adcMap.put( strips[iStrip], adc2Raw.begin(), adc2Raw.end() ); 
00132 
00133     LogTrace("CSCMake2DRecHit") << "[CSCMake2DRecHit] strip = " << strips[iStrip] << 
00134       " adcs= " << adc2Raw[0] << " " << adc2Raw[1] << " " << adc2Raw[2] << " " << adc2Raw[3];
00135 
00136   }
00137 
00138   //The tpeak finding for both edge and non-edge strips has been moved to here
00139   //tpeak will be a const argument for xMatchGatti_->findXOnStrip
00140   float adcArray[4];
00141   for ( int t = 0; t < 4; ++t ) {
00142     int k = t+4*(idCenterStrip);
00143     adcArray[t] = adc[k];
00144   }
00145   tpeak = peakTimeFinder_->peakTime( tmax, adcArray, tpeak ); 
00146   // Just for completeness, the start time of the pulse is 133 ns earlier, according to Stan :)
00147   float t_zero = tpeak - 133.;
00148   LogTrace("CSCRecHit") << "[CSCMake2DRecHit] " << 
00149     id << " strip=" << centerStrip << ", t_zero=" << t_zero << ", tpeak=" << tpeak;
00150 
00151 
00152   float positionWithinTheStrip= -99.;
00153   float sigmaWithinTheStrip = -99.;
00154   int quality = -1;
00155   LocalPoint lp0(0., 0.);
00156   
00157   float stripWidth = -99.;
00158   // If at the edge, then used 1 strip cluster only
00159   if ( centerStrip == 1 || centerStrip == specs_->nStrips() || nStrip < 2 ) {
00160     lp0 = layergeom_->stripWireIntersection( centerStrip, centerWire);
00161     positionWithinTheStrip = 0.;
00162     stripWidth = layergeom_->stripPitch(lp0);
00163     sigmaWithinTheStrip = stripWidth / sqrt_12;
00164     quality = 2;
00165   }
00166   else {
00167     // If not at the edge, used cluster of size ClusterSize:
00168     LocalPoint lp11  = layergeom_->stripWireIntersection( centerStrip, centerWire);
00169     stripWidth = layergeom_->stripPitch( lp11 );
00170     
00171     //---- Calculate local position within the strip
00172     float xWithinChamber = lp11.x();
00173     quality = 0;
00174     if(layergeom_->inside(lp11 )){// save time; this hit is to be discarded anyway - see isHitInFiducial(...)
00175 
00176       xMatchGatti_->findXOnStrip( id, layer_, sHit, centerStrip, 
00177                                   xWithinChamber,
00178                                   stripWidth,  tpeak, positionWithinTheStrip, 
00179                                   sigmaWithinTheStrip, quality);
00180     }                           
00181     lp0 = LocalPoint( xWithinChamber, layergeom_->yOfWire(centerWire, xWithinChamber) );
00182   }
00183 
00184   
00185   
00186   // compute the errors in local x and y
00187   LocalError localerr = layergeom_->localError( centerStrip, 
00188                                                 sigmaWithinTheStrip, sigmaWire );
00189 
00190   // Before storing the recHit, take the opportunity to change its time
00191   if (useTimingCorrections){
00192     float chipCorrection = recoConditions_->chipCorrection(id,centerStrip);
00193     float phaseCorrection = (sHit.stripsl1a()[0]>> (15-0) & 0x1)*25.;
00194     float chamberCorrection = recoConditions_->chamberTimingCorrection(id);
00195 
00196     GlobalPoint gp0 = layer_->toGlobal(lp0);
00197     float tofCorrection = gp0.mag()/29.9792458;
00198     float signalPropagationSpeed[11] = {0.0, -78, -76, -188, -262, -97, -99, -90, -99, -99, -113};
00199     float position = lp0.y()/sin(layergeom_->stripAngle(centerStrip));
00200     float yCorrection = position/signalPropagationSpeed[id_.iChamberType()];
00201     //printf("RecHit in e:%d s:%d r:%d c:%d l:%d strip:%d \n",id.endcap(),id.station(), id.ring(),id.chamber(),id.layer(),centerStrip);
00202     //printf("\t tpeak before = %5.2f \t chipCorr %5.2f phaseCorr %5.2f chamberCorr %5.2f tofCorr %5.2f \n",
00203     //     tpeak,chipCorrection, phaseCorrection,chamberCorrection,tofCorrection);
00204     //printf("localy = %5.2f, yCorr = %5.2f \n",lp0.y(),yCorrection);
00205     tpeak = tpeak + chipCorrection + phaseCorrection + chamberCorrection-tofCorrection+yCorrection;
00206     //printf("\t tpeak after = %5.2f\n",tpeak);
00207   }
00208 
00209   // Calculate wire time to the half bx level using time bins on
00210   // Store wire time with a precision of 0.01 as an int (multiply by 100)
00211   // Convert from bx to ns (multiply by 25)
00212   int scaledWireTime = 100*findWireBx(wHit.timeBinsOn(), tpeak,id)*25; 
00213 
00214 
00215   //Get the gas-gain correction for this rechit
00216   float gasGainCorrection = -999.;   
00217   if (useGasGainCorrections) {
00218     gasGainCorrection = recoConditions_->gasGainCorrection(id,centerStrip,centerWire);
00219   } 
00220 
00229   float energyDeposit = -999.;
00230   if (gasGainCorrection < -998.) {
00231     // if the user has chosen not to use the gas gain correction, set the energy to a different nonsense value
00232     energyDeposit = -998.;
00233 
00234   } else if (gasGainCorrection < 0.) {
00235     // if the gas gain correction from the database is a bad value, set the energy to yet another nonsense value
00236     energyDeposit = -997.;
00237 
00238   } else {
00239     // gas-gain correction is OK, correct the 3x3 ADC sum
00240     if (adcMap.size()==12) {
00241       energyDeposit =
00242         adcMap[0] * gasGainCorrection + adcMap[1] * gasGainCorrection + adcMap[2] * gasGainCorrection +
00243         adcMap[4] * gasGainCorrection + adcMap[5] * gasGainCorrection + adcMap[6] * gasGainCorrection +
00244         adcMap[8] * gasGainCorrection + adcMap[9] * gasGainCorrection + adcMap[10]* gasGainCorrection ; 
00245 
00246     } else if (adcMap.size()==4) {
00247       // if this is an edge strip, set the energy to yet another nonsense value
00248       energyDeposit = -996.;
00249     }
00250 
00251   }
00252 
00254 
00256    CSCRecHit2D::ChannelContainer L1A_and_strips = sHit.stripsTotal();        
00257 
00258    CSCRecHit2D::ChannelContainer BX_and_wgroups = wHit.wgroupsBXandWire();   
00259   // (sigmaWithinTheStrip/stripWidth) is in strip widths just like positionWithinTheStrip is!
00260      CSCRecHit2D rechit( id, lp0, localerr, L1A_and_strips,                  
00261      //adcMap, wgroups, tpeak, positionWithinTheStrip,
00262       adcMap, BX_and_wgroups, tpeak, positionWithinTheStrip,        
00263       sigmaWithinTheStrip/stripWidth, quality, sHit.deadStrip(), wHit.deadWG(), scaledWireTime,
00264       energyDeposit);
00265 
00267   // rechit.print();
00268 
00269   LogTrace("CSCRecHit") << "[CSCMake2DRecHit] rechit created in layer " << id << "... \n" << rechit;
00270 
00271   return rechit;
00272 
00273 }
00274 
00275 
00276 bool CSCMake2DRecHit::isHitInFiducial( const CSCLayer* layer, const CSCRecHit2D& rh ) {
00277 
00278   bool isInFiducial = true;
00279   const CSCLayerGeometry* layergeom_ = layer->geometry();
00280   LocalPoint rhPosition =  rh.localPosition();
00281   // is the rechit within the chamber? 
00282   //(the problem occurs in ME11a/b otherwise it is OK)
00283   // we could use also 
00284   //bool inside( const Local3DPoint&, const LocalError&, float scale=1.f ) const;
00285   if(!layergeom_->inside(rhPosition)){
00286     isInFiducial = false;
00287   }
00288   
00289   return isInFiducial;
00290 }
00291  
00292 
00293 void CSCMake2DRecHit::setConditions( const CSCRecoConditions* reco ) {
00294   xMatchGatti_->setConditions( reco );
00295   // And cache for use here
00296   recoConditions_ = reco;
00297 } 
00298 
00299 float CSCMake2DRecHit::findWireBx(std::vector <int> timeBinsOn, float tpeak ,const CSCDetId& id) {
00300   // Determine the wire Bx from the vector of time bins on for the wire digi with peak time as an intial estimate.
00301   // Assumes that a single hit should create either one time bin on or two consecutive time bins on
00302   // so algorithm looks for bin on nearest to peak time and checks if it has a bin on consecutive with it
00303   float anode_bx_offset = recoConditions_->anodeBXoffset(id);
00304   float wireBx=-1;
00305   float timeGuess=tpeak/25.+ anode_bx_offset;  
00306   float diffMin=9999.;
00307   int bestMatch=-9;
00308   for (int j=0; j<(int)timeBinsOn.size(); j++) {
00309     double diff=timeGuess-timeBinsOn[j];
00310     // Find bin on closest to peak time
00311     if (fabs(diff)<fabs(diffMin)) {
00312       diffMin=diff;
00313       bestMatch=j;
00314       wireBx=timeBinsOn[j];
00315     }
00316   }
00317   int side=diffMin/fabs(diffMin);
00318   bool unchanged=true;
00319   // First check if bin on the same side as peak time is on
00320   if ((bestMatch+side)>-1 && (bestMatch+side)<(int)timeBinsOn.size()) {      // Make sure one next to it within vector limits
00321     if (timeBinsOn[bestMatch]==(timeBinsOn[bestMatch+side]-side)) {      // See if next bin on in vector is consecutive in time
00322       // Set time to the average of the two bins
00323       wireBx=wireBx+(float)side/2.;
00324       unchanged=false;
00325     }
00326   }
00327   // If no match is found then check the other side
00328   if ((bestMatch-side)>-1 && (bestMatch-side)<(int)timeBinsOn.size() && unchanged) {       // Make sure one next to it exists
00329     if (timeBinsOn[bestMatch]==(timeBinsOn[bestMatch-side]+side)) {    // See if nextbin on is consecutive in time
00330       wireBx=wireBx-(double)side/2.;
00331       unchanged=false;
00332     }
00333   }
00334   return wireBx - anode_bx_offset; // expect collision muons to be centered near 0 bx
00335 }