CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/RecoLocalMuon/CSCRecHitD/src/CSCXonStrip_MatchGatti.cc

Go to the documentation of this file.
00001 // This is CSCXonStrip_MatchGatti.cc
00002 
00003 //---- Large part is copied from RecHitB
00004 //---- author: Stoyan Stoynev - NU
00005 
00006 #include <RecoLocalMuon/CSCRecHitD/src/CSCXonStrip_MatchGatti.h>
00007 #include <RecoLocalMuon/CSCRecHitD/src/CSCStripHit.h>
00008 
00009 #include <Geometry/CSCGeometry/interface/CSCLayer.h>
00010 #include <Geometry/CSCGeometry/interface/CSCChamberSpecs.h>
00011 
00012 #include <CondFormats/CSCObjects/interface/CSCDBGains.h>
00013 #include <CondFormats/DataRecord/interface/CSCDBGainsRcd.h>
00014 #include <CondFormats/CSCObjects/interface/CSCDBCrosstalk.h>
00015 #include <CondFormats/DataRecord/interface/CSCDBCrosstalkRcd.h>
00016 #include <CondFormats/CSCObjects/interface/CSCDBNoiseMatrix.h> 
00017 #include <CondFormats/DataRecord/interface/CSCDBNoiseMatrixRcd.h>
00018 
00019 
00020 #include <FWCore/MessageLogger/interface/MessageLogger.h>
00021 #include <FWCore/Utilities/interface/Exception.h>
00022 
00023 
00024 #include "DataFormats/CLHEP/interface/AlgebraicObjects.h"
00025 
00026 #include <vector>
00027 #include <cmath>
00028 #include <iostream>
00029 #include <fstream> 
00030 //#include <iomanip.h> 
00031 //#include <iomanip> 
00032                                                                                                  
00033 #ifndef M_PI_2
00034 #define M_PI_2 1.57079632679489661923
00035 #endif
00036                                                                                                  
00037 
00038 CSCXonStrip_MatchGatti::CSCXonStrip_MatchGatti(const edm::ParameterSet& ps) :
00039   recoConditions_( 0 )  {
00040 
00041   useCalib                   = ps.getParameter<bool>("CSCUseCalibrations");
00042   xtalksOffset               = ps.getParameter<double>("CSCStripxtalksOffset");
00043   noise_level_ME1a                 = ps.getParameter<double>("NoiseLevel_ME1a");
00044   xt_asymmetry_ME1a                = ps.getParameter<double>("XTasymmetry_ME1a");
00045   const_syst_ME1a                   = ps.getParameter<double>("ConstSyst_ME1a");
00046   noise_level_ME1b                 = ps.getParameter<double>("NoiseLevel_ME1b");
00047   xt_asymmetry_ME1b                = ps.getParameter<double>("XTasymmetry_ME1b");
00048   const_syst_ME1b                   = ps.getParameter<double>("ConstSyst_ME1b");
00049   noise_level_ME12                 = ps.getParameter<double>("NoiseLevel_ME12");
00050   xt_asymmetry_ME12                = ps.getParameter<double>("XTasymmetry_ME12");
00051   const_syst_ME12                   = ps.getParameter<double>("ConstSyst_ME12");
00052   noise_level_ME13                 = ps.getParameter<double>("NoiseLevel_ME13");
00053   xt_asymmetry_ME13                = ps.getParameter<double>("XTasymmetry_ME13");
00054   const_syst_ME13                   = ps.getParameter<double>("ConstSyst_ME13");
00055   noise_level_ME21                 = ps.getParameter<double>("NoiseLevel_ME21");
00056   xt_asymmetry_ME21                = ps.getParameter<double>("XTasymmetry_ME21");
00057   const_syst_ME21                   = ps.getParameter<double>("ConstSyst_ME21");
00058   noise_level_ME22                 = ps.getParameter<double>("NoiseLevel_ME22");
00059   xt_asymmetry_ME22                = ps.getParameter<double>("XTasymmetry_ME22");
00060   const_syst_ME22                   = ps.getParameter<double>("ConstSyst_ME22");
00061   noise_level_ME31                 = ps.getParameter<double>("NoiseLevel_ME31");
00062   xt_asymmetry_ME31                = ps.getParameter<double>("XTasymmetry_ME31");
00063   const_syst_ME31                   = ps.getParameter<double>("ConstSyst_ME31");
00064   noise_level_ME32                 = ps.getParameter<double>("NoiseLevel_ME32");
00065   xt_asymmetry_ME32                = ps.getParameter<double>("XTasymmetry_ME32");
00066   const_syst_ME32                   = ps.getParameter<double>("ConstSyst_ME32");
00067   noise_level_ME41                 = ps.getParameter<double>("NoiseLevel_ME41");
00068   xt_asymmetry_ME41                = ps.getParameter<double>("XTasymmetry_ME41");
00069   const_syst_ME41                   = ps.getParameter<double>("ConstSyst_ME41");
00070  
00071   getCorrectionValues("StringCurrentlyNotUsed");
00072 }
00073 
00074 
00075 CSCXonStrip_MatchGatti::~CSCXonStrip_MatchGatti(){
00076 }
00077 
00078 
00079 /* findPosition
00080  *
00081  */
00082 void CSCXonStrip_MatchGatti::findXOnStrip( const CSCDetId& id, const CSCLayer* layer, const CSCStripHit& stripHit, 
00083                                             int centralStrip, float& xWithinChamber, float& sWidth, 
00084                                             const float& tpeak, float& xWithinStrip, float& sigma, int & quality_flag) {
00085   quality_flag = 0; 
00086   // Initialize Gatti parameters using chamberSpecs
00087   // Cache specs_ info for ease of access
00088   specs_ = layer->chamber()->specs();
00089   stripWidth = sWidth;
00090   //initChamberSpecs();
00091   // Initialize output parameters  
00092   xWithinStrip = xWithinChamber;  
00093 
00094   CSCStripHit::ChannelContainer strips = stripHit.strips();
00095   int nStrips = strips.size();
00096   int centStrip = nStrips/2 + 1;   
00097   std::vector<float> adcs = stripHit.s_adc();
00098   int tmax = stripHit.tmax();
00099 
00101   //float t_peak = tpeak;
00102   //float t_zero = 0.;
00103   //float adc[4];
00104   //
00105   //if ( useCalib ) {
00106   //
00107   //  for ( int t = 0; t < 4; ++t ) {
00108   //    int k  = t + 4 * (centStrip-1);
00109   //    adc[t] = adcs[k];
00110   //  }
00111   //
00112   //  // t_peak from peak finder is now 'absolute' i.e. in ns from start of sca time bin 0
00113   //  t_peak = peakTimeFinder_->peakTime( tmax, adc, t_peak );
00114   //  // Just for completeness, the start time of the pulse is 133 ns earlier, according to Stan :)
00115   //  t_zero = t_peak - 133.;
00116   //  // and reset tpeak since that's the way it gets passed out of this function (Argh!)
00117   //  tpeak = t_peak;
00118   //  LogTrace("CSCRecHit|CSCXonStrip_MatchGatti") << "CSCXonStrip_MatchGatti: " << 
00119   //     id << " strip=" << centralStrip << ", t_zero=" << t_zero << ", t_peak=" << t_peak;
00120   //}
00121       
00122   //---- fill the charge matrix (3x3)
00123   float adc[4];
00124   int j = 0;
00125   for ( int i = 1; i <= nStrips; ++i ) {
00126     if ( i > (centStrip-2) && i < (centStrip+2) ) {
00127       std::vector<float> adcsFit;
00128       for ( int t = 0; t < 4; ++t ) {
00129         int k  = t + 4*(i-1);
00130         adc[t] = adcs[k];
00131         if ( t < 3) chargeSignal[j][t] = adc[t];
00132       }
00133       j++;
00134     }
00135   }
00136 
00137 
00138   // Load in x-talks:
00139 
00140   if ( useCalib ) {
00141     std::vector<float> xtalks;
00142     recoConditions_->crossTalk( id, centralStrip, xtalks );
00143     float dt = 50. * tmax - tpeak;
00144     // XTalks; l,r are for left, right XTalk; lr0,1,2 are for what charge "remains" in the strip 
00145     for ( int t = 0; t < 3; ++t ) {
00146       xt_l[0][t] = xtalks[0] * (50.* (t-1) + dt) + xtalks[1] + xtalksOffset;
00147       xt_r[0][t] = xtalks[2] * (50.* (t-1) + dt) + xtalks[3] + xtalksOffset;
00148       xt_l[1][t] = xtalks[4] * (50.* (t-1) + dt) + xtalks[5] + xtalksOffset;
00149       xt_r[1][t] = xtalks[6] * (50.* (t-1) + dt) + xtalks[7] + xtalksOffset;
00150       xt_l[2][t] = xtalks[8] * (50.* (t-1) + dt) + xtalks[9] + xtalksOffset;
00151       xt_r[2][t] = xtalks[10]* (50.* (t-1) + dt) + xtalks[11]+ xtalksOffset;
00152 
00153       xt_lr0[t] = (1. - xt_l[0][t] - xt_r[0][t]);
00154       xt_lr1[t] = (1. - xt_l[1][t] - xt_r[1][t]);
00155       xt_lr2[t] = (1. - xt_l[2][t] - xt_r[2][t]);
00156     }
00157   } else { 
00158     for ( int t = 0; t < 3; ++t ) {
00159       xt_l[0][t] = xtalksOffset;
00160       xt_r[0][t] = xtalksOffset;
00161       xt_l[1][t] = xtalksOffset; 
00162       xt_r[1][t] = xtalksOffset; 
00163       xt_l[2][t] = xtalksOffset; 
00164       xt_r[2][t] = xtalksOffset; 
00165 
00166       xt_lr0[t] = (1. - xt_l[0][t] - xt_r[0][t]);
00167       xt_lr1[t] = (1. - xt_l[1][t] - xt_r[1][t]);
00168       xt_lr2[t] = (1. - xt_l[2][t] - xt_r[2][t]);
00169     } 
00170   }
00171   
00172 
00173   // vector containing noise starts at tmax - 1, and tmax > 3, but....
00174   int tbin = tmax - 4;
00175 
00176   // .... originally, suppose to have tmax in tbin 4 or 5, but noticed in MTCC lots of 
00177   // hits with tmax == 3, so let's allow these, and shift down noise matrix by one element...
00178   // This is a patch because the calibration database doesn't have elements for tbin = 2, 
00179   // e.g. there is no element e[tmax-1,tmax+1] = e[2,4].
00180 
00181   if (tmax < 4) tbin = 0;    // patch
00182 
00183   // Load in auto-correlation noise matrices
00184   if ( useCalib ) {
00185     std::vector<float> nmatrix;
00186     recoConditions_->noiseMatrix( id, centralStrip, nmatrix );
00187     for ( int istrip =0; istrip < 3; ++istrip ) {
00188       a11[istrip] = nmatrix[0+tbin*3+istrip*15];
00189       a12[istrip] = nmatrix[1+tbin*3+istrip*15];
00190       a13[istrip] = nmatrix[2+tbin*3+istrip*15];
00191       a22[istrip] = nmatrix[3+tbin*3+istrip*15];
00192       a23[istrip] = nmatrix[4+tbin*3+istrip*15];
00193       a33[istrip] = nmatrix[6+tbin*3+istrip*15];
00194     }
00195   } else {
00196     // FIXME:  NO HARD WIRED VALUES !!!
00197     for ( int istrip =0; istrip < 3; ++istrip ) {
00198       a11[istrip] = 10.0;
00199       a12[istrip] = 0.0;
00200       a13[istrip] = 0.0;
00201       a22[istrip] = 10.0;
00202       a23[istrip] = 0.0;
00203       a33[istrip] = 10.0;
00204     }
00205   }
00206   
00207   //---- Set up noise, XTalk matrices 
00208   setupMatrix();
00209   //---- Calculate the coordinate within the strip and associate uncertainty
00210   bool ME1_1 = false;
00211   if("ME1/a" == specs_->chamberTypeName() || "ME1/b" == specs_->chamberTypeName()){
00212     ME1_1 = true;
00213   } 
00214 
00215   // due to cross talks and 3 time bin sum it is in principe possible that the center strip is not the maximum strip
00216   // in some cases the consequences could be quite extreme
00217   // take some measures against the extreme cases
00218   bool peakMismatch = false;
00219   std::vector <float> charges(3);
00220   charges[0] = q_sumL;
00221   charges[1] = q_sumC;
00222   charges[2] = q_sumR;
00223   int min_index = min_element(charges.begin(),charges.end()) - charges.begin();
00224   int max_index = max_element(charges.begin(),charges.end()) - charges.begin();
00225   if(1!=max_index && (1==min_index ||
00226                       // the condition below means that if the initial position estimate within strip (|xF|)
00227                       // is above  1.1/2 = 0.55 "strip widths" peakMismatch is set to true (so special case);
00228                       // in normal cases |xF|<=0.5 (0.5 is at the edge of the "central" strip)
00229                       (charges[max_index] - charges[min_index]) > 1.1*(q_sumC - charges[min_index]) )){
00230     peakMismatch = true;
00231     switch (max_index){
00232     case 0:
00233       xWithinStrip = -1;
00234       break;
00235     case 2:
00236       xWithinStrip = 1;
00237       break;
00238     default:
00239       // should be an error message here
00240       xWithinStrip = 0;// in case?
00241       break;
00242     }
00243   }
00244   // we don't have the needed information (it's similar to the "edge" strip case)  
00245   //else if(stripHit.isNearDeadStrip()){
00246   else if(stripHit.deadStrip()>0){
00247     xWithinStrip = 0;
00248   }
00249   else{
00250     //
00251     xWithinStrip = float(calculateXonStripPosition(stripWidth, ME1_1));
00252   }
00253   xWithinChamber = xWithinChamber + (xWithinStrip * stripWidth);
00254   if(peakMismatch){
00255     sigma = stripWidth/sqrt(12);
00256   }
00257   else{
00258     
00259     //---- error estimation
00260     int factorStripWidth = int( sqrt(stripWidth/0.38) );
00261     int maxConsecutiveStrips = 8;
00262     if(factorStripWidth){
00263       maxConsecutiveStrips /=  factorStripWidth ;
00264     }
00265     maxConsecutiveStrips++;
00266     
00267     std::map <std::string, int> chamberTypes;
00268     chamberTypes["ME1/a"] = 1;
00269     chamberTypes["ME1/b"] = 2;
00270     chamberTypes["ME1/2"] = 3;
00271     chamberTypes["ME1/3"] = 4;
00272     chamberTypes["ME2/1"] = 5;
00273     chamberTypes["ME2/2"] = 6;
00274     chamberTypes["ME3/1"] = 7;
00275     chamberTypes["ME3/2"] = 8;
00276     chamberTypes["ME4/1"] = 9;
00277     chamberTypes["ME4/2"] = 8;
00278     
00279     switch(chamberTypes[specs_->chamberTypeName()]){
00280     case 1:
00281       noise_level  = noise_level_ME1a;
00282       xt_asymmetry = xt_asymmetry_ME1a;
00283       const_syst = const_syst_ME1a;
00284       break;
00285       
00286     case 2:
00287       noise_level  = noise_level_ME1b;
00288       xt_asymmetry = xt_asymmetry_ME1b;
00289       const_syst = const_syst_ME1b;
00290       
00291     case 3:
00292       noise_level  = noise_level_ME12;
00293       xt_asymmetry = xt_asymmetry_ME12;
00294       const_syst = const_syst_ME12;
00295       break;
00296       
00297     case 4:
00298       noise_level  = noise_level_ME13;
00299       xt_asymmetry = xt_asymmetry_ME13;
00300       const_syst = const_syst_ME13;
00301       break;
00302       
00303     case 5:
00304       noise_level  = noise_level_ME21;
00305       xt_asymmetry = xt_asymmetry_ME21;
00306       const_syst = const_syst_ME21;
00307       break;
00308       
00309     case 6:
00310       noise_level  = noise_level_ME22;
00311       xt_asymmetry = xt_asymmetry_ME22;
00312       const_syst = const_syst_ME22;
00313       break;
00314 
00315     case 7:
00316       noise_level  = noise_level_ME31;
00317       xt_asymmetry = xt_asymmetry_ME31;
00318       const_syst = const_syst_ME31;
00319       break;
00320 
00321     case 8:
00322       noise_level  = noise_level_ME32;
00323       xt_asymmetry = xt_asymmetry_ME32;
00324       const_syst = const_syst_ME32;
00325       break;
00326 
00327     case 9:
00328       noise_level  = noise_level_ME41;
00329       xt_asymmetry = xt_asymmetry_ME41;
00330       const_syst = const_syst_ME41;
00331       break;
00332 
00333     default:
00334       noise_level  = noise_level_ME22;
00335       xt_asymmetry = xt_asymmetry_ME22;
00336       const_syst = const_syst_ME22;
00337 
00338     }
00339     if(0==stripHit.deadStrip() &&
00340        stripHit.numberOfConsecutiveStrips()<maxConsecutiveStrips &&
00341        fabs(stripHit.closestMaximum())>maxConsecutiveStrips/2 ){
00342       sigma =  float(calculateXonStripError(stripWidth, ME1_1));
00343     }
00344     else{ //---- near dead strip or too close maxima or too wide strip cluster
00345       sigma = stripWidth/sqrt(12);
00346     }
00347   }
00348   quality_flag = 1;
00349 }
00350 
00351 /* setupMatrix
00352  *
00353  */
00354 void CSCXonStrip_MatchGatti::setupMatrix() {
00355   //---- a??? and v??[] could be skipped for now...; not used yet
00356 
00357   /*
00358   double dd, a11t, a12t, a13t, a22t, a23t, a33t;
00359   double syserr = adcSystematics;
00360   double xtlk_err = xtalksSystematics;
00361   // Left strip
00362   a11t = a11[0] + syserr*syserr * ChargeSignal[0][0]*ChargeSignal[0][0] + xtlk_err*xtlk_err*ChargeSignal[1][0]*ChargeSignal[1][0];
00363   a12t = a12[0] + syserr*syserr * ChargeSignal[0][0]*ChargeSignal[0][1];
00364   a13t = a13[0] + syserr*syserr * ChargeSignal[0][0]*ChargeSignal[0][2];
00365   a22t = a22[0] + syserr*syserr * ChargeSignal[0][1]*ChargeSignal[0][1] + xtlk_err*xtlk_err*ChargeSignal[1][1]*ChargeSignal[1][1];
00366   a23t = a23[0] + syserr*syserr * ChargeSignal[0][1]*ChargeSignal[0][2];
00367   a33t = a33[0] + syserr*syserr * ChargeSignal[0][2]*ChargeSignal[0][2] + xtlk_err*xtlk_err*ChargeSignal[1][2]*ChargeSignal[1][2];
00368 
00369   dd     = (a11t*a33t*a22t - a11t*a23t*a23t - a33t*a12t*a12t 
00370                        + 2.* a12t*a13t*a23t - a13t*a13t*a22t );
00371 
00372   v11[0] = (a33t*a22t - a23t*a23t)/dd;
00373   v12[0] =-(a33t*a12t - a13t*a23t)/dd;
00374   v13[0] = (a12t*a23t - a13t*a22t)/dd;
00375   v22[0] = (a33t*a11t - a13t*a13t)/dd;
00376   v23[0] =-(a23t*a11t - a12t*a13t)/dd;
00377   v33[0] = (a22t*a11t - a12t*a12t)/dd;
00378      
00379   // Center strip
00380   a11t = a11[1] + syserr*syserr * ChargeSignal[1][0]*ChargeSignal[1][0] + xtlk_err*xtlk_err*(ChargeSignal[0][0]*ChargeSignal[0][0]+ChargeSignal[2][0]*ChargeSignal[2][0]);
00381   a12t = a12[1] + syserr*syserr * ChargeSignal[1][0]*ChargeSignal[1][1];
00382   a13t = a13[1] + syserr*syserr * ChargeSignal[1][0]*ChargeSignal[1][2];
00383   a22t = a22[1] + syserr*syserr * ChargeSignal[1][1]*ChargeSignal[1][1] + xtlk_err*xtlk_err*(ChargeSignal[0][1]*ChargeSignal[0][1]+ChargeSignal[2][1]*ChargeSignal[2][1]);
00384   a23t = a23[1] + syserr*syserr * ChargeSignal[1][1]*ChargeSignal[1][2];
00385   a33t = a33[1] + syserr*syserr * ChargeSignal[1][2]*ChargeSignal[1][2] + xtlk_err*xtlk_err*(ChargeSignal[0][2]*ChargeSignal[0][2]+ChargeSignal[2][2]*ChargeSignal[2][2]);
00386 
00387   dd     = (a11t*a33t*a22t - a11t*a23t*a23t - a33t*a12t*a12t
00388                        + 2.* a12t*a13t*a23t - a13t*a13t*a22t );
00389 
00390   v11[1] = (a33t*a22t - a23t*a23t)/dd;
00391   v12[1] =-(a33t*a12t - a13t*a23t)/dd;
00392   v13[1] = (a12t*a23t - a13t*a22t)/dd;
00393   v22[1] = (a33t*a11t - a13t*a13t)/dd;
00394   v23[1] =-(a23t*a11t - a12t*a13t)/dd;
00395   v33[1] = (a22t*a11t - a12t*a12t)/dd;
00396 
00397   // Right strip
00398   a11t = a11[2] + syserr*syserr * ChargeSignal[2][0]*ChargeSignal[2][0] + xtlk_err*xtlk_err*ChargeSignal[1][0]*ChargeSignal[1][0];
00399   a12t = a12[2] + syserr*syserr * ChargeSignal[2][0]*ChargeSignal[2][1];
00400   a13t = a13[2] + syserr*syserr * ChargeSignal[2][0]*ChargeSignal[2][2];
00401   a22t = a22[2] + syserr*syserr * ChargeSignal[2][1]*ChargeSignal[2][1] + xtlk_err*xtlk_err*ChargeSignal[1][1]*ChargeSignal[1][1];
00402   a23t = a23[2] + syserr*syserr * ChargeSignal[2][1]*ChargeSignal[2][2];
00403   a33t = a33[2] + syserr*syserr * ChargeSignal[2][2]*ChargeSignal[2][2] + xtlk_err*xtlk_err*ChargeSignal[1][2]*ChargeSignal[1][2];
00404 
00405   dd     = (a11t*a33t*a22t - a11t*a23t*a23t - a33t*a12t*a12t
00406                         +2.* a12t*a13t*a23t - a13t*a13t*a22t );
00407 
00408   v11[2] = (a33t*a22t - a23t*a23t)/dd;
00409   v12[2] =-(a33t*a12t - a13t*a23t)/dd;
00410   v13[2] = (a12t*a23t - a13t*a22t)/dd;
00411   v22[2] = (a33t*a11t - a13t*a13t)/dd;
00412   v23[2] =-(a23t*a11t - a12t*a13t)/dd;
00413   v33[2] = (a22t*a11t - a12t*a12t)/dd;
00414 */
00415   //---- Find the inverted XTalk matrix and apply it to the charge (3x3)
00416   //---- Thus the charge before the XTalk is obtained
00417   CLHEP::HepMatrix cross_talks(3,3);
00418   CLHEP::HepMatrix cross_talks_inv(3,3);
00419   int err = 0;
00420   //---- q_sum is 3 time bins summed; L, C, R - left, central, right strips
00421   q_sum = q_sumL = q_sumC = q_sumR = 0.;
00422   double charge = 0.;
00423   for(int iTime=0;iTime<3;iTime++){
00424     cross_talks_inv(1,1) = cross_talks(1,1) = xt_lr0[iTime];
00425     cross_talks_inv(1,2) = cross_talks(1,2) = xt_l[1][iTime];
00426     cross_talks_inv(1,3) = cross_talks(1,3) = 0.;
00427     cross_talks_inv(2,1) = cross_talks(2,1) =  xt_r[0][iTime];
00428     cross_talks_inv(2,2) = cross_talks(2,2) = xt_lr1[iTime];
00429     cross_talks_inv(2,3) = cross_talks(2,3) = xt_l[2][iTime];
00430     cross_talks_inv(3,1) = cross_talks(3,1) = 0.;
00431     cross_talks_inv(3,2) = cross_talks(3,2) = xt_r[1][iTime];
00432     cross_talks_inv(3,3) = cross_talks(3,3) = xt_lr2[iTime];
00433     cross_talks_inv.invert(err);
00434     if (err != 0) {
00435       edm::LogWarning("FailedXTalkiInversionNoCrosstalkCorrection") <<"Failed to invert XTalks matrix. No cross-talk correction for this rechit."; 
00436       //edm::LogError("CSCRecHit") << "Failed to invert XTalks matrix. No cross-talk correction for this rechit.";
00437       return;
00438     }
00439     //---- "charge" is XT-corrected charge
00440     charge = chargeSignal[0][iTime]*cross_talks_inv(1,1) + chargeSignal[1][iTime]*cross_talks_inv(1,2) + 
00441       chargeSignal[2][iTime]*cross_talks_inv(1,3);
00442     //---- Negative charge? According to studies (and logic) - better use 0 charge
00443     //----- Later studies suggest that this only do harm. I am still worried about 
00444     // charges of -50 ADC and below (0.5% of the cases) but let see 
00445     //if(charge<0.){
00446       //charge = 0.;
00447     //}
00448     q_sum+=charge;
00449     q_sumL+=charge;
00450     charge = chargeSignal[0][iTime]*cross_talks_inv(2,1) + chargeSignal[1][iTime]*cross_talks_inv(2,2) + 
00451       chargeSignal[2][iTime]* cross_talks_inv(2,3);
00452     //if(charge<0.){
00453       //charge = 0.;
00454     //}
00455     q_sum+=charge;
00456     q_sumC+=charge;
00457     charge = chargeSignal[0][iTime]*cross_talks_inv(3,1) + chargeSignal[1][iTime]*cross_talks_inv(3,2) + 
00458       chargeSignal[2][iTime]*cross_talks_inv(3,3);
00459     //if(charge<0.){
00460       //charge = 0.;
00461     //}
00462     q_sum+=charge;
00463     q_sumR+=charge;
00464   }
00465 }
00466 
00467 
00468 /* initChamberSpecs
00469  *
00470  */
00471 void CSCXonStrip_MatchGatti::initChamberSpecs() {
00472   // Not used directly but these are parameters used for extracting the correction values
00473   // in coordinate and error estimators
00474 
00475   // Distance between anode and cathode
00476   h = specs_->anodeCathodeSpacing();
00477   r = h / stripWidth;
00478 
00479   // Wire spacing
00480   double wspace = specs_->wireSpacing();
00481 
00482   // Wire radius
00483   double wradius = specs_->wireRadius();
00484 
00485   // Accepted parameters in Gatti function
00486   const double parm[5] = {.1989337e-02, -.6901542e-04, .8665786, 154.6177, -.680163e-03 };
00487 
00488   k_3 = ( parm[0]*wspace/h + parm[1] )
00489       * ( parm[2]*wspace/wradius + parm[3] + parm[4]*(wspace/wradius)*(wspace/wradius) );
00490 
00491   sqrt_k_3 = sqrt( k_3 );
00492   norm     = r * (0.5 / atan( sqrt_k_3 )); // changed from norm to r * norm
00493   k_2      = M_PI_2 * ( 1. - sqrt_k_3 /2. );
00494   k_1      = 0.25 * k_2 * sqrt_k_3 / atan( sqrt_k_3 );
00495 }
00496 
00497 
00498 void CSCXonStrip_MatchGatti::getCorrectionValues(std::string estimator){
00499   hardcodedCorrectionInitialization();
00500 }
00501 
00502 double CSCXonStrip_MatchGatti::estimated2GattiCorrection(double x_estimated, float stripWidth, bool ME1_1) {
00503   //---- 11 "nominal" strip widths : 0.6 - 1.6 cm; for ME1_1 just 6 "nominal" strip widths : 0.3 - 0.8 cm; see HardCodedCorrectionInitialization() 
00504   //---- Calculate corrections at specific  Xestimated (linear interpolation between points)
00505   int n_SW;
00506   int min_SW;
00507   if(ME1_1){
00508     n_SW = n_SW_ME1_1;
00509     min_SW = 3; // min SW calculated is 0.3 cm
00510   }
00511   else{
00512     n_SW = n_SW_noME1_1;
00513     min_SW = 6;// min SW calculated is 0.6 cm
00514   }
00515   int stripDown = int(10.*stripWidth) - min_SW; // 0 is at min strip width calculated
00516   int stripUp = stripDown + 1;
00517   if(stripUp>n_SW-1){
00518     //---- to be checked...
00519     //if(stripUp>n_SW){
00520       //std::cout<<" Is strip width = "<<stripWidth<<" OK?" <<std::endl;
00521     //}
00522     stripUp = n_SW-1;
00523   }
00524 
00525   double half_strip_width = 0.5;
00526   //const int Nbins = 501;
00527   const int n_bins = n_val;
00528   double corr_2_xestim = 999.;
00529   if(stripDown<0){
00530     corr_2_xestim = 1;
00531   }
00532   else{
00533     //---- Parametrized x_gatti minus x_estimated differences
00534 
00535     int xestim_bin = -999;
00536     double delta_strip_width = 999.;
00537     double delta_strip_widthUpDown = 999.;
00538     double diff_2_strip_width = 999.;
00539     delta_strip_width = stripWidth - int(stripWidth*10)/10.;
00540     delta_strip_widthUpDown = 0.1;
00541 
00542     if(fabs(x_estimated)>0.5){
00543       if(fabs(x_estimated)>1.){
00544         corr_2_xestim = 1.;// for now; to be investigated
00545       }
00546       else{      
00547         //if(fabs(Xestimated)>0.55){
00548           //std::cout<<"X position from the estimated position above 0.55 (safty margin)?! "<<std::endl;
00549           //CorrToXc = 999.;
00550         //}
00551         xestim_bin = int((1.- fabs(x_estimated))/half_strip_width * n_bins);
00552         if(ME1_1){
00553           diff_2_strip_width = x_correction_ME1_1[stripUp][xestim_bin]-x_correction_ME1_1[stripDown][xestim_bin];
00554           corr_2_xestim =  x_correction_ME1_1[stripDown][xestim_bin] +
00555             (delta_strip_width/delta_strip_widthUpDown)*diff_2_strip_width ;
00556         }
00557         else{
00558           diff_2_strip_width = x_correction_noME1_1[stripUp][xestim_bin]-x_correction_noME1_1[stripDown][xestim_bin];
00559           corr_2_xestim =  x_correction_noME1_1[stripDown][xestim_bin] +
00560             (delta_strip_width/delta_strip_widthUpDown)*diff_2_strip_width ;
00561         }
00562         corr_2_xestim = -corr_2_xestim;
00563       }
00564     }
00565     else{
00566       xestim_bin = int((fabs(x_estimated)/half_strip_width) * n_bins);
00567       if(ME1_1){
00568         diff_2_strip_width = x_correction_ME1_1[stripUp][xestim_bin] - x_correction_ME1_1[stripDown][xestim_bin];
00569         corr_2_xestim =  x_correction_ME1_1[stripDown][xestim_bin] +
00570           (delta_strip_width/delta_strip_widthUpDown)*diff_2_strip_width ;
00571       }
00572       else{
00573         diff_2_strip_width = x_correction_noME1_1[stripUp][xestim_bin] - x_correction_noME1_1[stripDown][xestim_bin];
00574         corr_2_xestim =  x_correction_noME1_1[stripDown][xestim_bin] +
00575           (delta_strip_width/delta_strip_widthUpDown)*diff_2_strip_width ;
00576       }
00577     }
00578     if(x_estimated<0.){
00579       corr_2_xestim = -corr_2_xestim;
00580     }
00581   }
00582   
00583   return corr_2_xestim;
00584 }
00585 
00586 
00587 double CSCXonStrip_MatchGatti::estimated2Gatti(double x_estimated, float stripWidth, bool ME1_1) {
00588 
00589  double x_corr = estimated2GattiCorrection(x_estimated, stripWidth, ME1_1);
00590  double x_gatti = x_estimated + x_corr;
00591 
00592  return x_gatti;
00593 }
00594 
00595 double CSCXonStrip_MatchGatti::xfError_Noise(double noise){
00596 
00597   double min, max;
00598   if(q_sumR>q_sumL){
00599     min = q_sumL;
00600     max = q_sumR;
00601   }
00602   else{
00603     min = q_sumR;
00604     max = q_sumL;
00605   }
00606   //---- Error propagation...
00607   //---- Names here are fake! Due to technical features
00608   double dr_L2 = pow(q_sumR-q_sumL,2);
00609   double dr_C2 = pow(q_sumC-min,2);
00610   double dr_R2 = pow(q_sumC-max,2);
00611   double error = sqrt(dr_L2 + dr_C2 + dr_R2)*noise/pow(q_sumC-min,2)/2;
00612 
00613   return error;
00614 }
00615 
00616 double CSCXonStrip_MatchGatti::xfError_XTasym(double xt_asym){
00617 
00618   double min;
00619   if(q_sumR>q_sumL){
00620     min = q_sumL;
00621   }
00622   else{
00623     min = q_sumR;
00624   }
00625   //---- Error propagation
00626   double dXTL = (pow(q_sumC,2)+pow(q_sumR,2)-q_sumL*q_sumR-q_sumR*q_sumC);
00627   double dXTR = (pow(q_sumC,2)+pow(q_sumL,2)-q_sumL*q_sumR-q_sumL*q_sumC);
00628   double dXT = sqrt(pow(dXTL,2) + pow(dXTR,2))/pow((q_sumC-min),2)/2;
00629   double error = dXT * xt_asym;
00630 
00631   return error;
00632 }
00633 
00634 
00635 double CSCXonStrip_MatchGatti::calculateXonStripError(float stripWidth, bool ME1_1){
00636   double min;
00637   if(q_sumR>q_sumL){
00638     min = q_sumL;
00639   }
00640   else{
00641     min = q_sumR;
00642   }
00643   
00644   double xf = (q_sumR - q_sumL)/(q_sumC - min)/2;
00645   double xf_ErrorNoise = xfError_Noise(noise_level);
00646   double xf_ErrorXTasym = xfError_XTasym(xt_asymmetry);
00647   // x_G = x_F + correction_functon(x_F)
00648   // as these are correlated the error should be simply d(x_G) = |d(x_F)| + [correction_functon(x_F+|d(x_F)|) - correction_functon(x_F)]
00649   double d_xf = sqrt( pow( xf_ErrorNoise, 2) + pow( xf_ErrorXTasym, 2));
00650         double d_corr = estimated2GattiCorrection(xf+d_xf, stripWidth, ME1_1) - estimated2GattiCorrection(xf, stripWidth, ME1_1);
00651   double x_shift = d_xf + d_corr;
00652   //  double x_shift = sqrt( pow( xf_ErrorNoise, 2) + pow( xf_ErrorXTasym, 2)) * 
00653   //(1 + (estimated2GattiCorrection(xf+0.001, stripWidth, ME1_1) -
00654   //  estimated2GattiCorrection(xf, stripWidth, ME1_1))*1000.);
00655   double x_error =   sqrt( pow( fabs(x_shift)*stripWidth, 2) + pow(const_syst, 2) );
00656   return  x_error; 
00657 }
00658 
00659 double CSCXonStrip_MatchGatti::calculateXonStripPosition(float stripWidth, bool ME1_1){ 
00660 
00661   double  x_estimated = -99.;
00662   double min;
00663   if(q_sumR>q_sumL){
00664     min = q_sumL;
00665   }
00666   else{
00667     min = q_sumR;
00668   }
00669   //---- This is XF ( X Florida - after the first group that used it)  
00670   x_estimated = (q_sumR - q_sumL)/(q_sumC - min)/2;
00671   double x_gatti = estimated2Gatti(x_estimated, stripWidth, ME1_1);
00672   return x_gatti;
00673 }
00674 
00675 // Define space for statics
00676 const int CSCXonStrip_MatchGatti::n_val;
00677 const int CSCXonStrip_MatchGatti::n_SW_noME1_1;
00678 const int CSCXonStrip_MatchGatti::n_SW_ME1_1;
00679