CMS 3D CMS Logo

CMSSW_4_4_3_patch1/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 
00032   xMatchGatti_        = new CSCXonStrip_MatchGatti( ps );
00033 
00034 }   
00035 
00036 
00037 CSCMake2DRecHit::~CSCMake2DRecHit() {
00038   delete xMatchGatti_;
00039 }
00040 
00041 
00042 CSCRecHit2D CSCMake2DRecHit::hitFromStripAndWire(const CSCDetId& id, const CSCLayer* layer,
00043                                                  const CSCWireHit& wHit, const CSCStripHit& sHit)
00044 {
00045   // Cache layer info for ease of access
00046   layer_        = layer;
00047   layergeom_    = layer_->geometry();
00048   specs_        = layer->chamber()->specs();
00049   id_           = id;
00050   
00051   const float sqrt_12 = 3.4641;
00052   
00053   float tpeak = -99.;
00054   
00055   CSCRecHit2D::ADCContainer adcMap;
00056   CSCRecHit2D::ChannelContainer wgroups;
00057   
00058   // Find wire hit position and wire properties
00059   wgroups = wHit.wgroups();
00060 
00061   int wg_left = wgroups[0];;
00062   int wg_right = wgroups[wgroups.size()-1];
00063   
00064   int Nwires1 = layergeom_->numberOfWiresPerGroup( wg_left );
00065   int Nwires2 = layergeom_->numberOfWiresPerGroup( wg_right );
00066 
00067   float Mwire1 = layergeom_->middleWireOfGroup( wg_left );
00068   float Mwire2 = layergeom_->middleWireOfGroup( wg_right );
00069   
00070   int centerWire_left = (int) (Mwire1 - Nwires1 / 2. + 0.5);
00071   int centerWire_right = (int) (Mwire2 + Nwires2 / 2.);
00072   
00073   float centerWire = (centerWire_left + centerWire_right) / 2.;
00074 
00075   //---- WGs around dead HV segment regions may need special treatment...
00076   //---- This is not addressed here.
00077     
00078   float sigmaWire = 0.;
00079   if(wHit.deadWG()>0 || wgroups.size()>2){
00080     //---- worst possible case; take most conservative approach
00081     for(unsigned int iWG=0;iWG<wgroups.size();iWG++){
00082       sigmaWire+=layergeom_->yResolution( wgroups[iWG] );
00083     }
00084   }
00085   else if(2==wgroups.size()){
00086     //---- 2 WGs - get the larger error (overestimation if a single track is passing
00087     //---- between the WGs; underestimation if there are two separate signal sources)
00088     if(layergeom_->yResolution( wgroups[0] ) > layergeom_->yResolution( wgroups[1] )){
00089       sigmaWire  = layergeom_->yResolution( wgroups[0]);
00090     }    
00091     else{
00092       sigmaWire  = layergeom_->yResolution( wgroups[1]);
00093     }
00094   }  
00095   else if(1==wgroups.size()){
00096     //---- simple - just 1 WG
00097     sigmaWire  = layergeom_->yResolution( wgroups[0]);
00098   }
00099   
00100   // Find strips position and properties
00101   
00102   CSCRecHit2D::ChannelContainer strips = sHit.strips();
00103   int tmax = sHit.tmax();
00104   int nStrip = strips.size();
00105   int idCenterStrip = nStrip/2;
00106   int centerStrip = strips[idCenterStrip];
00107   
00108   // Retrieve strip pulseheights from the CSCStripHit
00109   const std::vector<float>& adc    = sHit.s_adc();
00110   const std::vector<float>& adcRaw = sHit.s_adcRaw();
00111 
00112   std::vector<float> adc2;
00113   std::vector<float> adc2Raw;
00114 
00115   LogTrace("CSCRecHit") << "CSCMake2DRecHit: dump of adc values to be added to rechit follows...";
00116 
00117   for ( int iStrip = 0; iStrip < nStrip; ++iStrip) {
00118 
00119     adc2.clear();
00120     adc2Raw.clear();
00121     for ( int t = 0; t < 4; ++t ){
00122       adc2.push_back(adc[t+iStrip*4]);
00123       adc2Raw.push_back(adcRaw[t+iStrip*4]);
00124     }
00125     // OLD: Rechit takes _calibrated_ adc values
00126     // adcMap.put( strips[iStrip], adc2.begin(), adc2.end() ); 
00127     // NEW: Rechit takes _raw_ adc values
00128     adcMap.put( strips[iStrip], adc2Raw.begin(), adc2Raw.end() ); 
00129 
00130     LogTrace("CSCRecHit") << "CSCMake2DRecHit: strip = " << strips[iStrip] << 
00131       " adcs= " << adc2Raw[0] << " " << adc2Raw[1] << " " << adc2Raw[2] << " " << adc2Raw[3];
00132 
00133   }
00134 
00135   //The tpeak finding for both edge and non-edge strips has been moved to here
00136   //tpeak will be a const argument for xMatchGatti_->findXOnStrip
00137   float adcArray[4];
00138   for ( int t = 0; t < 4; ++t ) {
00139     int k = t+4*(idCenterStrip);
00140     adcArray[t] = adc[k];
00141   }
00142   tpeak = peakTimeFinder_->peakTime( tmax, adcArray, tpeak ); 
00143   // Just for completeness, the start time of the pulse is 133 ns earlier, according to Stan :)
00144   float t_zero = tpeak - 133.;
00145   LogTrace("CSCRecHit|CSCMake2DRecHit") << "CSCMake2DRecHit: " << 
00146     id << " strip=" << centerStrip << ", t_zero=" << t_zero << ", tpeak=" << tpeak;
00147 
00148 
00149   float positionWithinTheStrip= -99.;
00150   float sigmaWithinTheStrip = -99.;
00151   int quality = -1;
00152   LocalPoint lp0(0., 0.);
00153   
00154   float stripWidth = -99.;
00155   // If at the edge, then used 1 strip cluster only
00156   if ( centerStrip == 1 || centerStrip == specs_->nStrips() || nStrip < 2 ) {
00157     lp0 = layergeom_->stripWireIntersection( centerStrip, centerWire);
00158     positionWithinTheStrip = 0.;
00159     stripWidth = layergeom_->stripPitch(lp0);
00160     sigmaWithinTheStrip = stripWidth / sqrt_12;
00161     quality = 2;
00162   }
00163   else {
00164     // If not at the edge, used cluster of size ClusterSize:
00165     LocalPoint lp11  = layergeom_->stripWireIntersection( centerStrip, centerWire);
00166     stripWidth = layergeom_->stripPitch( lp11 );
00167     
00168     //---- Calculate local position within the strip
00169     float xWithinChamber = lp11.x();
00170     quality = 0;
00171     if(layergeom_->inside(lp11 )){// save time; this hit is to be discarded anyway - see isHitInFiducial(...)
00172 
00173       xMatchGatti_->findXOnStrip( id, layer_, sHit, centerStrip, 
00174                                   xWithinChamber,
00175                                   stripWidth,  tpeak, positionWithinTheStrip, 
00176                                   sigmaWithinTheStrip, quality);
00177     }                           
00178     lp0 = LocalPoint( xWithinChamber, layergeom_->yOfWire(centerWire, xWithinChamber) );
00179   }
00180 
00181   
00182   
00183   // compute the errors in local x and y
00184   LocalError localerr = layergeom_->localError( centerStrip, 
00185                                                 sigmaWithinTheStrip, sigmaWire );
00186 
00187   // Before storing the recHit, take the opportunity to change its time
00188   if (useTimingCorrections){
00189     float chipCorrection = recoConditions_->chipCorrection(id,centerStrip);
00190     float phaseCorrection = (sHit.stripsl1a()[0]>> (15-0) & 0x1)*25.;
00191     float chamberCorrection = recoConditions_->chamberTimingCorrection(id);
00192 
00193     GlobalPoint gp0 = layer_->toGlobal(lp0);
00194     float tofCorrection = gp0.mag()/29.9792458;
00195     float signalPropagationSpeed[11] = {0.0, -78, -76, -188, -262, -97, -99, -90, -99, -99, -113};
00196     float position = lp0.y()/sin(layergeom_->stripAngle(centerStrip));
00197     float yCorrection = position/signalPropagationSpeed[id_.iChamberType()];
00198     //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);
00199     //printf("\t tpeak before = %5.2f \t chipCorr %5.2f phaseCorr %5.2f chamberCorr %5.2f tofCorr %5.2f \n",
00200     //     tpeak,chipCorrection, phaseCorrection,chamberCorrection,tofCorrection);
00201     //printf("localy = %5.2f, yCorr = %5.2f \n",lp0.y(),yCorrection);
00202     tpeak = tpeak + chipCorrection + phaseCorrection + chamberCorrection-tofCorrection+yCorrection;
00203     //printf("\t tpeak after = %5.2f\n",tpeak);
00204   }
00205 
00206   // Calculate wire time to the half bx level using time bins on
00207   // Store wire time with a precision of 0.01 as an int (multiply by 100)
00208   // Convert from bx to ns (multiply by 25)
00209   int scaledWireTime = 100*findWireBx(wHit.timeBinsOn(), tpeak,id)*25; 
00210 
00212 
00214    CSCRecHit2D::ChannelContainer L1A_and_strips = sHit.stripsTotal();        
00215 
00216    CSCRecHit2D::ChannelContainer BX_and_wgroups = wHit.wgroupsBXandWire();   
00217   // (sigmaWithinTheStrip/stripWidth) is in strip widths just like positionWithinTheStrip is!
00218      CSCRecHit2D rechit( id, lp0, localerr, L1A_and_strips,                  
00219      //adcMap, wgroups, tpeak, positionWithinTheStrip,
00220       adcMap, BX_and_wgroups, tpeak, positionWithinTheStrip,        
00221       sigmaWithinTheStrip/stripWidth, quality, sHit.deadStrip(), wHit.deadWG(), scaledWireTime);
00222 
00224   // rechit.print();
00225 
00226   LogTrace("CSCRecHit") << "CSCMake2DRecHit: rechit created in layer " << id << "... \n" << rechit << "\n";
00227 
00228   return rechit;
00229 
00230 }
00231 
00232 
00233 bool CSCMake2DRecHit::isHitInFiducial( const CSCLayer* layer, const CSCRecHit2D& rh ) {
00234 
00235   bool isInFiducial = true;
00236   const CSCLayerGeometry* layergeom_ = layer->geometry();
00237   LocalPoint rhPosition =  rh.localPosition();
00238   // is the rechit within the chamber? 
00239   //(the problem occurs in ME11a/b otherwise it is OK)
00240   // we could use also 
00241   //bool inside( const Local3DPoint&, const LocalError&, float scale=1.f ) const;
00242   if(!layergeom_->inside(rhPosition)){
00243     isInFiducial = false;
00244   }
00245   
00246   return isInFiducial;
00247 }
00248  
00249 
00250 void CSCMake2DRecHit::setConditions( const CSCRecoConditions* reco ) {
00251   xMatchGatti_->setConditions( reco );
00252   // And cache for use here
00253   recoConditions_ = reco;
00254 } 
00255 
00256 float CSCMake2DRecHit::findWireBx(std::vector <int> timeBinsOn, float tpeak ,const CSCDetId& id) {
00257   // Determine the wire Bx from the vector of time bins on for the wire digi with peak time as an intial estimate.
00258   // Assumes that a single hit should create either one time bin on or two consecutive time bins on
00259   // so algorithm looks for bin on nearest to peak time and checks if it has a bin on consecutive with it
00260   float anode_bx_offset = recoConditions_->anodeBXoffset(id);
00261   float wireBx=-1;
00262   float timeGuess=tpeak/25.+ anode_bx_offset;  
00263   float diffMin=9999.;
00264   int bestMatch=-9;
00265   for (int j=0; j<(int)timeBinsOn.size(); j++) {
00266     double diff=timeGuess-timeBinsOn[j];
00267     // Find bin on closest to peak time
00268     if (fabs(diff)<fabs(diffMin)) {
00269       diffMin=diff;
00270       bestMatch=j;
00271       wireBx=timeBinsOn[j];
00272     }
00273   }
00274   int side=diffMin/fabs(diffMin);
00275   bool unchanged=true;
00276   // First check if bin on the same side as peak time is on
00277   if ((bestMatch+side)>-1 && (bestMatch+side)<(int)timeBinsOn.size()) {      // Make sure one next to it within vector limits
00278     if (timeBinsOn[bestMatch]==(timeBinsOn[bestMatch+side]-side)) {      // See if next bin on in vector is consecutive in time
00279       // Set time to the average of the two bins
00280       wireBx=wireBx+(float)side/2.;
00281       unchanged=false;
00282     }
00283   }
00284   // If no match is found then check the other side
00285   if ((bestMatch-side)>-1 && (bestMatch-side)<(int)timeBinsOn.size() && unchanged) {       // Make sure one next to it exists
00286     if (timeBinsOn[bestMatch]==(timeBinsOn[bestMatch-side]+side)) {    // See if nextbin on is consecutive in time
00287       wireBx=wireBx-(double)side/2.;
00288       unchanged=false;
00289     }
00290   }
00291   return wireBx - anode_bx_offset; // expect collision muons to be centered near 0 bx
00292 }