CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/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 yCorrection = lp0.y()*0.012;
00196     //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);
00197     //printf("\t tpeak before = %5.2f \t chipCorr %5.2f phaseCorr %5.2f chamberCorr %5.2f tofCorr %5.2f \n",
00198     //     tpeak,chipCorrection, phaseCorrection,chamberCorrection,tofCorrection);
00199     //printf("localy = %5.2f, yCorr = %5.2f \n",lp0.y(),yCorrection);
00200     tpeak = tpeak + chipCorrection + phaseCorrection + chamberCorrection-tofCorrection;//-yCorrection;
00201     //printf("\t tpeak after = %5.2f\n",tpeak);
00202   }
00203 
00204   // Calculate wire time to the half bx level using time bins on
00205   // Store wire time with a precision of 0.01 as an int (multiply by 100)
00206   // Convert from bx to ns (multiply by 25)
00207   int scaledWireTime = 100*findWireBx(wHit.timeBinsOn(), tpeak,id)*25; 
00208 
00210 
00212    CSCRecHit2D::ChannelContainer L1A_and_strips = sHit.stripsTotal();        
00213 
00214    CSCRecHit2D::ChannelContainer BX_and_wgroups = wHit.wgroupsBXandWire();   
00215   // (sigmaWithinTheStrip/stripWidth) is in strip widths just like positionWithinTheStrip is!
00216      CSCRecHit2D rechit( id, lp0, localerr, L1A_and_strips,                  
00217      //adcMap, wgroups, tpeak, positionWithinTheStrip,
00218       adcMap, BX_and_wgroups, tpeak, positionWithinTheStrip,        
00219       sigmaWithinTheStrip/stripWidth, quality, sHit.deadStrip(), wHit.deadWG(), scaledWireTime);
00220 
00222   // rechit.print();
00223 
00224   LogTrace("CSCRecHit") << "CSCMake2DRecHit: rechit created in layer " << id << "... \n" << rechit << "\n";
00225 
00226   return rechit;
00227 
00228 }
00229 
00230 
00231 bool CSCMake2DRecHit::isHitInFiducial( const CSCLayer* layer, const CSCRecHit2D& rh ) {
00232 
00233   bool isInFiducial = true;
00234   const CSCLayerGeometry* layergeom_ = layer->geometry();
00235   LocalPoint rhPosition =  rh.localPosition();
00236   // is the rechit within the chamber? 
00237   //(the problem occurs in ME11a/b otherwise it is OK)
00238   // we could use also 
00239   //bool inside( const Local3DPoint&, const LocalError&, float scale=1.f ) const;
00240   if(!layergeom_->inside(rhPosition)){
00241     isInFiducial = false;
00242   }
00243   
00244   return isInFiducial;
00245 }
00246  
00247 
00248 void CSCMake2DRecHit::setConditions( const CSCRecoConditions* reco ) {
00249   xMatchGatti_->setConditions( reco );
00250   // And cache for use here
00251   recoConditions_ = reco;
00252 } 
00253 
00254 float CSCMake2DRecHit::findWireBx(std::vector <int> timeBinsOn, float tpeak ,const CSCDetId& id) {
00255   // Determine the wire Bx from the vector of time bins on for the wire digi with peak time as an intial estimate.
00256   // Assumes that a single hit should create either one time bin on or two consecutive time bins on
00257   // so algorithm looks for bin on nearest to peak time and checks if it has a bin on consecutive with it
00258   float anode_bx_offset = recoConditions_->anodeBXoffset(id);
00259   float wireBx=-1;
00260   float timeGuess=tpeak/25.+ anode_bx_offset;  
00261   float diffMin=9999.;
00262   int bestMatch=-9;
00263   for (int j=0; j<(int)timeBinsOn.size(); j++) {
00264     double diff=timeGuess-timeBinsOn[j];
00265     // Find bin on closest to peak time
00266     if (fabs(diff)<fabs(diffMin)) {
00267       diffMin=diff;
00268       bestMatch=j;
00269       wireBx=timeBinsOn[j];
00270     }
00271   }
00272   int side=diffMin/fabs(diffMin);
00273   bool unchanged=true;
00274   // First check if bin on the same side as peak time is on
00275   if ((bestMatch+side)>-1 && (bestMatch+side)<(int)timeBinsOn.size()) {      // Make sure one next to it within vector limits
00276     if (timeBinsOn[bestMatch]==(timeBinsOn[bestMatch+side]-side)) {      // See if next bin on in vector is consecutive in time
00277       // Set time to the average of the two bins
00278       wireBx=wireBx+(float)side/2.;
00279       unchanged=false;
00280     }
00281   }
00282   // If no match is found then check the other side
00283   if ((bestMatch-side)>-1 && (bestMatch-side)<(int)timeBinsOn.size() && unchanged) {       // Make sure one next to it exists
00284     if (timeBinsOn[bestMatch]==(timeBinsOn[bestMatch-side]+side)) {    // See if nextbin on is consecutive in time
00285       wireBx=wireBx-(double)side/2.;
00286       unchanged=false;
00287     }
00288   }
00289   return wireBx - anode_bx_offset; // expect collision muons to be centered near 0 bx
00290 }