00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00013
00014
00015 #include "TrackDirectionModule.h"
00016 #include "NtpAlignmentRecord.h"
00017 #include "NtpAlignTrackStrip.h"
00018
00019
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
00029 #include "TFile.h"
00030 #include "TTree.h"
00031 #include "TH1D.h"
00032 #include "TH2D.h"
00033 #include "TStopwatch.h"
00034
00035
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),
00058 fMinTrackChargeCut(4000.0),
00059 fMaxSigmaOfTPosCut(0.03),
00060 fTrackChargeRatioCut(0.5),
00061 fMinCosZCut(0.25),
00062 fMinTrackStripChargeCut(100.0),
00063 fMaxTrackStripChargeCut(5000.0),
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
00176
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
00217
00218
00219
00220
00221 if(!fApplyCuts)
00222 return true;
00223
00224
00225 if(ntprec->vcharge > fMaxTrackChargeCut || ntprec->vcharge < fMinTrackChargeCut ||
00226 ntprec->ucharge > fMaxTrackChargeCut || ntprec->ucharge < fMinTrackChargeCut)
00227 {
00228 fNFailedTrackChargeCut++;
00229 return false;
00230 }
00231
00232
00233 if(ntprec->vsigmaoftpos > fMaxSigmaOfTPosCut || ntprec->usigmaoftpos > fMaxSigmaOfTPosCut)
00234 {
00235 fNFailedSigmaTPosCut++;
00236 return false;
00237 }
00238
00239
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
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
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
00424
00425
00426 Double_t halflen = ush.GetHalfLength();
00427
00428
00429 TVector3 localWestEnd(+halflen, 0.0, 0.0);
00430
00431
00432
00433
00434
00435
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
00463
00464
00465
00466
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 }