EmcIndexer.C

Go to the documentation of this file.
00001 #include <iostream> 
00002 #include <cstdio>
00003 #include <utility>
00004 #include <vector>
00005 #include <map>
00006 #include "EmcIndexer.h"
00007 #include "PbScIndexer.h"
00008 #include "PbGlIndexer.h"
00009 // 
00011 // E.Kistenev         6/10/99 
00012 // send comments to kistenev@bnl.gov 
00013 //                    6/11/99  conversion from PHNX SM number to Sector Number
00014 //                             and SM144 Number within the sector is included 
00016 
00017 using namespace std;
00018 
00019 // **********************************************************************
00020 
00022 struct emcTowerLocation {
00023   int arm,sector,yrow,zrow; 
00024 };
00025 
00026 vector<string> EmcIndexer::fEmcSectorIdent ;
00027 
00028 //_____________________________________________________________________________
00029 int 
00030 EmcIndexer::EmcSectorNumber(const char * SectorId)
00031 { 
00032   if (fEmcSectorIdent.empty()) {
00033     fEmcSectorIdent.push_back("W0") ;
00034     fEmcSectorIdent.push_back("W1") ;
00035     fEmcSectorIdent.push_back("W2") ;
00036     fEmcSectorIdent.push_back("W3") ;
00037     fEmcSectorIdent.push_back("E2") ;
00038     fEmcSectorIdent.push_back("E3") ;
00039     fEmcSectorIdent.push_back("E0") ;
00040     fEmcSectorIdent.push_back("E1") ;
00041     fEmcSectorIdent.push_back("NONE") ;
00042   }
00043 
00044   int SectorNumber=0;
00045 
00046   while (SectorNumber<8 && fEmcSectorIdent[SectorNumber]!=SectorId) {
00047     SectorNumber++ ;
00048   }
00049 
00050   if(SectorNumber>7) { 
00051     return -1;
00052   } 
00053   else { 
00054     return SectorNumber; 
00055   }
00056 }
00057 
00058 //_____________________________________________________________________________
00059 const char* 
00060 EmcIndexer::EmcSectorId(int SectorNumber)
00061 { 
00062   if (fEmcSectorIdent.empty()) {
00063     EmcIndexer::EmcSectorNumber("W0") ;
00064   }
00065 
00066   return fEmcSectorIdent[SectorNumber].c_str() ;
00067 }
00068 
00069 //_____________________________________________________________________________
00070 int EmcIndexer::SoftwareKey(int TowerId)
00071 {
00072   static vector<int> softkeys ;
00073   static const int PXMAX = 24768 ;
00074 
00075   if (softkeys.size()==0) {
00076 
00077     softkeys.resize(PXMAX) ;
00078 
00079     int ItemId ;
00080     
00081     int iS ;   // sector number (0-7)
00082     int iSMT ; // tower_index number within Sector
00083     int iarm ; // arm:0=West, 1=East;
00084     int iy ;   // row number of the tower_index within a sector (bottom=>row=0)
00085     int iz ;   /* column number of the tower_index within a sector. 
00086                   column=0 for
00087                   lower bottom left tower_index, 
00088                   when sector is viewed from back 
00089                   (i.e. you are looking at the electronics).
00090                */
00091     int swkey ; /* software key = 
00092                     100000 * iarm +
00093                     10000 * iS +
00094                     100 * iy +
00095                     iz
00096                  */
00097 
00098     for ( ItemId = 0 ; ItemId < PXMAX ; ItemId++ ) {
00099 
00100       EmcIndexer::iPXiSiST(ItemId,iS,iSMT) ; 
00101 
00102       iarm = ((iS<4)?0:1) ;
00103       if (iS<6) {
00104         iy = iSMT/72 ;
00105         iz = iSMT%72 ;
00106       }
00107       else {
00108         iy = iSMT/96 ;
00109         iz = iSMT%96 ; 
00110       }
00111       
00112       if(iS>=4){
00113         // change sector numbers to comply with PHENIX geography
00114         iS = ((iS -=6)<0)? iS+4 : iS;
00115       }
00116       swkey = SoftwareKey(iarm,iS,iy,iz) ;
00117       softkeys[ItemId] = swkey ;
00118     }
00119   }
00120 
00121   int rv ;
00122   
00123   if (TowerId<0 || static_cast<unsigned int>(TowerId) >= softkeys.size()) 
00124     {
00125       rv = 0 ;
00126     }
00127   else 
00128     {
00129       rv = softkeys[TowerId] ;
00130     }
00131   return rv ;
00132 }
00133 
00134 //_____________________________________________________________________________
00135 int
00136 EmcIndexer::SoftwareKey(int arm, int sector_in_arm, int yrow, int zrow)
00137 {
00138   return 100000*arm + 10000*sector_in_arm + 100*yrow + zrow ;
00139 }
00140 
00141 //_____________________________________________________________________________
00142 void 
00143 EmcIndexer::PXSM144_iSiSM144(int PXSM144, int &iS, int &iSM144)
00144 {
00145   //  PHENIX SM144 (1-172) -> Sector, SM NUmber(Sector SM)      
00146   if(PXSM144<108){
00147     iS    = PXSM144/18;
00148     iSM144= PXSM144%18;
00149   } else {
00150     iS    = 6 + (PXSM144-108)/32;
00151     iSM144= (PXSM144-108)%32;
00152   }
00153 }
00154 
00155 
00156 //_____________________________________________________________________________
00157 int  
00158 EmcIndexer::iSiSM144_PXSM144(int iS, int iSM144)
00159 {
00160   //  Sector, SM NUmber(Sector SM) -> PHENIX SM144 (1-172) 
00161   if(iS<6){
00162     return iS*18+iSM144;
00163   } else {
00164     return 108 + (iS-6)*32+iSM144;
00165   }
00166 }
00167 
00168 
00169 //_____________________________________________________________________________
00170 int 
00171 EmcIndexer::iSiSMiSMTiST(int  SectorNumber, int  SMNumber, int  SMTower)
00172 {
00173   // SectorNumber,SMNumber,SMTower -> Sector Tower
00174   if(SMTower<0) return SMTower;
00175   if(SectorNumber<6){
00176     PbScIndexer * gPbSc = PbScIndexer::buildPbScIndexer();
00177     return gPbSc->SMiSMTiST(SMNumber ,SMTower);
00178   } else {
00179     PbGlIndexer * gPbGl = PbGlIndexer::buildPbGlIndexer();
00180     return gPbGl->SMiSMTiST(SMNumber ,SMTower);
00181   }
00182 }
00183 
00184 //_____________________________________________________________________________
00185 int 
00186 EmcIndexer::iSiSMiSMTiPX(int SectorNumber, int SMNumber, int SMTower)
00187 {
00188   // SectorNumber,SMNumber,SMTower -> PHENIX Tower
00189   if(SMTower<0) return SMTower;
00190   if(SectorNumber<6){
00191     PbScIndexer * gPbSc = PbScIndexer::buildPbScIndexer();
00192     return 2592*SectorNumber + gPbSc->SMiSMTiST(SMNumber ,SMTower);
00193   } else {
00194     PbGlIndexer * gPbGl = PbGlIndexer::buildPbGlIndexer();
00195     return 15552 + 4608*(SectorNumber-6) + gPbGl->SMiSMTiST(SMNumber ,SMTower);
00196   }
00197 }
00198 
00199 //_____________________________________________________________________________
00200 void 
00201 EmcIndexer::iSiSTiSMiSMT(const int iS, const int iST, int & iSM, int & iSMT)
00202 {
00203   // SectorNumber, SectorTower -> SM NUmber, SM Tower
00204   int x, y; 
00205   if(iS<6){
00206     PbScIndexer * gPbSc = PbScIndexer::buildPbScIndexer();
00207     gPbSc->iST_SMInd(iST, iSM, iSMT, x, y);
00208   } else {
00209     PbGlIndexer * gPbGl = PbGlIndexer::buildPbGlIndexer();
00210     gPbGl->iST_SMInd(iST, iSM, iSMT, x, y);
00211   }
00212 }
00213 
00214 //_____________________________________________________________________________
00215 int 
00216 EmcIndexer::PXSM144iCH_iPX(const int PXSM144, const int iCH)
00217 {
00219   static vector<vector<int> > ifem_vs_ichannel_to_towerID ;
00220 
00221   static int nfem = MaxNumberOfFEMs() ;
00222   static int nchannels = 144 ;
00223 
00224   // assertion is probably not user friendly, but this
00225   // method is meant to be fast, so we'd like to have
00226   // as few if as possible.
00227   // SO : CHECK THAT YOUR INPUT ARGUMENTS ARE CORRECT !
00228   assert(PXSM144>=0 && PXSM144<nfem) ;
00229   assert(iCH>=0 && iCH<nchannels) ;
00230 
00231   if (ifem_vs_ichannel_to_towerID.empty()) {
00232     
00233     ifem_vs_ichannel_to_towerID.resize(nfem) ;
00234 
00235     int ifem, ichannel ;    
00236     int iS, iSM144, iSMT ;
00237 
00238     for (ifem=0;ifem<nfem;ifem++) {
00239 
00240       ifem_vs_ichannel_to_towerID[ifem].resize(nchannels) ;
00241 
00242       for (ichannel=0;ichannel<nchannels;ichannel++) {
00243         
00244         PXSM144_iSiSM144(ifem, iS, iSM144);
00245         iSMT = iCHiSMT(ichannel);
00246         ifem_vs_ichannel_to_towerID[ifem][ichannel] = 
00247           iSiSMiSMTiPX(iS, iSM144, iSMT);
00248       }
00249     }
00250   }
00251 
00252   return ifem_vs_ichannel_to_towerID[PXSM144][iCH] ;
00253 }
00254 
00255 //_____________________________________________________________________________
00256 int 
00257 EmcIndexer::iCHiSMT(int  iCH) 
00258 { 
00259   //  This is a very preliminary version which may well change at 
00260   //  a later time. It looks a bit complicated but it will be used
00261   //  only to establish look-up-tables for individual EmcFeeCrates
00262   int ASIC  = iCH/24;          //  2 tower wide columns
00263   int preamp = (iCH%24)/4;      //  2 tower wide rows counted 
00264                                     //  from above (0 at the top)
00265   int input  = iCH%4;
00266   //  convert input into x/y for cells within 'module' scope
00267   int xc, yc;
00268   yc = input/2;
00269   xc = 1-input%2;
00270   return 12*((5-preamp)*2+yc)+ASIC*2+xc;
00271 }
00272        
00273 //_____________________________________________________________________________
00274 int 
00275 EmcIndexer::iCHiSMT(const int Channel, const bool ASIC24)
00276 {
00277 
00278   //   FEE Channel , ASIC Readout Flag -> i(SM Tower) 
00279   //   FIX for 144/192 channels switching
00280 
00281   int chPerBoard = (ASIC24)? 24 : 32;
00282   int ASIC   = Channel/chPerBoard;          //  2 tower wide columns
00283   int ASICCh = Channel%chPerBoard;
00284   if(!ASIC24) {
00285     if((ASICCh>11&&ASICCh<16)||ASICCh>27) return -1;
00286     if(ASICCh>=16) ASICCh -=4;
00287   }
00288   int preamp = ASICCh/4;            //  2 tower wide rows counted 
00289   //  from above (0 at the top)
00290   int input  = Channel%4;
00291   //  convert input into x/y for cells within 'module' scope
00292   int xc, yc;
00293   yc = input/2;
00294   xc = 1-input%2;
00295   return 12*((5-preamp)*2+yc)+ASIC*2+xc;
00296 } 
00297 
00298 //_____________________________________________________________________________
00299 int   
00300 EmcIndexer::iSMTiCH(const int iSMT, bool ASIC24)
00301 {
00302   //   i(SM Tower), ASIC Readout Flag ->  FEE Channel 
00303   //   FIX for 144/192 channels switching
00304   int x, y;
00305   iSM144TxySM144T(iSMT, x, y);
00306   int ASIC = x/2;
00307   int ym = y/2;
00308   int preamp = 5-ym;
00309   int xc = x%2;
00310   int yc = y%2;
00311   int cell = 2*yc+(1-xc);
00312   if(ASIC24) {return ASIC*24+preamp*4+cell;
00313   } else {
00314     if(preamp<3) {return ASIC*32+preamp*4+cell;
00315     } else { return ASIC*32+4+preamp*4+cell;}
00316   }
00317 }
00318 
00319 //_____________________________________________________________________________
00320 int 
00321 EmcIndexer::absFEMCHiPX(const int absFEMCH)
00322 {
00323   int FEM, iS, iCH, iSM, iSMT;
00324   FEM      = absFEMCH/192;
00325   iCH      = absFEMCH%192;
00326   iSMT     = iCHiSMT(iCH, false); 
00327   if(iSMT<0) return iSMT;
00328   if(FEM<108){
00329     iS     = FEM/18;
00330     iSM    = FEM%18;
00331   } else {
00332     iS     = 6+(FEM-108)/32;
00333     iSM    = (FEM-108)%32;
00334   }
00335   return iSiSMiSMTiPX(iS, iSM, iSMT);
00336 }
00337 
00338 //_____________________________________________________________________________
00339 int 
00340 EmcIndexer::iPXabsFEMCH(const int iPX)
00341 {
00342   int iS,iST, iCH, iSM, iSMT;
00343   bool ASIC24 = false;
00344   EmcIndexer::iPXiSiST(iPX, iS, iST);
00345   iSiSTiSMiSMT(iS, iST, iSM, iSMT);
00346   iCH = iSMTiCH(iSMT, ASIC24);
00347   if(iS<6){
00348     return 192*(iS*18+iSM)+iCH;
00349   } else {
00350     return 192*(108+32*(iS-6)+iSM)+iCH;
00351   }
00352 }
00353 
00354 //_____________________________________________________________________________
00355 void 
00356 EmcIndexer::iCH192ASICi32(const int iCH192, int & ASIC, int & iCH32)
00357 {
00358   ASIC = iCH192/32;
00359   iCH32 = iCH192%32;
00360 }
00361 
00362 //_____________________________________________________________________________
00363 void 
00364 EmcIndexer::iSM144TxySM144T(const int iSMT, int & xsmt, int & ysmt)   
00365 { 
00366   ysmt = iSMT/12; 
00367   xsmt = iSMT - ysmt*12; 
00368 }
00369 
00370 //_____________________________________________________________________________
00371 void       
00372 EmcIndexer::iSM144TtoHWIndexes(int iSMT, bool ASIC24, int & QB, int &Cell, 
00373                                int &ASIC, int &Preamp, int &Input, 
00374                                int &FEMChannel)
00375 {
00376   int x, y;
00377   iSM144TxySM144T(iSMT, x, y);
00378   ASIC   = x/2;
00379   int ym = y/2;
00380   Preamp = 5-ym;
00381   QB     = ym*6 + ASIC;
00382   int xc = x%2;
00383   int yc = y%2;
00384   Cell   = 2*yc+(1-xc);
00385   Input  = Preamp*4 + Cell;
00386   if(ASIC24) {
00387     FEMChannel = ASIC*24+Preamp*4+Cell;
00388   } else {
00389     if(Preamp<3) {
00390       FEMChannel = ASIC*32+Preamp*4+Cell;
00391     } else { 
00392       FEMChannel = ASIC*32+4+Preamp*4+Cell;
00393     }
00394   }
00395 }
00396 
00397 //_____________________________________________________________________________
00398 void 
00399 EmcIndexer::findItemIdentity(const int ItemId, const bool ASIC24, 
00400                              const bool EMCalMapStyle, int & iS, int & iSM, 
00401                              int & iSMT, int &iFEM, int &iCH192, int &ASIC, 
00402                              int &ASICCh)
00403 {       
00404   // convert channel number from DataMap into Crate/ASIC/Channel 
00405   if(EMCalMapStyle) {
00406     // numbering in the space of PHENIX Towers 
00407     int  iST;
00408     EmcIndexer::iPXiSiST(ItemId, iS, iST);
00409     EmcIndexer::iSiSTiSMiSMT(iS , iST , iSM , iSMT);
00410     iCH192 = iSMTiCH(iSMT, 0);
00411     iFEM = (iS>5)? 108+(iS-6)*32 : iS*18;
00412     iFEM += iSM;
00413   } else {
00414     // numbering in the space of PHENIX FEM Channels (absFEM) 
00415     iFEM   = ItemId/192;
00416     iCH192 = ItemId%192;
00417     PXSM144_iSiSM144(iFEM, iS, iSM);
00418     iSMT   = iCHiSMT(iCH192,ASIC24);
00419   }
00420   iCH192ASICi32(iCH192 , ASIC, ASICCh);
00421 }
00422 
00423 //_____________________________________________________________________________
00424 bool 
00425 EmcIndexer::IsValid(int iS, int x, int y){
00426   if(x<0||y<0) return false;
00427   if(iS<6){
00428     if(x>=72||y>=36) return false;
00429   } else {
00430     if(x>=96||y>=48) return false;
00431   }
00432   return true;
00433 }
00434 
00435 //***************************************************************************
00436 
00437 int  EmcIndexer::iSiSTiPX(int iS, int iST){
00438   return ((iS<6)? 2592*iS+iST : 15552+4608*(iS-6)+iST);
00439 } 
00440 
00441 // **************************************************************************
00442 void EmcIndexer::iPXiSiST(const int iPX, int & iS, int & iST)
00443 {
00444   if(iPX<15552){
00445 // PbSc Calorimeter
00446     iS  = iPX/2592;
00447     iST = iPX%2592;
00448   } else {
00449 // PbGl Calorimeter
00450     iS  = 6+(iPX-15552)/4608;
00451     iST = (iPX-15552)%4608;
00452   }
00453 }
00454 
00455 // **************************************************************************
00456 void EmcIndexer::iPXiSiSMiSMT(int iPX, int &iS, int &iSM, int &iSMT){
00457   int iST, ix, iy;
00458   if(iPX<15552){
00459 // PbSc Calorimeter
00460     iS  = iPX/2592;
00461     iST = iPX%2592;
00462     ix  = iST%72;
00463     iy  = iST/72;
00464     iSM = iS*18 + (iy/12)*6+(ix/12);
00465   } else {
00466 // PbGl Calorimeter
00467     iS  = 6+(iPX-15552)/4608;
00468     iST = (iPX-15552)%4608;
00469     ix  = iST%96;
00470     iy  = iST/96;
00471     iSM = 108+(iS-6)*32 + (iy/12)*8+(ix/12);
00472   }
00473   iSMT = (iy%12)*12+ix%12;
00474 }
00475 //***************************************************************************
00476 
00477 void  EmcIndexer::iSTxyST(int iS, int iST, int & x, int & y){
00478   y = iST/((iS<6)? 72 : 96);
00479   x = iST%((iS<6)? 72 : 96);
00480 } 
00481 
00482 //***************************************************************************
00483 
00484 int  EmcIndexer::xySTiST(int iS, int x,int y){
00485   return ((iS<6)? 72*y+x : 96*y+x);
00486 }
00487 
00488 //***************************************************************************
00489 
00490 int  EmcIndexer::getTowerId(int iS, int x,int y){
00491   return ((iS<6)? 2592*iS+72*y+x : 15552+4608*(iS-6)+96*y+x);
00492 }
00493 
00494 //***************************************************************************
00495 
00496 void EmcIndexer::decodeTowerId(int TowerId, int & iS, int & x,int & y){
00497   int iST;
00498   iPXiSiST(TowerId, iS, iST);
00499   iSTxyST(iS, iST, x, y);
00500 }
00501 
00502 //_____________________________________________________________________________
00503 void 
00504 EmcIndexer::TowerLocation(int towerID, int& arm, int& sector_in_arm,
00505                           int& yrow, int& zrow)
00506 {
00507   static map<int,emcTowerLocation> towerLocationMap ;
00508 
00509   if (towerLocationMap.empty()) {
00510 
00511     size_t i ;
00512     int iS, iST, x, y ;
00513 
00514     for ( i = 0 ; i < 24768 ; i++ ) {
00515       iPXiSiST(i, iS, iST) ;
00516       iSTxyST(iS, iST, x, y) ;
00517       emcTowerLocation& tl = towerLocationMap[i] ;
00518       tl.arm = (iS<4) ? 0 : 1 ;
00519       if (tl.arm==1) {
00520         iS -= 6 ;
00521         if (iS<0) iS+=4 ; 
00522       }
00523       tl.sector = iS ;
00524       tl.yrow = y ;
00525       tl.zrow = x ;
00526     }
00527   }
00528 
00529   emcTowerLocation& tl = towerLocationMap[towerID] ;
00530 
00531   arm = tl.arm ;
00532   sector_in_arm = tl.sector ;
00533   yrow = tl.yrow ;
00534   zrow = tl.zrow ;
00535 }
00536 
00537 //_____________________________________________________________________________
00538 //int 
00539 //EmcIndexer::TowerID(int arm, int sector_in_arm, int yrow, int zrow)
00540 //{
00541 //}
00542 
00543 //_____________________________________________________________________________
00544 void EmcIndexer::PXPXSM144CH(int PX, int& PXSM144, int& CH) 
00545 {
00546   static vector<pair<int,int> > fPXPXSM144CH ; 
00547   static const int PXMAX = 24768 ;
00548 
00549   if (PX<0 || PX>=PXMAX) {
00550     PXSM144 = -1 ;
00551     CH = -1 ;
00552   }
00553 
00554   else {
00555 
00556     if (fPXPXSM144CH.empty()) {
00557 
00558       // Allocate on first call.
00559 
00560       fPXPXSM144CH.resize(PXMAX) ;
00561       int i ;
00562       int iS, iST, iSM, iSMT ;
00563       for (i=0;i<PXMAX;i++) {
00564         iPXiSiST(i,iS,iST) ;
00565         iSiSTiSMiSMT(iS,iST,iSM,iSMT);
00566         fPXPXSM144CH[i].first = iSiSM144_PXSM144(iS,iSM) ;
00567         fPXPXSM144CH[i].second = iSMTiCH(iSMT) ;
00568       }
00569     }
00570 
00571     pair<int,int>& thepair = fPXPXSM144CH[PX] ;
00572 
00573     PXSM144 = thepair.first ;
00574     CH = thepair.second ;
00575   }
00576 }
00577 
00578 
00579 //_____________________________________________________________________________
00580 int 
00581 EmcIndexer::sectorOfflineToOnline(int arm, int offline_sector)
00582 {
00583   //   ONLINE #  OFFLINE ARM #  OFFLINE SECTOR #
00584   //W0    0          0             0       PbSc
00585   //W1    1          0             1       PbSc 
00586   //W2    2          0             2       PbSc
00587   //W3    3          0             3       PbSc 
00588   //E2    4          1             2       PbSc
00589   //E3    5          1             3       PbSc 
00590   //E0    6          1             0       PbGl
00591   //E1    7          1             1       PbGl 
00592 
00593 // ///////////////////////////////////////////////////////////////////////////
00594 
00595   int online_sector = -1 ;
00596 
00597 
00598   if ( arm==0 ) {
00599     online_sector = offline_sector ;
00600   }
00601   else {
00602     online_sector = ( offline_sector >= 2 ) ? offline_sector+2 
00603       : offline_sector+6 ;  
00604   }
00605   return online_sector ;
00606 }
00607 
00608 // ///////////////////////////////////////////////////////////////////////////
00609 
00611 bool EmcIndexer::isPbScReference(int TowerId)
00612 {
00613         
00614         if(TowerId<24768) return false;
00615 
00616         int absFEM=((TowerId-24768)%96)/12+172;
00617         return ( absFEM>=172 && absFEM<=175 );
00618         
00619 }
00620 
00622 bool EmcIndexer::isPbGlReference(int TowerId)
00623 {
00624         
00625         if(TowerId<24768) return false;
00626         
00627         int absFEM=((TowerId-24768)%96)/12+172;
00628         return (absFEM>=176 && absFEM<=179 );
00629 }
00630 
00631 //_____________________________________________________________________________
00632 void 
00633 EmcIndexer::sectorOnlineToOffline(int sectorOnline, int& arm,
00634                                   int& offline_sector)
00635 {
00636   if ( sectorOnline < 0 || sectorOnline > 8 ) 
00637     {
00638       arm=-1;
00639       offline_sector=-1;
00640     }
00641 
00642   if ( sectorOnline < 4 ) 
00643     {
00644       arm = 0;
00645       offline_sector = sectorOnline;
00646     }
00647   else if ( sectorOnline < 6 )
00648     {
00649       arm = 1;
00650       offline_sector = sectorOnline-2;
00651     }
00652   else
00653     {
00654       arm = 1;
00655       offline_sector = sectorOnline-6;
00656     }
00657 }
00658 
00659 //_____________________________________________________________________________
00660 void 
00661 EmcIndexer::decodeSoftwareKey(int key, int& arm, int& sector, 
00662                               int& yrow, int& zrow)
00663 {
00664   arm    = key / 100000; 
00665   sector = ( key - arm * 100000 ) / 10000; 
00666   yrow   = ( key - arm * 100000 - sector * 10000 ) / 100; 
00667   zrow   = key - arm * 100000 - sector * 10000 - yrow * 100; 
00668 }
00669 
00670 //_____________________________________________________________________________
00671 int
00672 EmcIndexer::TowerID(int arm, int sector_in_arm, int yrow, int zrow)
00673 {
00674   int iS = sectorOfflineToOnline(arm,sector_in_arm);
00675   int iST = xySTiST(iS,zrow,yrow);
00676   return iSiSTiPX(iS,iST);
00677 }
00678 
00679 //_____________________________________________________________________________
00680 int
00681 EmcIndexer::TowerID(int softwarekey)
00682 {
00683   int arm,sector,yrow,zrow;
00684   EmcIndexer::decodeSoftwareKey(softwarekey,arm,sector,yrow,zrow);
00685   return TowerID(arm,sector,yrow,zrow);
00686 }