CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/src/L1Trigger/RPCTrigger/src/RPCStripsRing.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     RPCConeBuilder
00004 // Class  :     RPCStripsRing
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Tomasz Fruboes
00010 //         Created:  Tue Feb 26 15:13:10 CET 2008
00011 // $Id: RPCStripsRing.cc,v 1.3 2011/02/25 16:56:18 fruboes Exp $
00012 //
00013 
00014 // system include files
00015 
00016 // user include files
00017 //#include "L1TriggerConfig/RPCConeBuilder/interface/RPCStripsRing.h"
00018 #include "L1Trigger/RPCTrigger/interface/RPCStripsRing.h"
00019 #include "Geometry/RPCGeometry/interface/RPCGeomServ.h"
00020 #include "DataFormats/MuonDetId/interface/RPCDetId.h"
00021 #include "Geometry/RPCGeometry/interface/RPCGeometry.h"
00022 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00023 
00024 RPCStripsRing::RPCStripsRing() :
00025     m_hwPlane(-1),
00026     m_etaPartition(99),
00027     m_region(-2),
00028     m_isReferenceRing(false),
00029     m_didVirtuals(false),
00030     m_didFiltering(false)
00031 {
00032 
00033 }
00034 
00035 RPCStripsRing::RPCStripsRing(const RPCRoll * roll,
00036                              boost::shared_ptr<L1RPCConeBuilder::TConMap > cmap) :
00037     m_didVirtuals(false),
00038     m_didFiltering(false),
00039     m_connectionsMap(cmap)
00040 {
00041   
00042   RPCDetId detId = roll->id();
00043   RPCGeomServ grs(detId);
00044   
00045   m_etaPartition = grs.eta_partition();
00046   m_hwPlane = calculateHwPlane(roll);
00047   
00048   m_isReferenceRing = false;
00049   
00050   m_region = detId.region();
00051   
00052   int ring = detId.ring();
00053   
00054   if (m_region == 0 && std::abs(ring)<2 && m_hwPlane == 2) // for barell wheel -1,0,1 refplane is hwPlane=2
00055       m_isReferenceRing = true;
00056   else if (m_region == 0 && std::abs(ring)==2 && m_hwPlane == 6) // for barell wheel -2,2 refplane is hwPlane=6
00057       m_isReferenceRing = true;
00058   else if (m_region != 0 && m_hwPlane == 2) // for endcaps
00059       m_isReferenceRing = true;
00060   
00061   
00062   if( getRingId() == 2008 || getRingId() == 2108) //exception: endcaps;hwplane 2;farest roll from beam
00063       m_isReferenceRing = false;
00064     
00065   addRoll(roll);
00066 }
00067 
00068 
00069 void RPCStripsRing::addRoll(const RPCRoll * roll){
00070 
00071 //  RPCDetId detId = roll->id();
00072   
00073   if (getRingId() !=  getRingId(roll) ){
00074      throw cms::Exception("RPCInternal") << "RPCStripsRing::addRoll ringsIds dont match \n";
00075   }
00076   
00077   //iterate over the strips of this roll
00078   for (int i=1; i<=roll->nstrips(); i++ ) { 
00079     
00080        LocalPoint lStripCentre = roll->centreOfStrip(i);
00081        GlobalPoint gStripCentre = roll->toGlobal(lStripCentre);
00082        float phiRaw = gStripCentre.phi();
00083        
00084        TStrip newStrip(roll->id().rawId(), i);
00085        (*this)[phiRaw] = newStrip;
00086        
00087   }
00088 
00089 }
00090 
00091 int RPCStripsRing::getRingId(int etaPart, int hwPlane){
00092 
00093   int sign = 1; // positive
00094   if (etaPart < 0){
00095     sign = 0;
00096   }
00097    
00098   return  1000*(hwPlane) +     //1...6
00099           100*( sign ) + //
00100           1*( std::abs(etaPart) );     //-17...17
00101   
00102 }
00103 
00104 int RPCStripsRing::getRingId(){
00105 
00106   return getRingId(m_etaPartition, m_hwPlane);
00107    
00108 }
00109 
00110 int RPCStripsRing::getRingId(const RPCRoll * roll) {
00111 
00112       
00113    RPCDetId detId = roll->id();
00114    RPCGeomServ grs(detId);
00115    int etaPartition = grs.eta_partition();
00116    int hwPlane = calculateHwPlane(roll);
00117    
00118    return getRingId(etaPartition, hwPlane);
00119       
00120 }
00121 
00122 
00123 //  hwPlane is  station number for endcaps
00124 //  for barrell numbering goes 1 5 2 6 3 4 (first number means plane closest to the beam)
00125 int RPCStripsRing::calculateHwPlane(const RPCRoll * roll){
00126 
00127   int hwPlane = -1;  
00128   RPCDetId detId = roll->id();
00129   int station = detId.station();
00130   int layer = detId.layer(); 
00131   int region = detId.region(); 
00132   
00133   if (region != 0){ // endcaps
00134     hwPlane = station;
00135   }
00136   // Now comes the barell
00137   else if ( station > 2 ){
00138     hwPlane = station;
00139   } 
00140   else if ( station == 1 && layer == 1) {
00141     hwPlane = 1;
00142   }
00143   else if ( station == 1 && layer == 2) {
00144     hwPlane = 5;
00145   }
00146   else if ( station == 2 && layer == 1) {
00147     hwPlane = 2;
00148   }
00149   else if ( station == 2 && layer == 2) {
00150     hwPlane = 6;
00151   } 
00152   
00153   /*if (hwPlane < 1)
00154     std::cout << "prb: " << hwPlane << " "
00155         << region << " "
00156         << station << " "
00157   << layer << std::endl;*/
00158   if (hwPlane < 0) {
00159       throw cms::Exception("RPCInternal") << "Calculated negative hwplane \n";
00160   }
00161   
00162   
00163   return hwPlane;
00164   
00165 }
00166 
00167 void RPCStripsRing::filterOverlapingChambers(){
00168     
00169   if(m_didFiltering) return;
00170   m_didFiltering = true;
00171   
00172   if (m_region != 0 || m_hwPlane != 4) 
00173      return;
00174   
00175   typedef std::map<uint32_t,int> TDetId2StripNo;
00176   TDetId2StripNo det2stripNo;
00177   
00178   // Note: we begin in middle of first chamber (ch1), we have to handle that
00179   int ch1BegStrips = 0; // no of strips on the begining of the map (first=last chamber of map)
00180   int ch1EndStrips = 0; // no of strips on the end of the map (first=last chamber of map)
00181   
00182   // How many strips has each chamber?
00183   RPCStripsRing::iterator it = this->begin();
00184   uint32_t ch1Det = it->second.m_detRawId;
00185   for (; it!=this->end(); ++it){
00186     
00187     if ( det2stripNo.find(it->second.m_detRawId) == det2stripNo.end()){
00188       det2stripNo[it->second.m_detRawId]=1;      // Add new chamber to a map, set strip cnt to 1
00189     } else {
00190       ++det2stripNo[it->second.m_detRawId];     // Increase strip count of a chamber
00191     }
00192     
00193     if (det2stripNo.size() == 1 && ch1Det == it->second.m_detRawId) {
00194       ++ch1BegStrips;
00195     } else if (ch1Det == it->second.m_detRawId){
00196       ++ch1EndStrips;
00197     }
00198     
00199   }
00200   
00201   det2stripNo[ch1Det]-=ch1EndStrips;
00202   
00203  // std::cout << ch1BegStrips << " " << ch1EndStrips << std::endl;
00204   
00205   //TDetId2StripNo::iterator itIds = det2stripNo.begin();
00206   //for(;itIds!=det2stripNo.end();++itIds){
00207 //    std::cout << itIds->first << " " << itIds->second << std::endl;
00208 //  }
00209   
00210   
00211   
00212   it = this->begin();
00213   uint32_t lastDet = it->second.m_detRawId;
00214   while ( it!=this->end() ){
00215     
00216     if (det2stripNo[it->second.m_detRawId] < 0) {
00217       throw cms::Exception("RPCInternal") << " RPCStripsRing::filterOverlapingChambers() - no strips left \n";
00218     }
00219     if ( it->second.m_detRawId == lastDet) {
00220       --det2stripNo[lastDet];
00221       ++it;
00222     } else if (det2stripNo[lastDet] == 0) { // no more strips left in lastDet, proceed to new det
00223       
00224       if (lastDet == ch1Det) {
00225         det2stripNo[ch1Det]+=ch1EndStrips;
00226       }
00227       
00228       lastDet = it->second.m_detRawId;
00229       --det2stripNo[lastDet];
00230       ++it;
00231     } else { // there are still strips in last det, delete current strip
00232       --det2stripNo[it->second.m_detRawId];
00233       RPCStripsRing::iterator itErase = it;
00234       ++it;
00235       //std::cout << "Removing strip " <<  it->second.m_detRawId << " " << (int)it->second.m_strip << std::endl;
00236       this->erase(itErase); 
00237     }
00238     
00239   }
00240   
00241   
00242 
00243 }
00244 
00245 void RPCStripsRing::fillWithVirtualStrips()
00246 {
00247   
00248 
00249   if(m_didVirtuals) return;
00250   m_didVirtuals = true;
00251 
00252   const float pi = 3.141592654;
00253   double dphi=2.0*pi/1152; // defines angular granulation of strips.
00254   
00255   RPCStripsRing stripsToInsert;
00256     
00257   
00258   float delta = 0;
00259   int stripsToAdd = 0;
00260   
00261   
00262   RPCStripsRing::iterator it = this->begin();
00263   RPCStripsRing::iterator itLast = this->begin();
00264   for (; it!=this->end(); ++it){
00265   
00266     /*std::cout << it->first << " "
00267         << it->second.m_detRawId << " "
00268         << (int)it->second.m_strip << std::endl;
00269     */
00270     
00271     delta = it->first - itLast->first;        
00272     if (it == itLast || // skip first loop iteration
00273         itLast->second.m_detRawId == it->second.m_detRawId || // insert strips between two chambers only
00274         delta < 0)
00275     {
00276       itLast = it;
00277       continue;
00278     }
00279     
00280     
00281     stripsToAdd = (int)std::floor(delta/dphi)-1;
00282     //std::cout << delta << " " << stripsToAdd << std::endl;
00283     
00284     if ( isReferenceRing() && m_hwPlane==6) ++stripsToAdd;
00285     
00286     for (int i = 0;i<stripsToAdd;++i){
00287       
00288       stripsToInsert[itLast->first+dphi*(i+1)]=TStrip();
00289     
00290     }
00291     
00292     itLast = it; 
00293   }
00294   // TODO: check delta between first and last strip in map
00295   
00296   this->insert(stripsToInsert.begin(),stripsToInsert.end());
00297 
00298   
00299   
00300 }
00301 void RPCStripsRing::createRefConnections(TOtherConnStructVec & otherRings, int logplane, int logplaneSize)
00302 {
00303   //*
00304    /*std::cout << "RefCon for " << getRingId() 
00305        << " (" << getEtaPartition()<<  ")"
00306        << " tower: " << getTowerForRefRing()
00307        << " ; connected: "
00308        << otherRings.size() 
00309        << std::endl
00310        << std::endl;    
00311   //*/
00312        
00313   // XXX - TODO: warning on wrong logplaneSize
00314   
00315    if(!this->isReferenceRing()){
00316       throw cms::Exception("RPCInternal") << " RPCStripsRing::createRefConnections "
00317          << " called for non-reference ring \n";
00318    }
00319    
00320    /*
00321    if (logplaneSize!=8) {
00322      throw cms::Exception("RPCInternal") << " RPCStripsRing::createRefConnections "
00323          << " called for lpSize " << logplaneSize << " \n";
00324      
00325    }*/
00326    const float pi = 3.141592654;
00327    const float offset = (5./360.)*2*pi; // XXX
00328    
00329    //find first reference strip of first PAC (the strip with phi ~= 5deg)
00330    RPCStripsRing::iterator starEndIt = this->begin();
00331    while ( (++starEndIt)->first < offset ); 
00332          
00333    RPCStripsRing::iterator it = starEndIt;
00334    //--starEndIt;
00335    
00336    float angle = 0;
00337    int curPACno = -1;
00338    int curStripNo = 0;
00339    int curBegStripNo=0;
00340    
00341   bool firstIter = true;
00342 
00343    while(it!=starEndIt || firstIter ) { // iterate over strips
00344  
00345 
00346      firstIter = false;
00347       // New PAC  
00348      if(curStripNo%logplaneSize==0){ 
00349          ++curPACno; 
00350          curBegStripNo=curStripNo;
00351          RPCStripsRing::iterator plus8 = it;
00352          bool skipOccured = false;
00353          for (int i=0;i<7;++i){  
00354             ++plus8;
00355             if (plus8==this->end()){
00356                plus8=this->begin();
00357                skipOccured = true;
00358             }
00359          }
00360          
00361          // calculate angle
00362          float phi= it->first;
00363          float phiP8= plus8->first;
00364          if (skipOccured){
00365             // phiP8 is negative
00366             // phi is positive
00367             // xcheck
00368            if (phi*phiP8 > 0){
00369              throw cms::Exception("RPCInternal") << " RPCStripsRing::createRefConnections phi/phi8 error \n";
00370            }
00371            angle = (2*pi+phiP8+phi)/2;
00372            if(angle > pi){ // should land on positive side
00373               angle -= 2*pi;
00374            } 
00375             
00376            if (std::abs(angle) > pi) {
00377                throw cms::Exception("RPCInternal") << " RPCStripsRing::createRefConnections "
00378                      << " problem with angle calc \n";
00379            }
00380          }
00381          else {
00382            angle = (phiP8+phi)/2;
00383          }
00384          //std::cout << curPACno << " " << phiP8 << " " << phi << " "  << angle << std::endl;
00385          
00386          
00387          TOtherConnStructVec::iterator itOt = otherRings.begin();
00388          for (;itOt!=otherRings.end();++itOt){
00389            itOt->m_it->second.createOtherConnections(getTowerForRefRing(),
00390                                                      curPACno, 
00391                                                      itOt->m_logplane,
00392                                                      itOt->m_logplaneSize,
00393                                                      angle);
00394          }
00395       }
00396       
00397       
00398       if ( !it->second.isVirtual() ){
00399         L1RPCConeBuilder::TStripCon newCon;
00400         newCon.m_tower = getTowerForRefRing();
00401         newCon.m_PAC = curPACno;
00402         newCon.m_logplane = logplane;
00403         newCon.m_logstrip=curStripNo-curBegStripNo;
00404         //std::cout << " Adding con for " << it->second.m_detRawId << std::endl;
00405         (*m_connectionsMap)[it->second.m_detRawId][it->second.m_strip].push_back(newCon);
00406         //std::cout << " Adding ref connection " << std::endl;
00407       }
00408       ++curStripNo;
00409       ++it;
00410       if (it==this->end()){
00411          it=this->begin();
00412       }
00413        
00414    } // iteration over strips ends
00415    
00416    //std::cout << " refcon: " << curPACno << " PACs" << std::endl;
00417    //std::cout << "After refCon: " << m_connectionsMap.size() << std::endl;
00418 
00419 }
00420 
00421 void RPCStripsRing::createOtherConnections(int tower, int PACno, int logplane, int logplaneSize, float angle) {
00422 
00423    //std::cout << "    OtherCon for " << getRingId() << std::endl;
00424 
00425    if(this->isReferenceRing()){
00426       throw cms::Exception("RPCInternal") << " RPCStripsRing::createOtherConnections "
00427             << " called for reference ring \n";
00428    }
00429 
00430 
00431    RPCStripsRing::const_iterator it = this->lower_bound(angle);
00432    
00433    
00434    if (it == this->end())
00435      it = this->begin();
00436    
00437    for (int i=0; i < logplaneSize/2; i++){ 
00438      
00439       if (it==this->begin())
00440         it=this->end();  // (m_stripPhiMap.end()--) is ok.
00441       
00442       --it;
00443    }
00444   
00445      
00446    for (int i=0; i < logplaneSize; i++){
00447     
00448      if (! it->second.isVirtual() ){
00449         L1RPCConeBuilder::TStripCon newCon;
00450         newCon.m_tower = tower;
00451         newCon.m_PAC = PACno;
00452         newCon.m_logplane = logplane;
00453         newCon.m_logstrip= i;
00454         (*m_connectionsMap)[it->second.m_detRawId][it->second.m_strip].push_back(newCon);
00455         //std::cout << " Adding other connection " << std::endl;
00456       }
00457   
00458       ++it;
00459       if (it==this->end())
00460         it=this->begin();
00461    }
00462      
00463 }
00464 
00465 // Defines to which tower this ring (only ref ring) belongs
00466 int RPCStripsRing::getTowerForRefRing(){
00467 
00468   int ret = 0;
00469   
00470   if(!this->isReferenceRing()){
00471     throw cms::Exception("RPCInternal") << " RPCStripsRing::getTowerForRefRing() "
00472         << " called for non reference ring \n";
00473   }
00474 
00475   int etaAbs = std::abs(getEtaPartition());
00476   if (etaAbs < 8) {
00477     ret = getEtaPartition();
00478   } else if (etaAbs > 8) {
00479     int sign = (getEtaPartition() > 0 ? 1 : -1);
00480     ret = getEtaPartition()-sign;
00481   } else {
00482     throw cms::Exception("RPCInternal") << " RPCStripsRing::getTowerForRefRing() "
00483         << " called for etaPartition 8 \n";
00484   }
00485 
00486 
00487 
00488   return ret;
00489 
00490 }
00491 /*
00492       struct TStripCon{
00493         signed char m_tower;
00494         unsigned char m_PAC;
00495         unsigned char m_logplane;
00496         unsigned char m_logstrip;
00497       };
00498       typedef std::vector<TStripCon> TStripConVec;
00499       typedef std::map<unsigned char, TStripConVec> TStrip2ConVec;
00500       typedef std::map<uint32_t, TStrip2ConVec> TConMap;
00501 
00502       // compressed connections
00503       struct TCompressedCon{
00504         signed char m_tower;
00505         unsigned char m_PAC;
00506         signed char m_offset;
00507         signed char m_mul;
00508       };
00509       typedef std::vector<TCompressedCon> TCompressedConVec;
00510       typedef std::map<uint32_t, TCompressedConVec> TCompressedConMap;
00511 
00512 */
00513 
00514 
00515 void RPCStripsRing::compressConnections(){
00516 
00517   
00518   L1RPCConeBuilder::TConMap::iterator itChamber = m_connectionsMap->begin();
00519   
00520   boost::shared_ptr<L1RPCConeBuilder::TConMap > uncompressedConsLeft
00521   = boost::shared_ptr<L1RPCConeBuilder::TConMap >(new L1RPCConeBuilder::TConMap());
00522   
00523   m_compressedConnectionMap =        
00524                boost::shared_ptr<L1RPCConeBuilder::TCompressedConMap >
00525                (new L1RPCConeBuilder::TCompressedConMap());
00526   
00527   
00528   int compressedCons = 0, uncompressedConsBefore = 0, uncompressedConsAfter = 0;
00529   
00530 //   int offsetMin =0, offsetMax =0;
00531   
00532   for( ;itChamber!=m_connectionsMap->end(); ++itChamber ){
00533     
00534     uint32_t detId = itChamber->first;
00535     
00536     for (L1RPCConeBuilder::TStrip2ConVec::iterator itStrip = itChamber->second.begin();
00537          itStrip!=itChamber->second.end();
00538          ++itStrip)
00539     {
00540       
00541       // Iterate over strip Connections
00542       for(L1RPCConeBuilder::TStripConVec::iterator itConn = itStrip->second.begin();
00543           itConn!=itStrip->second.end(); 
00544           ++itConn)
00545       {
00546         // Check if this connection isn't allready present in the compressed map 
00547         ++uncompressedConsBefore;
00548         bool alreadyDone=false; 
00549         if (m_compressedConnectionMap->find(detId)!=m_compressedConnectionMap->end()){
00550           
00551           // iterate over the vec, check element by element
00552           for(L1RPCConeBuilder::TCompressedConVec::iterator itCompConn=(*m_compressedConnectionMap)[detId].begin();
00553               itCompConn!=(*m_compressedConnectionMap)[detId].end();
00554               ++itCompConn)
00555           {
00556             if (itCompConn->m_tower ==  itConn->m_tower
00557                 && itCompConn->m_PAC ==  itConn->m_PAC
00558                 && itCompConn->m_logplane ==  itConn->m_logplane) // connection allready compressed 
00559             {
00560               alreadyDone=true;
00561               
00562               int logStrip = itCompConn->m_mul*itStrip->first+itCompConn->m_offset;
00563               if (logStrip != itConn->m_logstrip){
00564                 //copy the problematic connection to the "safe" map
00565                 (*uncompressedConsLeft)[detId][itStrip->first].push_back(*itConn);
00566                 ++uncompressedConsAfter;
00567                 edm::LogWarning("RPCTriggerConfig") << " Compression failed for det " << detId 
00568                   << " strip " << (int)itStrip->first
00569                   << " . Got " << (int)logStrip
00570                   << " expected " << (int)itConn->m_logstrip
00571                   << std::endl;
00572               } else {
00573                 itCompConn->addStrip(itStrip->first);
00574               }
00575               
00576             }
00577           } // compressed connection iteration end
00578         }  
00579         //if (detId==637569977) std::cout << " Buld cons for strip " << (int)itStrip->first << std::endl;
00580         
00581         
00582         if (!alreadyDone){
00583             // find another strip contributing to the same PAC,tower,logplane
00584           L1RPCConeBuilder::TStrip2ConVec::iterator itStripOther = itStrip;  
00585           ++itStripOther;
00586           bool otherStripFound = false;
00587           signed char mul = 1;
00588           for (;itStripOther!=itChamber->second.end() && !otherStripFound;
00589                ++itStripOther)
00590           {
00591             for(L1RPCConeBuilder::TStripConVec::iterator itConnOther = itStripOther->second.begin();
00592                 itConnOther!=itStripOther->second.end(); 
00593                 ++itConnOther)
00594             {
00595               if (itConnOther->m_tower ==  itConn->m_tower
00596                   && itConnOther->m_PAC ==  itConn->m_PAC
00597                   && itConnOther->m_logplane ==  itConn->m_logplane) // connection to same PAC,logplane
00598               {
00599                 otherStripFound = true;
00600                 if ( (itStripOther->first-itStrip->first)*(itConnOther->m_logstrip-itConn->m_logstrip) < 0 ){
00601                   mul = -1;                
00602                 } 
00603                 break;
00604               }
00605             } // otherConnections iter ends
00606           } // otherStrip iter ends
00607           
00608           /*
00609           if (itConn->m_tower==3 && itConn->m_PAC==73 && itConn->m_logplane==4 && detId==637569977){
00610             std::cout << " Buld cons for strip " << (int)itStrip->first;
00611             if (otherStripFound)
00612               std::cout << " other strip " << itStrip->first;
00613             else 
00614               std::cout << " no other strip ";
00615             
00616             std::cout << std::endl;
00617             
00618         }*/
00619           
00620           L1RPCConeBuilder::TCompressedCon nCompConn;
00621           nCompConn.m_tower = itConn->m_tower;
00622           nCompConn.m_PAC   = itConn->m_PAC;
00623           nCompConn.m_logplane   = itConn->m_logplane;
00624           nCompConn.m_mul  = mul;
00625           nCompConn.m_offset  = itConn->m_logstrip - mul*(signed short)(itStrip->first);
00626           nCompConn.addStrip(itStrip->first);
00627           
00628           if (otherStripFound){
00629             
00630           }  else { 
00631             
00632             //  uncompressedConsLeft[detId][itStrip->first].push_back(*itConn);
00633             //  ++uncompressedConsAfter;
00634           }
00635           (*m_compressedConnectionMap)[detId].push_back(nCompConn);
00636           ++compressedCons;
00637 
00638 
00639         } // if(!allreadyDone)
00640       }// iterate on connections
00641     }// iterate on strips
00642   } // iterate on chambers
00643    
00644   // 159 -87
00645   //std::cout << offsetMax << " TT " << offsetMin << std::endl;
00646   
00647   edm::LogInfo("RPCTriggerConfig") 
00648       << " Compressed: " << compressedCons<< " " << sizeof(L1RPCConeBuilder::TCompressedCon)
00649       << " Uncompressed before: " << uncompressedConsBefore<< " " << sizeof(L1RPCConeBuilder::TStripCon)
00650       << " Uncompressed after: " << uncompressedConsAfter << " " << sizeof(L1RPCConeBuilder::TStripCon);
00651   m_connectionsMap = uncompressedConsLeft;
00652 
00653 }
00654