Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

KalFit.cxx

Go to the documentation of this file.
00001 // $Header: /nfs/slac/g/glast/ground/cvs/reconstruction/src/KalFit.cxx,v 1.10 2001/03/05 05:46:07 burnett Exp $
00002 
00003 //----------------------------------------------------------------------
00004 //
00005 //    Implementation of the Kalman Filter Functions
00006 //               KalTrack - doFit()
00007 //               KalPlane, KalHit, KalMatrix, KalPar  - related Objects
00008 //
00009 //               J.A. Hernando, B. Atwood.  Santa Cruz,  7/8/98,
00010 //-----------------------------------------------------------------------
00011 
00012 #include "reconstruction/KalFit.h"
00013 
00014 #include "geometry/Ray.h"
00015 #include "DetectorData.h"
00016 
00017 #include "gui/DisplayRep.h"
00018 
00019 #include <algorithm>
00020 #include <cmath>
00021 using std::min;
00022 
00023 double CONTROL_MaxEne = 2.;
00024 int CONTROL_maxPlanesEne = 8;
00025 
00026 //-------------------------------------------------------------------
00027 //  Access Data Functions (keep compatible with LSQFit)
00028 //-------------------------------------------------------------------
00029 
00030 //KalTrack::~KalTrack() {}
00031 
00032 //#####################################
00033 void KalTrack::clear()
00034 //#####################################
00035 {
00036         kplanelist.clear();
00037         ini();
00038 }
00039 //#####################################
00040 void KalTrack::writeOut(int level) const
00041 //#####################################
00042 {
00043         if (level == 0) return;
00044 
00045         if (numDataPoints() <3 || chiSquare() < 0) return;
00046 
00047         std::cout << " --- KalTrack Information --- " << "\n";
00048         std::cout << " IniEne " << iniEnergy() << "\n";
00049         std::cout << " nhits  " << numDataPoints() << "\n";
00050         std::cout << " ngaps  " << numGaps()       << "\n";
00051         std::cout << " chiSQFit " << chiSquare() << "\n";
00052         std::cout << " chiSQSmooth " << chiSquareSmooth()       << "\n";
00053 std::cout << " chiSQsegment " << chiSquareSegment()       << "\n";
00054 
00055         std::cout << " x      " << position(0.)    << "\n";
00056         std::cout << " Slope  " << slope()         << "\n";
00057         std::cout << " errX   " << errorPosition() << "\n";
00058         std::cout << " errSlp " << errorSlope()    << "\n";
00059         std::cout << " errSlpV" << errorSlopeAtVertex() << "\n";
00060         std::cout << " ECene  " << KalEnergy()     << "\n";
00061 
00062         if (level == 1) return;
00063 
00064         std::cout << " --> KalPlanes:" << "\n";
00065         for (int i = 0; i < 2; i++) kplanelist[i].writeOut(level);
00066 }
00067 //#####################################
00068 int KalTrack::numGaps() const
00069 //#####################################
00070 {
00071     int numGaps =0;
00072     if (numDataPoints() == 0) return numGaps;
00073 
00074     numGaps =1+ kplanelist.back().getIDPlane() -
00075         kplanelist.front().getIDPlane() - numDataPoints();
00076 
00077     return numGaps;
00078 }
00079 
00080 //#####################################
00081 int KalTrack::compareFits(KalTrack& ktrack)
00082 //#####################################
00083 {
00084     int numComData=0;
00085     if (kplanelist.size()==0||ktrack.kplanelist.size()==0)
00086         return numComData;
00087 
00088     for (unsigned int i=0;i<kplanelist.size();i++){
00089         for (unsigned int j=0; j<ktrack.kplanelist.size();j++){
00090             if (kplanelist[i].getIDHit()==
00091                 ktrack.kplanelist[j].getIDHit()) numComData++;
00092         }
00093     }
00094     return numComData;
00095 }
00096 
00097 //#####################################
00098 Point KalTrack::getHit(unsigned ipos)const
00099 //#####################################
00100 {
00101     if (ipos<kplanelist.size()){
00102         return kplanelist[ipos].getPoint(KalHit::MEAS);
00103     }
00104     //  else return Point(FLT_MAX,FLT_MAX,FLT_MAX);
00105     return Point(-999999.,-999999.,-999999.);
00106 }
00107 //#####################################
00108 unsigned KalTrack::getHitIndex(unsigned ipos)const
00109 //#####################################
00110 {
00111     unsigned index= 0xFFFFFFFF;
00112     if (ipos<kplanelist.size())
00113         index=kplanelist[ipos].getIDHit();
00114     return index;
00115 }
00116 
00117 //#####################################
00118 void KalTrack::printOn(std::ostream &) const
00119 //#####################################
00120 {}
00121 
00122 
00123 //#########################################
00124 void KalTrack::drawChiSq(gui::DisplayRep& v, SiData::Axis axis, KalHit::TYPE typ)
00125 //#########################################
00126 {
00127     // Two dimensional Projection Track Drawing
00128     int nplanes = kplanelist.size();
00129     for (int iplane=0; iplane<nplanes; iplane++) {
00130                 double x = kplanelist[iplane].getHit(typ).getPar().getPosition();
00131                 double Ox = kplanelist[iplane].getOrthPar().getPosition();
00132                 double z0  = kplanelist[iplane].getZPlane()+0.01;
00133                 double x0,y0;
00134                 if (axis == SiData::X) {
00135                         x0 = x;
00136                         y0 = Ox;
00137                 } else {
00138                         x0 = Ox;
00139                         y0 = x;
00140                 }
00141 
00142                 double delta= kplanelist[iplane].getDeltaChiSq(typ);
00143                 double xl,xr,yl,yr;
00144                 if (axis == SiData::X) {
00145                         xl = x0-0.5*delta;
00146                         xr = x0+0.5*delta;
00147                         yl = y0;
00148                         yr = y0;
00149                 } else {
00150                         xl = x0;
00151                         xr = x0;
00152                         yl = y0-0.5*delta;
00153                         yr = y0+0.5*delta;
00154                 }               
00155         v.moveTo(Point(xl,yl,z0));
00156         v.lineTo(Point(xr,yr,z0));
00157     }
00158 }
00159 
00160 //#########################################
00161 void KalTrack::drawTrack(gui::DisplayRep& v, SiData::Axis axis, KalHit::TYPE typ)
00162 //#########################################
00163 {
00164     // Two dimensional Projection Track Drawing
00165     //unused:   double XLIMIT = -95.;
00166     int nplanes = kplanelist.size();
00167     for (int iplane=0; iplane<nplanes-1; iplane++) {
00168         double x = kplanelist[iplane].getHit(typ).getPar().getPosition();
00169         double Ox = kplanelist[iplane].getOrthPar().getPosition();
00170 //      Ox = XLIMIT;
00171         double z0  = kplanelist[iplane].getZPlane()+0.01;
00172         double x0,y0;
00173         if (axis == SiData::X) {
00174             x0 = x;
00175             y0 = Ox;
00176         } else {
00177             x0 = Ox;
00178             y0 = x;
00179         }
00180 
00181         double tanx, tany;
00182         double tanX  = kplanelist[iplane].getHit(typ).getPar().getSlope();
00183                 double tanOX = kplanelist[iplane].getOrthPar().getSlope();
00184 //              tanOX = 0.;
00185                 if (axis == SiData::X){
00186                         tanx = tanX;
00187                         tany = tanOX;
00188                 } else {
00189                         tanx = tanOX;
00190                         tany = tanX;
00191                 }
00192 
00193                 Point origin(x0,y0,z0);
00194                 Vector dir = Vector(-1.*tanx,-1.*tany,-1.);
00195                 double mag = dir.mag();
00196                 dir = dir*(1./mag);
00197         
00198                 Ray segment(origin,dir);
00199                 double zstep=kplanelist[iplane+1].getZPlane()-z0;
00200                 double cosz=dir.z();
00201                 v.moveTo(segment.position(0.));
00202         v.lineTo(segment.position(zstep/cosz));
00203     }
00204 }
00205 
00206 double KalTrack::positionAtZ(double const z) const
00207 {
00208     if( kplanelist.empty() ) return 99;
00209     const KalPlane& plane = *kplanelist.begin();
00210     double  x = plane.getHit(KalHit::SMOOTH).getPar().getPosition(),
00211                 z0  = plane.getZPlane()+0.01,
00212                 tanX  = plane.getHit(KalHit::SMOOTH).getPar().getSlope();
00213     return x+(z-z0)*tanX;
00214 }
00215 
00216 //#####################################
00217 void KalTrack::setIniEnergy(double e)
00218 //#####################################
00219 {
00220         m_energy0 = e;
00221         for (unsigned int iplane = 0; iplane < kplanelist.size(); iplane++)
00222                 kplanelist[iplane].setEnergy(m_energy0);
00223 }
00224 //-------------------------------------
00225 //   Kalman Track Private
00226 //-------------------------------------
00227 
00228 //#####################################
00229 KalTrack::KalTrack()
00230 : m_energy0(0), m_x0(0), m_slopeX(0)
00231 , m_chisq(1e6), m_chisqSmooth(1e6)
00232 , m_KalEnergy(0), m_KalThetaMS(0), m_rmsResid(0)
00233 , m_numSegmentPoints(0), m_chisqSegment(0)
00234 //#####################################
00235 {
00236 }
00237 //#####################################
00238 double KalTrack::doFit()
00239 //#####################################
00240 {
00241     ini();
00242 
00243     int nplanes=kplanelist.size();
00244     if (nplanes<=2) return m_chisq;
00245 
00246     m_chisq       = 0.;
00247         m_chisqSmooth = 0.;
00248 
00249     // Generate the initial hit to start the Kalman Filter
00250     //----------------------------------------------------
00251     KalHit hitf=generateFirstFitHit();
00252     kplanelist[0].setHit(hitf);
00253 
00254     //  Filter
00255     //------------
00256     int iplane = 0;  // to be compatible with new scoping rules for (MSC_VER)
00257     for (iplane = 0 ; iplane<nplanes-1;iplane++){
00258         filterStep(iplane);
00259         if(iplane > 0) m_chisq+=kplanelist[iplane+1].getDeltaChiSq(KalHit::FIT);
00260     }
00261 
00262     // Smoother
00263     //---------
00264     KalHit hitsm=(kplanelist[nplanes-1].getHit(KalHit::FIT)).changeType(KalHit::SMOOTH);
00265     kplanelist[nplanes-1].setHit(hitsm);
00266     m_chisqSmooth=kplanelist[nplanes-1].getDeltaChiSq(KalHit::SMOOTH);
00267 
00268     for (iplane=nplanes-2; iplane>=0;iplane--){
00269         KalHit hitsm=kplanelist[iplane].smoother(kplanelist[iplane+1]);
00270         kplanelist[iplane].setHit(hitsm);
00271         m_chisqSmooth+=kplanelist[iplane].getDeltaChiSq(KalHit::SMOOTH);
00272     }
00273 
00274     // End the Calculations
00275     //---------------------
00276     finish();
00277 
00278     return m_chisq;
00279 }
00280 
00281 //#####################################
00282 void KalTrack::ini()
00283 //#####################################
00284 {
00285     m_energy0  = 0.;
00286     m_x0       = 0.;
00287     m_slopeX   = 0.;
00288     m_rmsResid = 0.;
00289     m_KalEnergy = 0.;
00290     m_chisq    = 1e6;
00291     m_chisqSmooth = 1e6;
00292     m_KalThetaMS = 0.;
00293     m_rmsResid = 0.;
00294     m_numSegmentPoints = 0;
00295     m_chisqSegment = 1e6;
00296 
00297     unsigned int iplane =0;
00298     for (;iplane < kplanelist.size();iplane++) {
00299         kplanelist[iplane].clean();
00300     }
00301 
00302 }
00303 //#####################################
00304 void KalTrack::finish()
00305 //#####################################
00306 {
00307     // Compute the fit variables
00308     if (m_chisq>=0){
00309                 int nplanes = kplanelist.size();
00310         m_x0=kplanelist[0].getHit(KalHit::SMOOTH).getPar().getPosition();
00311         m_slopeX=kplanelist[0].getHit(KalHit::SMOOTH).getPar().getSlope();
00312         m_rmsResid=-1.;
00313         m_chisq=m_chisq/(1.*nplanes-2.);
00314                 m_chisqSmooth/=(1.*nplanes-2.);
00315         m_rmsResid=0.;
00316                 int iplane = 0;
00317         for (iplane=0;iplane<nplanes;iplane++){
00318             double res=kplanelist[iplane].
00319                 getHit(KalHit::SMOOTH).getPar().getPosition()-
00320                 kplanelist[iplane].
00321                 getHit(KalHit::MEAS).getPar().getPosition();
00322             m_rmsResid+=res*res;
00323         }
00324         m_rmsResid=sqrt(m_rmsResid/(1.*nplanes));
00325     }
00326 
00327     //   Energy calculations
00328     eneDetermination();
00329 
00330     // Segment Calculation
00331     if (m_chisq>=0){
00332         m_numSegmentPoints = computeNumSegmentPoints();
00333         m_chisqSegment = computeChiSqSegment(m_numSegmentPoints);
00334     }   
00335 }
00336 
00337 //#######################################################
00338 void KalTrack::filterStep(int iplane)
00339 //#######################################################
00340 {
00341     KalHit hitp = kplanelist[iplane].predicted(kplanelist[iplane+1]);
00342     kplanelist[iplane+1].setHit(hitp);
00343     KalHit hitf1 = kplanelist[iplane+1].filter();
00344     kplanelist[iplane+1].setHit(hitf1);
00345 
00346     kplanelist[iplane+1].setDeltaEne(kplanelist[iplane].getEnergy());
00347 }
00348 
00349 //##########################################
00350 KalHit KalTrack::generateFirstFitHit()
00351 //##########################################
00352 {
00353 
00354     int nplanes=kplanelist.size();
00355     if (nplanes<2)
00356         std::cout << "ERROR - Kaltrack::generateFirstFitHit" << '\n';
00357 
00358     double slopeguess=(kplanelist[1].getHit(KalHit::MEAS).getPar().getPosition()-
00359         kplanelist[0].getHit(KalHit::MEAS).getPar().getPosition())/
00360         (kplanelist[1].getZPlane()-kplanelist[0].getZPlane());
00361     double x0guess=kplanelist[0].getHit(KalHit::MEAS).getPar().getPosition();
00362 
00363 
00364     double orth_slope = kplanelist[1].getOrthPar().getSlope();
00365     double cosZ = sqrt(1./(1. + slopeguess*slopeguess + orth_slope*orth_slope));
00366     double energy = kplanelist[1].getEnergy();
00367     if (energy == 0.) energy = m_energy0;
00368     // if (energy < 0.01) energy =0.01;
00369     double theta0=KalPlane::theta0ms(energy,
00370         cosZ,KalPlane::radLen(kplanelist[0].getIDPlane()));
00371     //  The first error is arbitrary to a degree: choose 10*(ms + 1-plane hit precision)
00372 
00373     double thetaerror=10.*(theta0*(1+slopeguess*slopeguess) + .0025);
00374     //  if (thetaerror>3.1416) thetaerror=3.1416;
00375     thetaerror*=thetaerror;
00376     KalMatrix m(0.,0.,0.,thetaerror);
00377     //KalMatrix m(0.,0.,0.,0.01);
00378 
00379     KalPar parguess(x0guess,slopeguess);
00380     KalHit hitf(KalHit::FIT,parguess,
00381         (kplanelist[0].getHit(KalHit::MEAS)).getCov()+m);
00382 
00383     return hitf;
00384 }
00385 
00386 //##########################################
00387 void KalTrack::eneDetermination()
00388 //##########################################
00389 {
00390     int nplanes = std::min(numDataPoints(),(int)CONTROL_maxPlanesEne);
00391     int iplane = 2;
00392     double totalRad = 0.;
00393     double eneSum = 0.;
00394     double thetaSum = 0.;
00395     for (iplane = 2; iplane < nplanes; iplane++) {
00396         int idplane = kplanelist[iplane].getIDPlane();
00397         double chie = kplanelist[iplane].getDeltaChiEne(KalHit::PRED);
00398         double eta = ((chie-1.)*(chie-1.)*(chie-1.))/((chie+2.)*(chie+2.));
00399         eta = sqrt(abs(eta));
00400 
00401         double slope = kplanelist[iplane].getHit(KalHit::SMOOTH).getPar().getSlope();
00402         double slope_orth = kplanelist[iplane].getOrthPar().getSlope();
00403         double cosZ= sqrt(1/(1.+ slope*slope+slope_orth*slope_orth));
00404         double cosX= sqrt(1/(1.+ slope*slope));
00405 
00406         double radlen = KalPlane::radLen(idplane)/cosZ;
00407         totalRad += radlen;
00408         double factor = 1./(2.-exp(-1.*totalRad));
00409         // double factor = 1./(1.+totalRad);
00410 
00411         double sigma = sqrt(kplanelist[iplane].getHit(KalHit::MEAS).getCov().getsiga());
00412         double distance = abs(kplanelist[iplane].getZPlane()-kplanelist[iplane-1].getZPlane());
00413 
00414         // factor - energy loss factor
00415         // sigma/distance - dimensions
00416         // eta - undimesnionless parameters
00417         // cosX, etx - geometrical factors
00418         double theta = factor*(sigma/distance)*eta*(cosX*cosZ*sqrt(cosZ));
00419         theta /= (sqrt(radlen)*(1+0.038*log(radlen)));
00420         thetaSum += theta;
00421 
00422     }
00423     m_KalThetaMS = thetaSum/(nplanes-2.);
00424     m_KalEnergy = 0.0136/m_KalThetaMS;
00425     double radlen = KalPlane::radLen(kplanelist[0].getIDPlane());
00426     m_KalThetaMS *= sqrt(radlen)*(1+0.038*log(radlen));
00427 }
00428 
00429 //##########################################
00430 double KalTrack::errorPosition() const
00431 //##########################################
00432 {
00433         double error = 0.;
00434         if (m_chisqSmooth == 0) return error;
00435         error = sqrt(kplanelist[0].getHit(KalHit::SMOOTH).getCov().getsiga());
00436         return error;
00437 }
00438 //##########################################
00439 double KalTrack::errorSlope() const
00440 //##########################################
00441 {
00442         double error = 0.;
00443         if (m_chisqSmooth == 0) return error;
00444         error = sqrt(kplanelist[0].getHit(KalHit::SMOOTH).getCov().getsigb());
00445         return error;
00446 }
00447 //##########################################
00448 double KalTrack::errorSlopeAtVertex() const
00449 //##########################################
00450 {
00451         double error = 0.;
00452         if (m_chisqSmooth == 0) return error;
00453 
00454         double slope     = m_slopeX;
00455         double ene       = kplanelist[0].getEnergy();
00456         KalMatrix Cov    = kplanelist[0].getHit(KalHit::SMOOTH).getCov();
00457         double orthSlope = kplanelist[0].getOrthPar().getSlope();
00458         int iplane       = kplanelist[0].getIDPlane();
00459         double radlen0   = KalPlane::radLen(iplane);
00460         KalMatrix Q=KalPlane::Q(ene,slope,orthSlope,0.5*radlen0);
00461 
00462         Cov = Cov + Q;
00463 
00464         error = sqrt(Cov.getsigb());
00465         return error;
00466 }
00467 
00468 //##########################################
00469 int KalTrack::computeNumSegmentPoints(KalHit::TYPE typ)
00470 //##########################################
00471 {
00472         
00473     unsigned int num_ist=0;
00474     // OSF alpha detected m_energy0 == -NaN here.
00475     // Paul_Kunz@slac.stanford.edu
00476 #ifndef _MSC_VER
00477     if ( !isnan(m_energy0) ) {                  
00478 #endif
00479         // potential square root of negative number here.
00480         // tburnett@u.washington.edu
00481         num_ist = m_energy0>0? static_cast<unsigned int>( 4.*sqrt(m_energy0)): 1000;
00482 #ifndef _MSC_VER
00483     } else {
00484       num_ist = 1000;
00485     }
00486 #endif
00487     if (num_ist <= 2) num_ist = 3;
00488     if (num_ist > kplanelist.size()) num_ist = kplanelist.size();
00489                         
00490     return num_ist;
00491         /*int npoints = 1;
00492         int iplane = 1;
00493         for (iplane = 1; iplane< kplanelist.size(); iplane++) {
00494                 double sigb0 = sqrt(kplanelist[iplane-1].getHit(typ).getCov().getsigb());
00495                 double sigb1 = sqrt(kplanelist[iplane].getHit(typ).getCov().getsigb());
00496                 double delta = (sigb0-sigb1)/sigb0;
00497                 if (abs(delta)>0.15) npoints++;
00498                 else break;
00499         }
00500         if (npoints<3) npoints = 3;
00501         return npoints; */
00502 
00503 }
00504 //##########################################
00505 double KalTrack::computeChiSqSegment(int nhits, KalHit::TYPE typ)
00506 //##########################################
00507 {
00508         double chi2 = 0;
00509     int ihit =0;
00510         for (ihit =0; ihit < nhits; ihit++) {
00511                 chi2 += kplanelist[ihit].getDeltaChiSq(typ);
00512         }
00513         chi2 /= (nhits-2.);
00514         return chi2;
00515 }
00516 //##########################################
00517 double KalTrack::kink(int iplane) const
00518 //##########################################
00519 {
00520         double kink = 0.;
00521         if (iplane<0 || iplane == numDataPoints()) return kink;
00522 
00523         double slope0 = kplanelist[iplane].getHit(KalHit::SMOOTH).getPar().getSlope();
00524         double slope1 = kplanelist[iplane+1].getHit(KalHit::SMOOTH).getPar().getSlope();
00525 
00526         kink = slope1-slope0;
00527 
00528         return kink;
00529 }
00530 //##########################################
00531 double KalTrack::kinkNorma(int iplane) const
00532 //##########################################
00533 {
00534         double k = 0.;
00535         k = kink(iplane);
00536 
00537         if (iplane <0 || iplane >= numDataPoints()) return k;
00538 
00539         double errorSQ = kplanelist[iplane+1].getHit(KalHit::SMOOTH).getCov().getsigb();
00540         errorSQ += kplanelist[iplane+1].getQmaterial().getsigb();
00541 
00542         double error = sqrt(errorSQ);
00543 
00544         double kinkNorma =  0.;
00545         if (error != 0.) kinkNorma = abs(k)/error;
00546 
00547         return kinkNorma;
00548 
00549 }
00550 //-------------------------------------
00551 //   Kalman Plane
00552 //-------------------------------------
00553 
00554 //#####################################
00555 void KalPlane::writeOut(int level) const
00556 //#####################################
00557 {
00558         std::cout << " --- KalPlane Information --- " << "\n";
00559         std::cout << " IDhit    " << getIDHit() << "\n";
00560         std::cout << " IDplane  " << getIDPlane() << "\n";
00561         std::cout << " IDtower  " << getIDTower() << "\n";
00562         std::cout << " z        " << getZPlane() << "\n";
00563         std::cout << " xmeas    " << getHit(KalHit::MEAS).getPar().getPosition() << "\n";
00564         std::cout << " xpred    " << getHit(KalHit::PRED).getPar().getSlope() << "\n";
00565         std::cout << " errXpred " << sqrt(getHit(KalHit::PRED).getCov().getsiga()) << "\n";
00566         
00567         std::cout << " xSm     " << getHit(KalHit::SMOOTH).getPar().getPosition() << "\n";
00568         std::cout << " SlopeSm " << getHit(KalHit::SMOOTH).getPar().getSlope() << "\n";
00569         std::cout << " errxSm  " << sqrt(getHit(KalHit::SMOOTH).getCov().getsiga()) << "\n";
00570         std::cout << " errSlSm " << sqrt(getHit(KalHit::SMOOTH).getCov().getsigb()) << "\n";
00571         std::cout << " chiSqFit " << getDeltaChiSq(KalHit::FIT) << "\n";
00572         std::cout << " chiSqSm  " << getDeltaChiSq(KalHit::SMOOTH) << "\n";
00573         std::cout << " chiSqEne " << getDeltaChiEne(KalHit::PRED)<< "\n";
00574 
00575 }
00576 //#####################################
00577 void KalPlane::removeHit()
00578 //#####################################
00579 {
00580         m_IDHit = 0;
00581         m_IDTower = 0;
00582         KalPar pnull(0.,0.);
00583         KalMatrix covnull(0.,0.,0.);
00584         setHit(KalHit(KalHit::MEAS,pnull,covnull));
00585         clean();
00586 }
00587 //#####################################
00588 void KalPlane::clean()
00589 //#####################################
00590 {
00591         KalPar pnull(0.,0.);
00592         KalMatrix covnull(0.,0.,0.);
00593         setHit(KalHit(KalHit::PRED,pnull,covnull));
00594         setHit(KalHit(KalHit::FIT,pnull,covnull));
00595         setHit(KalHit(KalHit::SMOOTH,pnull,covnull));
00596 }
00597 //#####################################
00598 void KalPlane::clear()
00599 //#####################################
00600 {
00601         KalPar pnull(0.,0.);
00602         KalMatrix covnull(0.,0.,0.);
00603 
00604         m_eneplane = 0.;
00605         m_IDHit = 0xffffffff;
00606         m_IDPlane  = -1;
00607         m_IDTower = -1;
00608         m_OrthPar = pnull;      
00609         m_zplane = 0.;
00610 
00611         setHit(KalHit(KalHit::MEAS,pnull,covnull));
00612         setHit(KalHit(KalHit::PRED,pnull,covnull));
00613         setHit(KalHit(KalHit::FIT,pnull,covnull));
00614         setHit(KalHit(KalHit::SMOOTH,pnull,covnull));
00615 }
00616 //#####################################
00617 void KalPlane::setHit(const KalHit& hit)
00618 //#####################################
00619 {
00620     KalHit::TYPE type;
00621     switch (type=hit.getType()){
00622     case KalHit::PRED:
00623         m_hitpred=hit;
00624         break;
00625     case KalHit::MEAS:
00626         m_hitmeas=hit;
00627         break;
00628     case KalHit::FIT:
00629         m_hitfit=hit;
00630         break;
00631     case KalHit::SMOOTH:
00632         m_hitsmooth=hit;
00633         break;
00634     case KalHit::UNKNOWN:
00635         break;
00636     }
00637 }
00638 
00639 //#####################################
00640 KalHit KalPlane::getHit(KalHit::TYPE type) const
00641 //#####################################
00642 {
00643     KalHit hit(KalHit::UNKNOWN);
00644 
00645     switch (type){
00646     case KalHit::PRED:
00647         hit=m_hitpred;
00648         break;
00649     case KalHit::MEAS:
00650         hit=m_hitmeas;
00651         break;
00652     case KalHit::FIT:
00653         hit=m_hitfit;
00654         break;
00655     case KalHit::SMOOTH:
00656         hit=m_hitsmooth;
00657         break;
00658     case KalHit::UNKNOWN:
00659         break;
00660     }
00661 
00662     return hit;
00663 }
00664 
00665 //#####################################
00666 Point KalPlane::getPoint(KalHit::TYPE type)const
00667 //#####################################
00668 {
00669     KalHit hit=getHit(type);
00670     return Point(hit.getPar().getPosition(),0.,getZPlane());
00671 }
00672 
00673 //#####################################
00674 double KalPlane::getDeltaChiEne(KalHit::TYPE type)const
00675 //#####################################
00676 {
00677     KalHit hit=getHit(type);
00678     double delpar=m_hitmeas.getPar().getPosition()-hit.getPar().getPosition();
00679     double sigma2=m_hitmeas.getCov().getsiga();
00680 
00681     double variance=(delpar*delpar)/sigma2;
00682     return variance;
00683 }
00684 
00685 //#####################################
00686 void KalPlane::setDeltaEne(double ene)
00687 //#####################################
00688 {
00689     double slope = getHit(KalHit::PRED).getPar().getSlope();
00690     double slope_orth = getOrthPar().getSlope();
00691     double cosZ= sqrt(1/(1.+ slope*slope+slope_orth*slope_orth));
00692     double cosX= sqrt(1/(1.+ slope*slope));
00693 
00694     double radlen = KalPlane::radLen(getIDPlane())/cosZ;
00695     double factor = exp(-1.*radlen);
00696 
00697     setEnergy(ene*factor);
00698 }
00699 
00700 //#####################################
00701 double KalPlane::getSigma(KalHit::TYPE type) const
00702 //#####################################
00703 {
00704 
00705         double sigma = 1e6;
00706 
00707     KalHit hit = getHit(type);
00708         KalHit hitmeas = getHit(KalHit::MEAS);
00709         
00710         double deltap = hit.getPar().getPosition()-hitmeas.getPar().getPosition();
00711         double error2 = hit.getCov().getsiga();
00712         sigma = fabs(deltap)/sqrt(error2);
00713 
00714         return sigma;
00715 }
00716 //#####################################
00717 double KalPlane::getDeltaChiSq(KalHit::TYPE type) const
00718 //#####################################
00719 {
00720 
00721     KalHit hit(KalHit::UNKNOWN);
00722 
00723     switch (type){
00724     case KalHit::FIT:
00725         hit=m_hitfit;
00726         break;
00727     case KalHit::SMOOTH:
00728         hit=m_hitsmooth;
00729         break;
00730     case KalHit::MEAS:
00731     case KalHit::PRED:
00732     case KalHit::UNKNOWN:
00733         break;
00734     }
00735 
00736         /*
00737     KalMatrix V=hitmeas.getCov();
00738     KalMatrix H(1.,0.,0.,0.);
00739     KalMatrix Ck=hit.getCov();
00740     KalMatrix R=V-(H*(Ck*H));
00741     double xval=1./R.getsiga();
00742 
00743     double pmeas=hitmeas.getPar().getPosition();
00744     double pk=hit.getPar().getPosition();
00745     double delpar=pmeas-pk;
00746 
00747     double deltachi2=delpar*xval*delpar;
00748 
00749     return deltachi2; */
00750 
00751     double delpar =   m_hitmeas.getPar().getPosition() -hit.getPar().getPosition();
00752     double variance = m_hitmeas.getCov().getsiga() -    hit.getCov().getsiga();
00753 
00754     // prevent division by zero: what should it do then?
00755         double chi2 = 0.;
00756         if (variance>0.) chi2 = (delpar*delpar)/variance;
00757         else if (variance<0.) chi2 = 1e6;
00758 
00759     return chi2;
00760 }
00761 
00762 //-------------------------------------
00763 //  Kalman Functions
00764 //-------------------------------------
00765 
00766 //#######################################################
00767 KalHit KalPlane::predicted(KalHit::TYPE typ, double zEnd, int klayer)
00768 //#######################################################
00769 {
00770     // Extrapolate the hit to the plane klayer, with a position zEnd;
00771     // This functions handels UP and DOWN predictions
00772     // The normal GLAST trajectories go down (negative z)
00773 
00774     KalHit hit=getHit(typ);
00775 
00776     KalPar pp=hit.getPar();
00777     KalMatrix Ck=hit.getCov();
00778 
00779     double ene =getEnergy();
00780     double slope = pp.getSlope();
00781     double orth_slope = getOrthPar().getSlope();
00782 
00783     int nsteps=klayer-getIDPlane();
00784     double down = -1.;
00785     if (nsteps <0 ) down = +1.; // going up;
00786     nsteps = abs(nsteps);
00787     double deltaZ=zEnd-getZPlane();
00788     int iplane=getIDPlane();
00789     double movedDeltaZ=0.;
00790 
00791     for (int istep=0; istep< abs(nsteps); istep++){     
00792         // double relDeltaZ= SiTracker::traySpacing();
00793         // if (istep==nsteps-1) relDeltaZ=abs(deltaZ)-movedDeltaZ;
00794         // movedDeltaZ+=relDeltaZ;
00795         
00796         // KalMatrix F(1.,-1.*relDeltaZ,0.,1.);
00797 
00798         double relDeltaZ = down * DetectorData::SiTracker::traySpacing();
00799         if (istep == abs(nsteps) -1) relDeltaZ = deltaZ - movedDeltaZ;
00800         movedDeltaZ+=relDeltaZ;
00801 
00802         KalMatrix F(1.,relDeltaZ,0.,1.);
00803         KalMatrix Q=KalPlane::Q(ene, slope, orth_slope, KalPlane::radLen(iplane+1));
00804         pp=F*pp;
00805         if (down == -1.) Ck=(F*(Ck*F.transpose()))+Q;
00806         else if (down == +1) Ck=(F*(Ck+Q)*F.transpose());
00807     }
00808 
00809 //    if (movedDeltaZ != deltaZ) std::cout << " error KalPlane predicted ";
00810 
00811     KalHit hitpred(KalHit::PRED, pp, Ck);
00812 
00813     return hitpred;
00814 
00815 }
00816 //#######################################################
00817 KalHit KalPlane::predicted(KalHit::TYPE typ, int nsteps)
00818 //#######################################################
00819 {
00820     // Extrapolate the hit to the plane (delta)
00821     // Note that GLAST trajectory evolutes along negative z values.
00822 
00823     KalHit hit=getHit(typ);
00824 
00825     KalPar pp=hit.getPar();
00826     KalMatrix Ck=hit.getCov();
00827 
00828     double ene =getEnergy();
00829     double slope = pp.getSlope();
00830     double orth_slope = getOrthPar().getSlope();
00831 
00832     double down = -1;
00833     if (nsteps < 0) down = +1;
00834     double deltaZ=down*abs(nsteps)* DetectorData::SiTracker::traySpacing();
00835 
00836     int iplane=getIDPlane();
00837     double movedDeltaZ=0.;
00838 
00839 
00840     for (int istep=0; istep<abs(nsteps); istep++){
00841 
00842         double relDeltaZ = down*DetectorData::SiTracker::traySpacing();
00843         if (istep == abs(nsteps) -1) relDeltaZ = deltaZ - movedDeltaZ;
00844         movedDeltaZ+=relDeltaZ;
00845 
00846         KalMatrix F(1.,relDeltaZ,0.,1.);
00847         KalMatrix Q=KalPlane::Q(ene, slope, orth_slope, KalPlane::radLen(iplane+1));
00848         pp=F*pp;
00849         if (down == -1.) Ck=(F*(Ck*F.transpose()))+Q;
00850         else if (down == +1) Ck=(F*(Ck+Q)*F.transpose());
00851     }
00852 
00853 //    if (movedDeltaZ != deltaZ) std::cout << " error KalPlane predicted ";
00854 
00855     KalHit hitpred(KalHit::PRED, pp, Ck);
00856 
00857     return hitpred;
00858 
00859 }
00860 //#######################################################
00861 KalHit KalPlane::predicted(KalPlane& kplaneNext)
00862 //#######################################################
00863 {
00864 
00865     // Extrapolate the hit to the next Kplane;
00866     // Note that GLAST trajectory is evolving in negative z coordinates.
00867     // The energy is necessary to compute the MS error.
00868 
00869     KalHit hit=getHit(KalHit::FIT);
00870 
00871     KalPar pp=hit.getPar();
00872     KalMatrix Ck=hit.getCov();
00873 
00874     double ene= getEnergy();
00875     double slope = pp.getSlope();
00876     double orth_slope = getOrthPar().getSlope();
00877 
00878     int nsteps=kplaneNext.getIDPlane()-getIDPlane();
00879 
00880     double down = -1.;
00881     if (nsteps <0) down = +1.;
00882 
00883     double deltaZ=kplaneNext.getZPlane()-getZPlane();
00884     double movedDeltaZ =0.;
00885     int iplane=getIDPlane();
00886 
00887     KalMatrix Qaccumul(0.,0.,0.);
00888 
00889     for (int istep=0; istep<abs(nsteps); istep++){
00890 
00891         double relDeltaZ = down* DetectorData::SiTracker::traySpacing();
00892         if (istep == abs(nsteps) -1) relDeltaZ = deltaZ - movedDeltaZ;
00893         movedDeltaZ+=relDeltaZ;
00894 
00895         KalMatrix F(1.,relDeltaZ,0.,1.);
00896         KalMatrix Q=KalPlane::Q(ene, slope, orth_slope, KalPlane::radLen(iplane+1));
00897 
00898         pp=F*pp;
00899         if (down == -1.) Ck=(F*(Ck*F.transpose()))+Q;
00900         else if (down == +1) Ck=(F*(Ck+Q)*F.transpose());
00901 
00902         if (down == -1.) {
00903             Qaccumul = Q + F*(Qaccumul*F.transpose());
00904         }
00905             if (down == +1.) Qaccumul = F*((Qaccumul+Q)*F.transpose());
00906     }
00907     // store the matrix with the material
00908     kplaneNext.m_Qmaterial = Qaccumul;
00909 
00910     KalHit hitpred(KalHit::PRED, pp, Ck);
00911 
00912     return hitpred;
00913 
00914 }
00915 
00916 //#######################################################
00917 KalHit KalPlane::filter()
00918 //#######################################################
00919 {
00920     // Weight the hits with their cov matricex
00921 
00922     KalHit hit1=getHit(KalHit::MEAS);
00923     KalMatrix H(1.,0.,0.,0.);
00924     KalMatrix G(1./hit1.getCov().getsiga(),0.,0.);
00925     KalPar pmeas=hit1.getPar();
00926 
00927     KalHit hit2=getHit(KalHit::PRED);
00928     KalMatrix Ckpred=hit2.getCov();
00929     KalMatrix Ckpredinv=Ckpred.invert();
00930     KalPar ppred=hit2.getPar();
00931 
00932     KalMatrix Ck=(Ckpredinv+H*(G*H)).invert();
00933     KalPar pk=((Ck*Ckpredinv)*ppred)+((Ck*G)*pmeas);
00934 
00935     KalHit hitfit(KalHit::FIT, pk, Ck);
00936 
00937     return hitfit;
00938 
00939 }
00940 
00941 //#######################################################
00942 KalHit KalPlane::smoother(const KalPlane& kplaneLast)
00943 //#######################################################
00944 {
00945     // Apply the smoother to a Fited hit!
00946     KalHit hitf0=getHit(KalHit::FIT);
00947 
00948     KalHit hitpred=kplaneLast.getHit(KalHit::PRED);
00949     KalHit hitsm=kplaneLast.getHit(KalHit::SMOOTH);
00950 
00951     // double distance=abs(kplaneLast.getZPlane()-getZPlane());
00952 
00953     // double distance=isteps*SiTracker::traySpacing();
00954     // KalMatrix F(1.,-1.*abs(distance),0.,1.);
00955 
00956     double distance=+kplaneLast.getZPlane()-getZPlane();
00957     // double distance=isteps*SiTracker::traySpacing();
00958     KalMatrix F(1.,distance,0.,1.);
00959 
00960     KalMatrix Ck=hitf0.getCov();
00961 
00962     KalMatrix Ck1pred=hitpred.getCov();
00963     KalMatrix Ck1sm=hitsm.getCov();
00964 
00965     KalPar pk=hitf0.getPar();
00966     KalPar pk1pred=hitpred.getPar();
00967     KalPar pk1sm=hitsm.getPar();
00968 
00969     KalMatrix A=Ck*((F.transpose())*Ck1pred.invert());
00970 
00971     KalPar psm=pk+A*(pk1sm-pk1pred);
00972     KalMatrix Csm=Ck+A*((Ck1sm-Ck1pred)*A.transpose());
00973 
00974     KalHit newhitsm(KalHit::SMOOTH,psm,Csm);
00975 
00976     return newhitsm;
00977 }
00978 
00979 //-------------------------------------
00980 // KalPlane Static Functions
00981 //-------------------------------------
00982 //#####################################
00983 double KalPlane::theta0ms(double ene, double cosZ, double radlen0)
00984 //#####################################
00985 {
00986     double radlen=radlen0/cosZ;
00987     double theta0=(0.0136/ene)*sqrt(radlen)*(1+0.038*log(radlen));
00988     //  double theta0 = radlen0;  // dimensionless case
00989     return theta0;
00990 }
00991 
00992 //#####################################
00993 double KalPlane::radLen(int kplane)
00994 //#####################################
00995 {
00996     double foamx0=625., siliconx0=9.36;
00997 
00998     int ipln = DetectorData::Tower::num_trays - 1 - kplane;
00999     double radlen=(DetectorData::SiTracker::convRadLen(ipln)
01000         +DetectorData::SiTracker::traySpacing()/foamx0
01001         +2.*0.02/18.
01002         +2.*DetectorData::SiTracker::siThickness()/siliconx0);
01003 
01004     //  radlen=SiTracker::convRadLen(); //dimensionless case
01005 
01006     return radlen;
01007 }
01008 
01009 //#####################################
01010 KalMatrix KalPlane::Q(double ene, double slope, double orth_slope, double radlen0)
01011 //#####################################
01012 {
01013     // WARNING - this functions uses the angle theta instead of the
01014     // slope==tan(theta) BUT it returns in Q the error for the slope
01015     double cosZ = sqrt(1./(1.+ slope*slope + orth_slope*orth_slope));
01016     double cosX = sqrt(1./(1.+ slope*slope));
01017     double theta0=KalPlane::theta0ms(ene,cosZ,radlen0);
01018     // double ocos=(1./(cosX*CosX));
01019     double ocos=(1./(cosX*cosZ));
01020     double jacovian=ocos*ocos;
01021     KalMatrix Q(0.,theta0*theta0*jacovian,0.);
01022     //  dimensionless case
01023     //  double theta0=KalPlane::theta0ms(ene,slope,radlen);
01024     //  KalMatrix Q(0.,theta0*theta0,0.);
01025     return Q;
01026 }
01027 //-------------------------------------------
01028 //   Kalman Hit
01029 //-------------------------------------------
01030 
01031 //#######################################################
01032 KalHit KalHit::changeType(TYPE typ)
01033 //#######################################################
01034 {
01035 
01036     KalHit hit;
01037 
01038     hit.type=typ;
01039     hit.par=par;
01040     hit.cov=cov;
01041 
01042     return hit;
01043 }
01044 //-------------------------------------------
01045 //   Kalman Parameter and Matrix
01046 //-------------------------------------------
01047 
01048 int KalMatrix::kfdim=2;
01049 
01050 //#####################################
01051 double operator*(const KalPar& pa, const KalPar& pb)
01052 //#####################################
01053 {
01054     double po=pa.position*pb.position+pa.slope*pb.slope;        
01055     return po;
01056 }
01057 
01058 //#####################################
01059 KalPar operator+(const KalPar& pa, const KalPar& pb)
01060 //#####################################
01061 {
01062     KalPar po(pa.position+pb.position,
01063         pa.slope+pb.slope);     
01064     return po;
01065 }
01066 
01067 //#####################################
01068 KalPar operator-(const KalPar& pa, const KalPar& pb)
01069 //#####################################
01070 {
01071     KalPar po(pa.position-pb.position,
01072         pa.slope-pb.slope);     
01073     return po;
01074 }
01075 
01076 //#####################################
01077 KalPar operator*(const KalMatrix& m, const KalPar& p)
01078 //#####################################
01079 {
01080     KalPar po(m.a[0][0]*p.position+m.a[0][1]*p.slope,
01081         m.a[1][0]*p.position+m.a[1][1]*p.slope);        
01082     return po;
01083 }
01084 
01085 //#####################################
01086 KalMatrix operator*(const KalMatrix& ma, const KalMatrix& mb)
01087 //#####################################
01088 {
01089     KalMatrix mc;
01090 
01091     for (int i=0;i<KalMatrix::kfdim;i++){
01092         for (int j=0;j<KalMatrix::kfdim;j++){   
01093             for (int k=0;k<KalMatrix::kfdim;k++){
01094                 mc.a[i][j]+=ma.a[i][k]*mb.a[k][j];
01095             }
01096         }
01097     }
01098 
01099     return mc;
01100 }
01101 
01102 //#####################################
01103 KalMatrix operator+(const KalMatrix& ma, const KalMatrix& mb)
01104 //#####################################
01105 {
01106     KalMatrix mc;
01107 
01108     for (int i=0;i<KalMatrix::kfdim;i++){
01109         for (int j=0;j<KalMatrix::kfdim;j++){   
01110             mc.a[i][j]=ma.a[i][j]+mb.a[i][j];   
01111         }
01112     }
01113 
01114 
01115     return mc;
01116 }
01117 
01118 //#####################################
01119 KalMatrix operator-(const KalMatrix& ma, const KalMatrix& mb)
01120 //#####################################
01121 {
01122     KalMatrix mc;
01123 
01124     for (int i=0;i<KalMatrix::kfdim;i++){
01125         for (int j=0;j<KalMatrix::kfdim;j++){   
01126             mc.a[i][j]=ma.a[i][j]-mb.a[i][j];   
01127         }
01128     }
01129 
01130     return mc;
01131 }
01132 
01133 //#####################################
01134 KalMatrix KalMatrix::invert()
01135 //#####################################
01136 {
01137     KalMatrix mc;
01138 
01139     double det=a[0][0]*a[1][1]-a[0][1]*a[1][0];
01140     if (det!=0.){
01141         mc.a[0][0]=a[1][1]/det;
01142         mc.a[1][0]=-1.*a[1][0]/det;
01143         mc.a[0][1]=-1.*a[0][1]/det;
01144         mc.a[1][1]=a[0][0]/det; 
01145     }
01146 
01147     return mc;
01148 }
01149 
01150 //#####################################
01151 KalMatrix KalMatrix::transpose()
01152 //#####################################
01153 {
01154     KalMatrix mc;
01155 
01156     for (int i=0;i<KalMatrix::kfdim;i++){       
01157         for (int j=0;j<KalMatrix::kfdim;j++){   
01158             mc.a[i][j]=a[j][i]; 
01159         }
01160     }
01161 
01162     return mc;
01163 }
01164 

Generated at Wed Nov 21 12:20:44 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000