CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/RecoLocalCalo/CaloTowersCreator/src/CaloTowersCreationAlgo.cc

Go to the documentation of this file.
00001 #include "RecoLocalCalo/CaloTowersCreator/interface/CaloTowersCreationAlgo.h"
00002 #include "Geometry/CaloTopology/interface/HcalTopology.h"
00003 #include "Geometry/CaloTopology/interface/CaloTowerConstituentsMap.h"
00004 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00005 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00006 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00007 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00008 #include "Math/Interpolator.h"
00009 
00010 CaloTowersCreationAlgo::CaloTowersCreationAlgo()
00011  : theEBthreshold(-1000.),
00012    theEEthreshold(-1000.),
00013 
00014    theUseEtEBTresholdFlag(false),
00015    theUseEtEETresholdFlag(false),
00016    theUseSymEBTresholdFlag(false),
00017    theUseSymEETresholdFlag(false),
00018 
00019 
00020    theHcalThreshold(-1000.),
00021    theHBthreshold(-1000.),
00022    theHESthreshold(-1000.),
00023    theHEDthreshold(-1000.),
00024    theHOthreshold0(-1000.),  
00025    theHOthresholdPlus1(-1000.),   
00026    theHOthresholdMinus1(-1000.),  
00027    theHOthresholdPlus2(-1000.),
00028    theHOthresholdMinus2(-1000.),   
00029    theHF1threshold(-1000.),
00030    theHF2threshold(-1000.),
00031    theEBGrid(std::vector<double>(5,10.)),
00032    theEBWeights(std::vector<double>(5,1.)),
00033    theEEGrid(std::vector<double>(5,10.)),
00034    theEEWeights(std::vector<double>(5,1.)),
00035    theHBGrid(std::vector<double>(5,10.)),
00036    theHBWeights(std::vector<double>(5,1.)),
00037    theHESGrid(std::vector<double>(5,10.)),
00038    theHESWeights(std::vector<double>(5,1.)),
00039    theHEDGrid(std::vector<double>(5,10.)),
00040    theHEDWeights(std::vector<double>(5,1.)),
00041    theHOGrid(std::vector<double>(5,10.)),
00042    theHOWeights(std::vector<double>(5,1.)),
00043    theHF1Grid(std::vector<double>(5,10.)),
00044    theHF1Weights(std::vector<double>(5,1.)),
00045    theHF2Grid(std::vector<double>(5,10.)),
00046    theHF2Weights(std::vector<double>(5,1.)),
00047    theEBweight(1.),
00048    theEEweight(1.),
00049    theHBweight(1.),
00050    theHESweight(1.),
00051    theHEDweight(1.),
00052    theHOweight(1.),
00053    theHF1weight(1.),
00054    theHF2weight(1.),
00055    theEcutTower(-1000.),
00056    theEBSumThreshold(-1000.),
00057    theEESumThreshold(-1000.),
00058    theHcalTopology(0),
00059    theGeometry(0),
00060    theTowerConstituentsMap(0),
00061    theHOIsUsed(true),
00062    // (for momentum reconstruction algorithm)
00063    theMomConstrMethod(0),
00064    theMomHBDepth(0.),
00065    theMomHEDepth(0.),
00066    theMomEBDepth(0.),
00067    theMomEEDepth(0.)
00068 {
00069 }
00070 
00071 CaloTowersCreationAlgo::CaloTowersCreationAlgo(double EBthreshold, double EEthreshold, 
00072 
00073                                                bool useEtEBTreshold,
00074                                                bool useEtEETreshold,
00075                                                bool useSymEBTreshold,
00076                                                bool useSymEETreshold,                               
00077 
00078                                                double HcalThreshold,
00079                                                double HBthreshold, double HESthreshold, double  HEDthreshold,
00080                                                double HOthreshold0, double HOthresholdPlus1, double HOthresholdMinus1,  
00081                                                double HOthresholdPlus2, double HOthresholdMinus2, 
00082                                                double HF1threshold, double HF2threshold,
00083                                                double EBweight, double EEweight,
00084                                                double HBweight, double HESweight, double HEDweight,
00085                                                double HOweight, double HF1weight, double HF2weight,
00086                                                double EcutTower, double EBSumThreshold, double EESumThreshold,
00087                                                bool useHO,
00088                                                // (momentum reconstruction algorithm)
00089                                                int momConstrMethod,
00090                                                double momHBDepth,
00091                                                double momHEDepth,
00092                                                double momEBDepth,
00093                                                double momEEDepth)
00094 
00095   : theEBthreshold(EBthreshold),
00096     theEEthreshold(EEthreshold),
00097 
00098     theUseEtEBTresholdFlag(useEtEBTreshold),
00099     theUseEtEETresholdFlag(useEtEETreshold),
00100     theUseSymEBTresholdFlag(useSymEBTreshold),
00101     theUseSymEETresholdFlag(useSymEETreshold),
00102 
00103     theHcalThreshold(HcalThreshold),
00104     theHBthreshold(HBthreshold),
00105     theHESthreshold(HESthreshold),
00106     theHEDthreshold(HEDthreshold),
00107     theHOthreshold0(HOthreshold0), 
00108     theHOthresholdPlus1(HOthresholdPlus1),
00109     theHOthresholdMinus1(HOthresholdMinus1),
00110     theHOthresholdPlus2(HOthresholdPlus2),
00111     theHOthresholdMinus2(HOthresholdMinus2),
00112     theHF1threshold(HF1threshold),
00113     theHF2threshold(HF2threshold),
00114     theEBGrid(std::vector<double>(5,10.)),
00115     theEBWeights(std::vector<double>(5,1.)),
00116     theEEGrid(std::vector<double>(5,10.)),
00117     theEEWeights(std::vector<double>(5,1.)),
00118     theHBGrid(std::vector<double>(5,10.)),
00119     theHBWeights(std::vector<double>(5,1.)),
00120     theHESGrid(std::vector<double>(5,10.)),
00121     theHESWeights(std::vector<double>(5,1.)),
00122     theHEDGrid(std::vector<double>(5,10.)),
00123     theHEDWeights(std::vector<double>(5,1.)),
00124     theHOGrid(std::vector<double>(5,10.)),
00125     theHOWeights(std::vector<double>(5,1.)),
00126     theHF1Grid(std::vector<double>(5,10.)),
00127     theHF1Weights(std::vector<double>(5,1.)),
00128     theHF2Grid(std::vector<double>(5,10.)),
00129     theHF2Weights(std::vector<double>(5,1.)),
00130     theEBweight(EBweight),
00131     theEEweight(EEweight),
00132     theHBweight(HBweight),
00133     theHESweight(HESweight),
00134     theHEDweight(HEDweight),
00135     theHOweight(HOweight),
00136     theHF1weight(HF1weight),
00137     theHF2weight(HF2weight),
00138     theEcutTower(EcutTower),
00139     theEBSumThreshold(EBSumThreshold),
00140     theEESumThreshold(EESumThreshold),
00141     theHOIsUsed(useHO),
00142     // (momentum reconstruction algorithm)
00143     theMomConstrMethod(momConstrMethod),
00144     theMomHBDepth(momHBDepth),
00145     theMomHEDepth(momHEDepth),
00146     theMomEBDepth(momEBDepth),
00147     theMomEEDepth(momEEDepth)
00148 
00149 {
00150 }
00151 
00152 CaloTowersCreationAlgo::CaloTowersCreationAlgo(double EBthreshold, double EEthreshold, 
00153        bool useEtEBTreshold,
00154        bool useEtEETreshold,
00155        bool useSymEBTreshold,
00156        bool useSymEETreshold,
00157 
00158        double HcalThreshold,
00159        double HBthreshold, double HESthreshold, double  HEDthreshold,
00160        double HOthreshold0, double HOthresholdPlus1, double HOthresholdMinus1,  
00161        double HOthresholdPlus2, double HOthresholdMinus2,  
00162        double HF1threshold, double HF2threshold,
00163        const std::vector<double> & EBGrid, const std::vector<double> & EBWeights,
00164        const std::vector<double> & EEGrid, const std::vector<double> & EEWeights,
00165        const std::vector<double> & HBGrid, const std::vector<double> & HBWeights,
00166        const std::vector<double> & HESGrid, const std::vector<double> & HESWeights,
00167        const std::vector<double> & HEDGrid, const std::vector<double> & HEDWeights,
00168        const std::vector<double> & HOGrid, const std::vector<double> & HOWeights,
00169        const std::vector<double> & HF1Grid, const std::vector<double> & HF1Weights,
00170        const std::vector<double> & HF2Grid, const std::vector<double> & HF2Weights,
00171        double EBweight, double EEweight,
00172        double HBweight, double HESweight, double HEDweight,
00173        double HOweight, double HF1weight, double HF2weight,
00174        double EcutTower, double EBSumThreshold, double EESumThreshold,
00175        bool useHO,
00176        // (for the momentum construction algorithm)
00177        int momConstrMethod,
00178        double momHBDepth,
00179        double momHEDepth,
00180        double momEBDepth,
00181        double momEEDepth)
00182 
00183   : theEBthreshold(EBthreshold),
00184     theEEthreshold(EEthreshold),
00185 
00186     theUseEtEBTresholdFlag(useEtEBTreshold),
00187     theUseEtEETresholdFlag(useEtEETreshold),
00188     theUseSymEBTresholdFlag(useSymEBTreshold),
00189     theUseSymEETresholdFlag(useSymEETreshold),
00190 
00191     theHcalThreshold(HcalThreshold),
00192     theHBthreshold(HBthreshold),
00193     theHESthreshold(HESthreshold),
00194     theHEDthreshold(HEDthreshold),
00195     theHOthreshold0(HOthreshold0), 
00196     theHOthresholdPlus1(HOthresholdPlus1),
00197     theHOthresholdMinus1(HOthresholdMinus1),
00198     theHOthresholdPlus2(HOthresholdPlus2),
00199     theHOthresholdMinus2(HOthresholdMinus2),
00200     theHF1threshold(HF1threshold),
00201     theHF2threshold(HF2threshold),
00202     theEBGrid(EBGrid),
00203     theEBWeights(EBWeights),
00204     theEEGrid(EEGrid),
00205     theEEWeights(EEWeights),
00206     theHBGrid(HBGrid),
00207     theHBWeights(HBWeights),
00208     theHESGrid(HESGrid),
00209     theHESWeights(HESWeights),
00210     theHEDGrid(HEDGrid),
00211     theHEDWeights(HEDWeights),
00212     theHOGrid(HOGrid),
00213     theHOWeights(HOWeights),
00214     theHF1Grid(HF1Grid),
00215     theHF1Weights(HF1Weights),
00216     theHF2Grid(HF2Grid),
00217     theHF2Weights(HF2Weights),
00218     theEBweight(EBweight),
00219     theEEweight(EEweight),
00220     theHBweight(HBweight),
00221     theHESweight(HESweight),
00222     theHEDweight(HEDweight),
00223     theHOweight(HOweight),
00224     theHF1weight(HF1weight),
00225     theHF2weight(HF2weight),
00226     theEcutTower(EcutTower),
00227     theEBSumThreshold(EBSumThreshold),
00228     theEESumThreshold(EESumThreshold),
00229     theHOIsUsed(useHO),
00230     // (momentum reconstruction algorithm)
00231     theMomConstrMethod(momConstrMethod),
00232     theMomHBDepth(momHBDepth),
00233     theMomHEDepth(momHEDepth),
00234     theMomEBDepth(momEBDepth),
00235     theMomEEDepth(momEEDepth)
00236 
00237 {
00238 }
00239 
00240 
00241 void CaloTowersCreationAlgo::setGeometry(const CaloTowerConstituentsMap* ctt, const HcalTopology* topo, const CaloGeometry* geo) {
00242   theTowerConstituentsMap=ctt;
00243   theHcalTopology = topo;
00244   theGeometry = geo;
00245   theTowerGeometry=geo->getSubdetectorGeometry(DetId::Calo,CaloTowerDetId::SubdetId);
00246 }
00247 
00248 void CaloTowersCreationAlgo::begin() {
00249   theTowerMap.clear();
00250   //hcalDropChMap.clear();
00251 }
00252 
00253 void CaloTowersCreationAlgo::process(const HBHERecHitCollection& hbhe) { 
00254   for(HBHERecHitCollection::const_iterator hbheItr = hbhe.begin();
00255       hbheItr != hbhe.end(); ++hbheItr)
00256     assignHit(&(*hbheItr));
00257 }
00258 
00259 void CaloTowersCreationAlgo::process(const HORecHitCollection& ho) { 
00260   for(HORecHitCollection::const_iterator hoItr = ho.begin();
00261       hoItr != ho.end(); ++hoItr)
00262     assignHit(&(*hoItr));
00263 }  
00264 
00265 void CaloTowersCreationAlgo::process(const HFRecHitCollection& hf) { 
00266   for(HFRecHitCollection::const_iterator hfItr = hf.begin();
00267       hfItr != hf.end(); ++hfItr)  
00268     assignHit(&(*hfItr));
00269 }
00270 
00271 void CaloTowersCreationAlgo::process(const EcalRecHitCollection& ec) { 
00272   for(EcalRecHitCollection::const_iterator ecItr = ec.begin();
00273       ecItr != ec.end(); ++ecItr)  
00274     assignHit(&(*ecItr));
00275 }
00276 
00277 // this method should not be used any more as the towers in the changed format
00278 // can not be properly rescaled with the "rescale" method.
00279 // "rescale was replaced by "rescaleTowers"
00280 // 
00281 void CaloTowersCreationAlgo::process(const CaloTowerCollection& ctc) {
00282   for(CaloTowerCollection::const_iterator ctcItr = ctc.begin();
00283       ctcItr != ctc.end(); ++ctcItr) { 
00284     rescale(&(*ctcItr));
00285     }
00286 }
00287 
00288 
00289 
00290 void CaloTowersCreationAlgo::finish(CaloTowerCollection& result) {
00291   // now copy this map into the final collection
00292   for(MetaTowerMap::const_iterator mapItr = theTowerMap.begin();
00293       mapItr != theTowerMap.end(); ++mapItr) {
00294 
00295     // Convert only if there is at least one constituent in the metatower. 
00296     // The check of constituents size in the coverted tower is still needed!
00297     if ( (mapItr->second).metaConstituents.empty() ) continue;
00298     convert(mapItr->first, mapItr->second, result);
00299   }
00300   theTowerMap.clear(); // save the memory
00301 }
00302 
00303 
00304 void CaloTowersCreationAlgo::rescaleTowers(const CaloTowerCollection& ctc, CaloTowerCollection& ctcResult) {
00305 
00306     for (CaloTowerCollection::const_iterator ctcItr = ctc.begin();
00307       ctcItr != ctc.end(); ++ctcItr) { 
00308       
00309       CaloTowerDetId  twrId = ctcItr->id(); 
00310       double newE_em    = ctcItr->emEnergy();
00311       double newE_had   = ctcItr->hadEnergy();
00312       double newE_outer = ctcItr->outerEnergy(); 
00313 
00314       double threshold = 0.0; // not used: we do not change thresholds
00315       double weight    = 1.0;
00316 
00317       // HF
00318       if (ctcItr->ietaAbs()>=30) {
00319         double E_short = 0.5 * newE_had;             // from the definitions for HF
00320         double E_long  = newE_em + 0.5 * newE_had;   //
00321         // scale
00322         E_long  *= theHF1weight;
00323         E_short *= theHF2weight;
00324         // convert
00325         newE_em  = E_long - E_short;
00326         newE_had = 2.0 * E_short;
00327       }
00328 
00329       else {   // barrel/endcap
00330 
00331         // find if its in EB, or EE; determine from first ecal constituent found
00332         for (unsigned int iConst = 0; iConst < ctcItr->constituentsSize(); ++iConst) {
00333           DetId constId = ctcItr->constituent(iConst);
00334           if (constId.det()!=DetId::Ecal) continue;
00335           getThresholdAndWeight(constId, threshold, weight);
00336           newE_em *= weight;
00337           break;
00338         }
00339         // HO
00340         for (unsigned int iConst = 0; iConst < ctcItr->constituentsSize(); ++iConst) {
00341           DetId constId = ctcItr->constituent(iConst);
00342           if (constId.det()!=DetId::Hcal) continue;
00343           if (HcalDetId(constId).subdet()!=HcalOuter) continue;
00344           getThresholdAndWeight(constId, threshold, weight);
00345           newE_outer *= weight;
00346           break;
00347         }
00348         // HB/HE
00349         for (unsigned int iConst = 0; iConst < ctcItr->constituentsSize(); ++iConst) {
00350           DetId constId = ctcItr->constituent(iConst);
00351           if (constId.det()!=DetId::Hcal) continue;
00352           if (HcalDetId(constId).subdet()==HcalOuter) continue;
00353           getThresholdAndWeight(constId, threshold, weight);
00354           newE_had *= weight;
00355           if (ctcItr->ietaAbs()>16) newE_outer *= weight;
00356           break;
00357         }
00358         
00359     }   // barrel/endcap region
00360 
00361     // now make the new tower
00362 
00363     double newE_hadTot = (theHOIsUsed &&  twrId.ietaAbs()<16)? newE_had+newE_outer : newE_had;
00364 
00365     GlobalPoint  emPoint = ctcItr->emPosition(); 
00366     GlobalPoint hadPoint = ctcItr->emPosition(); 
00367 
00368     double f_em  = 1.0/cosh(emPoint.eta());
00369     double f_had = 1.0/cosh(hadPoint.eta());
00370 
00371     CaloTower::PolarLorentzVector towerP4;
00372 
00373     if (ctcItr->ietaAbs()<30) {
00374       if (newE_em>0)     towerP4 += CaloTower::PolarLorentzVector(newE_em*f_em,   emPoint.eta(),  emPoint.phi(),  0); 
00375       if (newE_hadTot>0) towerP4 += CaloTower::PolarLorentzVector(newE_hadTot*f_had, hadPoint.eta(), hadPoint.phi(), 0); 
00376     }
00377     else {
00378       double newE_tot = newE_em + newE_had;
00379       // for HF we use common point for ecal, hcal shower positions regardless of the method
00380       if (newE_tot>0) towerP4 += CaloTower::PolarLorentzVector(newE_tot*f_had, hadPoint.eta(), hadPoint.phi(), 0);
00381     }
00382 
00383 
00384 
00385     CaloTower rescaledTower(twrId, newE_em, newE_had, newE_outer, -1, -1, towerP4, emPoint, hadPoint);
00386     // copy the timings, have to convert back to int, 1 unit = 0.01 ns
00387     rescaledTower.setEcalTime( int(ctcItr->ecalTime()*100.0 + 0.5) );
00388     rescaledTower.setHcalTime( int(ctcItr->hcalTime()*100.0 + 0.5) );
00389 
00390     std::vector<DetId> contains;
00391     for (unsigned int iConst = 0; iConst < ctcItr->constituentsSize(); ++iConst) {
00392       contains.push_back(ctcItr->constituent(iConst));
00393     }
00394     rescaledTower.addConstituents(contains);
00395 
00396     rescaledTower.setCaloTowerStatus(ctcItr->towerStatusWord());
00397 
00398     ctcResult.push_back(rescaledTower);
00399 
00400     } // end of loop over towers
00401 
00402 
00403 }
00404 
00405 
00406 
00407 void CaloTowersCreationAlgo::assignHit(const CaloRecHit * recHit) {
00408   DetId detId = recHit->detid();
00409 
00410   unsigned int chStatusForCT = (detId.det()==DetId::Hcal)?
00411     hcalChanStatusForCaloTower(recHit) :
00412     ecalChanStatusForCaloTower(recHit);
00413 
00414   // this is for skipping channls: mostly needed for the creation of
00415   // bad towers from hits i the bad channel collections.
00416   if (chStatusForCT==CaloTowersCreationAlgo::IgnoredChan) return;
00417 
00418   double threshold, weight;
00419   getThresholdAndWeight(detId, threshold, weight);
00420 
00421   double energy = recHit->energy();  // original RecHit energy is used to apply thresholds  
00422   double e = energy * weight;        // energies scaled by user weight: used in energy assignments
00423         
00424         
00425   // SPECIAL handling of tower 28/depth 3 --> half into tower 28 and half into tower 29
00426   if (detId.det()==DetId::Hcal && 
00427       HcalDetId(detId).subdet()==HcalEndcap &&
00428       HcalDetId(detId).depth()==3 &&
00429       HcalDetId(detId).ietaAbs()==28) {
00430 
00432       
00433     // bad channels are counted regardless of energy threshold
00434 
00435     if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
00436       CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(detId);
00437       if (towerDetId.null()) return;
00438       MetaTower & tower28 = find(towerDetId);
00439       CaloTowerDetId towerDetId29(towerDetId.ieta()+towerDetId.zside(),
00440                                   towerDetId.iphi());
00441       MetaTower & tower29 = find(towerDetId29);
00442       tower28.numBadHcalCells += 1;
00443       tower29.numBadHcalCells += 1;
00444     }
00445 
00446     else if (0.5*energy >= threshold) {  // not bad channel: use energy if above threshold
00447       
00448       CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(detId);
00449       if (towerDetId.null()) return;
00450       MetaTower & tower28 = find(towerDetId);
00451       CaloTowerDetId towerDetId29(towerDetId.ieta()+towerDetId.zside(),
00452                                   towerDetId.iphi());
00453       MetaTower & tower29 = find(towerDetId29);
00454 
00455       if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
00456         tower28.numRecHcalCells += 1;
00457         tower29.numRecHcalCells += 1;     
00458       }
00459       else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
00460         tower28.numProbHcalCells += 1;
00461         tower29.numProbHcalCells += 1;
00462       }
00463 
00464       // NOTE DIVIDE BY 2!!!
00465       double e28 = 0.5 * e;
00466       double e29 = 0.5 * e;
00467 
00468       tower28.E_had += e28;
00469       tower28.E += e28;
00470       std::pair<DetId,double> mc(detId,e28);
00471       tower28.metaConstituents.push_back(mc);
00472       
00473       tower29.E_had += e29;
00474       tower29.E += e29;
00475       tower29.metaConstituents.push_back(mc);
00476       
00477       // time info: do not use in averaging if timing error is found: need 
00478       // full set of status info to implement: use only "good" channels for now
00479 
00480       if (chStatusForCT == CaloTowersCreationAlgo::GoodChan) {
00481         tower28.hadSumTimeTimesE += ( e28 * recHit->time() );
00482         tower28.hadSumEForTime   += e28;
00483         tower29.hadSumTimeTimesE += ( e29 * recHit->time() );
00484         tower29.hadSumEForTime   += e29;
00485       }
00486 
00487       // store the energy in layer 3 also in E_outer
00488       tower28.E_outer += e28;
00489       tower29.E_outer += e29;
00490     } // not a "bad" hit
00491       
00492   }  // end of special case 
00493   
00494   else {
00495 
00496     DetId::Detector det = detId.det();
00497     
00498     if (det == DetId::Ecal) {
00499       
00501       
00502       // For ECAL we count all bad channels after the metatower is complete 
00503 
00504       // Include options for symmetric thresholds and cut on Et
00505       // for ECAL RecHits
00506 
00507       bool passEmThreshold = false;
00508       
00509       if (detId.subdetId() == EcalBarrel) {
00510         if (theUseEtEBTresholdFlag) energy /= cosh( (theGeometry->getGeometry(detId)->getPosition()).eta() ) ;
00511         if (theUseSymEBTresholdFlag) passEmThreshold = (fabs(energy) >= threshold);
00512         else  passEmThreshold = (energy >= threshold);
00513 
00514       }
00515       else if (detId.subdetId() == EcalEndcap) {
00516         if (theUseEtEETresholdFlag) energy /= cosh( (theGeometry->getGeometry(detId)->getPosition()).eta() ) ;
00517         if (theUseSymEETresholdFlag) passEmThreshold = (fabs(energy) >= threshold);
00518         else  passEmThreshold = (energy >= threshold);
00519       }
00520 
00521 
00522       //      if (chStatusForCT != CaloTowersCreationAlgo::BadChan && energy >= threshold) {
00523       if (chStatusForCT != CaloTowersCreationAlgo::BadChan && passEmThreshold) {
00524         CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(detId);
00525         if (towerDetId.null()) return;
00526         MetaTower & tower = find(towerDetId);
00527         tower.E_em += e;
00528         tower.E += e;
00529         
00530         if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan)  {
00531           tower.numRecEcalCells += 1;  
00532         }
00533         else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
00534           tower.numProbEcalCells += 1;
00535         }
00536         
00537         // change when full status info is available
00538         // for now use only good channels
00539         
00540         // add e>0 check (new options allow e<0)
00541         if (chStatusForCT == CaloTowersCreationAlgo::GoodChan && e>0 ) {
00542           tower.emSumTimeTimesE += ( e * recHit->time() );
00543           tower.emSumEForTime   += e;  // see above
00544         }
00545 
00546         std::pair<DetId,double> mc(detId,e);
00547         tower.metaConstituents.push_back(mc);
00548       }
00549     
00550     }  // end of ECAL
00551     
00552     // HCAL
00553     else {
00554       HcalDetId hcalDetId(detId);
00555       
00557 
00558       if(hcalDetId.subdet() == HcalOuter) {
00559  
00560         CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(detId);
00561         if (towerDetId.null()) return;
00562         MetaTower & tower = find(towerDetId);
00563 
00564         if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
00565             if (theHOIsUsed) tower.numBadHcalCells += 1;
00566         }
00567         
00568         else if (energy >= threshold) {
00569           tower.E_outer += e; // store HO energy even if HO is not used
00570           // add energy of the tower and/or flag if theHOIsUsed
00571           if(theHOIsUsed) {
00572             tower.E += e;
00573             
00574             if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
00575               tower.numRecHcalCells += 1;
00576             }
00577             else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
00578               tower.numProbHcalCells += 1;
00579             }
00580           } // HO is used
00581         
00582           
00583           // add HO to constituents even if it is not used: JetMET wants to keep these towers
00584           std::pair<DetId,double> mc(detId,e);
00585           tower.metaConstituents.push_back(mc);   
00586 
00587         } // not a bad channel, energy above threshold
00588       
00589       }  // HO hit 
00590       
00591       // HF calculates EM fraction differently
00592       else if(hcalDetId.subdet() == HcalForward) {
00593 
00594         if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
00595           CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(detId);
00596           if (towerDetId.null()) return;
00597           MetaTower & tower = find(towerDetId);
00598           tower.numBadHcalCells += 1;
00599         }
00600         
00601         else if (energy >= threshold)  {
00602           CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(detId);
00603           if (towerDetId.null()) return;
00604           MetaTower & tower = find(towerDetId);
00605 
00606           if (hcalDetId.depth() == 1) {
00607             // long fiber, so E_EM = E(Long) - E(Short)
00608             tower.E_em += e;
00609           } 
00610           else {
00611             // short fiber, EHAD = 2 * E(Short)
00612             tower.E_em -= e;
00613             tower.E_had += 2. * e;
00614           }
00615           tower.E += e;
00616           if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
00617             tower.numRecHcalCells += 1;
00618           }
00619           else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
00620             tower.numProbHcalCells += 1;
00621           }
00622           
00623           // put the timing in HCAL -> have to check timing errors when available
00624           // for now use only good channels
00625           if (chStatusForCT == CaloTowersCreationAlgo::GoodChan) {
00626             tower.hadSumTimeTimesE += ( e * recHit->time() );
00627             tower.hadSumEForTime   += e;
00628           }
00629 
00630           std::pair<DetId,double> mc(detId,e);
00631           tower.metaConstituents.push_back(mc);            
00632 
00633         } // not a bad HF channel, energy above threshold
00634       
00635       } // HF hit
00636       
00637       else {
00638         // HCAL situation normal in HB/HE
00639         if (chStatusForCT == CaloTowersCreationAlgo::BadChan) {
00640           CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(detId);
00641           if (towerDetId.null()) return;
00642           MetaTower & tower = find(towerDetId);
00643           tower.numBadHcalCells += 1;
00644         }
00645         else if (energy >= threshold) {
00646           CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(detId);
00647           if (towerDetId.null()) return;
00648           MetaTower & tower = find(towerDetId);
00649           tower.E_had += e;
00650           tower.E += e;
00651           if (chStatusForCT == CaloTowersCreationAlgo::RecoveredChan) {
00652             tower.numRecHcalCells += 1;
00653           }
00654           else if (chStatusForCT == CaloTowersCreationAlgo::ProblematicChan) {
00655             tower.numProbHcalCells += 1;
00656           }
00657           
00658           // Timing information: need specific accessors
00659           // for now use only good channels
00660           if (chStatusForCT == CaloTowersCreationAlgo::GoodChan) {
00661             tower.hadSumTimeTimesE += ( e * recHit->time() );
00662             tower.hadSumEForTime   += e;
00663           }
00664           // store energy in highest depth for towers 18-27 (for electron,photon ID in endcap)
00665           // also, store energy in HE part of tower 16 (for JetMET cleanup)
00666           HcalDetId hcalDetId(detId);
00667           if (hcalDetId.subdet()==HcalEndcap) {
00668             if ( (hcalDetId.depth()==2 && hcalDetId.ietaAbs()>=18 && hcalDetId.ietaAbs()<27) ||
00669                  (hcalDetId.depth()==3 && hcalDetId.ietaAbs()==27) ||
00670                  (hcalDetId.depth()==3 && hcalDetId.ietaAbs()==16) ) {
00671               tower.E_outer += e;
00672             }
00673           }
00674 
00675           std::pair<DetId,double> mc(detId,e);
00676           tower.metaConstituents.push_back(mc);   
00677        
00678         }   // not a "bad" channel, energy above threshold
00679       
00680       } // channel in HBHE (excluding twrs 28,29)
00681     
00682     }
00683     
00684   }  // recHit normal case (not in HE towers 28,29)
00685 
00686 }  // end of assignHit method
00687 
00688 
00689 
00690 
00691 // This method is not flexible enough for the new CaloTower format. 
00692 // For now make a quick compatibility "fix" : WILL NOT WORK CORRECTLY with anything 
00693 // except the default simple p4 assignment!!!
00694 // Must be rewritten for full functionality.
00695 void CaloTowersCreationAlgo::rescale(const CaloTower * ct) {
00696   double threshold, weight;
00697   CaloTowerDetId towerDetId = theTowerConstituentsMap->towerOf(ct->id());
00698   if (towerDetId.null()) return;
00699   MetaTower & tower = find(towerDetId);
00700 
00701   tower.E_em = 0.;
00702   tower.E_had = 0.;
00703   tower.E_outer = 0.;
00704   for (unsigned int i=0; i<ct->constituentsSize(); i++) {
00705     DetId detId = ct->constituent(i);
00706     getThresholdAndWeight(detId, threshold, weight);
00707     DetId::Detector det = detId.det();
00708     if(det == DetId::Ecal) {
00709       tower.E_em = ct->emEnergy()*weight;
00710     }
00711     else {
00712       HcalDetId hcalDetId(detId);
00713       if(hcalDetId.subdet() == HcalForward) {
00714         if (hcalDetId.depth()==1) tower.E_em = ct->emEnergy()*weight;
00715         if (hcalDetId.depth()==2) tower.E_had = ct->hadEnergy()*weight;
00716       }
00717       else if(hcalDetId.subdet() == HcalOuter) {
00718         tower.E_outer = ct->outerEnergy()*weight;
00719       }
00720       else {
00721         tower.E_had = ct->hadEnergy()*weight;
00722       }
00723     }
00724     tower.E = tower.E_had+tower.E_em+tower.E_outer;
00725 
00726     // this is to be compliant with the new MetaTower setup
00727     // used only for the default simple vector assignment
00728     std::pair<DetId, double> mc(detId, 0);
00729     tower.metaConstituents.push_back(mc);
00730   }
00731 
00732   // preserve time inforamtion
00733   tower.emSumTimeTimesE  = ct->ecalTime();
00734   tower.hadSumTimeTimesE = ct->hcalTime();
00735   tower.emSumEForTime = 1.0;
00736   tower.hadSumEForTime = 1.0;
00737 }
00738 
00739 CaloTowersCreationAlgo::MetaTower::MetaTower() : 
00740   E(0),E_em(0),E_had(0),E_outer(0), emSumTimeTimesE(0), hadSumTimeTimesE(0), emSumEForTime(0), hadSumEForTime(0),
00741   numBadEcalCells(0), numRecEcalCells(0), numProbEcalCells(0), numBadHcalCells(0), numRecHcalCells(0), numProbHcalCells(0) { }
00742 
00743 
00744 CaloTowersCreationAlgo::MetaTower & CaloTowersCreationAlgo::find(const CaloTowerDetId & detId) {
00745   MetaTowerMap::iterator itr = theTowerMap.lower_bound(detId);
00746   if(itr != theTowerMap.end() && ! (theTowerMap.key_comp()(detId,itr->first)))
00747     {
00748       // do nothing if exists
00749     }
00750   else
00751     {
00752       // build and insert a new tower
00753       // and return position
00754       itr = theTowerMap.insert(itr, std::pair<CaloTowerDetId,CaloTowersCreationAlgo::MetaTower>(detId, MetaTower()));
00755     }
00756    return itr->second;
00757 }
00758 
00759 
00760 void CaloTowersCreationAlgo::convert(const CaloTowerDetId& id, const MetaTower& mt,
00761                                      CaloTowerCollection & collection) 
00762 {
00763     double ecalThres=(id.ietaAbs()<=17)?(theEBSumThreshold):(theEESumThreshold);
00764     double E=mt.E;
00765     double E_em=mt.E_em;
00766     double E_had=mt.E_had;
00767     double E_outer=mt.E_outer;
00768 
00769     // Note: E_outer is used to save HO energy OR energy in the outermost depths in endcap region
00770     // In the methods with separate treatment of EM and HAD components:
00771     //  - HO is not used to determine direction, however HO energy is added to get "total had energy"
00772     //  => Check if the tower is within HO coverage before adding E_outer to the "total had" energy
00773     //     else the energy will be double counted
00774     // When summing up the energy of the tower these checks are performed in the loops over RecHits
00775 
00776     std::vector<std::pair<DetId,double> > metaContains=mt.metaConstituents;
00777     if (id.ietaAbs()<=29 && E_em<ecalThres) { // ignore EM threshold in HF
00778       E-=E_em;
00779       E_em=0;
00780       std::vector<std::pair<DetId,double> > metaContains_noecal;
00781 
00782     for (std::vector<std::pair<DetId,double> >::iterator i=metaContains.begin(); i!=metaContains.end(); ++i) 
00783                 if (i->first.det()!=DetId::Ecal) metaContains_noecal.push_back(*i);
00784       metaContains.swap(metaContains_noecal);
00785     }
00786     if (id.ietaAbs()<=29 && E_had<theHcalThreshold) {
00787       E-=E_had;
00788 
00789       if (theHOIsUsed && id.ietaAbs()<16)  E-=E_outer; // not subtracted before, think it should be done
00790      
00791       E_had=0;
00792       E_outer=0;
00793       std::vector<std::pair<DetId,double> > metaContains_nohcal;
00794 
00795       for (std::vector<std::pair<DetId,double> >::iterator i=metaContains.begin(); i!=metaContains.end(); ++i) 
00796         if (i->first.det()!=DetId::Hcal) metaContains_nohcal.push_back(*i);
00797       metaContains.swap(metaContains_nohcal);
00798     }
00799 
00800     if(metaContains.empty()) return;
00801 
00802     double E_had_tot = (theHOIsUsed && id.ietaAbs()<16)? E_had+E_outer : E_had;
00803 
00804 
00805     // create CaloTower using the selected algorithm
00806 
00807     GlobalPoint emPoint, hadPoint;
00808 
00809     CaloTower::PolarLorentzVector towerP4;
00810     
00811 
00812     // conditional assignment of depths for barrel/endcap
00813     // Some additional tuning may be required in the transitional region
00814     // 14<|iEta|<19
00815     double momEmDepth = 0.;
00816     double momHadDepth = 0.;
00817     if (id.ietaAbs()<=17) {
00818       momHadDepth = theMomHBDepth;
00819       momEmDepth  = theMomEBDepth;
00820     }
00821     else {
00822       momHadDepth = theMomHEDepth;
00823       momEmDepth  = theMomEEDepth;
00824     }
00825 
00826   switch (theMomConstrMethod) {
00827 
00828   case 0 :
00829     {  // Simple 4-momentum assignment
00830       GlobalPoint p=theTowerGeometry->getGeometry(id)->getPosition();
00831 
00832       double pf=1.0/cosh(p.eta());
00833       if (E>0) towerP4 = CaloTower::PolarLorentzVector(E*pf, p.eta(), p.phi(), 0);
00834       
00835       emPoint  = p;   
00836       hadPoint = p;
00837     }  // end case 0
00838     break;
00839 
00840   case 1 :
00841     {   // separate 4-vectors for ECAL, HCAL, add to get the 4-vector of the tower (=>tower has mass!)
00842       if (id.ietaAbs()<=29) {
00843         if (E_em>0) {
00844           emPoint   = emShwrPos(metaContains, momEmDepth, E_em);
00845           double emPf = 1.0/cosh(emPoint.eta());
00846           towerP4 += CaloTower::PolarLorentzVector(E_em*emPf, emPoint.eta(), emPoint.phi(), 0); 
00847         }
00848         if ( (E_had + E_outer) >0) {
00849           hadPoint  = hadShwrPos(id, momHadDepth);
00850           double hadPf = 1.0/cosh(hadPoint.eta());
00851           
00852           if (E_had_tot>0) {
00853             towerP4 += CaloTower::PolarLorentzVector(E_had_tot*hadPf, hadPoint.eta(), hadPoint.phi(), 0); 
00854           }
00855         }
00856       }
00857       else {  // forward detector: use the CaloTower position 
00858         GlobalPoint p=theTowerGeometry->getGeometry(id)->getPosition();
00859         double pf=1.0/cosh(p.eta());
00860         if (E>0) towerP4 = CaloTower::PolarLorentzVector(E*pf, p.eta(), p.phi(), 0);  // simple momentum assignment, same position
00861         emPoint  = p;   
00862         hadPoint = p;
00863       }
00864     }  // end case 1
00865     break;
00866 
00867   case 2:
00868     {   // use ECAL position for the tower (when E_cal>0), else default CaloTower position (massless tower)
00869       if (id.ietaAbs()<=29) {
00870         if (E_em>0)  emPoint = emShwrLogWeightPos(metaContains, momEmDepth, E_em);
00871         else emPoint = theTowerGeometry->getGeometry(id)->getPosition();
00872 
00873         double sumPf = 1.0/cosh(emPoint.eta());
00874         if (E>0) towerP4 = CaloTower::PolarLorentzVector(E*sumPf, emPoint.eta(), emPoint.phi(), 0); 
00875         
00876         hadPoint = emPoint;
00877       }
00878       else {  // forward detector: use the CaloTower position 
00879         GlobalPoint p=theTowerGeometry->getGeometry(id)->getPosition();
00880         double pf=1.0/cosh(p.eta());
00881         if (E>0) towerP4 = CaloTower::PolarLorentzVector(E*pf, p.eta(), p.phi(), 0);  // simple momentum assignment, same position
00882         emPoint  = p;   
00883         hadPoint = p;
00884       }
00885     }   // end case 2
00886     break;
00887 
00888   }  // end of decision on p4 reconstruction method
00889 
00890 
00891     CaloTower caloTower(id, E_em, E_had, E_outer, -1, -1, towerP4, emPoint, hadPoint);
00892     if(caloTower.energy() < theEcutTower) return;
00893     // set the timings
00894     float  ecalTime = (mt.emSumEForTime>0)?   mt.emSumTimeTimesE/mt.emSumEForTime  : -9999;
00895     float  hcalTime = (mt.hadSumEForTime>0)?  mt.hadSumTimeTimesE/mt.hadSumEForTime : -9999;
00896     caloTower.setEcalTime(compactTime(ecalTime));
00897     caloTower.setHcalTime(compactTime(hcalTime));
00898 
00899     // set the CaloTower status word =====================================
00900     // Channels must be counter exclusively in the defined cathegories
00901     // "Bad" channels (not used in energy assignment) can be flagged during
00902     // CaloTower creation only if specified in the configuration file
00903 
00904     unsigned int numBadHcalChan  = mt.numBadHcalCells;
00905     //    unsigned int numBadEcalChan  = mt.numBadEcalCells;
00906     unsigned int numBadEcalChan  = 0;   //
00907 
00908     unsigned int numRecHcalChan  = mt.numRecHcalCells;
00909     unsigned int numRecEcalChan  = mt.numRecEcalCells;
00910     unsigned int numProbHcalChan = mt.numProbHcalCells;
00911     unsigned int numProbEcalChan = mt.numProbEcalCells;
00912 
00913     // now add dead/off/... channels not used in RecHit reconstruction for HCAL 
00914     HcalDropChMap::iterator dropChItr = hcalDropChMap.find(id);
00915     if (dropChItr != hcalDropChMap.end()) numBadHcalChan += dropChItr->second;
00916     
00917 
00918     // for ECAL the number of all bad channels is obtained here -----------------------
00919 
00920     // get all possible constituents of the tower
00921     std::vector<DetId> allConstituents = theTowerConstituentsMap->constituentsOf(id);
00922 
00923     for (std::vector<DetId>::iterator ac_it=allConstituents.begin(); 
00924          ac_it!=allConstituents.end(); ++ac_it) {
00925 
00926       if (ac_it->det()!=DetId::Ecal) continue;
00927  
00928       int thisEcalSevLvl = -999;
00929      
00930       if (ac_it->subdetId() == EcalBarrel && theEbHandle.isValid()) {
00931         thisEcalSevLvl = theEcalSevLvlAlgo->severityLevel( *ac_it, *theEbHandle);//, *theEcalChStatus);
00932       }
00933       else if (ac_it->subdetId() == EcalEndcap && theEeHandle.isValid()) {
00934         thisEcalSevLvl = theEcalSevLvlAlgo->severityLevel( *ac_it, *theEeHandle);//, *theEcalChStatus);
00935       }
00936  
00937       // "bad" include "recovered" if the flag not to use them was set 
00938       // this is consistent with the treatment of what channels are accepted
00939       if (thisEcalSevLvl>int(theEcalAcceptSeverityLevel) || 
00940           ( thisEcalSevLvl==EcalSeverityLevelAlgo::kRecovered && !theRecoveredEcalHitsAreUsed) ) {
00941         
00942         ++numBadEcalChan;
00943       }
00944 
00945     }
00946     //--------------------------------------------------------------------------------------
00947 
00948     caloTower.setCaloTowerStatus(numBadHcalChan, numBadEcalChan,         
00949                               numRecHcalChan, numRecEcalChan,    
00950                               numProbHcalChan, numProbEcalChan);
00951   
00952     double maxCellE = -999.0; // for storing the hottest cell E in the calotower
00953 
00954     std::vector<DetId> contains;
00955     contains.reserve(metaContains.size());
00956     for (std::vector<std::pair<DetId,double> >::iterator i=metaContains.begin(); i!=metaContains.end(); ++i) {
00957 
00958       contains.push_back(i->first);
00959 
00960       if (maxCellE < i->second) {
00961         // need an extra check because of the funny towers that are empty except for the presence of an HO
00962         // hit in the constituents (JetMET wanted them saved)
00963         // This constituent is only used for storing the tower, but should not be concidered as a hot cell canditate for
00964         // configurations with useHO = false
00965 
00966 
00967         if (i->first.det()==DetId::Ecal) {  // ECAL
00968           maxCellE = i->second;
00969         }       
00970         else {  // HCAL
00971           if (HcalDetId(i->first).subdet() != HcalOuter) 
00972             maxCellE = i->second;
00973           else if (theHOIsUsed) maxCellE = i->second;
00974         }
00975 
00976       } // found higher E cell
00977 
00978     } // loop over matacontains
00979 
00980     caloTower.addConstituents(contains);
00981     caloTower.setHottestCellE(maxCellE);
00982 
00983     collection.push_back(caloTower);
00984 } 
00985 
00986 
00987 
00988 void CaloTowersCreationAlgo::getThresholdAndWeight(const DetId & detId, double & threshold, double & weight) const {
00989   DetId::Detector det = detId.det();
00990   weight=0; // in case the hit is not identified
00991 
00992   if(det == DetId::Ecal) {
00993     // may or may not be EB.  We'll find out.
00994 
00995     EcalSubdetector subdet = (EcalSubdetector)(detId.subdetId());
00996     if(subdet == EcalBarrel) {
00997       threshold = theEBthreshold;
00998       weight = theEBweight;
00999       if (weight <= 0.) {
01000         ROOT::Math::Interpolator my(theEBGrid,theEBWeights,ROOT::Math::Interpolation::kAKIMA);
01001         weight = my.Eval(theEBEScale);
01002       }
01003     }
01004     else if(subdet == EcalEndcap) {
01005       threshold = theEEthreshold;
01006       weight = theEEweight;
01007       if (weight <= 0.) {
01008         ROOT::Math::Interpolator my(theEEGrid,theEEWeights,ROOT::Math::Interpolation::kAKIMA);
01009         weight = my.Eval(theEEEScale);
01010       }
01011     }
01012   }
01013   else if(det == DetId::Hcal) {
01014     HcalDetId hcalDetId(detId);
01015     HcalSubdetector subdet = hcalDetId.subdet();
01016     
01017     if(subdet == HcalBarrel) {
01018       threshold = theHBthreshold;
01019       weight = theHBweight;
01020       if (weight <= 0.) {
01021         ROOT::Math::Interpolator my(theHBGrid,theHBWeights,ROOT::Math::Interpolation::kAKIMA);
01022         weight = my.Eval(theHBEScale);
01023       }
01024     }
01025     
01026     else if(subdet == HcalEndcap) {
01027       // check if it's single or double tower
01028       if(hcalDetId.ietaAbs() < theHcalTopology->firstHEDoublePhiRing()) {
01029         threshold = theHESthreshold;
01030         weight = theHESweight;
01031         if (weight <= 0.) {
01032           ROOT::Math::Interpolator my(theHESGrid,theHESWeights,ROOT::Math::Interpolation::kAKIMA);
01033           weight = my.Eval(theHESEScale);
01034         }
01035       }
01036       else {
01037         threshold = theHEDthreshold;
01038         weight = theHEDweight;
01039         if (weight <= 0.) {
01040           ROOT::Math::Interpolator my(theHEDGrid,theHEDWeights,ROOT::Math::Interpolation::kAKIMA);
01041           weight = my.Eval(theHEDEScale);
01042         }
01043       }
01044     }
01045     
01046     else if(subdet == HcalOuter) {
01047       //check if it's ring 0 or +1 or +2 or -1 or -2
01048       if(hcalDetId.ietaAbs() <= 4) threshold = theHOthreshold0;
01049       else if(hcalDetId.ieta() < 0) {
01050         // set threshold for ring -1 or -2
01051         threshold = (hcalDetId.ietaAbs() <= 10) ?  theHOthresholdMinus1 : theHOthresholdMinus2;
01052       } else {
01053         // set threshold for ring +1 or +2
01054         threshold = (hcalDetId.ietaAbs() <= 10) ?  theHOthresholdPlus1 : theHOthresholdPlus2;
01055       }
01056       weight = theHOweight;
01057       if (weight <= 0.) {
01058         ROOT::Math::Interpolator my(theHOGrid,theHOWeights,ROOT::Math::Interpolation::kAKIMA);
01059         weight = my.Eval(theHOEScale);
01060       }
01061     } 
01062 
01063     else if(subdet == HcalForward) {
01064       if(hcalDetId.depth() == 1) {
01065         threshold = theHF1threshold;
01066         weight = theHF1weight;
01067         if (weight <= 0.) {
01068           ROOT::Math::Interpolator my(theHF1Grid,theHF1Weights,ROOT::Math::Interpolation::kAKIMA);
01069           weight = my.Eval(theHF1EScale);
01070         }
01071       } else {
01072         threshold = theHF2threshold;
01073         weight = theHF2weight;
01074         if (weight <= 0.) {
01075           ROOT::Math::Interpolator my(theHF2Grid,theHF2Weights,ROOT::Math::Interpolation::kAKIMA);
01076           weight = my.Eval(theHF2EScale);
01077         }
01078       }
01079     }
01080   }
01081   else {
01082     edm::LogError("CaloTowersCreationAlgo") << "Bad cell: " << det << std::endl;
01083   }
01084 }
01085 
01086 void CaloTowersCreationAlgo::setEBEScale(double scale){
01087   if (scale>0.00001) *&theEBEScale = scale;
01088   else *&theEBEScale = 50.;
01089 }
01090 
01091 void CaloTowersCreationAlgo::setEEEScale(double scale){
01092   if (scale>0.00001) *&theEEEScale = scale;
01093   else *&theEEEScale = 50.;
01094 }
01095 
01096 void CaloTowersCreationAlgo::setHBEScale(double scale){
01097   if (scale>0.00001) *&theHBEScale = scale;
01098   else *&theHBEScale = 50.;
01099 }
01100 
01101 void CaloTowersCreationAlgo::setHESEScale(double scale){
01102   if (scale>0.00001) *&theHESEScale = scale;
01103   else *&theHESEScale = 50.;
01104 }
01105 
01106 void CaloTowersCreationAlgo::setHEDEScale(double scale){
01107   if (scale>0.00001) *&theHEDEScale = scale;
01108   else *&theHEDEScale = 50.;
01109 }
01110 
01111 void CaloTowersCreationAlgo::setHOEScale(double scale){
01112   if (scale>0.00001) *&theHOEScale = scale;
01113   else *&theHOEScale = 50.;
01114 }
01115 
01116 void CaloTowersCreationAlgo::setHF1EScale(double scale){
01117   if (scale>0.00001) *&theHF1EScale = scale;
01118   else *&theHF1EScale = 50.;
01119 }
01120 
01121 void CaloTowersCreationAlgo::setHF2EScale(double scale){
01122   if (scale>0.00001) *&theHF2EScale = scale;
01123   else *&theHF2EScale = 50.;
01124 }
01125 
01126 
01127 GlobalPoint CaloTowersCreationAlgo::emCrystalShwrPos(DetId detId, float fracDepth) {
01128    const CaloCellGeometry* cellGeometry = theGeometry->getGeometry(detId);
01129    GlobalPoint point = cellGeometry->getPosition();  // face of the cell
01130 
01131    if      (fracDepth<0) fracDepth=0;
01132    else if (fracDepth>1) fracDepth=1;
01133 
01134    if (fracDepth>0.0) {
01135      CaloCellGeometry::CornersVec cv = cellGeometry->getCorners();
01136      GlobalPoint backPoint = GlobalPoint( 0.25*( cv[4].x() + cv[5].x() + cv[6].x() + cv[7].x() ),
01137                                           0.25*( cv[4].y() + cv[5].y() + cv[6].y() + cv[7].y() ),
01138                                           0.25*( cv[4].z() + cv[5].z() + cv[6].z() + cv[7].z() ) );
01139      point += fracDepth * (backPoint-point);
01140    }
01141 
01142    return point;
01143 }
01144 
01145 GlobalPoint CaloTowersCreationAlgo::hadSegmentShwrPos(DetId detId, float fracDepth) {
01146    const CaloCellGeometry* cellGeometry = theGeometry->getGeometry(detId);
01147    GlobalPoint point = cellGeometry->getPosition();  // face of the cell
01148 
01149    if      (fracDepth<0) fracDepth=0;
01150    else if (fracDepth>1) fracDepth=1;
01151 
01152    if (fracDepth>0.0) {
01153      CaloCellGeometry::CornersVec cv = cellGeometry->getCorners();
01154      GlobalPoint backPoint = GlobalPoint( 0.25*( cv[4].x() + cv[5].x() + cv[6].x() + cv[7].x() ),
01155                                           0.25*( cv[4].y() + cv[5].y() + cv[6].y() + cv[7].y() ),
01156                                           0.25*( cv[4].z() + cv[5].z() + cv[6].z() + cv[7].z() ) );
01157      point += fracDepth * (backPoint-point);
01158    }
01159 
01160    return point;
01161 }
01162 
01163 
01164 GlobalPoint CaloTowersCreationAlgo::hadShwrPos(const std::vector<std::pair<DetId,double> >& metaContains,
01165                                                float fracDepth, double hadE) {
01166                                                   
01167   // this is based on available RecHits, can lead to different actual depths if
01168   // hits in multi-depth towers are not all there
01169   if (hadE<=0) return GlobalPoint(0,0,0);
01170 
01171   double hadX = 0.0;
01172   double hadY = 0.0;
01173   double hadZ = 0.0;
01174 
01175   int nConst = 0;
01176 
01177   std::vector<std::pair<DetId,double> >::const_iterator mc_it = metaContains.begin();
01178   for (; mc_it!=metaContains.end(); ++mc_it) {
01179     if (mc_it->first.det() != DetId::Hcal) continue;
01180     // do not use HO for deirection calculations for now
01181     if (HcalDetId(mc_it->first).subdet() == HcalOuter) continue;
01182     ++nConst;
01183 
01184     GlobalPoint p = hadSegmentShwrPos(mc_it->first, fracDepth);
01185 
01186     // longitudinal segmentation: do not weight by energy,
01187     // get the geometrical position
01188     hadX += p.x();
01189     hadY += p.y();
01190     hadZ += p.z();
01191   }
01192 
01193    return GlobalPoint(hadX/nConst, hadY/nConst, hadZ/nConst);
01194 }
01195 
01196 
01197 GlobalPoint CaloTowersCreationAlgo::hadShwrPos(CaloTowerDetId towerId, float fracDepth) {
01198 
01199   // set depth using geometry of cells that are associated with the
01200   // tower (regardless if they have non-zero energies)
01201 
01202 //  if (hadE <= 0) return GlobalPoint(0, 0, 0);
01203 
01204   if (fracDepth < 0) fracDepth = 0;
01205   else if (fracDepth > 1) fracDepth = 1;
01206 
01207   GlobalPoint point(0,0,0);
01208 
01209   int iEta = towerId.ieta();
01210   int iPhi = towerId.iphi();
01211 
01212   HcalDetId frontCellId, backCellId;
01213 
01214   if (towerId.ietaAbs() <= 14) {
01215     // barrel, one depth only
01216     frontCellId = HcalDetId(HcalBarrel, iEta, iPhi, 1);
01217     backCellId  = HcalDetId(HcalBarrel, iEta, iPhi, 1);
01218   }
01219   else if (towerId.ietaAbs() == 15) {
01220     // barrel, two depths
01221     frontCellId = HcalDetId(HcalBarrel, iEta, iPhi, 1);
01222     backCellId  = HcalDetId(HcalBarrel, iEta, iPhi, 2);
01223   }
01224   else if (towerId.ietaAbs() == 16) {
01225     // barrel and endcap: two depths HB, one depth HE 
01226     frontCellId = HcalDetId(HcalBarrel, iEta, iPhi, 1);
01227     backCellId  = HcalDetId(HcalEndcap, iEta, iPhi, 3);  // this cell is in endcap!
01228   }
01229   else if (towerId.ietaAbs() == 17) {
01230     // endcap, one depth only
01231    frontCellId = HcalDetId(HcalEndcap, iEta, iPhi, 1);
01232    backCellId  = HcalDetId(HcalEndcap, iEta, iPhi, 1);
01233   }
01234   else if (towerId.ietaAbs() >= 18 && towerId.ietaAbs() <= 26) {
01235   // endcap: two depths
01236   frontCellId = HcalDetId(HcalEndcap, iEta, iPhi, 1);
01237   backCellId  = HcalDetId(HcalEndcap, iEta, iPhi, 2);
01238   }
01239   else if (towerId.ietaAbs() <= 29) {
01240   // endcap: three depths
01241   frontCellId = HcalDetId(HcalEndcap, iEta, iPhi, 1);
01242   // there is no iEta=29 for depth 3
01243   if (iEta ==  29) iEta =  28;
01244   if (iEta == -29) iEta = -28;
01245   backCellId  = HcalDetId(HcalEndcap, iEta, iPhi, 3);
01246   }
01247   else if (towerId.ietaAbs() >= 30) {
01248   // forward, take the goemetry for long fibers
01249   frontCellId = HcalDetId(HcalForward, iEta, iPhi, 1);
01250   backCellId  = HcalDetId(HcalForward, iEta, iPhi, 1);
01251   }
01252   else {
01253     // should not get here
01254     return point;
01255   }
01256 
01257   point = hadShwPosFromCells(DetId(frontCellId), DetId(backCellId), fracDepth);
01258 
01259   return point;
01260 }
01261 
01262 GlobalPoint CaloTowersCreationAlgo::hadShwPosFromCells(DetId frontCellId, DetId backCellId, float fracDepth) {
01263 
01264    // uses the "front" and "back" cells
01265    // to determine the axis. point set by the predefined depth.
01266 
01267     const CaloCellGeometry* frontCellGeometry = theGeometry->getGeometry(DetId(frontCellId));
01268     const CaloCellGeometry* backCellGeometry  = theGeometry->getGeometry(DetId(backCellId));
01269 
01270     GlobalPoint point = frontCellGeometry->getPosition();
01271 
01272     CaloCellGeometry::CornersVec cv = backCellGeometry->getCorners();
01273 
01274     GlobalPoint backPoint = GlobalPoint(0.25 * (cv[4].x() + cv[5].x() + cv[6].x() + cv[7].x()),
01275       0.25 * (cv[4].y() + cv[5].y() + cv[6].y() + cv[7].y()),
01276       0.25 * (cv[4].z() + cv[5].z() + cv[6].z() + cv[7].z()));
01277 
01278     point += fracDepth * (backPoint - point);
01279 
01280     return point;
01281 }
01282 
01283 
01284 GlobalPoint CaloTowersCreationAlgo::emShwrPos(const std::vector<std::pair<DetId,double> >& metaContains, 
01285                                               float fracDepth, double emE) {
01286 
01287   if (emE<=0) return GlobalPoint(0,0,0);
01288 
01289   double emX = 0.0;
01290   double emY = 0.0;
01291   double emZ = 0.0;
01292 
01293   double eSum = 0;
01294 
01295   std::vector<std::pair<DetId,double> >::const_iterator mc_it = metaContains.begin();
01296   for (; mc_it!=metaContains.end(); ++mc_it) {
01297     if (mc_it->first.det() != DetId::Ecal) continue;
01298     GlobalPoint p = emCrystalShwrPos(mc_it->first, fracDepth);
01299     double e = mc_it->second;
01300 
01301     if (e>0) {
01302       emX += p.x() * e;
01303       emY += p.y() * e;
01304       emZ += p.z() * e;
01305       eSum += e;
01306     }
01307 
01308   }
01309 
01310    return GlobalPoint(emX/eSum, emY/eSum, emZ/eSum);
01311 }
01312 
01313 
01314 GlobalPoint CaloTowersCreationAlgo::emShwrLogWeightPos(const std::vector<std::pair<DetId,double> >& metaContains, 
01315                                float fracDepth, double emE) {
01316 
01317   double emX = 0.0;
01318   double emY = 0.0;
01319   double emZ = 0.0;
01320 
01321   double weight = 0;
01322   double sumWeights = 0;
01323   double sumEmE = 0;  // add crystals with E/E_EM > 1.5%
01324   double crystalThresh = 0.015 * emE;
01325 
01326   std::vector<std::pair<DetId,double> >::const_iterator mc_it = metaContains.begin();
01327   for (; mc_it!=metaContains.end(); ++mc_it) {
01328     if (mc_it->second < 0) continue;
01329     if (mc_it->first.det() == DetId::Ecal && mc_it->second > crystalThresh) sumEmE += mc_it->second;
01330   }
01331 
01332   for (mc_it = metaContains.begin(); mc_it!=metaContains.end(); ++mc_it) {
01333     
01334     if (mc_it->first.det() != DetId::Ecal || mc_it->second < crystalThresh) continue;
01335     
01336     GlobalPoint p = emCrystalShwrPos(mc_it->first, fracDepth);
01337 
01338     weight = 4.2 + log(mc_it->second/sumEmE);
01339     sumWeights += weight;
01340       
01341     emX += p.x() * weight;
01342     emY += p.y() * weight;
01343     emZ += p.z() * weight;
01344   }
01345 
01346    return GlobalPoint(emX/sumWeights, emY/sumWeights, emZ/sumWeights);
01347 }
01348 
01349 
01350 
01351 
01352 
01353 int CaloTowersCreationAlgo::compactTime(float time) {
01354 
01355   const float timeUnit = 0.01; // discretization (ns)
01356 
01357   if (time>  300.0) return  30000;
01358   if (time< -300.0) return -30000;
01359 
01360   return int(time/timeUnit + 0.5);
01361 
01362 }
01363 
01364 
01365 
01366 //========================================================
01367 //
01368 // Bad/anomolous cell handling 
01369 
01370 
01371 
01372 
01373 void CaloTowersCreationAlgo::makeHcalDropChMap() {
01374 
01375   // This method fills the map of number of dead channels for the calotower,
01376   // The key of the map is CaloTowerDetId.
01377   // By definition these channels are not going to be in the RecHit collections.
01378   hcalDropChMap.clear();
01379   std::vector<DetId> allChanInStatusCont = theHcalChStatus->getAllChannels();
01380 
01381   for (std::vector<DetId>::iterator it = allChanInStatusCont.begin(); it!=allChanInStatusCont.end(); ++it) {
01382 
01383      const uint32_t dbStatusFlag = theHcalChStatus->getValues(*it)->getValue();
01384 
01385     if (theHcalSevLvlComputer->dropChannel(dbStatusFlag)) {
01386 
01387       CaloTowerDetId twrId = theTowerConstituentsMap->towerOf(*it);
01388       
01389       hcalDropChMap[twrId] +=1;
01390       
01391       // special case for tower 29: if HCAL hit is in depth 3 add to twr 29 as well
01392       if (HcalDetId(*it).subdet()==HcalEndcap &&
01393           HcalDetId(*it).depth()==3 &&
01394           HcalDetId(*it).ietaAbs()==28) {
01395         
01396         CaloTowerDetId twrId29(twrId.ieta()+twrId.zside(), twrId.iphi());
01397         hcalDropChMap[twrId29] +=1;
01398       }
01399 
01400     }
01401 
01402   }
01403 
01404   return;
01405 }
01406 
01407 
01408 
01410 
01411 unsigned int CaloTowersCreationAlgo::hcalChanStatusForCaloTower(const CaloRecHit* hit) {
01412 
01413   const DetId id = hit->detid();
01414 
01415   const uint32_t recHitFlag = hit->flags();
01416   const uint32_t dbStatusFlag = theHcalChStatus->getValues(id)->getValue();
01417   
01418   int severityLevel = theHcalSevLvlComputer->getSeverityLevel(id, recHitFlag, dbStatusFlag); 
01419   bool isRecovered  = theHcalSevLvlComputer->recoveredRecHit(id, recHitFlag);
01420 
01421 
01422   // For use with hits rejected in the default reconstruction
01423   if (useRejectedHitsOnly) {
01424     
01425     if (!isRecovered) {
01426       if (severityLevel <= int(theHcalAcceptSeverityLevel) ||
01427           severityLevel > int(theHcalAcceptSeverityLevelForRejectedHit)) return CaloTowersCreationAlgo::IgnoredChan;
01428       // this hit was either already accepted or is worse than 
01429     }    
01430     else {
01431       
01432       if (theRecoveredHcalHitsAreUsed || !useRejectedRecoveredHcalHits) {
01433         // skip recovered hits either because they were already used or because there was an explicit instruction
01434         return CaloTowersCreationAlgo::IgnoredChan;
01435       }
01436       else if (useRejectedRecoveredHcalHits) {
01437         return CaloTowersCreationAlgo::RecoveredChan;
01438       }  
01439   
01440     }  // recovered channels
01441 
01442     // clasify channels as problematic: no good hits are supposed to be present in the
01443     // extra rechit collections
01444     return CaloTowersCreationAlgo::ProblematicChan;
01445 
01446   }  // treatment of rejected hits
01447 
01448 
01449 
01450 
01451   // this is for the regular reconstruction sequence
01452 
01453   if (severityLevel == 0) return CaloTowersCreationAlgo::GoodChan;
01454 
01455   if (isRecovered) {
01456     return (theRecoveredHcalHitsAreUsed) ? 
01457       CaloTowersCreationAlgo::RecoveredChan : CaloTowersCreationAlgo::BadChan;
01458   }
01459   else {
01460     if (severityLevel > int(theHcalAcceptSeverityLevel)) {
01461       return CaloTowersCreationAlgo::BadChan;
01462     }
01463     else {
01464       return CaloTowersCreationAlgo::ProblematicChan;
01465     }
01466   }  
01467 
01468 }
01469 
01470 
01471 
01472 unsigned int CaloTowersCreationAlgo::ecalChanStatusForCaloTower(const CaloRecHit* hit) {
01473 
01474   // const DetId id = hit->detid();
01475 
01476   //  uint16_t dbStatus = theEcalChStatus->find(id)->getStatusCode();
01477   //  uint32_t rhFlags  = hit->flags();
01478   //  int severityLevel = theEcalSevLvlAlgo->severityLevel(rhFlags, dbStatus);
01479   // The methods above will become private and cannot be usef for flagging ecal spikes.
01480   // Use the recommended interface - we leave the parameters for spilke removal to be specified by ECAL.
01481 
01482 
01483   //  int severityLevel = 999;
01484 
01485   EcalRecHit const & rh = *reinterpret_cast<EcalRecHit const *>(hit);
01486   int severityLevel = theEcalSevLvlAlgo->severityLevel(rh);
01487 
01488 //  if      (id.subdetId() == EcalBarrel) severityLevel = theEcalSevLvlAlgo->severityLevel( id, *theEbHandle);//, *theEcalChStatus);
01489 //  else if (id.subdetId() == EcalEndcap) severityLevel = theEcalSevLvlAlgo->severityLevel( id, *theEeHandle);//, *theEcalChStatus);
01490 
01491   // there should be no other ECAL types used in this reconstruction
01492 
01493   // The definition of ECAL severity levels uses categories that
01494   // are similar to the defined for CaloTower. (However, the categorization
01495   // for CaloTowers depends on the specified maximum acceptabel severity and therefore cannnot
01496   // be exact correspondence between the two. ECAL has additional categories describing modes of failure.)
01497   // This approach is different from the initial idea and from
01498   // the implementation for HCAL. Still make the logic similar to HCAL so that one has the ability to 
01499   // exclude problematic channels as defined by ECAL.
01500   // For definitions of ECAL severity levels see RecoLocalCalo/EcalRecAlgos/interface/EcalSeverityLevelAlgo.h
01501 
01502 
01503   bool isRecovered = (severityLevel == EcalSeverityLevelAlgo::kRecovered);
01504 
01505 
01506   // for use with rejected by the regular reconstruction hits
01507   if (useRejectedHitsOnly) {
01508     
01509     if (!isRecovered) {
01510       if (severityLevel <= int(theEcalAcceptSeverityLevel) ||
01511           severityLevel > int(theEcalAcceptSeverityLevelForRejectedHit)) return CaloTowersCreationAlgo::IgnoredChan;
01512       // this hit was either accepted already, or counted as bad under the conditions
01513     }    
01514     else {
01515       
01516       if (theRecoveredEcalHitsAreUsed || !useRejectedRecoveredEcalHits) {
01517         // skip recovered hits either because they were already used or because there was an explicit instruction
01518         return CaloTowersCreationAlgo::IgnoredChan;
01519       }
01520       else if (useRejectedRecoveredEcalHits) {
01521         return CaloTowersCreationAlgo::RecoveredChan;
01522       }  
01523   
01524     }  // recovered channels
01525 
01526     // clasify channels as problematic
01527     return CaloTowersCreationAlgo::ProblematicChan;
01528 
01529   }  // treatment of rejected hits
01530 
01531 
01532 
01533 
01534 
01535   // for normal reconstruction
01536   if (severityLevel == EcalSeverityLevelAlgo::kGood) return CaloTowersCreationAlgo::GoodChan;
01537 
01538   if (isRecovered) {
01539     return (theRecoveredEcalHitsAreUsed) ? 
01540       CaloTowersCreationAlgo::RecoveredChan : CaloTowersCreationAlgo::BadChan;
01541   }  
01542   else {
01543     if (severityLevel > int(theEcalAcceptSeverityLevel)) {
01544       return CaloTowersCreationAlgo::BadChan;
01545     }
01546     else {
01547       return CaloTowersCreationAlgo::ProblematicChan;
01548     }
01549   }
01550 
01551 
01552 }
01553