CMS 3D CMS Logo

CMSSW_4_4_3_patch1/src/DQM/EcalEndcapMonitorClient/src/EEBeamCaloClient.cc

Go to the documentation of this file.
00001 /*
00002  * \file EEBeamCaloClient.cc
00003  *
00004  * $Date: 2011/09/02 13:55:02 $
00005  * $Revision: 1.67 $
00006  * \author G. Della Ricca
00007  * \author A. Ghezzi
00008  *
00009  */
00010 
00011 #include <memory>
00012 #include <iostream>
00013 #include <sstream>
00014 #include <iomanip>
00015 #include <algorithm>
00016 #include <cmath>
00017 #include <math.h>
00018 
00019 #include "FWCore/ServiceRegistry/interface/Service.h"
00020 
00021 #include "DQMServices/Core/interface/DQMStore.h"
00022 #include "DQMServices/Core/interface/MonitorElement.h"
00023 
00024 #ifdef WITH_ECAL_COND_DB
00025 #include "OnlineDB/EcalCondDB/interface/MonOccupancyDat.h"
00026 #include "OnlineDB/EcalCondDB/interface/EcalCondDBInterface.h"
00027 #include "DQM/EcalCommon/interface/LogicID.h"
00028 #endif
00029 
00030 #include "DQM/EcalCommon/interface/UtilsClient.h"
00031 #include "DQM/EcalCommon/interface/Numbers.h"
00032 
00033 #include "DQM/EcalEndcapMonitorClient/interface/EEBeamCaloClient.h"
00034 
00035 EEBeamCaloClient::EEBeamCaloClient(const edm::ParameterSet& ps) {
00036 
00037   // cloneME switch
00038   cloneME_ = ps.getUntrackedParameter<bool>("cloneME", true);
00039 
00040   // verbose switch
00041   verbose_ = ps.getUntrackedParameter<bool>("verbose", true);
00042 
00043   // debug switch
00044   debug_ = ps.getUntrackedParameter<bool>("debug", false);
00045 
00046   // prefixME path
00047   prefixME_ = ps.getUntrackedParameter<std::string>("prefixME", "");
00048 
00049   // enableCleanup_ switch
00050   enableCleanup_ = ps.getUntrackedParameter<bool>("enableCleanup", false);
00051 
00052   // vector of selected Super Modules (Defaults to all 18).
00053   superModules_.reserve(18);
00054   for ( unsigned int i = 1; i <= 18; i++ ) superModules_.push_back(i);
00055   superModules_ = ps.getUntrackedParameter<std::vector<int> >("superModules", superModules_);
00056 
00057   checkedSteps_.reserve(86);
00058   // there should be not more than a eta row in an autoscan
00059   minEvtNum_ = 1800;//
00060   //FIX ME, this should be configurable and change with the beam energy
00061   aveEne1_    = 1850;  E1Th_   = 900;
00062   aveEne3x3_  = 2600;  E3x3Th_ = 2600;
00063   RMSEne3x3_  = 800;
00064 
00065   ReadCryErrThr_ = 0.01;// 1%
00066   //FIX ME, this should follow the prescaling in the monitoring
00067   prescaling_ = 20;
00068 
00070   for(int u=0;u<cryInArray_;u++) {
00071     hBGains_[u] = 0;
00072     hBpulse_[u] = 0;
00073     //hBGainsMoving_[u] = 0;
00074   }
00075   hBEne1_ = 0;
00076   //hBEne1Moving_ = 0;
00077   hBAllNeededCry_ = 0;
00078   hBNumReadCry_ = 0;
00079   hBE3x3_ = 0;
00080   hBE3x3Moving_ = 0;
00081   hBCryOnBeam_ = 0;
00082   hBMaxEneCry_ = 0;
00083   hBReadCryErrors_ = 0;
00084   hBE1vsCry_ = 0;
00085   hBE3x3vsCry_ = 0;
00086   hBEntriesvsCry_ = 0;
00087   hBcryDone_ = 0;
00088   hBBeamCentered_ = 0;
00089   hbTBmoving_ = 0;
00090   hbE1MaxCry_ = 0;
00091   hbDesync_ = 0;
00092   pBCriInBeamEvents_ = 0;
00093 
00094   meEEBCaloRedGreen_ = 0;
00095   meEEBCaloRedGreenReadCry_ = 0;
00096   meEEBCaloRedGreenSteps_ = 0;
00097 }
00098 
00099 EEBeamCaloClient::~EEBeamCaloClient() {
00100 
00101 }
00102 
00103 void EEBeamCaloClient::beginJob(void) {
00104 
00105   dqmStore_ = edm::Service<DQMStore>().operator->();
00106 
00107   if ( debug_ ) std::cout << "EEBeamCaloClient: beginJob" << std::endl;
00108 
00109   ievt_ = 0;
00110   jevt_ = 0;
00111 
00112 }
00113 
00114 void EEBeamCaloClient::beginRun(void) {
00115 
00116   if ( debug_ ) std::cout << "EEBeamCaloClient: beginRun" << std::endl;
00117 
00118   jevt_ = 0;
00119 
00120   this->setup();
00121 
00122 }
00123 
00124 void EEBeamCaloClient::endJob(void) {
00125 
00126   if ( debug_ ) std::cout << "EEBeamCaloClient: endJob, ievt = " << ievt_ << std::endl;
00127 
00128   this->cleanup();
00129 
00130 }
00131 
00132 void EEBeamCaloClient::endRun(void) {
00133 
00134   if ( debug_ ) std::cout << "EEBeamCaloClient: endRun, jevt = " << jevt_ << std::endl;
00135 
00136   this->cleanup();
00137 
00138 }
00139 
00140 void EEBeamCaloClient::setup(void) {
00141 
00142   std::string name;
00143 
00144   dqmStore_->setCurrentFolder( prefixME_ + "/EEBeamCaloClient" );
00145 
00146   if ( meEEBCaloRedGreen_ ) dqmStore_->removeElement( meEEBCaloRedGreen_->getName() );
00147   name = "EEBCT quality";
00148   meEEBCaloRedGreen_ = dqmStore_->book2D(name, name, 85, 0., 85., 20, 0., 20.);
00149 
00150   meEEBCaloRedGreen_->Reset();
00151 
00152   for ( int ie = 1; ie <= 85; ie++ ) {
00153     for ( int ip = 1; ip <= 20; ip++ ) {
00154 
00155       meEEBCaloRedGreen_ ->setBinContent( ie, ip, 2. );
00156 
00157     }
00158   }
00159 
00160   if ( meEEBCaloRedGreenReadCry_ ) dqmStore_->removeElement( meEEBCaloRedGreenReadCry_->getName() );
00161   name = "EEBCT quality read crystal errors";
00162   meEEBCaloRedGreenReadCry_ = dqmStore_->book2D(name, name, 1, 0., 1., 1, 0., 1.);
00163   meEEBCaloRedGreenReadCry_->Reset();
00164   meEEBCaloRedGreenReadCry_ ->setBinContent( 1, 1, 2. );
00165 
00166   if( meEEBCaloRedGreenSteps_ )  dqmStore_->removeElement( meEEBCaloRedGreenSteps_->getName() );
00167   name = "EEBCT quality entries or read crystals errors";
00168   meEEBCaloRedGreenSteps_ = dqmStore_->book2D(name, name, 86, 1., 87., 1, 0., 1.);
00169   meEEBCaloRedGreenSteps_->setAxisTitle("step in the scan");
00170   meEEBCaloRedGreenSteps_->Reset();
00171   for( int bin=1; bin <87; bin++) { meEEBCaloRedGreenSteps_->setBinContent( bin, 1, 2. );}
00172 
00173 }
00174 
00175 void EEBeamCaloClient::cleanup(void) {
00176   if ( ! enableCleanup_ ) return;
00177   if ( cloneME_ ) {
00178     for(int u=0;u<cryInArray_;u++) {
00179       if(hBGains_[u]) delete hBGains_[u];
00180       if(hBpulse_[u]) delete hBpulse_[u];
00181       //if(hBGainsMoving_[u])delete hBGainsMoving_[u];
00182     }
00183     if(hBEne1_) delete hBEne1_;
00184     //    if(hBEne1Moving_) delete hBEne1Moving_;
00185     if(hBAllNeededCry_) delete hBAllNeededCry_;
00186     if(hBNumReadCry_) delete hBNumReadCry_;
00187     if(hBE3x3_) delete hBE3x3_;
00188     if(hBE3x3Moving_) delete hBE3x3Moving_;
00189     if(hBCryOnBeam_) delete hBCryOnBeam_;
00190     if(hBMaxEneCry_) delete hBMaxEneCry_;
00191     if(hBReadCryErrors_) delete hBReadCryErrors_;
00192     if(hBE1vsCry_) delete hBE1vsCry_;
00193     if(hBE3x3vsCry_) delete hBE3x3vsCry_;
00194     if(hBEntriesvsCry_) delete hBEntriesvsCry_;
00195     if(hBcryDone_) delete hBcryDone_;
00196     if(hBBeamCentered_) delete hBBeamCentered_;
00197     if(hbTBmoving_) delete hbTBmoving_;
00198     if(hbE1MaxCry_) delete hbE1MaxCry_;
00199     if(hbDesync_) delete hbDesync_;
00200     if(pBCriInBeamEvents_) delete pBCriInBeamEvents_;
00201   }
00202 
00203   for(int u=0;u<cryInArray_;u++) {
00204     hBGains_[u] = 0;
00205     hBpulse_[u] = 0;
00206     //hBGainsMoving_[u] = 0;
00207   }
00208   hBEne1_ = 0;
00209   //hBEne1Moving_ = 0;
00210   hBAllNeededCry_ = 0;
00211   hBNumReadCry_ = 0;
00212   hBE3x3_ = 0;
00213   hBE3x3Moving_ = 0;
00214   hBCryOnBeam_ = 0;
00215   hBMaxEneCry_ = 0;
00216   hBReadCryErrors_ = 0;
00217   hBE1vsCry_ = 0;
00218   hBE3x3vsCry_ = 0;
00219   hBEntriesvsCry_ = 0;
00220   hBcryDone_ = 0;
00221   hBBeamCentered_ = 0;
00222   hbTBmoving_ = 0;
00223   hbE1MaxCry_ = 0;
00224   hbDesync_ = 0;
00225   pBCriInBeamEvents_ =0;
00226 
00227   dqmStore_->setCurrentFolder( prefixME_ + "/EEBeamCaloClient" );
00228 
00229   if ( meEEBCaloRedGreen_) dqmStore_->removeElement( meEEBCaloRedGreen_->getName() );
00230   meEEBCaloRedGreen_ = 0;
00231   if ( meEEBCaloRedGreenReadCry_) dqmStore_->removeElement( meEEBCaloRedGreenReadCry_->getName() );
00232   meEEBCaloRedGreenReadCry_ = 0;
00233   if( meEEBCaloRedGreenSteps_ ) dqmStore_->removeElement (  meEEBCaloRedGreenSteps_->getName() );
00234   meEEBCaloRedGreenSteps_ = 0;
00235 }
00236 
00237 #ifdef WITH_ECAL_COND_DB
00238 bool EEBeamCaloClient::writeDb(EcalCondDBInterface* econn, RunIOV* runiov, MonRunIOV* moniov, bool& status) {
00239 
00240   status = true;
00241 
00242   EcalLogicID ecid;
00243 
00244   MonOccupancyDat o;
00245   std::map<EcalLogicID, MonOccupancyDat> dataset;
00246 
00247   for ( unsigned int i=0; i<superModules_.size(); i++ ) {
00248 
00249     int ism = superModules_[i];
00250 
00251     if ( verbose_ ) {
00252       std::cout << " " << Numbers::sEE(ism) << " (ism=" << ism << ")" << std::endl;
00253       std::cout << std::endl;
00254     }
00255 
00256     const float n_min_tot = 1000.;
00257 
00258     float num01, num02;
00259     float mean01;
00260 
00261     for ( int ie = 1; ie <= 85; ie++ ) {
00262       for ( int ip = 1; ip <= 20; ip++ ) {
00263 
00264         num01 = num02 = -1.;
00265         mean01 = -1.;
00266 
00267         bool update_channel = false;
00268 
00269         if ( hBCryOnBeam_ && hBCryOnBeam_->GetEntries() >= n_min_tot ) {
00270           num01 = hBCryOnBeam_->GetBinContent(ie, ip);
00271           update_channel = true;
00272         }
00273 
00274         if ( hBMaxEneCry_ && hBMaxEneCry_->GetEntries() >= n_min_tot ) {
00275           num02 = hBMaxEneCry_->GetBinContent(ie, ip);
00276           update_channel = true;
00277         }
00278 
00279         mean01 = 0.;
00280         //int cry = ip+20*(ie-1);
00281         int ic = (ip-1) + 20*(ie-1) + 1;
00282         int step = 0;
00283         if (hBcryDone_) { step = (int) hBcryDone_->GetBinContent(ic);}
00284         if( step > 0 && step < 86) {
00285         //if(hBE3x3vsCry_) {mean01 = hBE3x3vsCry_->GetBinContent(step);}// E in the 3x3
00286         if( hBE1vsCry_ ) {mean01 = hBE1vsCry_->GetBinContent(ic);} // E1
00287         }
00288 
00289         if ( update_channel ) {
00290 
00291           if ( Numbers::icEB(ism, ie, ip) == 1 ) {
00292 
00293             if ( verbose_ ) {
00294               std::cout << "Preparing dataset for " << Numbers::sEE(ism) << " (ism=" << ism << ")" << std::endl;
00295               std::cout << "CryOnBeam (" << ie << "," << ip << ") " << num01  << std::endl;
00296               std::cout << "MaxEneCry (" << ie << "," << ip << ") " << num02  << std::endl;
00297               std::cout << "E1 ("        << ie << "," << ip << ") " << mean01 << std::endl;
00298               std::cout << std::endl;
00299             }
00300 
00301           }
00302 
00303           o.setEventsOverHighThreshold(int(num01));
00304           o.setEventsOverLowThreshold(int(num02));
00305 
00306           o.setAvgEnergy(mean01);
00307 
00308           if ( econn ) {
00309             ecid = LogicID::getEcalLogicID("EE_crystal_number", ism, ic);
00310             dataset[ecid] = o;
00311           }
00312 
00313         }
00314 
00315       }
00316     }
00317 
00318   }
00319 
00320   if ( econn ) {
00321     try {
00322       if ( verbose_ ) std::cout << "Inserting MonOccupancyDat ..." << std::endl;
00323       if ( dataset.size() != 0 ) econn->insertDataArraySet(&dataset, moniov);
00324       if ( verbose_ ) std::cout << "done." << std::endl;
00325     } catch (std::runtime_error &e) {
00326       std::cerr << e.what() << std::endl;
00327     }
00328   }
00329 
00330   return true;
00331 
00332 }
00333 #endif
00334 
00335 void EEBeamCaloClient::analyze(void) {
00336 
00337   ievt_++;
00338   jevt_++;
00339   if ( ievt_ % 10 == 0 ) {
00340     if ( debug_ ) std::cout << "EEBeamCaloClient: ievt/jevt = " << ievt_ << "/" << jevt_ << std::endl;
00341   }
00342 
00343   MonitorElement* me = 0;
00344 
00345   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT crystals done" );
00346   hBcryDone_ = UtilsClient::getHisto( me, cloneME_, hBcryDone_ );
00347 
00348   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT crystal on beam" );
00349   hBCryOnBeam_ = UtilsClient::getHisto( me, cloneME_, hBCryOnBeam_);
00350 
00351   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT all needed crystals readout" );
00352   hBAllNeededCry_ = UtilsClient::getHisto( me, cloneME_, hBAllNeededCry_);
00353 
00354   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT readout crystals number" );
00355   hBNumReadCry_ = UtilsClient::getHisto( me, cloneME_, hBNumReadCry_);
00356 
00357   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT rec Ene sum 3x3" );
00358   hBE3x3_ = UtilsClient::getHisto( me, cloneME_, hBE3x3_);
00359 
00360   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT readout crystals errors" );
00361   hBReadCryErrors_ = UtilsClient::getHisto( me, cloneME_, hBReadCryErrors_);
00362 
00363   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT rec energy cry 5" );
00364   hBEne1_ = UtilsClient::getHisto( me, cloneME_, hBEne1_);
00365 
00366   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT crystal with maximum rec energy" );
00367   hBMaxEneCry_ = UtilsClient::getHisto( me, cloneME_, hBMaxEneCry_);
00368 
00369   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT average rec energy in the 3x3 array" );
00370   hBE3x3vsCry_ = UtilsClient::getHisto( me, cloneME_, hBE3x3vsCry_);
00371 
00372   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT average rec energy in the single crystal" );
00373   hBE1vsCry_ = UtilsClient::getHisto( me, cloneME_, hBE1vsCry_);
00374 
00375   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT number of entries" );
00376   hBEntriesvsCry_ = UtilsClient::getHisto( me, cloneME_, hBEntriesvsCry_);
00377 
00378   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT energy deposition in the 3x3" );
00379   hBBeamCentered_ = UtilsClient::getHisto( me, cloneME_, hBBeamCentered_);
00380 
00381   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT table is moving" );
00382   hbTBmoving_ = UtilsClient::getHisto( me, cloneME_, hbTBmoving_);
00383 
00384   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT crystal in beam vs event" );
00385   pBCriInBeamEvents_ =  UtilsClient::getHisto( me, cloneME_, pBCriInBeamEvents_);
00386 
00387   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT E1 in the max cry" );
00388   hbE1MaxCry_ =  UtilsClient::getHisto( me, cloneME_, hbE1MaxCry_);
00389 
00390   me = dqmStore_->get( prefixME_ + "/EEBeamCaloTask/EEBCT Desynchronization vs step" );
00391   hbDesync_ =  UtilsClient::getHisto( me, cloneME_, hbDesync_);
00392 
00393   std::stringstream ss;
00394 
00395   for(int ind = 0; ind < cryInArray_; ind ++) {
00396     ss.str("");
00397     ss << prefixME_ << "/EEBeamCaloTask/EEBCT pulse profile in G12 cry " << std::setfill('0') << std::setw(1) << (ind+1);
00398     me = dqmStore_->get( ss.str() );
00399     hBpulse_[ind] = UtilsClient::getHisto( me, cloneME_, hBpulse_[ind]);
00400 
00401     ss.str("");
00402     ss << prefixME_ << "/EEBeamCaloTask/EEBCT found gains cry " << std::setfill('0') << std::setw(1) << (ind+1);
00403     me = dqmStore_->get( ss.str() );
00404     hBGains_[ind] = UtilsClient::getHisto( me, cloneME_, hBGains_[ind]);
00405   }
00406 
00407   int DoneCry = 0;//if it stays 1 the run is not an autoscan
00408   if (hBcryDone_) {
00409     for(int cry=1 ; cry<1701 ; cry ++) {
00410       int step = (int) hBcryDone_->GetBinContent(cry);
00411       if( step>0 ) {//this crystal has been scanned or is being scanned
00412         DoneCry++;
00413         float E3x3RMS = -1, E3x3 =-1, E1=-1;
00414         if(hBE3x3vsCry_) {
00415           E3x3RMS = hBE3x3vsCry_->GetBinError(cry);
00416           E3x3 = hBE3x3vsCry_->GetBinContent(cry);
00417         }
00418         if( hBE1vsCry_) {E1=hBE1vsCry_->GetBinContent(cry);}
00419         bool RMS3x3  =  (  E3x3RMS < RMSEne3x3_ && E3x3RMS >= 0 );
00420         bool Mean3x3 =  ( std::abs( E3x3 - aveEne3x3_ ) < E3x3Th_);
00421         bool Mean1   =  ( std::abs( E1 - aveEne1_ ) < E1Th_ );
00422         int ieta = ( cry - 1)/20 + 1 ;//+1 for the bin
00423         int iphi = ( cry - 1)%20 + 1 ;//+1 for the bin
00424         //fill the RedGreen histo
00425         if(ieta >0 && iphi >0 ) {
00426           if(RMS3x3 && Mean3x3 && Mean1) {meEEBCaloRedGreen_->setBinContent(ieta,iphi,1.);}
00427           else {meEEBCaloRedGreen_->setBinContent(ieta,iphi,0.);}
00428         }
00429 
00430         float Entries = -1;
00431         //if ( hBEntriesvsCry_ ) {Entries = hBEntriesvsCry_->GetBinContent(step);}
00432         if ( hBEntriesvsCry_ ) {Entries = hBEntriesvsCry_->GetBinContent(cry);}
00433         bool Nent = ( Entries * prescaling_  > minEvtNum_ );
00434         bool readCryOk = true;
00435         if( hBReadCryErrors_ ) {
00436           int step_bin = hBReadCryErrors_->GetXaxis()->FindFixBin(step);
00437           if ( step_bin > 0 && step_bin < hBReadCryErrors_->GetNbinsX() ) {
00438             if ( hBReadCryErrors_->GetBinContent(step_bin) <= Entries*ReadCryErrThr_ ) {readCryOk = true;}
00439             else {readCryOk = false;}
00440           }
00441         }
00442 
00443         if(Nent && readCryOk ) { meEEBCaloRedGreenSteps_->setBinContent(step,1,1.);}
00444         else{ meEEBCaloRedGreenSteps_->setBinContent(step,1,0.);}
00445 
00446         if (readCryOk &&  meEEBCaloRedGreenReadCry_->getBinContent(1,1) != 0.) { meEEBCaloRedGreenReadCry_->setBinContent(1,1, 1.);}
00447         else if ( !readCryOk ) { meEEBCaloRedGreenReadCry_->setBinContent(1,1, 0.);}
00448       }// end of if (step>0)
00449     }//end of loop over cry
00450   }//end of if(hBcryDone_)
00451 
00452   if(DoneCry == 1) {//this is probably not an auotscan or it is the first crystal
00453     float nEvt = 0;
00454     if(hBE3x3_) {nEvt = hBE3x3_->GetEntries();}
00455     if(nEvt > 1*prescaling_ && hBE3x3_ && hBEne1_ && hBCryOnBeam_ && meEEBCaloRedGreen_) {//check for mean and RMS
00456       bool RMS3x3  =  ( hBE3x3_->GetRMS() < RMSEne3x3_ );
00457       bool Mean3x3 =  ( std::abs( hBE3x3_->GetMean() - aveEne3x3_ ) < E3x3Th_ );
00458       bool Mean1   =  ( std::abs( hBEne1_->GetMean() - aveEne1_ ) < E1Th_ );
00459       //fill the RedGreen histo
00460       int ieta=0,iphi=0;
00461       float found =0; //there should be just one bin filled but...
00462       for (int b_eta =1; b_eta<86; b_eta++) {
00463         for (int b_phi =1; b_phi<21; b_phi++) {
00464           float bc = hBCryOnBeam_->GetBinContent(b_eta,b_phi);//FIX ME check if this is the correct binning
00465           if(bc > found) { found =bc; ieta = b_eta; iphi= b_phi;}
00466         }
00467       }
00468       if(ieta >0 && iphi >0 ) {
00469         if(RMS3x3 && Mean3x3 && Mean1) {meEEBCaloRedGreen_->setBinContent(ieta,iphi,1.);}
00470         else {meEEBCaloRedGreen_->setBinContent(ieta,iphi,0.);}
00471       }
00472     }
00473     if(hBReadCryErrors_) {
00474       float nErr = hBReadCryErrors_->GetBinContent(1);// for a non autoscan just the first bin should be filled
00475       if( nErr > nEvt*ReadCryErrThr_ ) { meEEBCaloRedGreenReadCry_->setBinContent(1,1,0.);}
00476       else { meEEBCaloRedGreenReadCry_->setBinContent(1,1,1.);}
00477     }
00478   }
00479 
00480 }
00481