StRichPIDMaker/StRichPIDMaker.cxx

00001 /****************************************************** 00002 * $Id: StRichPIDMaker.cxx,v 2.56 2007/04/28 17:56:50 perev Exp $ 00003 * 00004 * Description: 00005 * Implementation of the Maker main module. 00006 * 00007 * $Log: StRichPIDMaker.cxx,v $ 00008 * Revision 2.56 2007/04/28 17:56:50 perev 00009 * Redundant StChain.h removed 00010 * 00011 * Revision 2.55 2005/10/06 20:10:24 fisyak 00012 * persistent StMcEvent 00013 * 00014 * Revision 2.54 2004/02/11 22:33:13 perev 00015 * defence agains huge number 00016 * 00017 * Revision 2.53 2003/11/19 18:12:32 perev 00018 * Fix Float Point Exception 00019 * 00020 * Revision 2.52 2003/09/02 17:58:53 perev 00021 * gcc 3.2 updates + WarnOff 00022 * 00023 * Revision 2.51 2002/02/22 14:34:25 dunlop 00024 * Loosened cuts to match StRichSpectraMaker 00025 * 00026 * Revision 2.50 2002/02/18 22:59:34 dunlop 00027 * Keep also primaries > 1.5 GeV. Is global or primary now 00028 * 00029 * Revision 2.49 2002/02/01 16:17:34 lasiuk 00030 * include float.h to allow for use of FLT_MAX (gcc7.2) 00031 * 00032 * Revision 2.48 2001/11/12 16:16:44 jeromel 00033 * Removed unused variable 'olddist' ; unknown escape sequence `\W' fixed. 00034 * 00035 * Revision 2.47 2001/10/27 19:43:42 dunlop 00036 * Fix segfault when richCollection not present 00037 * 00038 * Revision 2.46 2001/10/02 19:20:58 horsley 00039 * modified TFile::SetFile(), ifdef'd for older versions of ROOT 00040 * 00041 * Revision 2.45 2001/09/27 00:52:43 perev 00042 * Remove call TFile::SetFormat 00043 * 00044 * Revision 2.44 2001/06/22 15:00:38 jeromel 00045 * Removed unused variables cosineOfD and oldsigma 00046 * 00047 * Revision 2.43 2001/05/29 22:04:08 dunlop 00048 * Made sure to clear mListOfRichTracks, even if event doesn't pass cuts. 00049 * Removes segvio 00050 * 00051 * Revision 2.42 2001/05/16 20:05:05 dunlop 00052 * Modified to also write into StEvent high pt hits. 00053 * 00054 * Revision 2.41 2001/04/25 00:31:40 lasiuk 00055 * HP changes. removal of reprocessTraits() 00056 * 00057 * Revision 2.40 2001/04/17 18:21:05 horsley 00058 * updated default index of refraction values, made correction to hit filter 00059 * 00060 * Revision 2.39 2001/02/22 21:10:39 lasiuk 00061 * remove debug output (dca) 00062 * 00063 * Revision 2.38 2001/02/22 21:06:05 lasiuk 00064 * fill the new StEvent structures in PidTraits, and richCollection 00065 * dca code now included 00066 * 00067 * Revision 2.37 2001/02/07 15:58:31 lasiuk 00068 * update for production (production version and StEvent changes) 00069 * refit and momentum loss are default behavior (Nikolai's parameterization) 00070 * richCollection kept as data member 00071 * reprocess the traits is default behavior 00072 * creation of PIDTraits is done earlier 00073 * 00074 * Revision 2.36 2001/02/01 17:55:29 horsley 00075 * set energy loss in CTB at 20 MeV (default) 00076 * ifdef'd out the TrackEntryClass 00077 * StRichTrack::fastEnough() has materialsDB input for wavelenght's 00078 * 00079 * Revision 2.35 2001/01/31 13:25:23 horsley 00080 * minimum number of fitpoints = 25 00081 * 00082 * Revision 2.34 2001/01/30 22:13:10 horsley 00083 * trajectory correction now default, added trajectory correction comments for log file 00084 * 00085 * Revision 2.33 2001/01/30 16:38:43 horsley 00086 * updated PID maker for next production run, included new class for TTree 00087 * 00088 * Revision 2.32 2000/12/15 01:05:49 horsley 00089 * corrected distHits entry number in hitFilter 00090 * 00091 * Revision 2.31 2000/12/15 00:05:18 horsley 00092 * added associated Mip's charge to dist ntuple 00093 * 00094 * Revision 2.30 2000/12/14 21:09:06 horsley 00095 * fixed error in filling ntuple with StTrack's momentum 00096 * 00097 * Revision 2.29 2000/12/14 19:20:48 horsley 00098 * added event run id to dist ntuple, 00099 * 00100 * added flag to bit mask in dist ntuple to indictae which checkTrack 00101 * check made entry to ntuple, 00102 * 00103 * dist ntuple has global p_vec and not local p_vec 00104 * 00105 * commented out StRichTrack pathlength check in constructor 00106 * 00107 * Revision 2.28 2000/12/08 20:09:31 horsley 00108 * updated monte carlo ntuples, member functions in StRichMCTrack, StRichPIDMaker 00109 * changed monte carlo double xCorrection = 0 in StRichTrack to xCorrection = 0 00110 * with no declaration of the double 00111 * 00112 * Revision 2.27 2000/12/08 14:59:41 horsley 00113 * thepids is now passed by reference 00114 * fillCorrectedNtuple now uses the particledefinition->pdgEncoding() 00115 * TpcHitVectorUtilites function commented out due to micro dst tpc hit 00116 * problem 00117 * 00118 * Revision 2.26 2000/12/08 06:32:48 lasiuk 00119 * fillcorrectedNtuple (ifdefs) 00120 * 00121 * Revision 2.25 2000/12/08 05:12:25 lasiuk 00122 * correct SUN iostream problem 00123 * 00124 * Revision 2.24 2000/12/08 04:54:56 lasiuk 00125 * hit filter changed for refit 00126 * fillCorrectedNTuple 00127 * energy loss 00128 * modify distup for PID 00129 * 00130 * Revision 2.23 2000/11/30 23:29:28 lasiuk 00131 * rectify constant area (pion flags) 00132 * 00133 * Revision 2.22 2000/11/28 19:21:01 lasiuk 00134 * correct memory leak in writing to StEvent 00135 * add additional WARNING for tracks without assigned MIP 00136 * 00137 * Revision 2.21 2000/11/27 17:19:40 lasiuk 00138 * fill the constant area in teh PID structure 00139 * 00140 * Revision 2.20 2000/11/26 15:08:56 lasiuk 00141 * move the setting of all flags to the pidtraits 00142 * 00143 * Revision 2.19 2000/11/25 12:27:12 lasiuk 00144 * mean angle -> psi. Fill the photonInfo. take care of flag 00145 * ambiguities where possible. Remove the old commented hitFilter 00146 * code. Store the TOTAL CONSTANT AREA and TOTAL CONSTANT AREA ON 00147 * ACTIVE PAD-PLANE 00148 * 00149 * Revision 2.18 2000/11/23 01:46:15 lasiuk 00150 * pt threshold modification 00151 * 00152 * Revision 2.17 2000/11/22 16:58:05 lasiuk 00153 * Uniform setting of flags in two places 00154 * remove dependence of dip angle on mean and sigma 00155 * 00156 * Revision 2.16 2000/11/21 19:49:13 lasiuk 00157 * fill the photon d in the StRichPid 00158 * remove parameterized dip angle dependence 00159 * of the mean/sigma d. Setting of hitflags 00160 * in fillPidTraits 00161 * 00162 * Revision 2.15 2000/11/21 16:24:22 horsley 00163 * Major overhaul of StRichArea, introduced monte carlo integration cross check, 00164 * all possible areas, angles calculated together. StRichRingCalculator, 00165 * StRichPIDMaker modified to support new StRichArea. StRichPIDMaker's hit finder 00166 * typo corrected. 00167 * 00168 * Revision 2.14 2000/11/14 22:32:50 lasiuk 00169 * order of setting flags corrected 00170 * 00171 * Revision 2.13 2000/11/07 14:30:58 lasiuk 00172 * d<3 adjustment and checkTrack() naming of varaiables 00173 * corrected 00174 * 00175 * Revision 2.12 2000/11/07 14:11:39 lasiuk 00176 * initCutParameters() and diagnositis print added. 00177 * bins for <d> and sigma_d added. 00178 * TPC hits for RICH tracks written out. 00179 * (file) ptr checked before writing ntuple. 00180 * check flags on Hits instead of ADC value 00181 * 00182 * Revision 2.11 2000/11/01 17:45:21 lasiuk 00183 * MAJOR. hitFilter overhaul. members reordered, padplane dimension kept as 00184 * a member. addition of initTuple. Additional dependencies of 00185 * min/max algorithms 00186 * 00187 * Revision 2.10 2000/10/26 20:29:55 lasiuk 00188 * move filename of ntuple into ifdef'd region 00189 * 00190 * Revision 2.9 2000/10/19 15:41:57 horsley 00191 * added set format option to TFile, file->SetFormat(1); 00192 * 00193 * Revision 2.8 2000/10/19 06:12:52 horsley 00194 * fixed pointer problem in fillPIDNtuple member function 00195 * 00196 * Revision 2.7 2000/10/19 01:13:23 horsley 00197 * added member functions to StRichPIDMaker to make cuts on hits, tracks, events. 00198 * added normal distance sigma cut on hits, quartz and radiator pathlengths 00199 * for individual photons, modified minimization routine to correct boundary 00200 * problems 00201 * 00202 * Revision 2.6 2000/10/03 19:26:01 horsley 00203 * fixed error in StRichTrack correct member function, now returns bool. 00204 * 00205 * Revision 2.5 2000/10/02 23:21:29 horsley 00206 * *** empty log message *** 00207 * 00208 * Revision 2.4 2000/10/02 23:06:33 horsley 00209 * *** empty log message *** 00210 * 00211 * Revision 2.3 2000/09/29 17:55:51 horsley 00212 * fixed bug in Minimization routine, included StMagF stuff (commented out) 00213 * changed StRichRingPoint HUGE_VALUE ---> MAXFLOAT for default value 00214 * 00215 * Revision 2.2 2000/09/29 01:35:37 horsley 00216 * Many changes, added StRichRingHits, StRichMcSwitch, TpcHitvecUtilities 00217 * Modified the StRichCalculator, StRichTracks, StRichMCTrack, StRichRingPoint 00218 * 00219 * Revision 1.5 2000/06/16 02:37:11 horsley 00220 * many additions, added features to pad plane display (MIPS, rings, etc) 00221 * along with Geant info. Added StMcRichTrack. Modified access to hit collection. 00222 * 00223 * Revision 1.3 2000/05/22 15:14:44 horsley 00224 * modified StRichRings, StRichDrawableTRings to comply with sun compiler 00225 * 00226 * Revision 1.2 2000/05/19 19:06:10 horsley 00227 * many revisions here, updated area calculation ring calc, ring, tracks , etc... 00228 * 00229 * Revision 1.1 2000/04/03 19:36:08 horsley 00230 * initial revision 00231 ******************************************************/ 00232 #include "StRichPIDMaker.h" 00233 00234 #include <map> 00235 #include <algorithm> 00236 #ifndef ST_NO_NAMESPACES 00237 using std::min; 00238 using std::max; 00239 using std::map; 00240 using std::pair; 00241 using std::make_pair; 00242 using std::less; 00243 00244 00245 #endif 00246 00247 // switches 00248 #include "StRichDisplayActivate.h" 00249 #include "StRichTrackingControl.h" 00250 #include "StRichMcSwitch.h" 00251 00252 #define myrICH_WITH_NTUPLE 1 00253 00254 00255 // StChain, etc... 00256 #include "St_DataSet.h" 00257 #include "St_DataSetIter.h" 00258 #include "StMessMgr.h" 00259 00260 // root 00261 #include "TH1.h" 00262 #include "TH3.h" 00263 #include "TNtuple.h" 00264 #include "Stiostream.h" 00265 #include <math.h> 00266 #include <float.h> 00267 #ifdef SUN 00268 #include <ieeefp.h> 00269 #endif 00270 00271 // 00272 // Pad monitor (StRichDisplayActivate) 00273 #ifdef RICH_WITH_PAD_MONITOR 00274 #include "StRichDisplayMaker/StRichDrawableTTrack.h" 00275 #include "StRichDisplayMaker/StRichDrawableTRings.h" 00276 #include "StRichDisplayMaker/StRichPadMonitor.h" 00277 #endif 00278 00279 #ifdef RICH_WITH_L3_TRACKS 00280 #include "StDaqLib/GENERIC/EventReader.hh" 00281 #include "StDaqLib/L3/L3_Reader.hh" 00282 #include "StDaqLib/TPC/trans_table.hh" 00283 #include "StDAQMaker/StDAQReader.h" 00284 #endif 00285 00286 00287 // StarClassLibrary 00288 #include "StGlobals.hh" 00289 #include "StParticleTypes.hh" 00290 #include "StParticleDefinition.hh" 00291 #include "StThreeVectorF.hh" 00292 #include "StPhysicalHelixD.hh" 00293 #include "StMemoryInfo.hh" 00294 #include "SystemOfUnits.h" 00295 #include "PhysicalConstants.h" 00296 00297 // StEvent 00298 #include "StEventTypes.h" 00299 #include "StRichPid.h" 00300 #include "StRichPhotonInfo.h" 00301 #include "StRichPidTraits.h" 00302 #include "StTpcDedxPidAlgorithm.h" 00303 00304 #include "StEventMaker/StRootEventManager.hh" 00305 00306 // StRrsMaker, StRchMaker 00307 #include "StRrsMaker/StRichGeometryDb.h" 00308 #include "StRrsMaker/StRichCoordinateTransform.h" 00309 #include "StRrsMaker/StRichEnumeratedTypes.h" 00310 #include "StRchMaker/StRichSimpleHitCollection.h" 00311 00312 // StRichPIDmaker 00313 #include "StRichRingCalculator.h" 00314 #include "StRichRingDefinition.h" 00315 #include "StRichTrack.h" 00316 #include "StRichMCTrack.h" 00317 00318 #ifdef myRICH_WITH_MC 00319 // StMCEvent 00320 #include "StMcEventTypes.hh" 00321 #include "StMcEvent.hh" 00322 00323 // StAssociationMaker 00324 #include "StAssociationMaker/StAssociationMaker.h" 00325 #include "StAssociationMaker/StTrackPairInfo.hh" 00326 00327 // g2t tables 00328 #include "tables/St_g2t_track_Table.h" 00329 #endif 00330 00331 00332 00333 #include "TObject.h" 00334 #include "TClonesArray.h" 00335 00336 #ifdef myPrivateVersion 00337 #include "TreeEntryClasses.h" 00338 #endif 00339 00340 // magnetic field map 00341 //#include "StarCallf77.h" 00342 //#define gufld F77_NAME(gufld,GUFLD) 00343 //extern "C" {void gufld(Float_t *, Float_t *);} 00344 00345 static const char rcsid[] = "$Id: StRichPIDMaker.cxx,v 2.56 2007/04/28 17:56:50 perev Exp $"; 00346 00347 StRichPIDMaker::StRichPIDMaker(const Char_t *name, bool writeNtuple) : StMaker(name) { 00348 drawinit = kFALSE; 00349 fileName = 0; 00350 kWriteNtuple=writeNtuple; 00351 00352 mTotalEvents = 0; 00353 mGoodEvents = 0; 00354 00355 // 00356 // default version 00357 mProductionVersion = -999; 00358 00359 // 00360 // initialize cuts, values and parameters for processing 00361 // 00362 00363 this->initCutParameters(); 00364 00365 } 00366 00367 StRichPIDMaker::~StRichPIDMaker() {} 00368 00369 void StRichPIDMaker::initCutParameters() { 00370 // 00371 // Event Level 00372 // 00373 mVertexWindow = 200.*centimeter; 00374 00375 00376 // 00377 // Track Level 00378 // 00379 mPtCut = 0.5*GeV; // GeV/c 00380 mEtaCut = 0.5; 00381 mLastHitCut = 100.0*centimeter; 00382 mDcaCut = 3.0*centimeter; 00383 mFitPointsCut = 20; 00384 mPathCut = 500*centimeter; 00385 mPadPlaneCut = 1.0*centimeter; 00386 mRadiatorCut = 1.0*centimeter; 00387 00388 mThresholdMomentum = 0.5*GeV; 00389 00390 // 00391 // Convergence parameter for psi determination 00392 // 00393 mPrecision = 100*micrometer; 00394 00395 } 00396 00397 Int_t StRichPIDMaker::Init() { 00398 00399 // 00400 // instantiate StParticleDefinition's and store in vector 00401 // 00402 pion = StPionMinus::instance(); 00403 kaon = StKaonMinus::instance(); 00404 proton = StAntiProton::instance(); 00405 00406 mListOfParticles.clear(); 00407 mListOfParticles.resize(3); 00408 mListOfParticles[0] = pion; 00409 mListOfParticles[1] = kaon; 00410 mListOfParticles[2] = proton; 00411 00412 // 00413 // 00414 // 00415 cout << "StRichPIDMaker::init() trajectory correction turned on." << endl; 00416 mTrackRefit = true; 00417 00418 00419 // 00420 // get data bases 00421 // 00422 mMaterialDb = StRichMaterialsDb::getDb(); 00423 mGeometryDb = StRichGeometryDb::getDb(); 00424 mCoordinateTransformation = StRichCoordinateTransform::getTransform(mGeometryDb); 00425 mMomentumTransformation = StRichMomentumTransform::getTransform(mGeometryDb); 00426 00427 // 00428 // set pad plane display pointer to zero 00429 // 00430 mPadMonitor = 0; 00431 00432 // 00433 // default for area calculation 00434 // 00435 mDoGapCorrection = true; 00436 00437 00438 // 00439 // hard coded values for now! 00440 // this->setWaveLenght(small,large) 00441 // can be used to change wavelenghts 00442 // 00443 mDefaultShortWave = 174.633e-7; 00444 mDefaultLongWave = 217.039e-7; 00445 00446 if ( (mDefaultShortWave != mShortWave) && 00447 (mDefaultLongWave != mLongWave) ) { 00448 mMaterialDb->setWavelengthRange(mDefaultShortWave,mDefaultLongWave); 00449 } 00450 00451 mPadPlaneDimension = mGeometryDb->padPlaneDimension(); 00452 mRadiatorDimension = mGeometryDb->radiatorDimension(); 00453 00454 // 00455 // print cut parameters upon initialization 00456 // 00457 this->printCutParameters(); 00458 this->initNtuples(); 00459 00460 return StMaker::Init(); 00461 } 00462 00463 00464 void StRichPIDMaker::Clear(Option_t *opt) { 00465 StMaker::Clear(); 00466 } 00467 00468 00469 Int_t StRichPIDMaker::Make() { 00470 00471 cout << "StRichPIDMaker::Make() production= "; 00472 cout << this->productionVersion() << endl; 00473 00474 mPrintThisEvent = false; 00475 mNumberOfRingHits=0; 00476 mTotalEvents++; 00477 00478 00479 #ifdef myRICH_WITH_MC 00480 // StMcEvent 00481 mEvent = 0; 00482 mEvent = ((StMcEvent*) GetDataSet("StMcEvent"); 00483 if (!mEvent) { 00484 cout << "StRichPIDMaker:Make() ---> No StMcEvent! Return kStWarn." << endl; 00485 return kStWarn; 00486 } 00487 #endif 00488 00489 00490 // 00491 // grab StEvent 00492 // 00493 StEvent* rEvent; 00494 rEvent = (StEvent *) GetInputDS("StEvent"); 00495 00496 00497 // 00498 // Load vertex and number of primaries 00499 // 00500 // JCD 5/16/01 moved bail to later. 00501 bool goodRichEvent = this->checkEvent(rEvent); 00502 // but bail if no StEvent or vertex 00503 if (!rEvent) { 00504 cout << "StRichPIDMaker::Make()\n"; 00505 cout << "\tWarning: No StEvent" << endl; 00506 return kStWarn; 00507 } 00508 if (!rEvent->primaryVertex()) { 00509 cout << "StRichPIDMaker::Make()\n"; 00510 cout << "\tWarning: No vertex" << endl; 00511 return kStWarn; 00512 } 00513 00514 00515 if (goodRichEvent) { 00516 mGoodEvents++; 00517 } 00518 00519 // 00520 // Initialize Parameters 00521 // 00522 00523 mRichTracks = 0; 00524 mNumberOfPrimaries = 0; 00525 mNegativePrimaries = 0; 00526 00527 // 00528 // get hits, clusters, pixels from StEvent 00529 // 00530 //const 00531 const StSPtrVecRichHit* pRichHits = 0; 00532 const StSPtrVecRichCluster* pRichClusters = 0; 00533 const StSPtrVecRichPixel* pRichPixels = 0; 00534 00535 int myRichHits = 0; 00536 int myRichPixels = 0; 00537 // Reorganized JCD 5/16/01. Used to be that you would bail. 00538 StRichCollection* richCollection=0; 00539 00540 if (goodRichEvent) { 00541 richCollection = rEvent->richCollection(); 00542 mRichCollection = richCollection; 00543 if (richCollection) { 00544 if (richCollection->pixelsPresent()) { 00545 myRichPixels = richCollection->getRichPixels().size(); 00546 const StSPtrVecRichPixel& richPixels = 00547 richCollection->getRichPixels(); 00548 pRichPixels = &richPixels; 00549 } 00550 00551 if (richCollection->clustersPresent()) { 00552 const StSPtrVecRichCluster& richClusters = 00553 richCollection->getRichClusters(); 00554 pRichClusters = &richClusters; 00555 } 00556 00557 if (richCollection->hitsPresent()) { 00558 const StSPtrVecRichHit& richHits = 00559 richCollection->getRichHits(); 00560 pRichHits = &richHits; 00561 if(pRichHits) 00562 myRichHits = pRichHits->size(); 00563 } 00564 // 00565 // LOAD TRACKS intersecting RICH 00566 // 00567 if (pRichHits) { 00568 00569 mNumberOfPrimaries = this->fillTrackList(rEvent,pRichHits); 00570 mRichTracks = mListOfStRichTracks.size(); 00571 } 00572 else { 00573 cout << "\trichCollection but no Hits: clearing richtracklist" << endl; 00574 this->clearTrackList(); 00575 } 00576 00577 } 00578 else { //need to clear the list: persistent across events 00579 cout << "\tNo richCollection: clearing richtracklist" << endl; 00580 this->clearTrackList(); 00581 } 00582 } 00583 else { // need to clear the list: persistent across events 00584 this->clearTrackList(); 00585 } 00586 00587 00588 // 00589 // Check if the tpcHitCollection Exists 00590 // If it does, be sure the hits which 00591 // are associated with the StTrack are there, 00592 // otherwise, put them there 00593 // 00594 size_t ii; 00595 00596 if(!rEvent->tpcHitCollection()) { 00597 //cout << "StRichPIDMaker:Make()\n"; 00598 //cout << "\tNo StTpcHitCollection\n"; 00599 //cout << "\tTry make one" << endl; 00600 StTpcHitCollection* theTpcHitCollection = new StTpcHitCollection(); 00601 rEvent->setTpcHitCollection(theTpcHitCollection); 00602 00603 //cout << "\tMake an StRootEventManager" << endl; 00604 StRootEventManager* theEvtManager = new StRootEventManager(); 00605 theEvtManager->setMaker(this); 00606 00607 //cout << "\tQuery to the .dst" << endl; 00608 int status = theEvtManager->openEvent("dst"); 00609 if(status == oocError) { 00610 cout << "StRichPIDMaker::Make()\n"; 00611 cout << "\tWARNING:\n"; 00612 cout << "\tCannot Open dataset \"dst\""; 00613 cout << "\tCannot make the StTpcHitCollection\n" << endl; 00614 } 00615 else { 00616 long nrows; 00617 dst_point_st* dstPoints = theEvtManager->returnTable_dst_point(nrows); 00618 00619 if(!dstPoints) { 00620 cout << "StRichPIDMaker::Make()\n"; 00621 cout << "\tWARNING: Cannot get the dstPoints\n"; 00622 cout << "\tContinuing..." << endl; 00623 } 00624 else { 00625 // Begin changes for high pt writing. JCD 5/16/01. 00626 // Use a map to avoid duplication of keys. Avoids having to sort on pointer. 00627 #ifndef ST_NO_TEMPLATE_DEF_ARGS 00628 typedef map < unsigned short, StTrack*> trackKeyToTrackMapType; 00629 #else 00630 typedef map < unsigned short, StTrack*, less<unsigned short>, allocator < OS_PAIR<unsigned short, StTrack* > > trackKeyToTrackMapType; 00631 #endif 00632 trackKeyToTrackMapType trackKeyToTrack; 00633 00634 if (goodRichEvent) { 00635 00636 for (ii=0; ii<mListOfStRichTracks.size(); ++ii) { 00637 StTrackNode* theTrackNode = mListOfStRichTracks[ii]->getStTrack()->node(); 00638 for (size_t jj=0; jj<theTrackNode->entries(); ++jj) { 00639 00640 StTrack* currentTrack = theTrackNode->track(jj); 00641 if (currentTrack->bad()) continue; 00642 00643 if(!currentTrack->detectorInfo()) { 00644 cout << "StRichPIDMaker::Make()\n"; 00645 cout << "\tWARNING: No detectorInfo()\n"; 00646 cout << "\tassocciated with the track. Continuing..." << endl; 00647 continue; 00648 } 00649 trackKeyToTrack.insert(make_pair(currentTrack->key(),currentTrack)); 00650 00651 break; 00652 } 00653 } 00654 } 00655 00656 // Now the global tracks that high pt wants. 00657 StSPtrVecTrackNode& theNodes = rEvent->trackNodes(); 00658 for (size_t nodeIndex = 0; nodeIndex<theNodes.size(); ++nodeIndex) { 00659 StTrackNode* theTrackNode = theNodes[nodeIndex]; 00660 // Anything 00661 for (size_t globalIndex=0; globalIndex<theTrackNode->entries();++globalIndex) { 00662 StTrack* currentTrack = theTrackNode->track(globalIndex); 00663 if (currentTrack->bad()) continue; 00664 // Hard coded cuts on global pt and eta 00665 if (currentTrack->geometry()->momentum().perp()>=1.5 00666 && 00667 fabs(currentTrack->geometry()->momentum().pseudoRapidity())<1. 00668 && 00669 currentTrack->flag()>=0) { 00670 if(!currentTrack->detectorInfo()) { 00671 cout << "StRichPIDMaker::Make()\n"; 00672 cout << "\tWARNING: No detectorInfo()\n"; 00673 cout << "\tassocciated with the track. Continuing..." << endl; 00674 continue; 00675 } 00676 trackKeyToTrack.insert(make_pair(currentTrack->key(),currentTrack)); 00677 00678 break; 00679 } 00680 } 00681 } 00682 00683 cout << "StRichPIDMaker::Make(): Adding hits to " << trackKeyToTrack.size() << " tracks" << endl; 00684 cout << "\t " << mListOfStRichTracks.size() << " Rich Tracks " << endl; 00685 00686 00687 // This can be made more efficient if necessary with multimaps. 00688 00689 for(trackKeyToTrackMapType::const_iterator titer= trackKeyToTrack.begin(); 00690 titer!=trackKeyToTrack.end(); ++titer) { 00691 00692 StTrack* currentTrack = (*titer).second; 00693 if (currentTrack->bad()) continue; 00694 00695 if(!currentTrack->detectorInfo()) { 00696 cout << "StRichPIDMaker::Make()\n"; 00697 cout << "\tWARNING: No detectorInfo()\n"; 00698 cout << "\tassocciated with the track. Continuing..." << endl; 00699 continue; 00700 } 00701 00702 unsigned short trackKey = currentTrack->key(); 00703 for(int i=0; i<nrows; i++) { //nrows 00704 if(dstPoints[i].id_track != trackKey) continue; 00705 StTpcHit* tpcHit = new StTpcHit(dstPoints[i]); 00706 00707 // 00708 // add the hit to the tpcHitCollection which 00709 // will own and manage the memory for the hit 00710 // while we must also add it to the detectorInfo() 00711 // of the current track, as this is how we will 00712 // access it later 00713 // 00714 if(theTpcHitCollection->addHit(tpcHit)) { 00715 currentTrack->detectorInfo()->addHit(tpcHit); 00716 } 00717 00718 } // loop over the hits 00719 } // loop over the map entries 00720 delete theEvtManager; 00721 theEvtManager=0; 00722 } // else Got 'em 00723 } // else 00724 } // check on the tpcHitCollection 00725 00726 // 00727 // The StTpcHitCollection should exist at this 00728 // point whether it is created by the PIDMaker 00729 // or not 00730 00731 // Now bail. JCD 5/16/2001 00732 if (!goodRichEvent) return kStWarn; 00733 if (!richCollection) { 00734 cout << "StRichPIDMaker::Make()\n"; 00735 cout << "\tWARNING: Cannot get richCollection from StEvent\n"; 00736 cout << "\tSkip Event" << endl; 00737 return kStWarn; 00738 } 00739 00740 00741 00742 // 00743 // This is the beginning of the main PID loop 00744 // 00745 00746 #ifdef RICH_WITH_PAD_MONITOR 00747 00748 // 00749 // if pad plane display monitor is active 00750 // get pointer and clear display 00751 // 00752 mPadMonitor=StRichPadMonitor::getInstance(mGeometryDb); 00753 mPadMonitor->clearMisc(); 00754 #endif 00755 00756 00757 StPtrVecHit tpcHits; 00758 StRichRingCalculator* ringCalc; 00759 00760 for (ii=0; ii<mListOfStRichTracks.size(); ii++) { 00761 00762 StRichTrack* richTrack = mListOfStRichTracks[ii]; 00763 00764 if (mTrackRefit) richTrack->correctTrajectory(); 00765 00766 // 00767 // for the refit assign the residual. Note 00768 // there is no energy loss associated with 00769 // this residual. It would require us to 00770 // assume a PID. This will be done later in 00771 // the StRichPid structure 00772 // 00773 00774 StThreeVectorF refitResidual(-999.,-999.,-999.); 00775 00776 if(richTrack->getAssociatedMIP()) { 00777 refitResidual = richTrack->getProjectedMIP() - richTrack->getAssociatedMIP()->local(); 00778 } 00779 richTrack->getPidTrait()->setRefitResidual(refitResidual); 00780 00781 if(richTrack->getStTrack()->detectorInfo()) 00782 tpcHits = richTrack->getStTrack()->detectorInfo()->hits(kTpcId); 00783 00784 // 00785 // This is the place for the track refit to be 00786 // done using the tpcHits 00787 // 00788 // unsigned short numberOfTpcHits = tpcHits.size(); 00789 // cout << "We have " << numberOfTpcHits 00790 // << " TPC hits to work with" << endl; 00791 // for(size_t zz=0; zz<numberOfTpcHits; zz++) 00792 // cout << "\t" << zz << " " << tpcHits[zz]->position() 00793 // << " row " << dynamic_cast<StTpcHit*>(tpcHits[zz])->padrow() 00794 // << endl; 00795 00796 // 00797 // Loop over the particle hypothesis 00798 // 00799 for (size_t iParticle=0; iParticle<mListOfParticles.size(); iParticle++) { 00800 00801 // 00802 // check if track is above Cherenkov threshold for this species 00803 // and if the back portion of the ring is not refracted away 00804 // 00805 if ( richTrack->fastEnough(mListOfParticles[iParticle]) && 00806 richTrack->isGood(mListOfParticles[iParticle]) ) { 00807 00808 ringCalc = new StRichRingCalculator(richTrack,mListOfParticles[iParticle]); 00809 00810 // 00811 // calculate all areas, angles using default input parameters 00812 // gap correction on, no angle cut 00813 // (but the constant area is still ok) and 00814 // number of points used in calculation == 3600 00815 // 00816 ringCalc->calculateArea(); 00817 00818 00819 // 00820 // assign the points to the pi/K/p rings 00821 // 00822 this->hitFilter(pRichHits,ringCalc); 00823 00824 00825 // 00826 // fill PID traits 00827 // 00828 00829 this->fillPIDTraits(ringCalc); 00830 00831 delete ringCalc; 00832 ringCalc = 0; 00833 } 00834 00835 } // loop over particles 00836 00837 } // loop over all tracks 00838 00839 00840 // 00841 // now that we have looked at all the photons for all 00842 // tracks we can set the bit flags properly 00843 // 00844 00845 00846 // 00847 // Original reprocssing of the hit flags to 00848 // make sure the multiply used bit is set properly 00849 // and uniformly 00850 // For the refit it is not needed (or desired) 00851 // 00852 00853 for (ii=0; ii<mListOfStRichTracks.size(); ii++) { 00854 00855 StRichTrack* richTrack = mListOfStRichTracks[ii]; 00856 00857 StRichPidTraits* theTraits = richTrack->getPidTrait(); 00858 00859 if(!theTraits) { 00860 cout << "StRichPIDMaker::Make()\n"; 00861 cout << "\tERROR Processing the PIDTraits\n"; 00862 cout << "\tContinuing..." << endl; 00863 continue; 00864 } 00865 00866 00867 // 00868 // reprocessTheTraits is commented out for now 00869 // 00870 // if(!this->reprocessTheTraits(theTraits)) { 00871 // // 00872 // // if necessary I can take action here 00873 // // 00874 // cout << "StRichPIDMaker::Make()\n"; 00875 // cout << "\treprocessTheTraits() failed." << endl; 00876 // } 00877 00878 // 00879 // fill the StTrack's StRichPidTrait with RICH PID info 00880 // 00881 StTrack* track = richTrack->getStTrack(); 00882 if (track && !track->bad()) { 00883 00884 // 00885 // add pid 00886 // 00887 track->addPidTraits(richTrack->getPidTrait()); 00888 00889 00890 #ifdef myPrivateVersion 00891 // 00892 // here i will fill the tree 00893 // 00894 m_Track->addTrackInfo(richTrack,rEvent,mMaterialDb, 00895 mListOfStRichTracks.size(),mNegativePrimaries); 00896 00897 // pion 00898 vector<StRichRingHit*> piHits = richTrack->getRingHits(pion); 00899 for (int i=0;i<piHits.size();i++) { 00900 HitEntry tempHit(piHits[i]->getHit()->local().x(),piHits[i]->getHit()->local().y(), 00901 piHits[i]->getDist(), piHits[i]->getNSigma(), 00902 piHits[i]->getAngle()/degree, 00903 pion->pdgEncoding(),piHits[i]->getHit()->charge(), 00904 (*pRichClusters)[piHits[i]->getHit()->clusterNumber()]->numberOfPads(), 00905 piHits.size()); 00906 m_Track->addHit(tempHit); 00907 } 00908 00909 // kaon 00910 vector<StRichRingHit*> kaHits = richTrack->getRingHits(kaon); 00911 for (int i=0;i<kaHits.size();i++) { 00912 HitEntry tempHit(kaHits[i]->getHit()->local().x(),kaHits[i]->getHit()->local().y(), 00913 kaHits[i]->getDist(), kaHits[i]->getNSigma(), 00914 kaHits[i]->getAngle()/degree, 00915 kaon->pdgEncoding(),kaHits[i]->getHit()->charge(), 00916 (*pRichClusters)[kaHits[i]->getHit()->clusterNumber()]->numberOfPads(), 00917 kaHits.size()); 00918 m_Track->addHit(tempHit); 00919 } 00920 00921 00922 // proton 00923 vector<StRichRingHit*> prHits = richTrack->getRingHits(proton); 00924 for (int i=0;i<prHits.size();i++) { 00925 HitEntry tempHit(prHits[i]->getHit()->local().x(),prHits[i]->getHit()->local().y(), 00926 prHits[i]->getDist(), prHits[i]->getNSigma(), 00927 prHits[i]->getAngle()/degree, 00928 proton->pdgEncoding(),prHits[i]->getHit()->charge(), 00929 (*pRichClusters)[prHits[i]->getHit()->clusterNumber()]->numberOfPads(), 00930 prHits.size()); 00931 m_Track->addHit(tempHit); 00932 } 00933 00934 myTree->Fill(); 00935 m_Track->clear(); 00936 #endif 00937 } 00938 00939 else { 00940 cout << "StRichPIDMaker::Make()\n"; 00941 cout << "\tCannot fill the PidTrait to the StTrack" << endl; 00942 cout << "\tContinuing..." << endl; 00943 } 00944 richTrack = 0; 00945 } 00946 // 00947 // end of PID loop 00948 // 00949 00950 00951 00952 00953 // 00954 // draw rings on padplane, fill software monitor 00955 // 00956 #ifdef RICH_WITH_PAD_MONITOR 00957 this->drawPadPlane(rEvent,mPrintThisEvent); 00958 #endif 00959 00960 this->fillRichSoftwareMonitor(rEvent); 00961 00962 00963 #ifdef myRICH_WITH_MC 00964 if (kWriteNtuple) this->fillMcTrackNtuple(pRichClusters); 00965 if (kWriteNtuple) this->fillMcPixelNtuple(pRichPixels); 00966 if (kWriteNtuple) this->fillMcPhotonNtuple(mEvent,pRichClusters,pRichHits); 00967 if (kWriteNtuple) this->fillGeantHitNtuple(); 00968 #endif 00969 00970 return kStOK; 00971 } 00972 00973 00974 Int_t StRichPIDMaker::Finish() { 00975 00976 cout << "StRichPIDMaker::Finish()" << endl; 00977 this->printCutParameters(); 00978 00979 #ifdef myRICH_WITH_NTUPLE 00980 if(file) { 00981 cout << "StRichPIDMaker::Finish() writing file ...." << endl; 00982 file->Write(); 00983 file->Close(); 00984 delete file; 00985 file = 0; 00986 cout << "StRichPIDMaker::Finish() done writing file." << endl; 00987 } 00988 #endif 00989 00990 cout << "Total Number of Events = " << mTotalEvents << endl; 00991 cout << "Total Number of Events that passed cuts = " << mGoodEvents << endl; 00992 00993 return kStOK; 00994 } 00995 00996 void StRichPIDMaker::setTrackRefit(bool refit) {mTrackRefit = refit;} 00997 00998 void StRichPIDMaker::clearTrackList() { 00999 01000 for (size_t trackIndex=0; trackIndex<mListOfStRichTracks.size(); trackIndex++) { 01001 delete mListOfStRichTracks[trackIndex]; 01002 mListOfStRichTracks[trackIndex] = 0; 01003 } 01004 mListOfStRichTracks.clear(); 01005 mListOfStRichTracks.resize(0); 01006 } 01007 01008 Int_t StRichPIDMaker::fillTrackList(StEvent* tempEvent, 01009 const StSPtrVecRichHit* richHits) { 01010 01011 mNumberOf1GeV=0; 01012 this->clearTrackList(); 01013 01014 mNumberOfPrimaries = tempEvent->primaryVertex()->numberOfDaughters(); 01015 01016 for (int ii=0; ii<mNumberOfPrimaries; ii++) { 01017 01018 StTrack* track = tempEvent->primaryVertex()->daughter(ii); 01019 01020 if (this->checkTrack(track)) { 01021 01022 #ifdef myRICH_WITH_MC 01023 StRichMCTrack* tempTrack = new StRichMCTrack(track,mMagField); 01024 cout << "StRichPIDMaker::fillTrackList() --> creating StMcTrack!" 01025 << endl; 01026 #else 01027 StRichTrack* tempTrack = new StRichTrack(track,mMagField); 01028 #endif 01029 // 01030 // we need theGlobalTrack to calculate the signed dca 01031 // 01032 StTrack* theGlobalTrack = track->node()->track(global); 01033 01034 if(!theGlobalTrack->bad() && this->checkTrack(tempTrack)) { 01035 01036 // 01037 // set the eAssociatedMIP flag 01038 // 01039 tempTrack->assignMIP(richHits); 01040 01041 if (tempTrack->getMomentum().mag()>1) 01042 mNumberOf1GeV++; 01043 01044 // 01045 // Create an StRichPidTrait and fill the information 01046 // - productionNumber 01047 // - associatedMip Pointer 01048 // - associatedMip Residual 01049 // 01050 01051 StRichPidTraits* theRichPidTraits = new StRichPidTraits(); 01052 01053 StRichHit* theAssociatedMip = 0; 01054 StThreeVectorD theMipResidual(-999.,-999.,-999.); 01055 01056 if (!tempTrack->getAssociatedMIP()) { 01057 cout << "StRichPIDMaker::fillTrackList()\n"; 01058 cout << "\tWARNING Rich Track has no AssociatedMIP\n"; 01059 cout << "\tp= " 01060 << tempTrack->getStTrack()->geometry()->momentum().mag() 01061 << endl; 01062 } 01063 else { 01064 theAssociatedMip = tempTrack->getAssociatedMIP(); 01065 theMipResidual = 01066 tempTrack->getProjectedMIP() - theAssociatedMip->local(); 01067 } 01068 01069 theRichPidTraits->setProductionVersion(mProductionVersion); 01070 01071 theRichPidTraits->setAssociatedMip(theAssociatedMip); 01072 theRichPidTraits->setMipResidual(theMipResidual); 01073 01074 double signed3dDca = -999.; 01075 double signed2dDca = -999.; 01076 01077 if(theGlobalTrack) { 01078 signed3dDca = this->calculateSignedDca(theGlobalTrack, &signed2dDca); 01079 } 01080 // PR(signed2dDca); 01081 // PR(signed3dDca); 01082 01083 theRichPidTraits->setSignedDca2d(signed2dDca); 01084 theRichPidTraits->setSignedDca3d(signed3dDca); 01085 01086 mRichCollection->addTrack(tempTrack->getStTrack()); 01087 01088 // 01089 // Add the StRichPidTrait to the StRichTrack 01090 // ...this will be passed to StEvent 01091 // (NO RESPONSIBILITY FOR MEMORY) 01092 // This will show up as a memory leak 01093 // 01094 01095 tempTrack->addPidTrait(theRichPidTraits); 01096 01097 // 01098 // energy loss for CTB 01099 // 01100 tempTrack->setMomentumLoss(); 01101 01102 mListOfStRichTracks.push_back(tempTrack); 01103 } 01104 else { 01105 delete tempTrack; 01106 tempTrack=0; 01107 } 01108 } 01109 // if (tempTrack->geometry()->charge() < 0) { 01110 if (tempEvent->primaryVertex()->daughter(ii)->geometry()->charge() < 0) { 01111 mNegativePrimaries++; 01112 } 01113 } 01114 01115 // 01116 // make monte carlo associations 01117 // 01118 #ifdef myRICH_WITH_MC 01119 if (!makeTrackAssociations(mEvent,richHits)) { 01120 cout << "can not make track associations. Return kStWarn! " << endl; 01121 return kStWarn; 01122 } 01123 #endif 01124 01125 cout << "StRichPIDMaker::trackList=" << mListOfStRichTracks.size() << endl; 01126 return mNumberOfPrimaries; 01127 } 01128 01129 01130 Float_t StRichPIDMaker::calculateSignedDca(const StTrack* track, double* dca2d) { 01131 01132 // 01133 // Calculation of the signed dca to the vertex 01134 // -- the 3d value is the function return value 01135 // -- the 2d value is returned by pointer 01136 // 01137 01138 StHelixD aHelix = track->geometry()->helix(); 01139 01140 double dca3d = aHelix.distance(mVertexPos); 01141 01142 // 01143 // now determine the sign 01144 // 01145 StThreeVectorD circleCenter(aHelix.xcenter(), aHelix.ycenter(), 0.); 01146 01147 StThreeVectorD vertex2d(mVertexPos.x(), mVertexPos.y(), 0.); 01148 01149 double distanceToCircleCenterFromVertex = 01150 abs(circleCenter - vertex2d); 01151 01152 *dca2d = 01153 (1./aHelix.curvature() - distanceToCircleCenterFromVertex); 01154 01155 double signOfDca = sign((*dca2d)); 01156 01157 return (signOfDca * dca3d); 01158 } 01159 01160 void StRichPIDMaker::hitFilter(const StSPtrVecRichHit* richHits, 01161 StRichRingCalculator* ringCalculator) { 01162 01163 // 01164 // make sure the hits exist 01165 // 01166 if(!richHits) { 01167 cout << "StRichPIDMaker::hitFilter()\n"; 01168 cout << "\tERROR no hits..." << endl; 01169 return; 01170 } 01171 01172 StThreeVectorF pointOnRing; 01173 StRichTrack* currentTrack = ringCalculator->getRing(eInnerRing)->getTrack(); 01174 01175 if(!currentTrack) { 01176 cout << "StRichPIDMaker::hitFilter()\n"; 01177 cout << "\tERROR no track" << endl; 01178 return; 01179 } 01180 01181 StThreeVectorF trackMomentum = currentTrack->getMomentum(); 01182 01183 if(!checkTrackMomentum(abs(trackMomentum))) return; 01184 01185 StRichHit* centralHit = currentTrack->getAssociatedMIP(); 01186 if(!centralHit) { 01187 cout << "StRichPIDMaker::hitFilter()\n"; 01188 cout << "\tERROR no associated MIP" << endl; 01189 return; 01190 } 01191 01192 // 01193 // Possible to take action if the central 01194 // hit is not classified as a MIP 01195 // 01196 if( !centralHit->isSet(eMip) ) { 01197 cout << "StRichPIDMaker::hitFilter()\n"; 01198 cout << "\tWARNING!\n"; 01199 cout << "\tCentral Hit is not classified as\n"; 01200 cout << "\ta MIP q=(" << centralHit->charge() << ")\n"; 01201 cout << "\tContinuing...for now..." << endl; 01202 //return; 01203 } 01204 01205 StThreeVectorF central = centralHit->local(); 01206 // os << "CENTRAL HIT: " << central << endl; 01207 01208 // 01209 // Careful in assignment of projected MIP the position 01210 // is taken at the Anode wire plane 01211 // 01212 StThreeVectorF mipResidual = 01213 ( central - currentTrack->getProjectedMIP() ); 01214 01215 StParticleDefinition* particle = 01216 ringCalculator->getRing(eInnerRing)->getParticleType(); 01217 int particleType = particle->pdgEncoding(); 01218 // os << "particleType " << particleType << endl; 01219 01220 01221 // os << "Drawing central " << central << endl; 01222 #ifdef RICH_WITH_PAD_MONITOR 01223 mPadMonitor->drawMarker(central); 01224 #endif 01225 01226 // os << "LOOP OVER HITS start" << endl; 01227 01228 // 01229 // loop over hits 01230 // 01231 int photonNumber=0; 01232 const int maxIterForInitialPsi = 40; 01233 const int maxIterForRingPsi = 50; 01234 01235 StSPtrVecRichHitConstIterator hitIter; 01236 for (hitIter = richHits->begin(); 01237 hitIter != richHits->end(); hitIter++) { 01238 01239 if( (*hitIter) == centralHit) continue; 01240 if ( !(*hitIter)->isSet(ePhotoElectron) ) continue; 01241 01242 ringCalculator->clear(); 01243 StThreeVectorF hit = (*hitIter)->local(); 01244 01245 // 01246 // we are waiting for the database 01247 // Disregard any hit that is in the first column (FENCE POST) 01248 // 01249 if( hit.x()<-65 ) continue; 01250 01251 // 01252 // OLD VARIABLE CALCULATION 01253 // 01254 innerDistance = ringCalculator->getInnerDistance(hit,innerAngle); 01255 outerDistance = ringCalculator->getOuterDistance(hit,outerAngle); 01256 meanDistance = ringCalculator->getMeanDistance(hit,meanAngle); 01257 ringWidth = ringCalculator->getRingWidth(); 01258 double quartzPath = ringCalculator->getMeanPathInQuartz(); 01259 double radPath = ringCalculator->getMeanPathInRadiator(); 01260 01261 // double olddist = ((outerDistance/ringWidth > 1 && 01262 // (innerDistance/ringWidth < outerDistance/ringWidth )) ? 01263 // (-1.0):(1.0))*innerDistance/ringWidth; 01264 // double oldsigma = this->getHitSigma(olddist); 01265 01266 01267 photonNumber++; 01268 // os << "\n***\noldsigma " << oldsigma << endl; 01269 // os << "looping hit" << hit << endl; 01270 01271 #ifdef RICH_WITH_PAD_MONITOR 01272 // mPadMonitor->drawMarker(hit,26); 01273 #endif 01274 01275 // 01276 // Find the angle Psi on the inner ring that intersects 01277 // the line from the MIP to the hit 01278 // 01279 StThreeVectorF referenceLine = (hit-central); 01280 if (referenceLine.mag()<1.e-10) continue; 01281 // os << "referenceLine " << referenceLine << endl; 01282 #ifdef RICH_WITH_PAD_MONITOR 01283 //mPadMonitor->drawLine(central,hit); 01284 #endif 01285 // 01286 // Find the minimum distance to the InnerRing 01287 // from the hit 01288 // 01289 // float idist = ringCalculator->getInnerDistance(hit,innerAngle); 01290 // os << "idist " << idist << "\tinnerAngle " << innerAngle << endl; 01291 01292 ringCalculator->getRing(eInnerRing)->getPoint(innerAngle,pointOnRing); 01293 if(pointOnRing.x() == FLT_MAX) { 01294 // os << "StRichPIDMaker::hitFilter()\n"; 01295 // os << "\tPANIC\n"; 01296 // os << "\tINITIAL ANGLE DOES NOT CORRESPOND"; 01297 // os << "\tTO A POINT ON THE PAD PLANE. SKIP" << endl; 01298 continue; 01299 } 01300 // os << "pointOnRing" << pointOnRing << endl; 01301 01302 StThreeVectorF ringPointLine = pointOnRing - central; 01303 // os << "ringPointLine " << ringPointLine << endl; 01304 01305 double psi = innerAngle; 01306 // os << "psi " << psi << endl; 01307 01308 // 01309 // Find the distance of closest approach from the ring 01310 // point to the reference line: 01311 // 01312 // ^ ^ 01313 // | A | A x B 01314 // 01315 // where: 01316 // A = ringPointLine 01317 // B = referenceLine 01318 // 01319 // z component = 01320 // AxBy - AyBx 01321 // 01322 01323 int signOfTheta = 01324 sign(ringPointLine.x()*referenceLine.y() - ringPointLine.y()*referenceLine.x()); 01325 double sineTheta = abs( (ringPointLine.unit()).cross(referenceLine.unit()) ); 01326 // os << "sineTheta* (" << signOfTheta << ") " << sineTheta << endl; 01327 01328 float minDistToRefLine = 01329 fabs(ringPointLine.mag())* sineTheta; 01330 // os << "minDistToRefLine " << minDistToRefLine << endl; 01331 01332 01333 StThreeVectorF newPointOnRing; 01334 bool anotherIteration = true; 01335 bool convergence = false; 01336 01337 double step = 1.*degree; 01338 double maxChange = 5.*degree; 01339 01340 // 01341 // take the initial step according to the sign of theta 01342 // 01343 01344 if(signOfTheta<0) step *= -1.; 01345 // os << "initial step " << step << endl; 01346 01347 int ctr = 0; 01348 while (anotherIteration && ctr<maxIterForInitialPsi) { 01349 01350 // 01351 // make sure you are in range 01352 // 01353 // if(psi>0 && psi>M_PI) { 01354 // os << "Adjustment (-1)" << endl; 01355 // psi -= (2.*M_PI); 01356 // step *= -1.; 01357 // } 01358 // if(psi<0 && psi< (-1.*M_PI) ) { 01359 // os << "Adjustment (+1)" << endl; 01360 // psi += (2.*M_PI); 01361 // step *= -1.; 01362 // } 01363 01364 psi += step; 01365 ctr++; 01366 // os << "ctr* " << ctr << "\t" << "psi " << psi << endl; 01367 01368 ringCalculator->getRing(eInnerRing)->getPoint(psi,newPointOnRing); 01369 // os << "newPointOnRing " << newPointOnRing << endl; 01370 if(newPointOnRing.x() == FLT_MAX) { 01371 // os << "StRichPIDMaker::hitFilter()\n"; 01372 // os << "REFRACTED AWAY" << endl; 01373 psi -= step; 01374 step *= 0.5; 01375 continue; 01376 } 01377 01378 ringPointLine = newPointOnRing - central; 01379 01380 int signOfNewTheta = 01381 sign(ringPointLine.x()*referenceLine.y() - 01382 ringPointLine.y()*referenceLine.x()); 01383 sineTheta = abs( (ringPointLine.unit()).cross(referenceLine.unit()) ); 01384 // os << "sineNewTheta (" << signOfNewTheta << ") " << sineTheta << endl; 01385 01386 double newDistToRefLine = 01387 abs(ringPointLine)* sineTheta; 01388 01389 // os << "newDistToRefLine " << newDistToRefLine << endl; 01390 // os << "sineTheta " << sineTheta << endl; 01391 01392 if(ctr > maxIterForRingPsi) 01393 anotherIteration = false; 01394 01395 if (newDistToRefLine<mPrecision) { 01396 convergence = true; 01397 break; 01398 } 01399 01400 // os << "step " << step << endl; 01401 01402 if( (signOfTheta != signOfNewTheta) || 01403 ( (signOfTheta == signOfNewTheta) && 01404 (newDistToRefLine > minDistToRefLine) ) ) { 01405 // wrong way 01406 signOfTheta = signOfNewTheta; 01407 step *= -0.5; 01408 } 01409 else { 01410 //make the step size bigger, unless you are close 01411 //change in the distances (check angles) 01412 step = (step>0) ? 01413 min(maxChange,(step*1.2)) : max(-1.*maxChange,step*1.2); 01414 01415 if(newDistToRefLine < 3.*centimeter) { 01416 // os << "BRAKES step " << step << endl; 01417 step = (step>0) ? 01418 min(1.*degree,step) : max(-1.*degree,step); 01419 } 01420 01421 } // else 01422 // os << "step " << step << endl; 01423 01424 minDistToRefLine = newDistToRefLine; 01425 01426 }; 01427 01428 if(!convergence) continue; 01429 01430 // 01431 // assign the point on the ring 01432 // 01433 StThreeVectorF innerRingPoint = newPointOnRing; 01434 // os << "Drawing innerRingPoint " << innerRingPoint << endl; 01435 #ifdef RICH_WITH_PAD_MONITOR 01436 //mPadMonitor->drawMarker(innerRingPoint,22); 01437 #endif 01438 // 01439 // Given an initial guess for psi, find the "line of constant psi" 01440 // which crosses both rings and intersects with the hit 01441 // 01442 // os << "current best guess for psi " << psi << endl; 01443 01444 // 01445 // determine the outerRingPoint with the corresponding Psi 01446 // 01447 StThreeVectorF outerRingPoint; 01448 01449 int iterationNumber = 0; 01450 double littleStep = 1.*degree; 01451 double modifiedPsi = psi; 01452 if(modifiedPsi < 0) littleStep *= -1.; 01453 01454 while (iterationNumber<maxIterForInitialPsi) { 01455 iterationNumber++; 01456 ringCalculator->getRing(eOuterRing)->getPoint(modifiedPsi,outerRingPoint); 01457 01458 // ---------> fix brackets 01459 if ( (outerRingPoint.x() == FLT_MAX) || 01460 ( 01461 fabs(outerRingPoint.x()) > mGeometryDb->padPlaneDimension().x() || 01462 fabs(outerRingPoint.y()) > mGeometryDb->padPlaneDimension().y() 01463 ) 01464 ) { 01465 // os << "An OuterRingPoint DOES NOT EXIST with this psi..( " 01466 // << iterationNumber << ")" << endl; 01467 modifiedPsi+=littleStep; 01468 } 01469 else { 01470 // we found a point 01471 break; 01472 } 01473 } 01474 01475 // os << "old psi " << psi << endl; 01476 psi = modifiedPsi; 01477 // os << "new (starting) psi " << psi << endl; 01478 01479 ringCalculator->getRing(eInnerRing)->getPoint(psi,innerRingPoint); 01480 ringCalculator->getRing(eOuterRing)->getPoint(psi,outerRingPoint); 01481 01482 01483 01484 // -----------> fix brackets 01485 if ( (fabs(outerRingPoint.x()) > mPadPlaneDimension.x()) || 01486 (fabs(outerRingPoint.y()) > mPadPlaneDimension.y()) || 01487 (fabs(innerRingPoint.x()) > mPadPlaneDimension.x()) || 01488 (fabs(innerRingPoint.y()) > mPadPlaneDimension.y()) ) { 01489 // os << "ERROR: PANIC BAD POINT...continue" << endl; 01490 continue; 01491 } 01492 01493 01494 // 01495 // the constant Psi line between the inner and outer rings 01496 // 01497 01498 StThreeVectorF consPsiVector = outerRingPoint - innerRingPoint; 01499 // os << "consPsiVector " << consPsiVector << endl; 01500 #ifdef RICH_WITH_PAD_MONITOR 01501 // mPadMonitor->drawLine(innerRingPoint,outerRingPoint); 01502 // mPadMonitor->drawMarker(innerRingPoint,2,1); 01503 // mPadMonitor->drawMarker(outerRingPoint,2,1); 01504 #endif 01505 01506 // 01507 // the line from the innerRing Point to the hit 01508 // 01509 StThreeVectorF consPsiRefLine = hit - innerRingPoint; 01510 01511 // 01512 // minimize the distance of closest approach between the 01513 // two lines as a function of the angle of the psi line 01514 // 01515 // ^ ^ 01516 // | A | A x B 01517 // 01518 // where: 01519 // A = consPsiRefLine 01520 // B = consPsiVector 01521 // 01522 // z component = 01523 // AxBy - AyBx 01524 // 01525 01526 signOfTheta = 01527 sign(consPsiRefLine.x()*consPsiVector.y() - 01528 consPsiRefLine.y()*consPsiVector.x()); 01529 sineTheta = abs( (consPsiRefLine.unit()).cross(consPsiVector.unit()) ); 01530 // os << "sineTheta2 (" << signOfTheta << ") " << sineTheta << endl; 01531 01532 double minDistToConsPsiRefLine = 01533 abs(consPsiRefLine) * sineTheta; 01534 01535 // os << "minDistToConsPsiRefLine " << minDistToConsPsiRefLine << endl; 01536 01537 anotherIteration = true; 01538 convergence = false; 01539 step = 1.*degree; 01540 01541 StThreeVectorF newInnerPointOnRing; 01542 StThreeVectorF newOuterPointOnRing; 01543 double newMinDistToConsPsiRefLine; 01544 01545 if(signOfTheta>0) step *= -1.; 01546 // os << "initial step " << step << endl; 01547 ctr = 0; 01548 while (anotherIteration || ctr<maxIterForRingPsi) { 01549 01550 // 01551 // make sure you are in range 01552 // 01553 // if(psi>0 && psi>M_PI) { 01554 // os << "Adjustment (-2) psi " << psi << endl; 01555 // psi -= (2.*M_PI); 01556 // step *= -1.; 01557 // } 01558 // if(psi<0 && psi< (-1.*M_PI) ) { 01559 // os << "Adjustment (+2) psi " << psi << endl; 01560 // psi += (2.*M_PI); 01561 // step *= -1.; 01562 // } 01563 01564 psi += step; 01565 ctr++; // os << "ctr " << ctr << "\t" << "psi " << psi << endl; 01566 01567 ringCalculator->getRing(eInnerRing)->getPoint(psi,newInnerPointOnRing); 01568 ringCalculator->getRing(eOuterRing)->getPoint(psi,newOuterPointOnRing); 01569 01570 // os << "newInnerPointOnRing " << newInnerPointOnRing << endl; 01571 // os << "newOuterPointOnRing " << newOuterPointOnRing << endl; 01572 01573 if( (newInnerPointOnRing.x() == FLT_MAX) || 01574 (newOuterPointOnRing.x() == FLT_MAX) ) { 01575 // os << "REFRACTED AWAY" << endl; 01576 psi-=step; 01577 step *=0.5; 01578 continue; 01579 } 01580 01581 consPsiRefLine = hit - newInnerPointOnRing; 01582 consPsiVector = newOuterPointOnRing - newInnerPointOnRing; 01583 01584 // 01585 // ^ ^ 01586 // | A | A x B 01587 // 01588 // where: 01589 // A = consPsiRefLine 01590 // B = consPsiVector 01591 01592 int signOfNewTheta = 01593 sign(consPsiRefLine.x()*consPsiVector.y() - 01594 consPsiRefLine.y()*consPsiVector.x()); 01595 sineTheta = abs( (consPsiRefLine.unit()).cross(consPsiVector.unit()) ); 01596 // os << "sineTheta 2*(" << signOfNewTheta << ") " << sineTheta << endl; 01597 01598 newMinDistToConsPsiRefLine = 01599 abs(consPsiRefLine) * sineTheta; 01600 01601 // os << "newMinDistToConsPsiRefLine " << newMinDistToConsPsiRefLine << endl; 01602 01603 if( ctr > maxIterForRingPsi ) 01604 anotherIteration = false; 01605 01606 if(newMinDistToConsPsiRefLine < mPrecision) { 01607 convergence = true; 01608 break; 01609 } 01610 01611 if( (signOfTheta != signOfNewTheta) || 01612 ( (signOfTheta == signOfNewTheta) && 01613 (newMinDistToConsPsiRefLine > minDistToConsPsiRefLine) ) ) { 01614 //wrong way 01615 signOfTheta = signOfNewTheta; 01616 step *= -0.5; 01617 } 01618 else { 01619 // make the step size bigger if we are moving 01620 // in the right direction 01621 step = (step>0) ? 01622 min(maxChange,(step*1.2)) : max(-1.*maxChange,step*1.2); 01623 01624 if(newMinDistToConsPsiRefLine < 3.*centimeter) { 01625 // os << "BRAKES(2) " << endl; 01626 step = (step>0) ? 01627 min(1.*degree,step) : max(-1.*degree,step); 01628 } 01629 } 01630 01631 minDistToConsPsiRefLine = newMinDistToConsPsiRefLine; 01632 // os << "step " << step << endl; 01633 }; 01634 01635 if(!convergence) continue; 01636 01637 // os << "minDistToConsPsiRefLine " << minDistToConsPsiRefLine << endl; 01638 // os << "psi " << psi << endl; 01639 01640 #ifdef RICH_WITH_PAD_MONITOR 01641 // mPadMonitor->drawMarker(newInnerPointOnRing,2,1); 01642 // mPadMonitor->drawLine(newInnerPointOnRing,hit); 01643 #endif 01644 01645 // 01646 // Calculated Quantities 01647 // 01648 01649 // 01650 // ring width 01651 // 01652 StThreeVectorF lengthOfD = newOuterPointOnRing - newInnerPointOnRing; 01653 // os << "photonNumber " << photonNumber << endl; 01654 // os << "abs(lengthOfD) " << abs(lengthOfD) << endl; 01655 // os << "consPsiVector " << abs(consPsiVector) << endl; 01656 01657 // 01658 // distance to hit at constant psi 01659 // 01660 01661 StThreeVectorF hitDVector = hit - newInnerPointOnRing; 01662 01663 // os << "abs(hitDVector) " << abs(hitDVector) << endl; 01664 // os << "consPsiRefLine " << consPsiRefLine << endl; 01665 01666 int signOfD = sign(lengthOfD*hitDVector); 01667 01668 // float cosineOfD = lengthOfD.unit()*hitDVector.unit(); 01669 // os << "cosineOfD " << cosineOfD << endl; 01670 01671 double normalizedD = signOfD * (abs(hitDVector)/abs(lengthOfD)); 01672 // os << "normalizedD " << normalizedD << endl; 01673 01674 #ifdef RICH_WITH_PAD_MONITOR 01675 if(normalizedD>0 && normalizedD<1) 01676 mPadMonitor->drawMarker(hit,29,1.2,3); 01677 #endif 01678 01679 01680 01681 // 01682 // Take only photons with -1 < d < 3 01683 // 01684 // 01685 double sigmaOfD; 01686 double meanOfD; 01687 01688 // First Attempt 01689 // double sigmaOfD = .96; 01690 // double meanOfD = .65; 01691 01692 // 01693 // dipAngle of the track (in degrees) 01694 // 01695 // double trackDipAngle = atan(trackMomentum.x()/trackMomentum.z())/degree; 01696 // PR(trackDipAngle); 01697 01698 // int charge, bin; 01699 // For helix h>0 01700 // if(trackDipAngle<-10) 01701 // bin = 0; 01702 // else if(trackDipAngle>-10 && trackDipAngle<-5) 01703 // bin = 1; 01704 // else if(trackDipAngle>-5 && trackDipAngle<0) 01705 // bin = 2; 01706 // else if(trackDipAngle>0 && trackDipAngle<5) 01707 // bin = 3; 01708 // else if(trackDipAngle>5 && trackDipAngle<10) 01709 // bin = 4; 01710 // else if(trackDipAngle>10) 01711 // bin = 5; 01712 01713 // if(currentTrack->getStTrack()->geometry()->helix().h() > 0) 01714 // charge = 1; // positive 01715 // else 01716 // charge =0; // negative 01717 01718 // meanOfD = meanD[bin][charge]; 01719 // sigmaOfD = sigmaD[bin][charge]; 01720 01721 // 01722 // constant area 01723 // 01724 meanOfD = 0.5; 01725 sigmaOfD = 0.25; 01726 01727 if( normalizedD<-3. || normalizedD>6. ) continue; 01728 01729 bool inArea = false; 01730 if(normalizedD>=0 && normalizedD<=1 ) 01731 inArea = true; 01732 01733 double sigma = (normalizedD - meanOfD)/sigmaOfD; 01734 // 01735 //**************** hitfilter ******************* 01736 // setting the flags 01737 // 01738 01739 if(particleType == -211 || // pion 01740 particleType == -321 || // kaon 01741 particleType == -2212 ) { // proton 01742 01743 ringCalculator-> 01744 getRing(eInnerRing)-> 01745 getTrack()-> 01746 addHit((*hitIter),normalizedD,sigma,psi,radPath,quartzPath,particle); 01747 } 01748 else { 01749 cout << "StRichPIDMaker::hitfilter()\n"; 01750 cout << "\tWARNING:\n"; 01751 cout << "Unknown particle type: (" 01752 << particleType << ")" << endl; 01753 } 01754 01755 01756 } // loop over hits 01757 01758 // 01759 // Report from the counter for the rings of this particle 01760 // 01761 01762 01763 } 01764 01765 01766 void StRichPIDMaker::hitFilter(StRichRingCalculator* ringCalculator, 01767 StThreeVectorF& hit, float& angle, float& dist) { 01768 01769 // calculate distance from inner,mean, outer rings 01770 01771 ringCalculator->clear(); 01772 angle = -999; 01773 dist = -999; 01774 innerDistance = ringCalculator->getInnerDistance(hit,innerAngle); 01775 outerDistance = ringCalculator->getOuterDistance(hit,outerAngle); 01776 meanDistance = ringCalculator->getMeanDistance(hit,meanAngle); 01777 ringWidth = ringCalculator->getRingWidth(); 01778 if (ringWidth==0) {return;} 01779 angle = meanAngle; 01780 dist = ((outerDistance/ringWidth > 1 && (innerDistance/ringWidth < outerDistance/ringWidth )) ? 01781 (-1.0):(1.0))*innerDistance/ringWidth; 01782 return; 01783 } 01784 01785 01786 void StRichPIDMaker::tagMips(StEvent* tempEvent, StSPtrVecRichHit* hits) { 01787 01788 cout << "StRichPIDMaker::tagMips() ---> Tagging Mips using global tracks ..." << endl; 01789 01790 StSPtrVecTrackNode& theTrackNodes = tempEvent->trackNodes(); 01791 for (size_t nodeIndex=0;nodeIndex<theTrackNodes.size();nodeIndex++) { 01792 for (size_t trackIndex=0; 01793 trackIndex<theTrackNodes[nodeIndex]->entries(global); 01794 trackIndex++) { 01795 StTrack* track = 01796 theTrackNodes[nodeIndex]->track(global,trackIndex); 01797 if (track && 01798 !track->bad() && 01799 track->flag()>=0 && 01800 track->fitTraits().numberOfFitPoints(kTpcId) >= 10 ) { 01801 01802 StRichTrack* tempTrack = new StRichTrack(track,mMagField); 01804 if ( checkTrack(tempTrack) ) { 01805 StThreeVectorF trackPredictor = tempTrack->getProjectedMIP(); 01806 StThreeVectorF testThisResidual; 01807 StRichHit* mAssociatedMIP = 0; 01808 float smallestResidual = 3.0*centimeter; 01809 float adcCut = 300; 01810 01811 StSPtrVecRichHitIterator hitIter; 01812 for (hitIter = hits->begin(); hitIter != hits->end(); ++hitIter) { 01813 testThisResidual = ((*hitIter)->local() - trackPredictor); 01814 if ( (testThisResidual.perp() < smallestResidual) && 01815 ((*hitIter)->charge() > adcCut) ) { 01816 smallestResidual = testThisResidual.perp(); 01817 mAssociatedMIP = *hitIter; 01818 } 01819 } 01820 // mAssociatedMIP->setMipFlag(); 01821 mAssociatedMIP = 0; 01822 } 01823 delete tempTrack; 01824 } 01825 } 01826 } 01827 } 01828 01829 bool StRichPIDMaker::checkEvent(StEvent* event) { 01830 01831 // 01832 // right now just checks if event and vertex exist 01833 // later will implement cut on vertex, nparticles, etc... 01834 // 01835 if (!event) { 01836 cout << "StRichPIDMaker::checkEvent()\n"; 01837 cout << "\tERROR: Bad Event. Skipping..." << endl; 01838 return false; 01839 } 01840 01841 if(!event->primaryVertex()) { 01842 cout << "StRichPIDMaker::checkEvent()\n"; 01843 cout << "\tERROR: No Vertex. Skipping..." << endl; 01844 return false; 01845 } 01846 01847 mVertexPos = event->primaryVertex()->position(); 01848 mEventN = event->id(); 01849 mEventRunId = event->runId(); 01850 01851 01852 if( fabs(mVertexPos.z()) > mVertexWindow) { 01853 cout << "StRichPIDMaker::checkEvent()\n"; 01854 cout << "\tVertex Cut not satisfied ("; 01855 cout << (mVertexWindow/centimeter) << " cm)\n"; 01856 cout << "\tz=" << mVertexPos.z() << endl; 01857 return false; 01858 } 01859 // cout << "StRichPIDMaker::checkEvent() =>\n"; 01860 // cout << "event vertex z = " << mVertexPos.z() << endl; 01861 // cout << "event run id = " << mEventN << endl; 01862 01863 mMagField = 2.49117; 01864 if (event->summary()) { 01865 mMagField = event->summary()->magneticField(); 01866 cout << " B field = " << mMagField << endl; 01867 } 01868 else { 01869 cout << "StRichPIDMaker::checkEvent().\n"; 01870 cout << "\tWARNING!\n"; 01871 cout << "\tCannot get B field from event->summary(). \n"; 01872 cout << "\tUse B= " << mMagField << endl; 01873 } 01874 01875 return true; 01876 } 01877 01878 // bool StRichPIDMaker::checkTrack(StTrack* track) { 01879 01880 // if (track && 01881 // track->flag()>=0 && 01882 // track->geometry() && 01883 // (track->geometry()->helix().distance(mVertexPos)<mDcaCut) && 01884 // (track->fitTraits().numberOfFitPoints(kTpcId) >= mFitPointsCut) && 01885 // (fabs(track->geometry()->momentum().pseudoRapidity()) < mEtaCut) && 01886 // (track->geometry()->momentum().perp() > mPtCut)) { 01887 01888 // return true; 01889 // } 01890 01891 // return false; 01892 // } 01893 01894 bool StRichPIDMaker::checkTrack(StTrack* track) { 01895 01896 bool status = true; 01897 int bitmask = 0; 01898 if (track->bad()) { 01899 status = false; 01900 bitmask += 1<<0; 01901 return status; 01902 } 01903 01904 if (!track->geometry()) { 01905 status = false; 01906 bitmask += 1<<1; 01907 } 01908 01909 if (track->geometry()->helix().distance(mVertexPos) > mDcaCut) { 01910 status = false; 01911 bitmask += 1<<2; 01912 } 01913 01914 if (track->fitTraits().numberOfFitPoints(kTpcId) < mFitPointsCut) { 01915 status = false; 01916 bitmask += 1<<3; 01917 } 01918 01919 if (fabs(track->geometry()->momentum().pseudoRapidity()) > mEtaCut) { 01920 status = false; 01921 bitmask += 1<<4; 01922 } 01923 01924 if (track->geometry()->momentum().perp() < mPtCut) { 01925 status = false; 01926 bitmask += 1<<5; 01927 } 01928 //cout << "StRichPIDMaker:checkTrack()\n"; 01929 //cout << "\tbitmask = " << bitmask << endl; 01930 01931 #ifdef myRICH_WITH_NTUPLE 01932 01933 01934 #ifdef myRICH_WITH_MC 01935 float distHits[35]; 01936 #else 01937 float distHits[34]; 01938 #endif 01939 01940 distHits[0] = 0; 01941 distHits[1] = 0; 01942 distHits[2] = 0; 01943 distHits[3] = 0; 01944 distHits[4] = 0; 01945 distHits[5] = 0; 01946 distHits[6] = 0; 01947 01948 // OLD labels 01949 distHits[7] = 0; 01950 distHits[8] = 0; 01951 distHits[9] = 0; 01952 // 01953 // the photon 01954 distHits[10] = 0; 01955 distHits[11] = 0; 01956 // 01957 // the MIP 01958 distHits[12] = 0; 01959 distHits[13] = 0; 01960 01961 01962 distHits[14] = track->geometry()->momentum().x(); 01963 distHits[15] = track->geometry()->momentum().y(); 01964 distHits[16] = track->geometry()->momentum().z(); 01965 01966 // Track incident angle 01967 //theta = acos(-pz/::sqrt(px**2+py**2+pz**2)) 01968 distHits[17] = 0; 01969 distHits[18] = mEventN; 01970 01971 distHits[19] = -2.0; 01972 01973 distHits[20] = 0; 01974 distHits[21] = 0; 01975 distHits[22] = bitmask; 01976 01977 distHits[23] = 0; 01978 distHits[24] = 0; 01979 distHits[25] = 0; 01980 01981 distHits[26] = track->geometry()->momentum().mag(); 01982 distHits[27] = track->geometry()->charge(); 01983 distHits[28] = mVertexPos.z(); 01984 distHits[29] = 0; 01985 distHits[30] = 0; 01986 distHits[31] = 0; 01987 distHits[32] = mEventRunId; 01988 distHits[33] = 0; 01989 #ifdef myRICH_WITH_MC 01990 distHits[34] = 0; 01991 #endif 01992 01993 distup->Fill(distHits); 01994 01995 #endif 01996 01997 return status; 01998 } 01999 02000 bool StRichPIDMaker::checkTrack(StRichTrack* track) { 02001 02002 bool status = true; 02003 StThreeVectorF extrapolatedPosition = track->getProjectedMIP(); 02004 StThreeVectorF impactPoint = track->getImpactPoint(); 02005 02006 float bitmask = 0; 02007 if (fabs(extrapolatedPosition.x()) > (mPadPlaneDimension.x() - mPadPlaneCut)) { 02008 status = false; 02009 bitmask += ::pow(2.,6); 02010 } 02011 02012 if ( fabs(extrapolatedPosition.y()) > (mPadPlaneDimension.y() - mPadPlaneCut) ) { 02013 status = false; 02014 bitmask += ::pow(2.,7); 02015 } 02016 02017 if (fabs(extrapolatedPosition.x()) < (mPadPlaneCut) ) { 02018 status = false; 02019 bitmask += ::pow(2.,8); 02020 } 02021 02022 if (fabs(extrapolatedPosition.y()) < (mPadPlaneCut) ) { 02023 status = false; 02024 bitmask += ::pow(2.,9); 02025 } 02026 02027 if (fabs(impactPoint.x()) > (mRadiatorDimension.x() - mRadiatorCut) ) { 02028 status = false; 02029 bitmask += ::pow(2.,10); 02030 } 02031 02032 if (fabs(impactPoint.y()) > (mRadiatorDimension.y() - mRadiatorCut) ) { 02033 status = false; 02034 bitmask += ::pow(2.,11); 02035 } 02036 02037 if (fabs(impactPoint.x()) < (mRadiatorCut)) { 02038 status = false; 02039 bitmask += ::pow(2.,12); 02040 } 02041 02042 if (fabs(impactPoint.y()) < (mRadiatorCut)) { 02043 status = false; 02044 bitmask += ::pow(2.,13); 02045 } 02046 02047 if (track->getPathLength()<0 || track->getPathLength()>mPathCut/centimeter) { 02048 status = false; 02049 bitmask += ::pow(2.,14); 02050 } 02051 02052 if (track->getLastHit().perp()<mLastHitCut) { 02053 status = false; 02054 bitmask += ::pow(2.,15); 02055 } 02056 02057 //cout << "StRichPIDMaker::checkTrack(St)\n"; 02058 //cout << "\tbitmask = " << bitmask << endl; 02059 02060 #ifdef myRICH_WITH_NTUPLE 02061 02062 #ifdef myRICH_WITH_MC 02063 float distHits[35]; 02064 #else 02065 float distHits[34]; 02066 #endif 02067 02068 02069 float amipq = -999; 02070 if (track->getAssociatedMIP()) { 02071 amipq = track->getAssociatedMIP()->charge(); 02072 } 02073 02074 distHits[0] = 0; 02075 distHits[1] = 0; 02076 distHits[2] = 0; 02077 distHits[3] = 0; 02078 distHits[4] = 0; 02079 distHits[5] = 0; 02080 distHits[6] = 0; 02081 02082 // OLD labels 02083 distHits[7] = 0; 02084 distHits[8] = 0; 02085 distHits[9] = 0; 02086 // 02087 // the photon 02088 distHits[10] = 0; 02089 distHits[11] = 0; 02090 // 02091 // the MIP 02092 distHits[12] = track->getProjectedMIP().x(); 02093 distHits[13] = track->getProjectedMIP().y(); 02094 02095 distHits[14] = track->getStTrack()->geometry()->momentum().x(); 02096 distHits[15] = track->getStTrack()->geometry()->momentum().y(); 02097 distHits[16] = track->getStTrack()->geometry()->momentum().z(); 02098 02099 // Track incident angle 02100 //theta = acos(-pz/::sqrt(px**2+py**2+pz**2)) 02101 distHits[17] = 0; 02102 distHits[18] = mEventN; 02103 02104 distHits[19] = -1.0; 02105 02106 distHits[20] = 0; 02107 distHits[21] = 0; 02108 distHits[22] = bitmask; 02109 02110 distHits[23] = 0; 02111 distHits[24] = 0; 02112 distHits[25] = 0; 02113 02114 distHits[26] = track->getMomentum().mag(); 02115 distHits[27] = track->getStTrack()->geometry()->charge(); 02116 distHits[28] = mVertexPos.z(); 02117 distHits[29] = 0; 02118 distHits[30] = 0; 02119 distHits[31] = 0; 02120 distHits[32] = mEventRunId; 02121 distHits[33] = amipq; 02122 02123 02124 #ifdef myRICH_WITH_MC 02125 distHits[34] = 0; 02126 #endif 02127 02128 02129 distup->Fill(distHits); 02130 #endif 02131 02132 02133 return status; 02134 // 02135 // Old code to be reimplemented when 02136 // the above histogram is removed 02137 // 02138 // // 02139 // // values for the pad plane and radiator dimension should 02140 // // be kept as data members to avoid the dereferencing 02141 // // 02142 // if ( fabs(extrapolatedPosition.x()) < (mGeometryDb->padPlaneDimension().x() - mPadPlaneCut) && 02143 // fabs(extrapolatedPosition.y()) < (mGeometryDb->padPlaneDimension().y() - mPadPlaneCut) && 02144 // fabs(extrapolatedPosition.x()) > (mPadPlaneCut) && 02145 // fabs(extrapolatedPosition.y()) > (mPadPlaneCut) && 02146 // fabs(impactPoint.x()) < (mGeometryDb->radiatorDimension().x() - mRadiatorCut) && 02147 // fabs(impactPoint.y()) < (mGeometryDb->radiatorDimension().y() - mRadiatorCut) && 02148 // fabs(impactPoint.x()) > (mRadiatorCut) && 02149 // fabs(impactPoint.y()) > (mRadiatorCut) && 02150 // (track->getPathLength()>0 && track->getPathLength()<mPathCut) && 02151 // track->getLastHit().perp()>mLastHitCut) { 02152 // return true; 02153 // } 02154 02155 // return false; 02156 } 02157 02158 bool StRichPIDMaker::checkTrackMomentum(float mag) { 02159 if(mag<mThresholdMomentum) 02160 return false; 02161 02162 return true; 02163 } 02164 02165 02166 bool StRichPIDMaker::checkHit(StRichHit* hit) { 02167 // 02168 // should use mip/hit flag 02169 // 02170 if (hit && hit->charge()<mAdcCut) {return true;} 02171 return false; 02172 } 02173 02174 02175 02176 02177 void StRichPIDMaker::fillPIDTraits(StRichRingCalculator* ringCalc) { 02178 02179 //cout << "StRichPIDMaker::fillPIDTraits()" << endl; 02180 02181 // 02182 // Preliminary checks to make sure the pointer are all there 02183 // 02184 if (!ringCalc) { 02185 cout << "StRichPIDMaker::fillPIDTraits()\n"; 02186 cout << "\tRingCalculator Pointer is lost\n"; 02187 cout << "\tReturning" << endl; 02188 return; 02189 } 02190 02191 if (!ringCalc->getRing(eInnerRing)) { 02192 cout << "StRichPIDMaker::fillPIDTraits()\n"; 02193 cout << "\tRingCalculator lost inner ring\n"; 02194 cout << "\tReturning" << endl; 02195 return; 02196 } 02197 02198 // 02199 // grab track, particle type from Ring Calculator 02200 // 02201 StRichTrack* richTrack = ringCalc->getRing(eInnerRing)->getTrack(); 02202 if(!richTrack) { 02203 cout << "StRichPIDMaker::fillPidTraits()\n"; 02204 cout << "\tWARNING Cannot get StRichTrack:\n"; 02205 cout << "\tReturning..." << endl; 02206 return; 02207 } 02208 02209 if(!richTrack->getStTrack()) { 02210 cout << "StRichPIDMaker::fillPidTraits()\n"; 02211 cout << "\tWARNING Cannot get StTrack from StRichTrack\n"; 02212 cout << "\tReturning..." << endl; 02213 return; 02214 } 02215 02216 if(!richTrack->getStTrack()->detectorInfo()) { 02217 cout << "StRichPIDMaker::fillPidTraits()\n"; 02218 cout << "\tWARNING Cannot get DetectorInfo from StTrack\n"; 02219 cout << "\tReturning..." << endl; 02220 return; 02221 } 02222 02223 StParticleDefinition* part = 02224 ringCalc->getRing(eInnerRing)->getParticleType(); 02225 02226 unsigned int totalHitsInArea = 0; 02227 unsigned int hitsInConstantAngle = 0; 02228 unsigned int hitsInConstantArea = 0; 02229 unsigned int sig1 = 0; 02230 unsigned int sig2 = 0; 02231 02232 // 02233 // if the track meets minimum criteria, 02234 // create and fill an StRichPid structure. 02235 // It is kept in a ROOT-STL container so 02236 // it is by pointer 02237 // 02238 if ( richTrack->fastEnough(part) && 02239 richTrack->isGood(part) ) { 02240 02241 StRichPid* pid = new StRichPid(); 02242 pid->setRingType(part); 02243 02244 // 02245 // set the constant area of the Ring 02246 // 02247 pid->setTotalArea(ringCalc->getTotalConstantArea()); 02248 pid->setTotalAzimuth(ringCalc->getTotalConstantAngle()); 02249 02250 // 02251 // set the constant area on the active portion of pad plane 02252 // takes into account the edge and gap 02253 // 02254 pid->setTruncatedArea(ringCalc->getTotalConstantAreaOnActivePadPlane()); 02255 pid->setTruncatedAzimuth(ringCalc->getTotalConstantAngleOnActivePadPlane()); 02256 02257 vector<StRichRingHit*> hits = richTrack->getRingHits(part); 02258 02259 // 02260 // Add the StRichHit information to the StRichPid 02261 // remember we keep a reference to the hit in 02262 // the StTrackDetectorInfo structure as well. 02263 // 02264 for (size_t i=0; i<hits.size(); i++) { // loop over track's hits 02265 02266 StRichHit* theCurrentHit = hits[i]->getHit(); 02267 pid->addHit(theCurrentHit); 02268 richTrack->getStTrack()->detectorInfo()->addHit(theCurrentHit); 02269 02270 float normalizedD = hits[i]->getDist(); 02271 float sigma = hits[i]->getNSigma(); 02272 float psi = hits[i]->getAngle(); 02273 // 02274 // do we need the hit's adc, npads, (x,y) ? 02275 // 02276 02277 pid->addPhotonInfo(new StRichPhotonInfo(normalizedD, sigma, psi)); 02278 02279 // 02280 // boolean flags 02281 // 02282 bool inArea = false; 02283 bool inConstantAngle = false; 02284 bool inConstantArea = false; 02285 02286 if ( (normalizedD >= 0) && (normalizedD <= 1) ) { 02287 inArea = true; 02288 totalHitsInArea++; 02289 } 02290 02291 pid->setConstantAreaCut(ringCalc->getConstantAreaAngle()); 02292 02293 if ( fabs(psi) > ringCalc->getConstantAreaAngle()) { 02294 inConstantAngle = true; 02295 hitsInConstantAngle++; 02296 } 02297 02298 if(inArea && inConstantAngle) { 02299 inConstantArea = true; 02300 hitsInConstantArea++; 02301 } 02302 02303 if(part == pion) { // pion 02304 02305 if( theCurrentHit->isSet(eInMultipleCAreaPi) ) continue; 02306 02307 if( theCurrentHit->isSet(eInAreaPi) || 02308 theCurrentHit->isSet(eInConstantAnglePi) ) { 02309 // 02310 // it was touched by another pion ring 02311 theCurrentHit->setBit(eMultiplyAssigned); 02312 } 02313 02314 if(inArea) { 02315 if( theCurrentHit->isSet(eInAreaPi) ) { 02316 theCurrentHit->setBit(eInMultipleAreaPi); 02317 } 02318 else { 02319 theCurrentHit->setBit(eInAreaPi); 02320 } 02321 } 02322 02323 if(inConstantAngle) { 02324 if( theCurrentHit->isSet(eInConstantAnglePi) ) { 02325 theCurrentHit->setBit(eInMultipleCAnglePi); 02326 } 02327 else { 02328 theCurrentHit->setBit(eInConstantAnglePi); 02329 } 02330 } 02331 02332 if( inConstantAngle && !theCurrentHit->isSet(eInMultipleCAnglePi) ) { 02333 if( fabs(sigma)<1 ) {theCurrentHit->setBit(e1SigmaPi);sig1++;} 02334 if( fabs(sigma)<2 ) {theCurrentHit->setBit(e2SigmaPi);sig2++;} 02335 } 02336 02337 02338 if(inConstantArea) { 02339 if( theCurrentHit->isSet(eInConstantAreaPi) ) { 02340 theCurrentHit->setBit(eInMultipleCAreaPi); 02341 } 02342 else { 02343 theCurrentHit->setBit(eInConstantAreaPi); 02344 } 02345 } 02346 02347 } // end of pion 02348 02349 02350 if(part == kaon) { // kaon 02351 if( theCurrentHit->isSet(eInMultipleCAreaK) ) continue; 02352 02353 if( theCurrentHit->isSet(eInAreaK) || 02354 theCurrentHit->isSet(eInConstantAngleK) ) { 02355 // 02356 // it was touched by another kaon ring 02357 theCurrentHit->setBit(eMultiplyAssigned); 02358 } 02359 02360 if(inArea) { 02361 if( theCurrentHit->isSet(eInAreaK) ) { 02362 theCurrentHit->setBit(eInMultipleAreaK); 02363 } 02364 else { 02365 theCurrentHit->setBit(eInAreaK); 02366 } 02367 } 02368 02369 if(inConstantAngle) { 02370 if( theCurrentHit->isSet(eInConstantAngleK) ) { 02371 theCurrentHit->setBit(eInMultipleCAngleK); 02372 } 02373 else { 02374 theCurrentHit->setBit(eInConstantAngleK); 02375 } 02376 } 02377 02378 if( inConstantAngle && !theCurrentHit->isSet(eInMultipleCAngleK) ) { 02379 if( fabs(sigma)<1 ) {theCurrentHit->setBit(e1SigmaK);sig1++;} 02380 if( fabs(sigma)<2 ) {theCurrentHit->setBit(e2SigmaK);sig2++;} 02381 } 02382 02383 if(inConstantArea) { 02384 if( theCurrentHit->isSet(eInConstantAreaK) ) { 02385 theCurrentHit->setBit(eInMultipleCAreaK); 02386 } 02387 else { 02388 theCurrentHit->setBit(eInConstantAreaK); 02389 } 02390 } 02391 02392 } // end of kaon 02393 02394 if(part == proton) { // proton 02395 if( theCurrentHit->isSet(eInMultipleCAreap) ) continue; 02396 02397 if( theCurrentHit->isSet(eInAreap) || 02398 theCurrentHit->isSet(eInConstantAnglep) ) { 02399 02400 // 02401 // it was touched by another proton ring 02402 theCurrentHit->setBit(eMultiplyAssigned); 02403 } 02404 02405 if(inArea) { 02406 if( theCurrentHit->isSet(eInAreap) ) { 02407 theCurrentHit->setBit(eInMultipleAreap); 02408 } 02409 else { 02410 theCurrentHit->setBit(eInAreap); 02411 } 02412 } 02413 02414 if(inConstantAngle) { 02415 if( theCurrentHit->isSet(eInConstantAnglep) ) { 02416 theCurrentHit->setBit(eInMultipleCAnglep); 02417 } 02418 else { 02419 theCurrentHit->setBit(eInConstantAnglep); 02420 } 02421 } 02422 02423 if(inConstantAngle && !theCurrentHit->isSet(eInMultipleCAnglep) ) { 02424 if( fabs(sigma)<1 ) {theCurrentHit->setBit(e1Sigmap);sig1++;} 02425 if( fabs(sigma)<2 ) {theCurrentHit->setBit(e2Sigmap);sig2++;} 02426 } 02427 02428 if(inConstantArea) { 02429 if( theCurrentHit->isSet(eInConstantAreap) ) { 02430 theCurrentHit->setBit(eInMultipleCAreap); 02431 } 02432 else { 02433 theCurrentHit->setBit(eInConstantAreap); 02434 } 02435 } 02436 02437 } // end of proton 02438 02439 02440 02441 // if(part==pion) { 02442 // cout << "pi " 02443 // << theCurrentHit->isSet(eInAreaPi) 02444 // << theCurrentHit->isSet(eInConstantAnglePi) 02445 // << theCurrentHit->isSet(eInConstantAreaPi) 02446 // << theCurrentHit->isSet(e1SigmaPi) 02447 // << theCurrentHit->isSet(e2SigmaPi) << " " 02448 // << theCurrentHit->isSet(eInMultipleAreaPi) 02449 // << theCurrentHit->isSet(eInMultipleCAnglePi) 02450 // << theCurrentHit->isSet(eInMultipleCAreaPi); 02451 // } 02452 // else if(part==kaon) { 02453 // cout << "K " 02454 // << theCurrentHit->isSet(eInAreaK) 02455 // << theCurrentHit->isSet(eInConstantAngleK) 02456 // << theCurrentHit->isSet(eInConstantAreaK) 02457 // << theCurrentHit->isSet(e1SigmaK) 02458 // << theCurrentHit->isSet(e2SigmaK) << " " 02459 // << theCurrentHit->isSet(eInMultipleAreaK) 02460 // << theCurrentHit->isSet(eInMultipleCAngleK) 02461 // << theCurrentHit->isSet(eInMultipleCAreaK); 02462 // } 02463 // else if(part==proton) { 02464 // cout << "p " 02465 // << theCurrentHit->isSet(eInAreap) 02466 // << theCurrentHit->isSet(eInConstantAnglep) 02467 // << theCurrentHit->isSet(eInConstantAreap) 02468 // << theCurrentHit->isSet(e1Sigmap) 02469 // << theCurrentHit->isSet(e2Sigmap) << " " 02470 // << theCurrentHit->isSet(eInMultipleAreap) 02471 // << theCurrentHit->isSet(eInMultipleCAnglep) 02472 // << theCurrentHit->isSet(eInMultipleCAreap); 02473 // } 02474 // cout << " " << theCurrentHit << endl; 02475 02476 } // end of hits loop 02477 02478 02479 02480 pid->setTotalDensity(hitsInConstantArea/pid->getTotalArea()); 02481 pid->setTruncatedDensity(hitsInConstantArea/pid->getTruncatedArea()); 02482 02483 pid->setTotalHits(totalHitsInArea); 02484 pid->setTruncatedHits(hitsInConstantArea); 02485 02486 StThreeVectorD residual(-999.,-999.,-999.); 02487 if (!richTrack->getAssociatedMIP()) { 02488 cout << "StRichPIDMaker::fillPIDTraits()\n"; 02489 cout << "\tWARNING Rich Track has no AssociatedMIP*\n"; 02490 cout << "\tp= " << richTrack->getStTrack()->geometry()->momentum().mag() << endl; 02491 } 02492 else { 02493 residual = richTrack->getProjectedMIP() - richTrack->getAssociatedMIP()->local(); 02494 } 02495 02496 // 02497 // This residual is specifically for the refit 02498 // when the particle species energy/momentum loss 02499 // is used. 02500 // The "generic" residual is stored in the PidTrait 02501 // and is the same for all Pids 02502 // 02503 pid->setMipResidual(residual); 02504 02505 // 02506 // assign the pid to the StRichTrack 02507 // 02508 02509 richTrack->getPidTrait()->addPid(pid); 02510 02511 } // end of track check 02512 02513 } 02514 02515 bool StRichPIDMaker::reprocessTheTraits(StRichPidTraits* traits) 02516 { 02517 // 02518 // get the hypothesis 02519 // 02520 const StSPtrVecRichPid& allThePids = traits->getAllPids(); 02521 for(size_t ii=0; ii<allThePids.size(); ii++) { // thepids 02522 StRichPid* pid = allThePids[ii]; 02523 if(!pid) { 02524 cout << "StRichPIDMaker::reprocessTheTraits()\n"; 02525 cout << "\tERROR cannot get the StRichPid\n"; 02526 cout << "\tcontinuing..." << endl; 02527 continue; 02528 } 02529 02530 const StPtrVecRichHit& hit = pid->getAssociatedRichHits(); 02531 02532 unsigned int hitsInConstantArea = 0; 02533 for(size_t jj=0; jj<hit.size(); jj++) { 02534 switch(pid->getParticleNumber()) { 02535 case -211: 02536 // cout << "pi " 02537 // << hit[jj]->isSet(eInAreaPi) 02538 // << hit[jj]->isSet(eInConstantAnglePi) 02539 // << hit[jj]->isSet(eInConstantAreaPi) 02540 // << hit[jj]->isSet(e1SigmaPi) 02541 // << hit[jj]->isSet(e2SigmaPi) << " " 02542 // << hit[jj]->isSet(eInMultipleAreaPi) 02543 // << hit[jj]->isSet(eInMultipleCAnglePi) 02544 // << hit[jj]->isSet(eInMultipleCAreaPi); 02545 02546 if( hit[jj]->isSet(eInMultipleCAreaPi) ) continue; 02547 if( hit[jj]->isSet(eInConstantAreaPi) ) { 02548 hitsInConstantArea++; 02549 } 02550 break; 02551 02552 case -321: 02553 // cout << "K " 02554 // << hit[jj]->isSet(eInAreaK) 02555 // << hit[jj]->isSet(eInConstantAngleK) 02556 // << hit[jj]->isSet(eInConstantAreaK) 02557 // << hit[jj]->isSet(e1SigmaK) 02558 // << hit[jj]->isSet(e2SigmaK) << " " 02559 // << hit[jj]->isSet(eInMultipleAreaK) 02560 // << hit[jj]->isSet(eInMultipleCAngleK) 02561 // << hit[jj]->isSet(eInMultipleCAreaK); 02562 02563 if( hit[jj]->isSet(eInMultipleCAreaK) ) continue; 02564 if( hit[jj]->isSet(eInConstantAreaK) ) { 02565 hitsInConstantArea++; 02566 } 02567 break; 02568 02569 case -2212: 02570 // cout << "p " 02571 // << hit[jj]->isSet(eInAreap) 02572 // << hit[jj]->isSet(eInConstantAnglep) 02573 // << hit[jj]->isSet(eInConstantAreap) 02574 // << hit[jj]->isSet(e1Sigmap) 02575 // << hit[jj]->isSet(e2Sigmap) << " " 02576 // << hit[jj]->isSet(eInMultipleAreap) 02577 // << hit[jj]->isSet(eInMultipleCAnglep) 02578 // << hit[jj]->isSet(eInMultipleCAreap); 02579 02580 if( hit[jj]->isSet(eInMultipleCAreap) ) continue; 02581 if( hit[jj]->isSet(eInConstantAreap) ) { 02582 hitsInConstantArea++; 02583 } 02584 break; 02585 02586 default: 02587 cout << "StRichPIDMaker::reprocessTheTraits()\n"; 02588 cout << "\tERROR Unknown Particle Type\n"; 02589 cout << "\tContinuing..." << endl; 02590 } 02591 //cout << " " << hit[jj] << endl; 02592 } // loop over the hits 02593 02594 if(pid->getTruncatedHits() != hitsInConstantArea) { 02595 //cout << "adjusted < (old) " << hitsInConstantArea; 02596 //cout << "(" << pid->getTruncatedHits() << ")" << endl; 02597 if(hitsInConstantArea > pid->getTruncatedHits()) { 02598 //cout << "StRichPIDMaker::reprocessTheTraits()\n"; 02599 //cout << "\tCANNOT HAVE MORE HITS!!!!\n"; 02600 //cout << "\tAnother Track has touched this..." << endl; 02601 break; 02602 } 02603 02604 pid->setTruncatedHits(hitsInConstantArea); 02605 pid->setTruncatedDensity(hitsInConstantArea/pid->getTruncatedArea()); 02606 } 02607 } // loop over the pids 02608 02609 // 02610 // This is the place an ID should be assigned and 02611 // a probability written out 02612 // ....in progress from the StRichSpectraMaker 02613 // 02614 return true; 02615 } 02616 02617 void StRichPIDMaker::fillRichSoftwareMonitor(StEvent* evnt) { 02618 02619 StSoftwareMonitor* monitor = evnt->softwareMonitor(); 02620 if (monitor) { 02621 StRichSoftwareMonitor* richMonitor = monitor->rich(); 02622 if (richMonitor) { 02623 richMonitor->setNumberOfTracksCrossing(mRichTracks); 02624 richMonitor->setNumberOfTracksAbove1Gev(mNumberOf1GeV); 02625 richMonitor->setNumberOfHitsInRings(mNumberOfRingHits); 02626 } 02627 } 02628 } 02629 02630 void StRichPIDMaker::drawPadPlane(StEvent* rEvent, bool kCreatePsFile) { 02631 02632 #ifdef RICH_WITH_PAD_MONITOR 02633 02634 // StThreeVectorF VertexPos(-999,-999,-999); 02635 // if (rEvent->primaryVertex()) { 02636 // VertexPos = rEvent->primaryVertex()->position(); 02637 // } 02638 02639 mPadMonitor = StRichPadMonitor::getInstance(mGeometryDb); 02640 mPadMonitor->clearTracks(); 02641 mPadMonitor->drawZVertex(mVertexPos.z(),mNumberOfPrimaries,mRichTracks); 02642 mPadMonitor->drawEventInfo(rEvent->runId(),rEvent->id()); 02643 mPadMonitor->drawFileName(fileName); 02644 02645 for (size_t trackIndex=0; trackIndex<mListOfStRichTracks.size(); trackIndex++) { 02646 mPadMonitor->addTrack(mListOfStRichTracks[trackIndex]); 02647 } 02648 02649 mPadMonitor->drawRings(); 02650 //mPadMonitor->hiLiteHits(eInAreaPi,pion); 02651 //mPadMonitor->hiLiteHits(eInAreaK,kaon); 02652 mPadMonitor->hiLiteHits(eInAreap,proton); 02653 //mPadMonitor->hiLiteHits(); 02654 //mPadMonitor->hiLiteHits(e2SigmaPi,pion); 02655 // mPadMonitor->hiLiteHits(e2SigmaK,kaon); 02656 mPadMonitor->hiLiteHits(e2Sigmap,proton); 02657 02658 mPadMonitor->drawRingInfo(); 02659 mPadMonitor->update(); 02660 02661 if (kCreatePsFile) { 02662 cout << "print it...." << endl; 02663 mPadMonitor->printCanvas("~anyDirectory",fileName,rEvent->id()); 02664 } 02665 #endif 02666 } 02667 02668 // 02669 // THE Cuts 02670 // Cut values can be set at the macro level here 02671 // Make sure to respect units 02672 // 02673 02674 void StRichPIDMaker::printCutParameters(ostream& os) const 02675 { 02676 os << "==============================================" << endl; 02677 os << "StRichPIDMaker::printCutParameters()" << endl; 02678 os << "----------------------------------------------" << endl; 02679 os << "Event Level:" << endl; 02680 os << "\tVertexWindow = " << (mVertexWindow/centimeter) << " cm" << endl; 02681 os << "Hit Level:" << endl; 02682 os << "\tAdcCut = " << (mAdcCut) << endl; 02683 os << "Track Level:" << endl; 02684 os << "\tPtCut = " << (mPtCut/GeV) << " GeV/c" << endl; 02685 os << "\tEtaCut = " << mEtaCut << endl; 02686 os << "\tLastHitCut = " << (mLastHitCut/centimeter) << " cm" << endl; 02687 os << "\tDcaCut = " << (mDcaCut/centimeter) << " cm" << endl; 02688 os << "\tFitPointsCut = " << mFitPointsCut << endl; 02689 os << "\tPathCut = " << (mPathCut/centimeter) << " cm" << endl; 02690 os << "\tPadPlaneCut = " << (mPadPlaneCut/centimeter) << " cm" << endl; 02691 os << "\tRadiatorCut = " << (mRadiatorCut/centimeter) << " cm" << endl; 02692 os << "\tThreshMom = " << (mThresholdMomentum/GeV) << " GeV/c" << endl; 02693 os << "----------------------------------------------" << endl; 02694 os << "++++++++++++++++++++++++++++++++++++++++++++++" << endl; 02695 os << "Convergence Precision:" << endl; 02696 os << "\tPrecision = " << (mPrecision/micrometer) << " um" << endl; 02697 os << "----------------------------------------------" << endl; 02698 02699 // os << "<d> " << "\t" << "sigma_d" << endl; 02700 // os << "Negatives" << endl; 02701 // os << meanD[0][0] << "\t" << sigmaD[0][0] << endl; 02702 // os << meanD[1][0] << "\t" << sigmaD[1][0] << endl; 02703 // os << meanD[2][0] << "\t" << sigmaD[2][0] << endl; 02704 // os << meanD[3][0] << "\t" << sigmaD[3][0] << endl; 02705 // os << meanD[4][0] << "\t" << sigmaD[4][0] << endl; 02706 // os << meanD[5][0] << "\t" << sigmaD[5][0] << endl; 02707 02708 // os << "Positives" << endl; 02709 // os << meanD[0][1] << "\t" << sigmaD[0][1] << endl; 02710 // os << meanD[1][1] << "\t" << sigmaD[1][1] << endl; 02711 // os << meanD[2][1] << "\t" << sigmaD[2][1] << endl; 02712 // os << meanD[3][1] << "\t" << sigmaD[3][1] << endl; 02713 // os << meanD[4][1] << "\t" << sigmaD[4][1] << endl; 02714 // os << meanD[5][1] << "\t" << sigmaD[5][1] << endl; 02715 // os << "----------------------------------------------" << endl; 02716 // os << "----------------------------------------------\n" << endl; 02717 02718 } 02719 02720 // Event Level 02721 void StRichPIDMaker::setVertexWindow(float window) { 02722 cout << "StRichPIDMaker::setVertexWindow() " << window << endl; 02723 mVertexWindow = window; 02724 } 02725 02726 // Hit Level 02727 void StRichPIDMaker::setAdcCut(int cut) {mAdcCut = cut;} 02728 02729 // Track Level 02730 void StRichPIDMaker::setLastHitCut(float cut) {mLastHitCut = cut;} 02731 void StRichPIDMaker::setDcaCut(float cut) {mDcaCut = cut;} 02732 void StRichPIDMaker::setPtCut(float cut) {mPtCut = cut;} 02733 void StRichPIDMaker::setEtaCut(float cut) {mEtaCut = cut;} 02734 void StRichPIDMaker::setFitPointsCut(int cut) {mFitPointsCut = cut;} 02735 void StRichPIDMaker::setPathLengthCut(float cut) {mPathCut = cut;} 02736 void StRichPIDMaker::setPadPlaneCut(float cut) {mPadPlaneCut = cut;} 02737 void StRichPIDMaker::setRadiatorCut(float cut) {mRadiatorCut = cut;} 02738 float StRichPIDMaker::getHitSigma(float hitDist) { 02739 float sigma = 0.4; 02740 float mean = 0.45; 02741 return fabs(hitDist-mean)/sigma; 02742 } 02743 02744 02745 void StRichPIDMaker::DefineSaveDirectory(char* directory) { 02746 mySaveDirectory=directory; 02747 } 02748 02749 02750 void StRichPIDMaker::setFileName(char * name){ 02751 fileName = name; 02752 } 02753 02754 02755 void StRichPIDMaker::setWavelengthRange(double shortest , double longest) { 02756 mShortWave = shortest; 02757 mLongWave = longest; 02758 mMaterialDb = StRichMaterialsDb::getDb(); 02759 mMaterialDb->setWavelengthRange(mShortWave,mLongWave); 02760 } 02761 02762 02763 #ifdef myRICH_WITH_MC 02764 void StRichPIDMaker::fillMcPixelNtuple(const StSPtrVecRichPixel* pixels) { 02765 02766 if (!pixels) return; 02767 02768 // loop over hits 02769 StRichMCPixel* monteCarloRichPixel = 0; 02770 for (StSPtrVecRichPixelConstIterator iter = pixels->begin();iter != pixels->end(); ++iter) { 02771 02772 monteCarloRichPixel = dynamic_cast<StRichMCPixel*>(*iter); 02773 if (monteCarloRichPixel) { 02774 Long_t gid[4] = {0,0,0,0}; 02775 Float_t gq[4] = {0,0,0,0}; 02776 Long_t gproc[4] = {0,0,0,0}; 02777 02778 unsigned int n = monteCarloRichPixel->contributions(); 02779 unsigned int limit = (n>4)?(4):(n); 02780 for (int i=0;i<limit;i++) { 02781 gid[i] = monteCarloRichPixel->getMCInfo()[i]->gid(); 02782 gq[i] = monteCarloRichPixel->getMCInfo()[i]->charge(); 02783 gproc[i] = monteCarloRichPixel->getMCInfo()[i]->process(); 02784 } 02785 02786 geantPixelNtuple->Fill(monteCarloRichPixel->adc(),monteCarloRichPixel->contributions(), 02787 gid[0],gid[1],gid[2],gid[3],gq[0],gq[1],gq[2],gq[3], 02788 gproc[0],gproc[1],gproc[2],gproc[3]); 02789 } 02790 } 02791 } 02792 #endif 02793 02794 02795 02796 02797 #ifdef myRICH_WITH_MC 02798 void StRichPIDMaker::fillGeantHitNtuple() { 02799 02800 StRichMCTrack* richMcTrack=0; 02801 02802 float constAngle=-999; 02803 for (size_t trackIndex=0; trackIndex<mListOfStRichTracks.size();trackIndex++) { 02804 richMcTrack = dynamic_cast<StRichMCTrack*>(mListOfStRichTracks[trackIndex]); 02805 if (richMcTrack) { 02806 if (mListOfStRichTracks[trackIndex]->getPidTrait() && 02807 mListOfStRichTracks[trackIndex]->getPidTrait()->getPid(pion)) { 02808 constAngle = mListOfStRichTracks[trackIndex]->getPidTrait()->getPid(pion)->getTruncatedAzimuth(); 02809 } 02810 02811 vector<StMcRichHit*> tempHits = richMcTrack->getGeantPhotons(); 02812 float wave1,psi1,z1; 02813 float wave2,psi2,z2; 02814 float wave1save,wave2save; 02815 float psi1save,psi2save; 02816 float z1save,z2save; 02817 float gtheta1,gtheta2; 02818 float thetap1,thetap2; 02819 float x1,y1,x2,y2; 02820 02821 for (int i=0;i<tempHits.size();i++) { 02822 for (int j=i+1;j<tempHits.size();j++) { 02823 02824 getGeantPhotonInfo(richMcTrack,tempHits[i]->parentTrack(),wave1,psi1,z1,gtheta1,thetap1); 02825 getGeantPhotonInfo(richMcTrack,tempHits[j]->parentTrack(),wave2,psi2,z2,gtheta2,thetap2); 02826 02827 if (fabs(psi1)>constAngle && fabs(psi2)>constAngle) { 02828 02829 if (psi1<0) psi1 = psi1 + 2.0*M_PI; 02830 if (psi2<0) psi2 = psi2 + 2.0*M_PI; 02831 if ( fabs(psi1-psi2) < fabs(psi1save-psi2save)) { 02832 psi1save=psi1; 02833 psi2save=psi2; 02834 wave1save=wave1; 02835 wave2save=wave2; 02836 z1save = z1; 02837 z2save = z2; 02838 x1 = tempHits[i]->position().x(); 02839 y1 = tempHits[i]->position().y(); 02840 x2 = tempHits[j]->position().x(); 02841 y2 = tempHits[j]->position().y(); 02842 } 02843 } 02844 } 02845 } 02846 02847 float array[13]; 02848 array[0] = richMcTrack->getMomentum().mag(); 02849 array[1] = richMcTrack->getTheta()/degree; 02850 array[2] = wave1save/nanometer; 02851 array[3] = wave2save/nanometer; 02852 array[4] = psi1save/degree; 02853 array[5] = psi2save/degree; 02854 array[6] = z1save; 02855 array[7] = z2save; 02856 array[8] = x1; 02857 array[9] = y1; 02858 array[10] = x2; 02859 array[11] = y2; 02860 array[12] = constAngle/degree; 02861 geantCloseHitNtuple->Fill(array); 02862 } 02863 } 02864 } 02865 #endif 02866 02867 02868 02869 02870 02871 02872 #ifdef myRICH_WITH_MC 02873 void StRichPIDMaker::fillMcPhotonNtuple(StMcEvent* mcevent, 02874 const StSPtrVecRichCluster* clusters, 02875 const StSPtrVecRichHit* richHits) { 02876 02877 if (!mcevent || !richHits || !clusters) return; 02878 02879 // need to get the g2t info 02880 St_DataSet* dsGeant = GetDataSet("geant"); 02881 if(!dsGeant || !dsGeant->GetList()) { 02882 dsGeant = GetDataSet("event/geant/Event"); 02883 if(!dsGeant || !dsGeant->GetList()) { return;} 02884 } 02885 02886 St_DataSetIter geantDstI(dsGeant); 02887 St_g2t_track *g2t_track = (St_g2t_track *) geantDstI("g2t_track"); 02888 02889 StRichMCTrack* richMcTrack = 0; 02890 StParticleDefinition* geantParticle = 0; 02891 02892 StRichMCHit* monteCarloRichHit = 0; 02893 StMcTrack* theHitsStMcTrack = 0; 02894 StMcTrack* theHitsParentStMcTrack = 0; 02895 02896 for (size_t trackIndex=0; trackIndex<mListOfStRichTracks.size();trackIndex++) { 02897 02898 richMcTrack = dynamic_cast<StRichMCTrack*>(mListOfStRichTracks[trackIndex]); 02899 geantParticle = richMcTrack->getStMcTrack()->particleDefinition(); 02900 02901 if (richMcTrack && geantParticle) { 02902 02903 richMcTrack->useTPCInfo(); 02904 StRichRingCalculator* TPC_RingCalc = new StRichRingCalculator(richMcTrack,geantParticle); 02905 TPC_RingCalc->calculateArea(); 02906 02907 //if (richMcTrack->fastEnough(geantParticle) && richMcTrack->isGood(geantParticle)) { 02908 //TPC_RingCalc->calculateConstantArea(mPionSaturatedArea,true,totArea);} 02909 02910 richMcTrack->useGeantInfo(); 02911 StRichRingCalculator* GEANT_RingCalc = new StRichRingCalculator(richMcTrack,geantParticle); 02912 GEANT_RingCalc->calculateArea(); 02913 02914 //if (richMcTrack->fastEnough(geantParticle) && richMcTrack->isGood(geantParticle)) { 02915 //GEANT_RingCalc->calculateConstantArea(mPionSaturatedArea,true,totArea);} 02916 02917 richMcTrack->useTPCInfo(); 02918 02919 float defaultValue = -999.0; 02920 float mcWave,mcPsi,mcZ,mcTheta,mcPhotTheta; 02921 int signalPhoton; 02922 02923 // loop over hits 02924 StSPtrVecRichHitConstIterator iter; 02925 for (iter = richHits->begin();iter != richHits->end(); ++iter) { 02926 02927 monteCarloRichHit = dynamic_cast<StRichMCHit*>(*iter); 02928 theHitsStMcTrack = getStMcTrack(monteCarloRichHit, mcevent, g2t_track); 02929 02930 if (monteCarloRichHit && theHitsStMcTrack) { 02931 02932 if (theHitsStMcTrack->geantId() == 50) {theHitsParentStMcTrack = theHitsStMcTrack->parent();} 02933 else {theHitsParentStMcTrack = theHitsStMcTrack;} 02934 02935 // determine if photon's parent == StRichTrack 02936 signalPhoton = 0; 02937 if (monteCarloRichHit->getMCInfo().process()==ePhoton && 02938 theHitsParentStMcTrack == richMcTrack->getStMcTrack() 02939 && theHitsStMcTrack->geantId()==50) { 02940 signalPhoton=1; 02941 } 02942 02943 mcWave = defaultValue; mcPsi = defaultValue; 02944 mcZ = defaultValue; mcTheta = defaultValue; 02945 mcPhotTheta = defaultValue; 02946 getGeantPhotonInfo(richMcTrack,theHitsStMcTrack,mcWave,mcPsi,mcZ,mcTheta,mcPhotTheta); 02947 StThreeVectorF geantRichHit = getTheGeantHitOnPadPlane(theHitsStMcTrack,monteCarloRichHit->local()); 02948 02949 Float_t photonArray[54]; 02950 02951 photonArray[0] = richMcTrack->getStTrack()->geometry()->charge(); 02952 photonArray[1] = richMcTrack->getMomentum().x(); 02953 photonArray[2] = richMcTrack->getMomentum().y(); 02954 photonArray[3] = richMcTrack->getMomentum().z(); 02955 photonArray[4] = richMcTrack->getImpactPoint().x(); 02956 02957 photonArray[5] = richMcTrack->getImpactPoint().y(); 02958 photonArray[6] = richMcTrack->getGeantImpactPointAtRadiator().x(); 02959 photonArray[7] = richMcTrack->getGeantImpactPointAtRadiator().y(); 02960 photonArray[8] = richMcTrack->getProjectedMIP().x(); 02961 photonArray[9] = richMcTrack->getProjectedMIP().y(); 02962 02963 StRichMCHit* tempHit = dynamic_cast<StRichMCHit*>(richMcTrack->getAssociatedMIP()); 02964 if (tempHit) { 02965 02966 photonArray[10] = tempHit->getMCInfo().id(); 02967 photonArray[11] = tempHit->getMCInfo().process(); 02968 photonArray[12] = tempHit->charge(); 02969 photonArray[13] = tempHit->local().x(); 02970 photonArray[14] = tempHit->local().y(); 02971 photonArray[15] = (*clusters)[tempHit->clusterNumber()]->numberOfPads(); 02972 } 02973 02974 tempHit = richMcTrack->getGeantRecoMIP(); 02975 if (tempHit) { 02976 photonArray[16] = tempHit->getMCInfo().id(); 02977 photonArray[17] = tempHit->getMCInfo().process(); 02978 photonArray[18] = tempHit->charge(); 02979 photonArray[19] = tempHit->local().x(); 02980 photonArray[20] = tempHit->local().y(); 02981 photonArray[21] = (*clusters)[tempHit->clusterNumber()]->numberOfPads(); 02982 } 02983 tempHit=0; 02984 02985 photonArray[22] = richMcTrack->getGeantMIP().x(); 02986 photonArray[23] = richMcTrack->getGeantMIP().y(); 02987 photonArray[24] = richMcTrack->getGeantMomentumAtRadiator().x(); 02988 photonArray[25] = richMcTrack->getGeantMomentumAtRadiator().y(); 02989 photonArray[26] = richMcTrack->getGeantMomentumAtRadiator().z(); 02990 02991 photonArray[27] = richMcTrack->getTheta()/degree; 02992 photonArray[28] = richMcTrack->getGeantThetaAtRadiator()/degree; 02993 photonArray[29] = richMcTrack->getPhi()/degree; 02994 photonArray[30] = richMcTrack->getGeantPhiAtRadiator()/degree; 02995 photonArray[31] = richMcTrack->getStMcTrack()->geantId(); 02996 02997 photonArray[32] = signalPhoton; 02998 photonArray[33] = mcWave; 02999 photonArray[34] = mcPsi/degree; 03000 photonArray[35] = mcZ; 03001 photonArray[36] = monteCarloRichHit->getMCInfo().process(); 03002 03003 photonArray[37] = monteCarloRichHit->local().x(); 03004 photonArray[38] = monteCarloRichHit->local().y(); 03005 photonArray[39] = geantRichHit.x(); 03006 photonArray[40] = geantRichHit.y(); 03007 photonArray[41] = geantParticle->mass(); 03008 03009 bool kWriteTheNtuple = false; 03010 03011 richMcTrack->useTPCInfo(); 03012 if (richMcTrack->fastEnough(geantParticle) && richMcTrack->isGood(geantParticle)) { 03013 photonArray[42] = TPC_RingCalc->getConstantAreaAngle(); 03014 this->hitFilter(TPC_RingCalc, monteCarloRichHit->local(),photonArray[43],photonArray[44]); 03015 this->hitFilter(TPC_RingCalc,geantRichHit,photonArray[45],photonArray[46]); 03016 if (fabs(photonArray[44])<5 || fabs(photonArray[46])<5) kWriteTheNtuple=true; 03017 } 03018 else { 03019 photonArray[42]=defaultValue; 03020 photonArray[43]=defaultValue; 03021 photonArray[44]=defaultValue; 03022 photonArray[45]=defaultValue; 03023 photonArray[46]=defaultValue; 03024 } 03025 03026 03027 03028 richMcTrack->useGeantInfo(); 03029 if (richMcTrack->fastEnough(geantParticle) && richMcTrack->isGood(geantParticle)) { 03030 photonArray[47] = GEANT_RingCalc->getConstantAreaAngle(); 03031 this->hitFilter(GEANT_RingCalc,monteCarloRichHit->local(),photonArray[48],photonArray[49]); 03032 this->hitFilter(GEANT_RingCalc,geantRichHit,photonArray[50],photonArray[51]); 03033 if (fabs(photonArray[49])<5 || fabs(photonArray[51])<5) kWriteTheNtuple=true; 03034 } 03035 else { 03036 photonArray[47]=defaultValue; 03037 photonArray[48]=defaultValue; 03038 photonArray[49]=defaultValue; 03039 photonArray[50]=defaultValue; 03040 photonArray[51]=defaultValue; 03041 } 03042 03043 photonArray[52]=mcTheta/degree; 03044 photonArray[53]=mcPhotTheta/degree; 03045 03046 richMcTrack->useTPCInfo(); 03047 geantPhotonNtuple->Fill(photonArray); 03048 } 03049 } 03050 delete TPC_RingCalc; 03051 delete GEANT_RingCalc; 03052 TPC_RingCalc = 0; 03053 GEANT_RingCalc = 0; 03054 } 03055 } 03056 } 03057 #endif 03058 03059 03060 03061 03062 03063 03064 #ifdef myRICH_WITH_MC 03065 void StRichPIDMaker::fillMcTrackNtuple(const StSPtrVecRichCluster* clusters) { 03066 03067 03068 03069 for (size_t trackIndex=0;trackIndex<mListOfStRichTracks.size();trackIndex++) { 03070 StRichMCTrack* track = dynamic_cast<StRichMCTrack*>(mListOfStRichTracks[trackIndex]); 03071 if (!track) { 03072 cout << "trying to send a StTrack to the monte carlo ntuple! " << endl; 03073 abort(); 03074 } 03075 03076 03077 cout << "geant track ntuple" << endl; 03078 StRichPidTraits* pidTrait = track->getPidTrait(); 03079 if (pidTrait) { 03080 03081 StRichPid* pionPid = pidTrait->getPid(pion); 03082 StRichPid* kaonPid = pidTrait->getPid(kaon); 03083 StRichPid* protonPid = pidTrait->getPid(proton); 03084 03085 double PionTotalArea = 0; 03086 double PionConstantArea = 0; 03087 double PionTotalAreaAngle = 0; 03088 double PionConstantAreaAngle = 0; 03089 int PionTotalHits = 0; 03090 int PionConstantHits = 0; 03091 double PionFactor = 0; 03092 03093 if (pionPid) { 03094 PionTotalArea = pionPid->getTotalArea(); 03095 PionConstantArea = pionPid->getTruncatedArea(); 03096 PionTotalAreaAngle = pionPid->getTotalAzimuth(); 03097 PionConstantAreaAngle = pionPid->getTruncatedAzimuth(); 03098 PionTotalHits = pionPid->getTotalHits(); 03099 PionConstantHits = pionPid->getTruncatedHits(); 03100 } 03101 03102 03103 double KaonTotalArea = 0; 03104 double KaonConstantArea = 0; 03105 double KaonTotalAreaAngle = 0; 03106 double KaonConstantAreaAngle = 0; 03107 int KaonTotalHits = 0; 03108 int KaonConstantHits = 0; 03109 double KaonFactor = 0; 03110 03111 if (kaonPid) { 03112 KaonTotalArea = kaonPid->getTotalArea(); 03113 KaonConstantArea = kaonPid->getTruncatedArea(); 03114 KaonTotalAreaAngle = kaonPid->getTotalAzimuth(); 03115 KaonConstantAreaAngle = kaonPid->getTruncatedAzimuth(); 03116 KaonTotalHits = kaonPid->getTotalHits(); 03117 KaonConstantHits = kaonPid->getTruncatedHits(); 03118 } 03119 03120 03121 double ProtonTotalArea = 0; 03122 double ProtonConstantArea = 0; 03123 double ProtonTotalAreaAngle = 0; 03124 double ProtonConstantAreaAngle = 0; 03125 double ProtonFactor = 0; 03126 int ProtonTotalHits = 0; 03127 int ProtonConstantHits = 0; 03128 03129 if (protonPid) { 03130 ProtonTotalArea = protonPid->getTotalArea(); 03131 ProtonConstantArea = protonPid->getTruncatedArea(); 03132 ProtonTotalAreaAngle = protonPid->getTotalAzimuth(); 03133 ProtonConstantAreaAngle = protonPid->getTruncatedAzimuth(); 03134 ProtonTotalHits = protonPid->getTotalHits(); 03135 ProtonConstantHits = protonPid->getTruncatedHits(); 03136 } 03137 03138 03139 03140 03141 StThreeVectorF globalp(track->getStTrack()->geometry()->momentum()); 03142 int counter=0; 03143 float defaultValue = -999; 03144 int const entries=88; 03145 float trackArray[entries]; 03147 03148 trackArray[counter++] = mEventN; 03149 trackArray[counter++] = mNumberOfPrimaries; 03150 trackArray[counter++] = mNegativePrimaries; 03151 trackArray[counter++] = mVertexPos.z(); 03152 trackArray[counter++] = mRichTracks; 03153 03154 trackArray[counter++] = globalp.x(); 03155 trackArray[counter++] = globalp.y(); 03156 trackArray[counter++] = globalp.z(); 03157 trackArray[counter++] = track->getMomentum().x(); 03158 trackArray[counter++] = track->getMomentum().y(); // ---> 10 03159 03160 trackArray[counter++] = track->getMomentum().z(); 03161 trackArray[counter++] = globalp.pseudoRapidity(); 03162 trackArray[counter++] = track->getStTrack()->geometry()->charge(); 03163 03164 StRichMCHit* tempHit = dynamic_cast<StRichMCHit*>(track->getAssociatedMIP()); 03165 if (tempHit) { 03166 trackArray[counter++] = tempHit->getMCInfo().id(); 03167 trackArray[counter++] = tempHit->getMCInfo().process(); 03168 trackArray[counter++] = tempHit->charge(); 03169 trackArray[counter++] = tempHit->local().x(); 03170 trackArray[counter++] = tempHit->local().y(); 03171 trackArray[counter++] = (*clusters)[tempHit->clusterNumber()]->numberOfPads(); 03172 } 03173 else { 03174 trackArray[counter++] = defaultValue; 03175 trackArray[counter++] = defaultValue; 03176 trackArray[counter++] = defaultValue; 03177 trackArray[counter++] = defaultValue; 03178 trackArray[counter++] = defaultValue; 03179 trackArray[counter++] = defaultValue; 03180 } 03181 trackArray[counter++] = track->getProjectedMIP().x(); 03182 03183 03184 trackArray[counter++] = track->getProjectedMIP().y(); 03185 03186 tempHit = track->getGeantRecoMIP(); 03187 if (tempHit) { 03188 trackArray[counter++] = tempHit->getMCInfo().id(); 03189 trackArray[counter++] = tempHit->getMCInfo().process(); 03190 trackArray[counter++] = tempHit->charge(); 03191 trackArray[counter++] = tempHit->local().x(); 03192 trackArray[counter++] = tempHit->local().y(); 03193 trackArray[counter++] = (*clusters)[tempHit->clusterNumber()]->numberOfPads(); 03194 } 03195 else { 03196 trackArray[counter++] = defaultValue; 03197 trackArray[counter++] = defaultValue; 03198 trackArray[counter++] = defaultValue; 03199 trackArray[counter++] = defaultValue; 03200 trackArray[counter++] = defaultValue; 03201 trackArray[counter++] = defaultValue; 03202 } 03203 03204 03205 trackArray[counter++] = track->getImpactPoint().x(); // ----> 10 + 20 == 30 03206 trackArray[counter++] = track->getImpactPoint().y(); 03207 03208 //trackArray[counter++] = track->getUnCorrectedImpactPoint().x(); 03209 //trackArray[counter++] = track->getUnCorrectedImpactPoint().y(); 03210 03211 03212 // 03213 // changed this dec 3, 2000 03214 // 03215 trackArray[counter++] = track->getGeantMomentumAtPadPlane().perp(); 03216 trackArray[counter++] = track->getGeantMomentumAtPadPlane().z(); 03217 03218 03219 03220 trackArray[counter++] = track->getUnCorrectedMomentum().x(); 03221 03222 trackArray[counter++] = track->getUnCorrectedMomentum().y(); 03223 03224 trackArray[counter++] = track->getUnCorrectedMomentum().z(); 03225 trackArray[counter++] = track->getFirstRow(); 03226 trackArray[counter++] = track->getLastRow(); 03227 trackArray[counter++] = track->getLastHit().x(); 03228 trackArray[counter++] = track->getLastHit().y(); 03229 03230 trackArray[counter++] = track->getLastHit().z(); 03231 trackArray[counter++] = track->getLastHitDCA(); 03232 trackArray[counter++] = track->getPathLength(); 03233 trackArray[counter++] = track->getMaxChain(); 03234 trackArray[counter++] = track->getMaxGap(); 03235 03236 trackArray[counter++] = track->getStTrack()->detectorInfo()->numberOfPoints(kTpcId); 03237 trackArray[counter++] = track->getStTrack()->fitTraits().numberOfFitPoints(kTpcId); 03238 trackArray[counter++] = mMaterialDb->indexOfRefractionOfC6F14At(mMaterialDb->innerWavelength()); 03239 trackArray[counter++] = mMaterialDb->indexOfRefractionOfC6F14At(mMaterialDb->outerWavelength()); 03240 trackArray[counter++] = track->getGeantMomentumAtRadiator().x(); 03241 03242 trackArray[counter++] = track->getGeantMomentumAtRadiator().y(); // 30 + 20 = 50 03243 trackArray[counter++] = track->getGeantMomentumAtRadiator().z(); 03244 trackArray[counter++] = track->getGeantImpactPointAtRadiator().x(); 03245 trackArray[counter++] = track->getGeantImpactPointAtRadiator().y(); 03246 trackArray[counter++] = track->getGeantMIP().x(); 03247 03248 trackArray[counter++] = track->getGeantMIP().y(); 03249 if (track->getStMcTrack() && track->getStMcTrack()->stopVertex()) { 03250 trackArray[counter++] = track->getStMcTrack()->stopVertex()->position().x(); 03251 trackArray[counter++] = track->getStMcTrack()->stopVertex()->position().y(); 03252 trackArray[counter++] = track->getStMcTrack()->stopVertex()->position().z(); 03253 } 03254 else { 03255 trackArray[counter++] = defaultValue; 03256 trackArray[counter++] = defaultValue; 03257 trackArray[counter++] = defaultValue; 03258 } 03259 trackArray[counter++] = track->getGeantPhotons().size(); 03260 trackArray[counter++] = track->getRecoGeantPhotons().size(); 03261 03262 trackArray[counter++] = track->getNumberOfGeantHitsInRadiator(); // 50 + 10 = 60 03263 trackArray[counter++] = track->getCommonTpcHits(); 03264 if (track->getStMcTrack()) { 03265 trackArray[counter++] = track->getStMcTrack()->momentum().x(); 03266 trackArray[counter++] = track->getStMcTrack()->momentum().y(); 03267 trackArray[counter++] = track->getStMcTrack()->momentum().z(); 03268 } 03269 else { 03270 trackArray[counter++] = defaultValue; 03271 trackArray[counter++] = defaultValue; 03272 trackArray[counter++] = defaultValue; 03273 } 03274 03275 03276 if (track->getStMcTrack()) { trackArray[counter++] = track->getStMcTrack()->geantId();} 03277 else { trackArray[counter++] = defaultValue;} 03278 03279 if (track->getStMcTrack() && track->getStMcTrack()->stopVertex()) { 03280 trackArray[counter++] = track->getStMcTrack()->stopVertex()->geantProcess();} 03281 else { trackArray[counter++] = defaultValue;} 03282 03283 trackArray[counter++] = track->getNumberOfPartners(); 03284 trackArray[counter++] = PionFactor; 03285 trackArray[counter++] = PionTotalArea; 03286 03287 trackArray[counter++] = PionConstantArea; // 60 + 10 = 70 03288 trackArray[counter++] = PionTotalAreaAngle; 03289 trackArray[counter++] = PionConstantAreaAngle; 03290 trackArray[counter++] = PionTotalHits; 03291 trackArray[counter++] = PionConstantHits; 03292 03293 trackArray[counter++] = KaonFactor; 03294 trackArray[counter++] = KaonTotalArea; 03295 trackArray[counter++] = KaonConstantArea; 03296 trackArray[counter++] = KaonTotalAreaAngle; 03297 trackArray[counter++] = KaonConstantAreaAngle; 03298 03299 trackArray[counter++] = KaonTotalHits; 03300 trackArray[counter++] = KaonConstantHits; 03301 trackArray[counter++] = ProtonFactor; 03302 trackArray[counter++] = ProtonTotalArea; 03303 trackArray[counter++] = ProtonConstantArea; 03304 03305 trackArray[counter++] = ProtonTotalAreaAngle; 03306 trackArray[counter++] = ProtonConstantAreaAngle; 03307 trackArray[counter++] = ProtonTotalHits; 03308 trackArray[counter++] = ProtonConstantHits; // 18 + 70 = 88 03309 03310 if (counter != entries) {cout << "StRichPIDMaker::fillMcPidNtuple wrong counter. abort." << endl; abort();} 03311 03312 cout << "writing out the ntuple" << endl; 03313 geantTrackNtuple->Fill(trackArray); 03314 } 03315 } 03316 } 03317 #endif 03318 03319 03320 03321 03322 03323 void StRichPIDMaker::initNtuples() { 03324 03325 #ifdef myRICH_WITH_NTUPLE 03326 char finalname[200]; 03327 sprintf(finalname,"%s.root",mySaveDirectory); 03328 file = new TFile(finalname,"RECREATE"); 03329 03330 #ifdef ROOT_VERSION_CODE < ROOT_VERSION(3,01,00) 03331 file->SetFormat(1); 03332 #endif 03333 03334 03335 file->SetCompressionLevel(9); 03336 03337 #ifdef myPrivateVersion 03338 cout << "StRichPIDMaker::initNtuples --> creating mStRichUstTrack. " << endl; 03339 m_Track = new TrackEntry(); 03340 myTree = new TTree("myTree","rich pid analysis tree"); 03341 myTree->SetAutoSave(10000000); 03342 int bufsize = 2.0*64000; 03343 int split = 1; 03344 myTree->Branch("TrackBranch","TrackEntry",&m_Track,bufsize,split); 03345 #endif 03346 03347 03348 03349 #ifdef myRICH_WITH_MC 03350 distup = new TNtuple("dist","b","xi:yi:xo:yo:si:ld:d:oldd:oldsig:oldsi:phx:phy:x:y:px:py:pz:theta:evt:numb:resx:resy:res:ring:cos:d2siline:p:q:vtx:refit:constang:energyloss:runid:amipq:gid"); 03351 #else 03352 distup = new TNtuple("dist","b","xi:yi:xo:yo:si:ld:d:oldd:oldsig:oldsi:phx:phy:x:y:px:py:pz:theta:evt:numb:resx:resy:res:ring:cos:d2siline:p:q:vtx:refit:constang:energyloss:runid:amipq"); 03353 #endif 03354 03355 03356 03357 03358 #ifdef myRICH_WITH_MC 03359 geantTrackNtuple = new TNtuple("geantTrackNtuple","geant trackwise tuple", 03360 "evtn:nprimaries:nnegprimaries:vz:nrichtracks:globalpx:globalpy:globalpz:localpx:localpy:localpz:eta:q:amipid:amipproc:amipq:amipx:amipy:amipnpads:pmipx:pmipy:gmipid:gmipproc:gmipq:gmipx:gmipy:gmipnpads:radx:rady:gPtp:gPz:olocalpx:olocalpy:olocalpz:firstrow:lastrow:lasthitx:lasthity:lasthitz:lasthitdca:pathlength:maxchain:maxgap:tpchits:tpcfitpoints:innerwave:outerwave:glocalpx:glocalpy:glocalpz:gradx:grady:geantmipx:geantmipy:gstopvertx:gstopverty:gstopvertz:gphots:grecophots:gradhits:gtpccommonhits:gglobalpx:gglobalpy:gglobalpz:gid:gstopproc:gnpartners:pionfactor:piontotalarea:pionconstarea:piontotalangle:pionconstangle:piontotalhits:pionconsthits:kaonfactor:kaontotalarea:kaonconstarea:kaontotalangle:kaonconstangle:kaontotalhits:kaonconsthits:protonfactor:protontotalarea:protonconstarea:protontotalangle:protonconstangle:protontotalhits:protonconsthits"); 03361 03362 geantPhotonNtuple = new TNtuple("geantPhotonNtuple","geant photon wise tnuple","q:localpx:localpy:localpz:radx:rady:gradx:grady:pmipx:pmipy:amipid:amipproc:amipq:amipx:amipy:amipnpads:gamipid:gamipproc:gamipq:gamipx:gamipy:gamipnpads:gmipx:gmipy:glocalpx:glocalpy:glocalpz:theta:gtheta:phi:gphi:gid:signal:gwave:gpsi:gz:gproc:x:y:gx:gy:gmass:constangle:trdist:trang:tgdist:tgang:gconstangle:grdist:grang:ggdist:ggang:gcher:gphottheta"); 03363 03364 geantPixelNtuple = new TNtuple("geantPixelNtuple","pixels","adc:n:gid0:gid1:gid2:gid3:q0:q1:q2:q3:proc0:proc1:proc2:proc3"); 03365 geantCloseHitNtuple = new TNtuple("geantHitNtuple","pixels","p:theta:w1:w2:psi1:psi2:z1:z2:x1:y1:x2:y2:constAngle"); 03366 #endif 03367 03368 #endif 03369 } 03370 03371 03372 03373 #ifdef myRICH_WITH_MC 03374 bool StRichPIDMaker::makeTrackAssociations(StMcEvent* temp_mEvent, const StSPtrVecRichHit* hits ) { 03375 03376 cout << "StRichPIDMaker:makeTrackAssociations()\n"; 03377 03378 if (!temp_mEvent || !hits) { 03379 cout << "StRichPIDMaker:makeTrackAssociations()\n"; 03380 cout << "No StMcEvent/rich hits!" << endl; 03381 return false;} 03382 03383 // StAssociationMaker 03384 StAssociationMaker* assoc = 0; 03385 assoc = (StAssociationMaker*) GetMaker("StAssociationMaker"); 03386 if (!assoc) { 03387 cout << "StRichPIDMaker:makeTrackAssociation() \n"; 03388 cout << "No association maker!" << endl; 03389 return false;} 03390 03391 rcTrackMapType* theTrackMap = 0; 03392 theTrackMap = assoc->rcTrackMap(); 03393 if (!theTrackMap) { 03394 cout << "StRichPIDMaker:makeTrackAssociation() \n"; 03395 cout << "No track map!" << endl; 03396 return false;} 03397 03398 for (size_t trackIndex=0; trackIndex<mListOfStRichTracks.size(); trackIndex++) { // track 03399 03400 unsigned int maxCommonTpcHits = 0; 03401 unsigned int numberOfPartners = 0; 03402 03403 StMcTrack* mcPartner = 0; 03404 StRichMCTrack* richMcTrack = dynamic_cast<StRichMCTrack*>(mListOfStRichTracks[trackIndex]); 03405 cout << "rich mc track = " << richMcTrack << endl; 03406 if (richMcTrack && richMcTrack->getStTrack() && 03407 richMcTrack->getStTrack()->node() && 03408 richMcTrack->getStTrack()->node()->track(global)) { 03409 03410 StGlobalTrack* globaltrack = 03411 dynamic_cast<StGlobalTrack*>(richMcTrack->getStTrack()->node()->track(global)); 03412 cout << "global track pointer= " << globaltrack << endl; 03413 03414 if (globaltrack) { 03415 pair<rcTrackMapIter,rcTrackMapIter> trackBounds = theTrackMap->equal_range(globaltrack); 03416 cout << "about to loop over track bounds " << endl; 03417 03418 for (rcTrackMapIter rcIt = trackBounds.first; rcIt != trackBounds.second; ++rcIt) { 03419 numberOfPartners++; 03420 if ((*rcIt).second->commonTpcHits() > maxCommonTpcHits) { 03421 mcPartner = (*rcIt).second->partnerMcTrack(); 03422 maxCommonTpcHits = (*rcIt).second->commonTpcHits(); 03423 } 03424 } 03425 03426 03427 // need to get the g2t info 03428 St_DataSet* dsGeant = GetDataSet("geant"); 03429 if(!dsGeant || !dsGeant->GetList()) { 03430 gMessMgr->Warning() << "Could not find dataset geant" << endm; 03431 dsGeant = GetDataSet("event/geant/Event"); 03432 if(!dsGeant || !dsGeant->GetList()) { // Try direct output from Geant 03433 gMessMgr->Warning() << "Could not find dataset event/geant/Event" << endm; 03434 return false; 03435 } 03436 } 03437 03438 // Now the Iterator is set up, and this allows us to access the tables 03439 // This is done like so: 03440 // TableClass *instanceOfTableClassPointer = 03441 // cast to TableClassPointer instanceOfDataSetIter("actual name of table in data set"); 03442 St_DataSetIter geantDstI(dsGeant); 03443 St_g2t_track *g2t_track = (St_g2t_track *) geantDstI("g2t_track"); 03444 03445 richMcTrack->setStMcTrack(mcPartner); 03446 richMcTrack->setGeantPhotons(temp_mEvent); 03447 richMcTrack->setCommonTpcHits(maxCommonTpcHits); 03448 richMcTrack->setNumberOfPartners(numberOfPartners); 03449 richMcTrack->setGeantRecoMIP(hits, temp_mEvent, g2t_track); 03450 richMcTrack->setRecoGeantPhotons(hits,temp_mEvent,g2t_track); 03451 } 03452 } 03453 } 03454 return true; 03455 } 03456 #endif 03457 03458 03459 #ifdef myRICH_WITH_MC 03460 StMcTrack* StRichPIDMaker::getStMcTrack(StRichMCHit* hit, StMcEvent* mcevt, St_g2t_track* geantTracks) { 03461 03462 StMcTrack* mcTrack=0; 03463 if (!hit || !mcevt || !geantTracks) return mcTrack; 03464 g2t_track_st *trackList = geantTracks->GetTable(); 03465 03466 unsigned int hitIndex = 0; 03467 if (hit->getMCInfo().process()==ePhoton) hitIndex = hit->getMCInfo().id(); 03468 else if (hit->getMCInfo().process()==eCharged) hitIndex = hit->getMCInfo().trackp(); 03469 else { return 0;} 03470 03471 float start=0; 03472 float end = mcevt->tracks().size()-1; 03473 int index = hitIndex; 03474 int counter=0; 03475 bool searching=true; 03476 while (searching) { 03477 if (index >= mcevt->tracks().size()-1) return 0; 03478 if (trackList[hitIndex].id == mcevt->tracks()[index]->key()) {return mcevt->tracks()[index];} 03479 if (trackList[hitIndex].id > mcevt->tracks()[index]->key()) {start=index;} 03480 else {end=index;} 03481 index=(end-start)/2 + start; 03482 counter++; 03483 if (counter>mcevt->tracks().size()-1) searching=false; 03484 } 03485 return mcTrack; 03486 } 03487 #endif 03488 03489 03490 03491 #ifdef myRICH_WITH_MC 03492 void StRichPIDMaker::getGeantPhotonInfo(StRichMCTrack* richTrack, StMcTrack* photon, 03493 float& wave, float& gpsi, float& z, float& gtheta, float& gphottheta) { 03494 03495 wave = -999; 03496 gpsi = -999; 03497 z = -999; 03498 gtheta = -999; 03499 gphottheta = -999; 03500 if (!richTrack || !photon || photon->geantId()!=50) { return;} 03501 03502 StRichLocalCoordinate localStartVert(-999,-999,-999); 03503 if (photon->startVertex()) { 03504 StGlobalCoordinate globalStartVert(photon->startVertex()->position().x(), 03505 photon->startVertex()->position().y(), 03506 photon->startVertex()->position().z()); 03507 (*mCoordinateTransformation)(globalStartVert,localStartVert); 03508 } 03509 z = localStartVert.position().z(); 03510 03511 03512 // get photons momentum at emission pt 03513 StThreeVector<double> globalMomentum(photon->momentum().x(), 03514 photon->momentum().y(), 03515 photon->momentum().z()); 03516 03517 // get geant photons azimuthal angle of emission 03518 // need to normalize vector (mag of photon vector ~ 1.0e-9) 03519 if (globalMomentum.mag()==0) {return;} 03520 globalMomentum.setMag(1.0); 03521 StThreeVector<double> localMomentum; 03522 mMomentumTransformation->localMomentum(globalMomentum,localMomentum); 03523 03524 gphottheta = acos(-localMomentum.z()/localMomentum.mag()); 03525 03526 StThreeVectorF trackLocalMomentum = richTrack->getGeantMomentumAtRadiator(); 03527 if (trackLocalMomentum.mag() == 0) {return;} 03528 trackLocalMomentum.setMag(1.0); 03529 03530 StThreeVectorF vect(0.0,0.0,1.0); 03531 double rotationTheta = acos(vect.dot(trackLocalMomentum)); 03532 double rotationPhi = trackLocalMomentum.phi(); 03533 03534 // do rotation 03535 StThreeVectorF 03536 rotatedTrackMomentum(cos(rotationTheta)*cos(rotationPhi)*trackLocalMomentum.x() + 03537 cos(rotationTheta)*sin(rotationPhi)*trackLocalMomentum.y() - 03538 sin(rotationTheta)*trackLocalMomentum.z(), 03539 03540 -sin(rotationPhi)*trackLocalMomentum.x() + 03541 cos(rotationPhi)*trackLocalMomentum.y(), 03542 03543 cos(rotationPhi)*sin(rotationTheta)*trackLocalMomentum.x() + 03544 sin(rotationPhi)*sin(rotationTheta)*trackLocalMomentum.y() + 03545 cos(rotationTheta)*trackLocalMomentum.z()); 03546 03547 StThreeVectorF 03548 photonRotatedMomentum(cos(rotationTheta)*cos(rotationPhi)*localMomentum.x() + 03549 cos(rotationTheta)*sin(rotationPhi)*localMomentum.y() - 03550 sin(rotationTheta)*localMomentum.z(), 03551 03552 -sin(rotationPhi)*localMomentum.x() + 03553 cos(rotationPhi)*localMomentum.y(), 03554 03555 cos(rotationPhi)*sin(rotationTheta)*localMomentum.x() + 03556 sin(rotationPhi)*sin(rotationTheta)*localMomentum.y() + 03557 cos(rotationTheta)*localMomentum.z()); 03558 03559 gpsi = atan2( rotatedTrackMomentum.x() - photonRotatedMomentum.x(), 03560 rotatedTrackMomentum.y() - photonRotatedMomentum.y()); 03561 03562 gtheta = acos(rotatedTrackMomentum.dot(photonRotatedMomentum)); 03563 03564 // cout << "chernekov angle of emission = " << gtheta/degree << endl; 03565 // cout << "angle against normal = " << gphottheta/degree << endl; 03566 03567 double constantPhaseDifference = M_PI/2.0; 03568 gpsi = gpsi - constantPhaseDifference; 03569 if (gpsi < -M_PI) {gpsi = gpsi + 2.0*M_PI;} 03570 03571 // get photons wavelength (nm) 03572 wave = ( ( (h_Planck/eV)*c_light)/(photon->energy()/eV) )/nanometer; 03573 } 03574 #endif 03575 03576 03577 #ifdef myRICH_WITH_MC 03578 StThreeVectorF StRichPIDMaker::getTheGeantHitOnPadPlane(StMcTrack* mcTrack, StThreeVectorF& inputHit) { 03579 03580 03581 double anodeDistanceToPadPlane = mGeometryDb->anodeToPadSpacing(); 03582 float defaultValue = -999.9; 03583 StThreeVectorF hit(defaultValue,defaultValue,defaultValue); 03584 StThreeVectorF tempHit(defaultValue,defaultValue,defaultValue); 03585 if (!mcTrack) return hit; 03586 03587 // photon case --> get point on pad plane 03588 if (mcTrack->geantId()==50) { 03589 03590 StGlobalCoordinate testGlobal(mcTrack->richHits()[0]->position().x(), 03591 mcTrack->richHits()[0]->position().y(), 03592 mcTrack->richHits()[0]->position().z()); 03593 03594 StRichLocalCoordinate testLocalPoint(0,0,0); 03595 (*mCoordinateTransformation)(testGlobal,testLocalPoint); 03596 03597 hit.setX(testLocalPoint.position().x()); 03598 hit.setY(testLocalPoint.position().y()); 03599 hit.setZ(testLocalPoint.position().z()); 03600 } 03601 03602 // charged particle case ---> get point on anode wire 03603 else { 03604 for (size_t i=0;i<mcTrack->richHits().size();i++) { 03605 03606 StGlobalCoordinate testGlobal(mcTrack->richHits()[i]->position().x(), 03607 mcTrack->richHits()[i]->position().y(), 03608 mcTrack->richHits()[i]->position().z()); 03609 03610 StRichLocalCoordinate testLocalPoint(0,0,0); 03611 (*mCoordinateTransformation)(testGlobal,testLocalPoint); 03612 03613 tempHit.setX(testLocalPoint.position().x()); 03614 tempHit.setY(testLocalPoint.position().y()); 03615 tempHit.setZ(testLocalPoint.position().z()); 03616 03617 // geant mip at anode wire position 03618 if ( fabs(tempHit.z()) > 0.00 && fabs(tempHit.z()) < 2.0*anodeDistanceToPadPlane ) { 03619 if ( (tempHit-inputHit).perp() < (hit-inputHit).perp() ) {hit = tempHit;} 03620 } 03621 } 03622 } 03623 03624 return hit; 03625 } 03626 03627 #endif 03628 03629 03630 #ifdef RICH_WITH_L3_TRACKS 03631 double StRichPIDMaker::findL3ZVertex(globalTrack * trackVec,int nTracks){ 03632 03633 TH1D temp("temp","vertex",500,-100,100); 03634 for(int i = 0;i<nTracks;i++){ 03635 double currentVertex; 03636 currentVertex = trackVec[i].z0-trackVec[i].tanl*trackVec[i].r0*cos(trackVec[i].psi-trackVec[i].phi0); 03637 temp.Fill(currentVertex); 03638 } 03639 03640 return temp.GetBinCenter(temp.GetMaximumBin()); 03641 } 03642 #endif 03643 03644 03645 03646 03647 ClassImp(StRichPIDMaker) 03648 03649 03650 03651 03652 03653 03654 03655 03656 03657

Generated on Tue Mar 17 04:55:51 2009 for StRoot by doxygen 1.3.7