Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

TrackDirectionModule.cxx

Go to the documentation of this file.
00001 
00002 //
00003 //
00004 // TrackDirectionModule
00005 //
00006 // Package: DetectorAlignment
00007 //
00008 // Contact: rustem@fnal.gov
00009 //
00010 // Created on: Fri Jul 23 15:26:05 2005
00011 //
00013 
00014 //LOCAL package headers
00015 #include "TrackDirectionModule.h"
00016 #include "NtpAlignmentRecord.h"
00017 #include "NtpAlignTrackStrip.h"
00018 
00019 //MINOS headers
00020 #include "JobControl/JobCModuleRegistry.h"
00021 #include "MessageService/MsgService.h"
00022 #include "MessageService/MsgFormat.h"
00023 #include "MinosObjectMap/MomNavigator.h"
00024 #include "Validity/VldContext.h"
00025 #include "UgliGeometry/UgliGeomHandle.h"
00026 #include "AstroUtil/AstCoordinate.h"
00027 
00028 //ROOT headers
00029 #include "TFile.h"
00030 #include "TTree.h"
00031 #include "TH1D.h"
00032 #include "TH2D.h"
00033 #include "TStopwatch.h"
00034 
00035 //C++ headers
00036 #include <cassert>
00037 #include <sstream>
00038 #include <cmath>
00039 
00040 CVSID("$Id: TrackDirectionModule.cxx,v 1.2 2005/07/30 21:25:31 rustem Exp $");
00041 
00042 JOBMODULE(TrackDirectionModule,"TrackDirectionModule","TrackDirectionModule");
00043 
00044 using namespace std;
00045 
00046 TrackDirectionModule::TrackDirectionModule()
00047    :fTrackDirectionFile(0),
00048     fRun(0),
00049     fSubRun(0),
00050     fhCosX(0),
00051     fhCosY(0),
00052     fhCosZ(0),
00053     fhTrackLength(0),
00054     f2hCosXvsCosZ(0),
00055     f2hCosYvsCosZ(0),
00056     f2hCosYvsCosX(0),
00057     fMaxTrackChargeCut(60000.0),       //cut on max 2d track charge used for alignment
00058     fMinTrackChargeCut(4000.0),        //cut on min 2d track charge used for alignment
00059     fMaxSigmaOfTPosCut(0.03),          //cut on uncertainty in tpos from 2d track fit
00060     fTrackChargeRatioCut(0.5),         //min 3d track's charge ratio to total snarl charge
00061     fMinCosZCut(0.25),                 //min fabs(cosz) of 3d track angle with Z axis
00062     fMinTrackStripChargeCut(100.0),    //min charge in a alternative track strip 
00063     fMaxTrackStripChargeCut(5000.0),   //max charge in a hit alignment strip
00064     fApplyCuts(false),
00065     fNRecords(0),
00066     fNFailedRead(0),
00067     fFailedCut(0),
00068     fNFailedCutMaxVStripCharge(0),
00069     fNFailedCutMaxUStripCharge(0),
00070     fNFailedTrackChargeCut(0),
00071     fNFailedCosZCut(0),
00072     fNFailedChargeRatioCut(0),
00073     fNFailedSigmaTPosCut(0)
00074 {
00075 }
00076 
00077 void TrackDirectionModule::BeginJob()
00078 { 
00079    MSG("TrackDir", Msg::kDebug) << "TrackDirectionModule::BeginJob()"<< endl;
00080    MSG("TrackDir", Msg::kInfo) << "Initializing variables and histograms..." << endl;
00081 
00082    string OutfilePath;
00083    const char* strENV_OUTFILE_DIR = getenv("ENV_OUTFILE_DIR");
00084    if ( strENV_OUTFILE_DIR == 0 || strlen(strENV_OUTFILE_DIR) == 0 )
00085    {
00086       MSG("TrackDir", Msg::kFatal) << "ENV_OUTFILE_DIR is not set!"
00087                                 << " Program is terminating now." <<endl;
00088       abort();
00089    } else 
00090       OutfilePath = string(strENV_OUTFILE_DIR);
00091    
00092    const char* strENV_APPLY_TRACK_CUTS = getenv("ENV_APPLY_TRACK_CUTS");
00093    if ( strENV_APPLY_TRACK_CUTS == 0 || strlen(strENV_APPLY_TRACK_CUTS) == 0 )
00094    {
00095       MSG("TrackDir", Msg::kWarning) << "ENV_APPLY_TRACK_CUTS is not set!"
00096                                   << " Using default value: fApplyCuts=" <<fApplyCuts<<endl;
00097    } else 
00098       if(atoi(strENV_APPLY_TRACK_CUTS) == 1)
00099          fApplyCuts = true;
00100       else
00101          fApplyCuts = false;
00102    
00103    
00104    MSG("TrackDir", Msg::kInfo) << "OutfilePath = " << OutfilePath << endl
00105                             << "fApplyCuts = " << fApplyCuts << endl << endl;
00106    
00107    stringstream ss;
00108    ss << OutfilePath << "/track_direction.root";
00109 
00110    fTrackDirectionFile = new TFile(ss.str().c_str(), "RECREATE");
00111    fTrackDirectionTree = new TTree("TrackDirection", "TrackDirection");
00112 
00113    fTrackDirectionTree -> Branch("Run", &fRun, "fRun/D"); 
00114    fTrackDirectionTree -> Branch("SubRun", &fSubRun, "fSubRun/D"); 
00115    fTrackDirectionTree -> Branch("CosX", &fCosX, "fCosX/D"); 
00116    fTrackDirectionTree -> Branch("CosY", &fCosY, "fCosY/D"); 
00117    fTrackDirectionTree -> Branch("CosZ", &fCosZ, "fCosZ/D"); 
00118    fTrackDirectionTree -> Branch("Length", &fLength, "fLength/D"); 
00119    fTrackDirectionTree -> Branch("Sigma", &fSigma, "fSigma/D"); 
00120    fTrackDirectionTree -> Branch("Time", &fTime, "fTime/D"); 
00121    fTrackDirectionTree -> Branch("Altitude", &fAltitude, "fAltitude/D"); 
00122    fTrackDirectionTree -> Branch("Azimuth", &fAzimuth, "fAzimuth/D"); 
00123    fTrackDirectionTree -> Branch("Charge", &fCharge, "fCharge/D"); 
00124    fTrackDirectionTree -> Branch("NStrip", &fNStrip, "fNStrip/D"); 
00125    fTrackDirectionTree -> Branch("Year", &fYear, "fYear/i"); 
00126    fTrackDirectionTree -> Branch("Month", &fMonth, "fMonth/i"); 
00127    fTrackDirectionTree -> Branch("Day", &fDay, "fDay/i"); 
00128    fTrackDirectionTree -> Branch("Hour", &fHour, "fHour/i"); 
00129    fTrackDirectionTree -> Branch("Minute", &fMinute, "fMinute/i"); 
00130    fTrackDirectionTree -> Branch("Sec", &fSec, "fSec/i"); 
00131 
00132    fhCosX = new TH1D("CosX", "Directional cosine with x axis", 100, -1.0, 1.0);
00133    fhCosY = new TH1D("CosY", "Directional cosine with y axis", 100,  0.0, 1.0);
00134    fhCosZ = new TH1D("CosZ", "Directional cosine with z axis", 100, -1.0, 1.0);
00135    fhTrackLength = new TH1D("TrackLength", "Track length in meter", 500, 0.0, 16.0);
00136    
00137    f2hCosXvsCosZ = new TH2D("CosXvsCosZ", "CosX vs CosZ", 100, -1.0, 1.0, 100, -1.0, 1.0);
00138    f2hCosYvsCosZ = new TH2D("CosYvsCosZ", "CosY vs CosZ", 100, -1.0, 1.0, 100,  0.0, 1.0);
00139    f2hCosYvsCosX = new TH2D("CosYvsCosX", "CosY vs CosX", 100, -1.0, 1.0, 100,  0.0, 1.0);   
00140 
00141    fTimer.Start();
00142    fTimerInterval.Start();
00143 }
00144 
00145 
00146 JobCResult TrackDirectionModule::Ana(const MomNavigator* mom)
00147 {
00148 
00149    NtpAlignmentRecord* ntprec =
00150       dynamic_cast<NtpAlignmentRecord*>(mom->GetFragment("NtpAlignmentRecord"));
00151    
00152    if(!ntprec)
00153       return JobCResult::kAOK;   
00154 
00155    const RecHeader hdr = ntprec->GetHeader();
00156    const VldContext vldc = hdr.GetVldContext();
00157    fRun = (ntprec -> GetHeader()).GetRun();
00158    fSubRun = (ntprec -> GetHeader()).GetSubRun();
00159    if(fNRecords % 10000 == 0){
00160       MsgFormat f("%10d");      
00161       MSG("TrackDir", Msg::kInfo) << "Found NtpAlignmentRecord #" << f(fNRecords)
00162                                   << " from run #" << fRun << ", subrun #" << fSubRun
00163                                   << ", cpu time = " << fTimerInterval.RealTime() <<endl;
00164       fTimerInterval.Reset();
00165       fTimerInterval.Start();
00166    }   
00167    
00168    fNRecords++;      
00169    
00170    if(!GetTrackRecoQuality(ntprec)){
00171       fFailedCut++;
00172       return JobCResult::kAOK;   
00173    }      
00174       
00175    //Read residuals and other strips' info to vectors of AlignmentStrips
00176    //This is the main function where lots of work is done
00177    if(!ProcessRecord(ntprec, vldc)){
00178       fFailedCut++;
00179       return JobCResult::kAOK;      
00180    }   
00181    
00182    if(GetDirectionalCosines(fCosX, fCosY, fCosZ, fLength, fSigma, vldc)){
00183       fTime = vldc.GetTimeStamp().GetSec();
00184       vldc.GetTimeStamp().GetDate(kTRUE, 0, &fYear, &fMonth, &fDay);
00185       vldc.GetTimeStamp().GetTime(kTRUE, 0, &fHour, &fMinute, &fSec);
00186       fCharge = ntprec -> ucharge + ntprec -> vcharge;
00187       fNStrip = ntprec -> ntrackustrip + ntprec -> ntrackvstrip;
00188       AstUtil::LocalToHorizon(fCosX, fCosY, fCosZ, vldc.GetDetector(), fAltitude, fAzimuth);
00189       fTrackDirectionTree -> Fill();
00190       
00191       fhCosX -> Fill(fCosX);
00192       fhCosY -> Fill(fCosY);
00193       fhCosZ -> Fill(fCosZ);
00194       fhTrackLength -> Fill(fLength);
00195       
00196       f2hCosXvsCosZ -> Fill(fCosZ, fCosX);
00197       f2hCosYvsCosZ -> Fill(fCosZ, fCosY);
00198       f2hCosYvsCosX -> Fill(fCosX, fCosY);
00199    }
00200    
00201    return JobCResult::kAOK;   
00202 }
00203 
00204 void TrackDirectionModule::EndJob()
00205 { 
00206    PrintJobStatistics();   
00207 
00208    fTrackDirectionFile -> Write();
00209    fTrackDirectionFile -> Close();
00210 
00211    MSG("TrackDir", Msg::kInfo) << "TrackDirectionModule is done." <<endl;
00212 }
00213 
00214 bool TrackDirectionModule::GetTrackRecoQuality(const NtpAlignmentRecord* ntprec)
00215 {
00216    //Check that: 1) Ratio of track charge to total charge in the current 
00217    //            record is greater than fTrackChargeRatioCut
00218    //            2) Uncertainty in tpos of a fit is less that fSigmaOfTPosCut
00219    //            3) Charge of 2d tracks is less that fTrackChargeCut
00220 
00221    if(!fApplyCuts)
00222       return true;
00223 
00224    //Cut on 2d track charge
00225    if(ntprec->vcharge > fMaxTrackChargeCut || ntprec->vcharge < fMinTrackChargeCut ||
00226       ntprec->ucharge > fMaxTrackChargeCut || ntprec->ucharge < fMinTrackChargeCut)
00227    {
00228       fNFailedTrackChargeCut++;
00229       return false;
00230    }
00231 
00232    //Cut in tpos uncertainty from linear fit to a track
00233    if(ntprec->vsigmaoftpos > fMaxSigmaOfTPosCut || ntprec->usigmaoftpos > fMaxSigmaOfTPosCut)
00234    {
00235       fNFailedSigmaTPosCut++;
00236       return false;
00237    }
00238 
00239    //Cut on 3d track Hough cos with horizontal z axis
00240    if(fabs(ntprec->hcosz) < fMinCosZCut)
00241    {
00242       fNFailedCosZCut++;
00243       return false;
00244    }
00245 
00246    const double allcharge = ntprec -> vcharge + ntprec -> ucharge
00247       + ntprec -> vcandcharge + ntprec -> ucandcharge;
00248 
00249    if(allcharge < 1.0)
00250       return false;
00251    
00252    Double_t ratio = (ntprec -> vcharge + ntprec -> ucharge)/allcharge;
00253    
00254    if(ratio < fTrackChargeRatioCut)
00255    {
00256       fNFailedChargeRatioCut++;
00257       return false;
00258    }   
00259 
00260    return true;
00261 }
00262 
00263 
00264 bool TrackDirectionModule::ProcessRecord(const NtpAlignmentRecord* ntprec, 
00265                                         const VldContext& vldc)
00266 {
00267    fTrackVStrip.clear();
00268    fTrackUStrip.clear();
00269    
00270    UgliGeomHandle ugh(vldc);   
00271 
00272    for(unsigned int i = 0; i < ntprec -> ntrackvstrip; ++i){
00273       NtpAlignTrackStrip* strip = dynamic_cast<NtpAlignTrackStrip*>(ntprec->trackvstrip->At(i));
00274       assert(strip);
00275       
00276       AlignmentStrip astrip(strip);
00277       if(fApplyCuts && astrip.charge > fMaxTrackStripChargeCut){
00278          fNFailedCutMaxVStripCharge++;
00279          return false;
00280       }
00281       
00282       PlexStripEndId plexid(astrip.plexseid);
00283       UgliStripHandle ush = ugh.GetStripHandle(plexid);
00284 
00285       astrip.plane = plexid.GetPlane();
00286       astrip.strip = plexid.GetStrip();
00287       astrip.tpos = ush.GetTPos();
00288       astrip.zpos = ush.GetScintPlnHandle().GetZ0();
00289       astrip.tposrelmdl = ush.GetTPosRelMdl();
00290       astrip.lposrelmdl = ush.GetLPosRelMdl();
00291 
00292       //use fit results in opposite view to get longitudinal position
00293       astrip.ghitpos = (ntprec -> ufita)*astrip.zpos + ntprec -> ufitb;      
00294 
00295       ConvertToLocal(astrip, plexid, ugh, ush);
00296       fTrackVStrip.push_back(astrip);
00297    }
00298 
00299 
00300    for(unsigned int i = 0; i < ntprec -> ntrackustrip; ++i){
00301       NtpAlignTrackStrip* strip = dynamic_cast<NtpAlignTrackStrip*>(ntprec->trackustrip->At(i));
00302       assert(strip);
00303       
00304       AlignmentStrip astrip(strip);      
00305       if(fApplyCuts && astrip.charge > fMaxTrackStripChargeCut){
00306          fNFailedCutMaxUStripCharge++;
00307          return false;
00308       }
00309 
00310       PlexStripEndId plexid(astrip.plexseid);
00311       UgliStripHandle ush = ugh.GetStripHandle(plexid);
00312 
00313       astrip.plane = plexid.GetPlane();
00314       astrip.strip = plexid.GetStrip(); 
00315       astrip.tpos = ush.GetTPos();
00316       astrip.zpos = ush.GetScintPlnHandle().GetZ0();
00317       astrip.tposrelmdl = ush.GetTPosRelMdl();
00318       astrip.lposrelmdl = ush.GetLPosRelMdl();
00319 
00320       //use fit results in opposite view to get longitudinal position
00321       astrip.ghitpos = (ntprec -> vfita)*astrip.zpos + ntprec -> vfitb;
00322       
00323       ConvertToLocal(astrip, plexid, ugh, ush);
00324       fTrackUStrip.push_back(astrip);
00325    }
00326 
00327    return true;
00328 }
00329 
00330 
00331 bool TrackDirectionModule::GetDirectionalCosines(Double_t &cosx, Double_t &cosy, Double_t &cosz, 
00332                                                  Double_t &length, Double_t &sigma, const VldContext &vld)
00333 {
00334    UgliGeomHandle ugh(vld);
00335    map<int, TVector3> track;
00336    for(unsigned int i = 0; i < fTrackVStrip.size(); ++i){
00337       AlignmentStrip &astrip = fTrackVStrip[i];
00338       TVector3 uvz(astrip.ghitpos, astrip.tpos, astrip.zpos);
00339       TVector3 xyz = ugh.uvz2xyz(uvz);
00340       pair <int, TVector3> p(astrip.plane, xyz);
00341       track.insert(p);
00342    }
00343    
00344    for(unsigned int i = 0; i < fTrackUStrip.size(); ++i){
00345       AlignmentStrip &astrip = fTrackUStrip[i];
00346       TVector3 uvz(astrip.tpos, astrip.ghitpos, astrip.zpos);
00347       TVector3 xyz = ugh.uvz2xyz(uvz);
00348       pair <int, TVector3> p(astrip.plane, xyz);
00349       track.insert(p);
00350    }
00351    
00352    Double_t A=0.0, B=0.0, D=0.0;
00353    Double_t Cx=0.0, Ex=0.0, Fx=0.0;
00354    Double_t Cy=0.0, Ey=0.0, Fy=0.0;
00355 
00356    int firstplane=1000, lastplane=0;
00357    for(map<int, TVector3>::const_iterator it = track.begin(); it != track.end(); ++it){
00358       const TVector3 &v = it->second;
00359       const Double_t &x = v.x();
00360       const Double_t &y = v.y();
00361       const Double_t &z = v.z();
00362       A += z, B += 1.0, D += z*z;
00363       Cx += x, Ex += z*x, Fx += x*x;
00364       Cy += y, Ey += z*y, Fy += y*y;
00365       const int &plane = it -> first;
00366       if(firstplane > plane)
00367          firstplane = plane;
00368       if(lastplane < plane)
00369          lastplane = plane;
00370    }
00371 
00372    Double_t det = B*D - A*A;
00373 
00374    if(fabs(det) < 0.000001){
00375       MSG("TrackDir", Msg::kWarning) << "Linear fit failed!" << endl;
00376       return false;
00377    }
00378    
00379    Double_t FitAx = (Ex*B-Cx*A)/det;
00380    Double_t FitAy = (Ey*B-Cy*A)/det;
00381    Double_t FitBx = (D*Cx-Ex*A)/det;
00382    Double_t FitBy = (D*Cy-Ey*A)/det;
00383 
00384    if(FitAy < 0.0)
00385       cosz = - pow(1.0/(FitAx*FitAx + FitAy*FitAy + 1.0), 0.5);
00386    else 
00387       cosz = pow(1.0/(FitAx*FitAx + FitAy*FitAy + 1.0), 0.5);
00388 
00389    cosy = fabs(FitAy*cosz);
00390    cosx = FitAx*fabs(cosz);
00391    
00392    const TVector3 &fs = track[firstplane];
00393    const TVector3 &ls = track[lastplane];
00394    TVector3 tl(fs.x()-ls.x(), fs.y()-ls.y(), fs.z()-ls.z());
00395    length = tl.Mag();
00396 
00397    Double_t sumx=0.0, sumy=0.0, npoints=0.0;
00398    for(map<int, TVector3>::const_iterator it = track.begin(); it != track.end(); ++it){
00399       const TVector3 &v = it->second;
00400       const Double_t &x = v.x();
00401       const Double_t &y = v.y();
00402       const Double_t &z = v.z();
00403       sumx += (x-FitAx*z-FitBx)*(x-FitAx*z-FitBx);
00404       sumy += (y-FitAy*z-FitBy)*(y-FitAy*z-FitBy);
00405       npoints += 1.0;
00406    }
00407    
00408    npoints = npoints - 2.0;
00409    if(npoints < 0.9){
00410       MSG("TrackDir", Msg::kWarning) << "Linear fit failed!" << endl;
00411       return false;
00412    }
00413    sigma = pow(sumx/npoints, 0.5) + pow(sumy/npoints, 0.5);
00414    return true;
00415 }
00416 
00417 
00418 void TrackDirectionModule::ConvertToLocal(AlignmentStrip &astrip,
00419                                          PlexStripEndId &plexid, 
00420                                          UgliGeomHandle &ugh,
00421                                          UgliStripHandle &ush)
00422 {
00423    // calculate the position of strip ends in (strip) local co-ordinates
00424    // x = distance along the strip, y=distance in +tpos coordinate
00425    // the "logical" strip is the one as-if there were no coil/bypass
00426    Double_t halflen = ush.GetHalfLength();
00427    //   TVector3 localCenter(0,0,0);  // center of the "logical" strip
00428    //   TVector3 localEastEnd(-halflen,0,0);
00429    TVector3 localWestEnd(+halflen, 0.0, 0.0);
00430    //   TVector3 localHitLPos(astrip.lhitpos,0,0);
00431    
00432    // calculate the positions in global XYZ space
00433    //TVector3 xyz0 = ush.LocalToGlobal(localCenter);
00434    //TVector3 xyzE = ush.LocalToGlobal(localEastEnd);
00435    //TVector3 xyzW = ush.LocalToGlobal(localWestEnd);
00436 
00437    Double_t u = 0.0, v = 0.0;
00438 
00439    if(plexid.GetPlaneView() == PlaneView::kU){
00440       v = astrip.ghitpos;
00441       u = astrip.residual + astrip.tpos;
00442    } else {
00443       u = astrip.ghitpos;
00444       v = astrip.residual + astrip.tpos;
00445    }
00446    
00447 
00448    TVector3 ghituvz(u, v, astrip.zpos);
00449    TVector3 ghitxyz = ugh.uvz2xyz(ghituvz);
00450    TVector3 lhitxyz = ush.GlobalToLocal(ghitxyz);
00451       
00452    astrip.length = 2.0*halflen;
00453    astrip.lhitpos = lhitxyz.x();
00454    astrip.pigtail = ush.WlsPigtail(StripEnd::kWest);
00455    astrip.wlsbypass = ush.WlsBypass();
00456 
00457    if(fabs(lhitxyz.x()) > halflen)
00458       astrip.goodhit = false;
00459 
00460    return;
00461 /*   
00462      double y = lhitxyz.y();
00463      double z = lhitxyz.z();
00464      fHistogram -> FillRoundingErrors(plexid, y, z);
00465      if(fabs(y + z) > 1.0e-4)
00466      MSG("TrackDir", Msg::kWarning) <<"In local coordinates y + z = " << fabs(y + z) << endl;
00467 */
00468 }
00469 
00470 
00471 void TrackDirectionModule::PrintJobStatistics()
00472 {
00473    MSG("TrackDir", Msg::kInfo) << "TrackDirectionModule::EndJob()"<< endl << endl;    
00474 
00475    MSG("TrackDir", Msg::kInfo) << "Cpu time = " << fTimer.CpuTime() <<endl;
00476    MSG("TrackDir", Msg::kInfo) << "Real time = " << fTimer.RealTime() <<endl;
00477    MSG("TrackDir", Msg::kInfo) << "fNRecords  = " << fNRecords << endl;
00478    MSG("TrackDir", Msg::kInfo) << "fFailedCut = " << fFailedCut << endl;
00479    MSG("TrackDir", Msg::kInfo) << "fNFailedRead = " << fNFailedRead << endl;
00480    MSG("TrackDir", Msg::kInfo) << "fNFailedCutMaxVStripCharge = " << fNFailedCutMaxVStripCharge <<endl;
00481    MSG("TrackDir", Msg::kInfo) << "fNFailedCutMaxUStripCharge = " << fNFailedCutMaxUStripCharge <<endl;
00482    MSG("TrackDir", Msg::kInfo) << "fNFailedTrackChargeCut  = " << fNFailedTrackChargeCut << endl;
00483    MSG("TrackDir", Msg::kInfo) << "fNFailedCosZCut  = "        << fNFailedCosZCut << endl;
00484    MSG("TrackDir", Msg::kInfo) << "fNFailedSigmaTPosCut  = "   << fNFailedSigmaTPosCut << endl;
00485    MSG("TrackDir", Msg::kInfo) << "fNFailedChargeRatioCut  = " << fNFailedChargeRatioCut << endl;
00486 }

Generated on Mon Feb 15 11:07:43 2010 for loon by  doxygen 1.3.9.1