mEmcToolsModule.C

Go to the documentation of this file.
00001 //-------------------------------------------------------------------------
00002 // 
00003 // Package: offline/packages/emc
00004 //
00005 // Purpose: Encapsulate functions basically used by the simul+real embedding procedure
00006 // 
00007 // Copyright (C) PHENIX collaboration, 2000-2001
00008 //
00009 // Author: David D'ENTERRIA SUBATECH 
00010 //-------------------------------------------------------------------------
00011 
00012 
00013 #include "mEmcToolsModule.h"
00014 #include "dEmcCalibTowerWrapper.h"
00015 #include "emcCalibratedDataObject.h"
00016 #include "fkinWrapper.h"
00017 #include "KinPISAHit.h"
00018 #include "EmcIndexer.h"
00019 #include "emcManageable.h"
00020 #include "emcDataManager.h"
00021 #include "emcRawDataAccessor.h"
00022 #include "EmcDynamicData.h"
00023 #include "emcDBMS.h"
00024 #include "mEmcGeometryModule.h"
00025 
00026 
00027 #include "PHIODataNode.h"
00028 #include "PHNodeReset.h"
00029 
00030 #include "TTree.h"
00031 
00032 #include "gsl/gsl_math.h"
00033 
00034 #include <cstdlib>
00035 #include <iomanip>
00036 #include <cassert>
00037 
00038 using namespace std;
00039 
00040 //_____________________________________________________________________________
00041 // Default constructor
00042 
00043 mEmcToolsModule::mEmcToolsModule()
00044 {
00045   fEmc_QA = 0;
00046   fVerbose = 0 ;
00047   fZeroEnergyAndTOFInDeadTowers = true;
00048 }
00049 
00050 //_____________________________________________________________________________
00051 mEmcToolsModule*
00052 mEmcToolsModule::instance()
00053 {
00054   static mEmcToolsModule* single = new mEmcToolsModule();
00055   return single;
00056 }
00057 
00058 //_____________________________________________________________________________
00059 //
00060 // Set ecal and tof to zero if the tower is dead (default)
00061 // Set it to false if you want a pure simulation without real data deadmap effects
00062 // (e.g. for pure acceptance)
00063 
00064 void
00065 mEmcToolsModule::setEnergyAndTOFtoZeroInDeadTowers(const bool DeadToZero) 
00066 { 
00067   fZeroEnergyAndTOFInDeadTowers = DeadToZero;
00068 }
00069 
00070 //_____________________________________________________________________________
00071 Int_t
00072 mEmcToolsModule::EmcCollectDeadMap(const PHTimeStamp when)
00073 {
00074 
00075   PHTimeStamp when1;
00076   when1.set("Mon Jul 1 00:00:00 2000"); // Run-1 ~start
00077 
00078   if ( when < when1 )
00079     {
00080       cout << "<W> EmcCollectDeadMap: " << when << " is not a valid date." << endl ;
00081       return -1;
00082     }
00083 
00084   // Get DataMap of current configuration
00085   int emcmap = EmcGetDataMap();
00086   if ( emcmap ==-1 )
00087     {
00088       return -1;
00089     }
00090 
00091   // Collection of Q&As from Database
00092   emcQAs qaDriver ;
00093 
00094   PHTimeStamp when2;
00095   when2.set("Mon Jan 1 00:00:00 2001"); // Run-2 start
00096 
00097   string ExtraRejectListFilename ;
00098 
00099   emcDataManager* dm = emcDataManager::GetInstance() ;
00100 
00101   // Set some parameters for the qa object we want
00102   qaDriver.SetSource(emcDBMS::get()) ;
00103 
00104   // New MV reject list format 
00105   if ( when < when2 )  // Year-1
00106     {
00107       ExtraRejectListFilename = "/afs/rhic/phenix/phnxemc/PBGL/emc_extra_reject_yr1.list" ;  
00108       qaDriver.SetExtraRejectListFilename(ExtraRejectListFilename.c_str())  ;  
00109     }
00110   else if ( when > when2 ) // Year-2
00111     {
00112       ExtraRejectListFilename = "/afs/rhic/phenix/phnxemc/DATA/emc_extra_reject_Run2pp.list";
00113       //ExtraRejectListFilename = "/afs/rhic/phenix/phnxemc/DATA/emc_extra_reject_Run2AuAu.list";
00114       qaDriver.SetExtraRejectListFilename(ExtraRejectListFilename.c_str())  ;  
00115     }
00116 
00117   cout << "<I> EmcCollectDeadMap: extrareject list: " << qaDriver.GetExtraRejectListFilename() << endl ;
00118 
00119   // Collect it
00120   fEmc_QA = dynamic_cast<emcQAs*>( dm->Collect(qaDriver,when) ) ;
00121   if (!fEmc_QA) 
00122     {
00123       cerr << "<E> EmcCollectDeadMap: Could not collect Q&A ?!" << endl ;
00124       return -1;
00125     }
00126 
00127   return 0;
00128 }
00129 
00130 //_____________________________________________________________________________
00131 // Gets DataMap for current EMCal configuration
00132 Int_t
00133 mEmcToolsModule::EmcGetDataMap()
00134 {
00135 
00136   vector<Int_t> emc_map; // transitory DataMap [index<->channel] for QA
00137   emcRawDataAccessor* tmp_rda = emcRawDataAccessor::GetInstance() ;
00138   assert(tmp_rda!=0);
00139 
00140   Int_t nchannel = (Int_t)tmp_rda->GetDynamicData()->getEmcSize(); // get size of emc dyn. arrays
00141   Int_t* tmp_map = (Int_t*)tmp_rda->GetDynamicData()->getEmcMap();
00142   if (!tmp_map) 
00143     {
00144       cerr << "<E> EmcGetDataMap: Could not collect Q&A data map ?!" << endl ;
00145       return -1;
00146     }
00147 
00148   // Fill associated STL vector with data mapping. Style:  
00149   // 'true' = absolute FEM addresses (channel #):  address=absFEM*192+ch, where absFEM=FEM#(0-171), ch=channel#(0-191).
00150   // 'false'= EMCal towers mapping style (towers number): address=tower#(0-24767).
00151   if (!tmp_rda->GetDynamicData()->getMapStyle()) 
00152     {
00153       cout << "<W> EmcGetDataMap: Datamap for deadmap is in tower-number style "
00154            << " (this is not expected in offline !!)" << endl ;
00155       // FIXME: We do not need to reproduce address=tower# numbering (0-24767) in this strange case ... otherwise:
00156       //if (emc_map.empty()) {
00157       //emc_map.resize(nchannel);
00158       //for (Int_t i=0; i<nchannel; i++) emc_map.push_back(i); 
00159       //}
00160       return -1;
00161     }
00162 
00163   if (fVerbose >0)
00164     {
00165       cout << "<I> EmcGetDataMap: Datamap for deadmap is in FEM-type style" << endl ;
00166     }
00167   if (emc_map.empty()) 
00168     {
00169       emc_map.resize(nchannel);
00170       copy(tmp_map,tmp_map+nchannel,emc_map.begin());
00171     }
00172 
00173   // let's swap the order of the indexes in the vector so that it is easier to find a given channel
00174   // Definite DataMap [channel<->index] for QA
00175   fEmc_map.clear();
00176   for (Int_t i = 0 ; i < nchannel ; i++ ) 
00177     { 
00178       fEmc_map[ (Int_t) emc_map[i] ] = i ;
00179     }
00180 
00181   return 0;
00182 }
00183 
00184 //_____________________________________________________________________________
00185 // Assign DeadMap of real towers to simulated ones
00186 Int_t 
00187 mEmcToolsModule::AssignRealDeadMaptoSimulTowers(PHCompositeNode *topNode)
00188 {
00189 
00190   if (!fEmc_QA) 
00191     {
00192       cout << "<W> AssignRealDeadMaptoSimulTowers: EMC dead-map propagation requested" 
00193            << " but no EMC dead-map available" << endl ;
00194       return -1;
00195     }
00196 
00197   PHNodeIterator mainIter(topNode);
00198 
00199   dEmcCalibTowerWrapper* dEmcCalibTower = 0;
00200   PHIODataNode<PHTable>* dEmcCalibTowerNode = 0;
00201   dEmcCalibTowerNode =(PHIODataNode<PHTable>*)mainIter.findFirst("PHIODataNode","dEmcCalibTower");
00202   if (dEmcCalibTowerNode)
00203     {
00204       dEmcCalibTower = (dEmcCalibTowerWrapper*)dEmcCalibTowerNode->getData();
00205     }
00206   else
00207     {
00208       cout << "<W> AssignRealDeadMaptoSimulTower: dEmcCalibTower table not found ..." << endl;
00209       return -1 ;
00210     }
00211   
00212   Int_t dead = 0 ;
00213   Int_t arm = 0, isector = 0, yrow = 0, zrow = 0;
00214   Int_t towerid = 0; 
00215   Int_t rowcount = 0;
00216   Int_t dead_count = 0;
00217 
00218   rowcount = (Int_t)dEmcCalibTower->RowCount();
00219 
00220   if (rowcount) 
00221     {
00222       cout << endl << "<I> AssignRealDeadMaptoSimulTower: Retrieved EMCal DeadMaps for " 
00223            << (rowcount-1) << " Calibtowers " << endl;
00224     }
00225 
00226   for( Int_t j = 0 ; j < rowcount; j++ ) 
00227     {
00228       isector  = (Int_t)dEmcCalibTower->get_sector(j) ;
00229       yrow     = (Int_t)dEmcCalibTower->get_ind(1,j) ;
00230       zrow     = (Int_t)dEmcCalibTower->get_ind(0,j) ;
00231       arm      = (Int_t)dEmcCalibTower->get_arm(j) ; 
00232       // transform offline sector number (0-3 West and 0-3 East) into online one (0-7)
00233       // Valid transformation for Year-1 and Year-2 data. CKB 28 Nov. '01 
00234       if ( arm == 1 )
00235         {
00236           if( isector > 1 )
00237             {
00238               isector+=2;
00239             }
00240           else
00241             {
00242               isector+=6;
00243             }
00244         }
00245       towerid = EmcIndexer::getTowerId(isector,zrow,yrow);
00246       
00247       dead     = fEmc_QA->GetDead( (Int_t)fEmc_map[towerid]); 
00248       if ( (dead & emcQAs::IamDeadMask()) && fZeroEnergyAndTOFInDeadTowers ) 
00249         { 
00250           if (!(dead_count)) cout << "<I> AssignRealDeadMaptoSimulTower: EMCal dead channel(s): " ;
00251           cout << towerid << " (" << fEmc_map[towerid] << ") = " << dead << ", " << flush ;
00252           // set ecal and tof to zero 
00253           // In the case of real data (in MDO -> RDO):
00254           // a) in compressed mode: the tower is simply dropped 
00255           // b) in non-compressed mode: ADC and TDC are set to zero
00256           // We adopt b) here.  When merging with a real event,
00257           // the tower will be there (i.e. observable by the evaluator) but empty.
00258           dEmcCalibTower->set_ecal(j,0.) ;
00259           dEmcCalibTower->set_tof(j,0.) ;
00260           dead_count++;
00261         }
00262       dEmcCalibTower->set_deadmap(j,dead) ; 
00263     }
00264   if (dead_count) cout << "<I> Total num. of EMCal dead channels: " << dead_count << endl ;
00265   
00266   return 0;
00267 }
00268 
00269 //_____________________________________________________________________________
00270 PHBoolean
00271 mEmcToolsModule::event(PHCompositeNode* topNode)
00272 {
00273   int rv = AssignRealDeadMaptoSimulTowers(topNode);
00274   if ( rv )
00275     {
00276       return false;
00277     }
00278   else
00279     {
00280       return true;
00281     }
00282 }
00283 
00284 //_____________________________________________________________________________
00285 // Get the Calibrated Data Object from the CalibTower Table 
00286 // (temporary thing till we git rid of calibtower table in dst)
00287 void 
00288 mEmcToolsModule::GetCdoFromCalibTowerTable(const dEmcCalibTowerWrapper& dEmcCalibTower, 
00289                                            emcCalibratedDataObject& cdo, 
00290                                            const Float_t SimCorrection)
00291 {
00292   Int_t j;
00293   Int_t towerid = 0;
00294   Int_t arm = 0 , isector = 0 , yrow = 0 , zrow = 0;
00295   Int_t dummy = 0 , deadNeighbours = 0;
00296   Float_t energy = 0. , time = 0.;  
00297   Float_t etotal = 0.;
00298   Long_t softkey = 0; 
00299   Int_t rowcount = 0 ;
00300   Int_t warn = 0;
00301 
00302   rowcount = (Int_t)dEmcCalibTower.RowCount();
00303   cdo.Reset();
00304 
00305   // fill the Cdo from the CalibTower table
00306   for (j = 0 ; j < rowcount; j++) 
00307     {
00308       // this is a tricky workaround to get part of the calibtower data
00309       // members just using the softkey and the cdo decodekey function
00310       softkey = (Long_t)dEmcCalibTower.get_swkey(j) ;
00311       cdo.DecodeKey( softkey, arm, isector, yrow, zrow);
00312       
00313       // alternatively this is the "long" way ...
00314       //arm     = dEmcCalibTower.get_arm(j) ; 
00315       //isector = dEmcCalibTower.get_sector(j) ;
00316       //yrow    = dEmcCalibTower.get_ind(1,j) ;
00317       //zrow    = dEmcCalibTower.get_ind(0,j) ;
00318       
00319       // let's transform offline sector number (0-3 West and 0-3 East) into online one (0-7)
00320       // Valid transformation for year-1 and year-2 data. CKB 28 Nov. '01 
00321       if ( arm == 1 )
00322         {
00323           if( isector > 1 )
00324             {
00325               isector+=2;
00326             }
00327           else
00328             {
00329               isector+=6;
00330             }
00331         }
00332       towerid = EmcIndexer::getTowerId(isector,zrow,yrow);
00333 
00334       // Correction for PbGl Simulation, to take 15% energy correction for real events into account
00335       if( (arm) && (isector>=6) ) energy  = dEmcCalibTower.get_ecal(j)*SimCorrection;
00336       else energy  = dEmcCalibTower.get_ecal(j) ;
00337       
00338       time    = dEmcCalibTower.get_tof(j) ;
00339       deadNeighbours = dEmcCalibTower.get_deadmap(j) ;
00340       warn    = dEmcCalibTower.get_warnmap(j) ;
00341       cdo.Set(j, towerid, softkey, dummy, energy, time, deadNeighbours, warn);
00342       
00343       etotal += energy ;
00344       if ( fVerbose>0 ) 
00345         {
00346           if ( j == 0 ) cout << " Cdo Filled (id,towerid,softkey,errflag,ecal,tof,deadneigh,warn) = " << endl;
00347           cout << j      << "," << towerid << "," << softkey        << "," << dummy << "," 
00348                << energy << "," << time    << "," << deadNeighbours << "," << warn ;
00349           cout << "  Softkey CalibTower: " << dEmcCalibTower.get_swkey(j) << " CDO Generated: " 
00350                << cdo.GenerateSoftwareKey(towerid) << " CDO Gotten: " << cdo.GetSoftwareKey(j) << endl ;
00351         }
00352     }
00353   
00354   cdo.SetTotalEnergy(etotal);
00355   cdo.SetZeroSuppressedFlag(true);
00356   cdo.SetEnergyCalibratedFlag(true);
00357   cdo.SetTimeCalibratedFlag(true) ;
00358 
00359 }
00360 
00361 //_____________________________________________________________________________
00362 // Get the CalibTower Table from the Calibrated Data Object
00363 // (temporary thing till we git rid of calibtower table in dst)
00364 void 
00365 mEmcToolsModule::GetCalibTowerTableFromCdo( dEmcCalibTowerWrapper& dEmcCalibTower, 
00366                                             const emcCalibratedDataObject& cdo)
00367 {
00368 
00369   Int_t j;
00370   Int_t arm = 0, sector = 0, yrow = 0 , zrow = 0;
00371   Short_t outrow = 0 ;   
00372   Long_t softkey = 0 ;  
00373   Float_t energy = 0.;
00374   Float_t tof = 0.;
00375   Int_t type = 1; // Type = 1 (PbSc) by default ...
00376   Int_t dead = 0 ;
00377   Int_t warn = 0 ;
00378  
00379   emcCalibratedDataObject cdo2(cdo); // copy to update indexmap and softkeys otherwise softkey are zero (??)
00380   cdo2.Update();
00381 
00382   // fill the CalibTower table from cdo
00383   for (j = 0 ; j < cdo.GetSize(); j++) 
00384     {
00385       cdo.Get( j, energy, tof) ;
00386       softkey = cdo2.GetSoftwareKey(j) ;
00387       dead = (Int_t)cdo.GetDead(j) ;
00388       warn = (Int_t)cdo.GetWarn(j) ;
00389 
00390       if (energy > 0.001) { // Hard-coded 1 MeV CalibTower threshold
00391         cdo.DecodeKey( softkey, arm, sector, yrow, zrow);
00392         dEmcCalibTower.set_id(outrow,outrow) ;
00393         dEmcCalibTower.set_hwkey(outrow,0) ;
00394         dEmcCalibTower.set_swkey(outrow,softkey) ;
00395         dEmcCalibTower.set_type(outrow,type) ;
00396         dEmcCalibTower.set_arm(outrow,arm) ;
00397         dEmcCalibTower.set_sector(outrow,sector) ;
00398         dEmcCalibTower.set_ind(1,outrow,yrow) ;
00399         dEmcCalibTower.set_ind(0,outrow,zrow) ;
00400         dEmcCalibTower.set_ecal(outrow,energy) ;
00401         dEmcCalibTower.set_tof(outrow,tof) ;
00402         dEmcCalibTower.set_deadmap(outrow,dead) ;
00403         dEmcCalibTower.set_warnmap(outrow, warn);
00404         
00405         if ( fVerbose>0 ) 
00406           {
00407             if ( outrow==0 )
00408               {
00409                 cout << "dEmcCalibTower Filled (id,hwkey,swkey,type,arm,sector,yrow,zrow,ecal,tof,dead,warn) = " << endl ;
00410               }
00411             cout << outrow << "," << 0    << "," << softkey << "," << type   << "," << arm << "," 
00412                  << sector << "," << yrow << "," << zrow    << "," << energy << "," << tof << ","
00413                  << dead   << "," << warn << endl;
00414           }
00415         outrow++ ;
00416       }
00417     }
00418   
00419   dEmcCalibTower.SetRowCount(outrow);
00420   
00421 }
00422 
00423 //_____________________________________________________________________________
00424 //
00425 // If the particle of momentum p and vertex v heads into EMCal
00426 // return the sector number (iS = 0-7). Otherwise return -1.
00427 // Original function: CKB April '02
00428 int
00429 mEmcToolsModule::HitInEMCalAcceptance(const float *v, const float *p)
00430 {
00431   cout << "<E> mEmcToolsModule::HitInEMCalAcceptance(..) not supported anymore." << endl
00432        << "    use mEmcGeometryModule::HitInEMCalAcceptance(..) instead ! " << endl
00433        << "    EVENT NOT ACCEPTED " << endl;
00434   return -1;
00435 
00436   static mEmcGeometryModule EmcGeometry;
00437  
00438   // Separate the "Directions" of the track
00439   // p[0] < 0 is East, p[0] > 0 is West  
00440   // This is important because a line has no starting point
00441   // like a track
00442 
00443   // this is a real Point
00444   PHPoint vtx(v[0],v[1],v[2]);
00445 
00446   // take care that p gives only the direction of the momentum vector
00447   PHVector hit(p[0],p[1],p[2]);
00448   PHLine line(vtx,hit);
00449 
00450   int is;
00451 
00452   // isIntersection routine tells you wether a given PHLine
00453   // intersects with sector is (in emc convention)
00454   //        / 3   \  4
00455   // West  |  2    | 5 East
00456   //       |  1    | 6 
00457   //        \ 0   /  7
00458 
00459   if(p[0]>0){
00460     for( is = 0; is<4; is++ ){ // loop over the west arm
00461       if(EmcGeometry.isIntersection(line,is)) return is;
00462     }
00463   }
00464   else if(p[0]<0){
00465     for( is = 4 ; is<8 ; is++ ){ // loop over the east arm
00466       if(EmcGeometry.isIntersection(line,is)) return is;
00467     }
00468   }
00469   
00470   return -1;
00471  
00472 }
00473 
00474 //_____________________________________________________________________________
00475 //
00476 // The same as the former method, but now we pass the geometry as argument 
00477 //
00478 int 
00479 mEmcToolsModule::HitInEMCalAcceptance(const float *v, 
00480                                       const float *p, 
00481                                       mEmcGeometryModule* EmcGeometry )
00482 {
00483 
00484   cout << "<E> mEmcToolsModule::HitInEMCalAcceptance(..) not supported anymore." << endl
00485        << "    use mEmcGeometryModule::HitInEMCalAcceptance(..) instead ! " << endl
00486        << "    EVENT NOT ACCEPTED " << endl;
00487   return -1;
00488 
00489   if (!EmcGeometry) 
00490     {
00491       HitInEMCalAcceptance(v, p);
00492     }
00493 
00494   // Separate the "Directions" of the track
00495   // p[0] < 0 is East, p[0] > 0 is West  
00496   // This is important because a line has no starting point
00497   // like a track
00498 
00499   // this is a real Point
00500   PHPoint vtx(v[0],v[1],v[2]);
00501 
00502   // take care that p gives only the direction of the momentum vector
00503   PHVector hit(p[0],p[1],p[2]);
00504   PHLine line(vtx,hit);
00505 
00506   int is;
00507 
00508   // isIntersection routine tells you wether a given PHLine
00509   // intersects with sector is (in emc convention)
00510   //        / 3   \  4
00511   // West  |  2    | 5 East
00512   //       |  1    | 6 
00513   //        \ 0   /  7
00514 
00515   if(p[0]>0){
00516     for( is = 0; is<4; is++ ){ // loop over the west arm
00517       if(EmcGeometry->isIntersection(line,is)) return is;
00518     }
00519   }
00520   else if(p[0]<0){
00521     for( is = 4 ; is<8 ; is++ ){ // loop over the east arm
00522       if(EmcGeometry->isIntersection(line,is)) return is;
00523     }
00524   }
00525   
00526   return -1;
00527  
00528 }
00529 
00530 //_____________________________________________________________________________
00531 //
00532 // If the single direct gamma or the 2 decay-gammas from a pi0/eta decay
00533 // head into EMCal return 1. Otherwise, return 0.
00534 // Original function: CKB, April '02
00535 int 
00536 mEmcToolsModule::EventInEMCalAcceptance(const PISAEvent *pisaEvent, 
00537                                         const int kevent, TTree *T, 
00538                                         mEmcGeometryModule* geom)
00539 {
00540  
00541   cout << "<E> mEmcToolsModule::EventInEMCalAcceptance(..) not supported anymore." << endl
00542        << "    use mEmcGeometryModule::EventInEMCalAcceptance(..) instead ! " << endl
00543        << "    EVENT NOT ACCEPTED " << endl;
00544   return 0;
00545 
00546   T->GetEvent(kevent);
00547   int kpart = pisaEvent->GetKinNhit();
00548   if ( !kpart ) { return 0; } // no particle information: skip event
00549  
00550   float ptot;
00551   float pthet;
00552   float pphi;
00553 
00554   float p[3];
00555   float v[3];
00556 
00557   // loop on pisaEvent
00558   for( int ipart = 0; ipart<kpart; ipart++)
00559     {
00560       TClonesArray *fpisaKinHits = pisaEvent->GetKinHits();
00561       KinPISAHit *KinHit = (KinPISAHit*)fpisaKinHits->UncheckedAt(ipart);
00562       
00563       int idpart  = KinHit->GetIdpart();
00564       int idparent = KinHit->GetIdparent();
00565       int itparent = KinHit->GetItparent();
00566       
00567       int nGamma = 0;
00568       int nGamAcc = 0;
00569 
00570       // Found a primary photon
00571       if( idparent==0 && idpart==1 && itparent < 0 )
00572         {
00573           v[0] = 0; // Pi0 decays instantly
00574           v[1] = 0;
00575           v[2] = KinHit->GetZvertex();
00576           
00577           ptot = KinHit->GetPtot() ;
00578           pphi = KinHit->GetPhi() *M_PI/180.;
00579           pthet = KinHit->GetPthet() *M_PI/180.;
00580           
00581           p[0] = ptot * sin (pthet) * cos (pphi);
00582           p[1] = ptot * sin (pthet) * sin (pphi);
00583           p[2] = ptot * cos (pthet);
00584       
00585           if (HitInEMCalAcceptance(v,p,geom)>=0) nGamAcc++; // 0 is a valid sector: W0 !
00586           if ( nGamAcc!=1 ) return 0; // gamma not on detector
00587 
00588           return 1;
00589 
00590         } // photon
00591       
00592       // Found a primary pion
00593       // We accept only Two-Photon Decays where
00594       // both can hit the detector
00595       if( idparent==0 && idpart==7 && itparent < 0 )
00596         {
00597           if(kpart<3) // at least one decay photon not even stored 
00598             { 
00599               return 0;  // ==> no hit on active surface so skip it
00600             }
00601  
00602           for(int i = 0;i < kpart;i++)
00603             {
00604               // Search for Decay gammas
00605               KinPISAHit *Hit = (KinPISAHit*)fpisaKinHits->UncheckedAt(i);
00606               if( Hit->GetIdparent () == 7  && Hit->GetIdpart () == 1 )
00607                 {
00608                   if(nGamma<2)
00609                     {
00610                       // cout << "Photon Nr " << nGamma << endl;
00611                       v[0] = 0; // Pi0 decays instantly
00612                       v[1] = 0;
00613                       v[2] = Hit->GetZvertex();
00614              
00615                       ptot = Hit->GetPtot() ;
00616                       pphi = Hit->GetPhi() *M_PI/180.;
00617                       pthet = Hit->GetPthet() *M_PI/180.;
00618                       
00619                       p[0] = ptot * sin (pthet) * cos (pphi);
00620                       p[1] = ptot * sin (pthet) * sin (pphi);
00621                       p[2] = ptot * cos (pthet);
00622                       
00623                       if (HitInEMCalAcceptance(v,p,geom)>=0) nGamAcc++; // 0 is a valid sector: W0 !
00624                     }
00625                   nGamma++;         
00626                 }
00627             }
00628      
00629           if( nGamma!=2 ) { return 0; } // Not a 2-gamma Decay !
00630           if( nGamAcc!=2 ){ return 0; } // Not both gammas on Detector 
00631 
00632           return 1;
00633           
00634         } // pi0
00635   
00636       // Found a primary eta
00637       // We accept only Two-Photon Decays where
00638       // both head to the detector
00639       if( idparent==0 && idpart==17 && itparent < 0)
00640         {
00641           if(kpart<3) // at  least one decay photon not even stored 
00642             {
00643               return 0;  // ==> no hit on active surface so skip it
00644             }
00645       
00646           int nGamma = 0;
00647           int nGamAcc = 0;
00648           
00649           for(int i = 0;i < kpart;i++)
00650             {
00651               // Search for Decay gammas
00652               KinPISAHit *Hit = (KinPISAHit*)fpisaKinHits->UncheckedAt(i);
00653               if(Hit->GetIdparent () == 17 && Hit->GetIdpart () == 1)
00654                 {
00655                   if(nGamma<2)
00656                     {
00657                       //cout << "Photon Nr " << nGamma << endl;
00658                       v[0] = 0; // eta decays instantly
00659                       v[1] = 0;
00660                       v[2] = Hit->GetZvertex();
00661                       
00662                       ptot = Hit->GetPtot() ;
00663                       pphi = Hit->GetPhi() *M_PI/180.;
00664                       pthet = Hit->GetPthet() *M_PI/180.;
00665                       
00666                       p[0] = ptot * sin (pthet) * cos (pphi);
00667                       p[1] = ptot * sin (pthet) * sin (pphi);
00668                       p[2] = ptot * cos (pthet);
00669                       
00670                       if (HitInEMCalAcceptance(v,p,geom)>=0) nGamAcc++; // 0 is a valid sector: W0 !
00671                     }
00672                   nGamma++;                 
00673                 } 
00674             }
00675 
00676           if( nGamma!=2 )  { return 0; } // Not a 2-gamma Decay !
00677           if( nGamAcc!=2 ) { return 0; } // Not both gammas heading to the detector
00678           
00679           return 1;
00680 
00681         } // eta
00682 
00683     } // end loop on pisaEvent
00684 
00685   cout << "<W> EventInEMCalAcceptance: " 
00686        << "No primary pi0, eta or gamma found ... NO acceptance cut applied !" << endl;
00687 
00688   return 1;
00689 }
00690 
00691 
00692 //_____________________________________________________________________________
00693 //
00694 // If the particle of momentum p and vertex v heads into PbSc
00695 // return true. Otherwise return false.
00696 bool
00697 mEmcToolsModule::HitInPbSc(const float *v, const float *p, int& sector, 
00698                            mEmcGeometryModule* EmcGeometry)
00699 {
00700 
00701   cout << "<E> mEmcToolsModule::HitInPbSc() not supported anymore." << endl
00702        << "    use mEmcGeometryModule::HitInPbSc() instead ! " << endl
00703        << "    EVENT NOT ACCEPTED " << endl;
00704   return false;
00705 
00706   sector = HitInEMCalAcceptance(v,p,EmcGeometry);
00707 
00708   // PbSc sectors (in EMC convention)
00709   if ( sector == 0 || sector == 1 || sector == 2 || sector == 3 || sector == 4 || sector == 5 ) return true;
00710 
00711   return false; // case: -1 (outside EMCal) or 6,7 (PbGl)
00712 
00713 }
00714 
00715 //_____________________________________________________________________________
00716 //
00717 // If the particle of momentum p and vertex v heads into PbGl
00718 // return true. Otherwise return false.
00719 bool
00720 mEmcToolsModule::HitInPbGl(const float *v, const float *p, int& sector, 
00721                            mEmcGeometryModule* EmcGeometry)
00722 {
00723   cout << "<E> mEmcToolsModule::HitInPbGl() not supported anymore." << endl
00724        << "    use mEmcGeometryModule::HitInPbGl() instead ! " << endl
00725        << "    EVENT NOT ACCEPTED " << endl;
00726   return false;
00727 
00728   sector = HitInEMCalAcceptance(v,p,EmcGeometry);
00729   if ( sector == 7 || sector == 6 ) return true; // PbGl sectors (in EMC convention)
00730 
00731   return false; // case: -1 (outside EMCal) or 0-5 (PbSc)
00732 
00733 }