CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/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       // check if the Ecal severity is ok to keep
00938       std::vector<int>::const_iterator sevit = std::find(theEcalSeveritiesToBeExcluded.begin(),
00939                                                          theEcalSeveritiesToBeExcluded.end(),
00940                                                          thisEcalSevLvl);
00941       if (sevit!=theEcalSeveritiesToBeExcluded.end()) {
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 
00989 void CaloTowersCreationAlgo::getThresholdAndWeight(const DetId & detId, double & threshold, double & weight) const {
00990   DetId::Detector det = detId.det();
00991   weight=0; // in case the hit is not identified
00992 
00993   if(det == DetId::Ecal) {
00994     // may or may not be EB.  We'll find out.
00995 
00996     EcalSubdetector subdet = (EcalSubdetector)(detId.subdetId());
00997     if(subdet == EcalBarrel) {
00998       threshold = theEBthreshold;
00999       weight = theEBweight;
01000       if (weight <= 0.) {
01001         ROOT::Math::Interpolator my(theEBGrid,theEBWeights,ROOT::Math::Interpolation::kAKIMA);
01002         weight = my.Eval(theEBEScale);
01003       }
01004     }
01005     else if(subdet == EcalEndcap) {
01006       threshold = theEEthreshold;
01007       weight = theEEweight;
01008       if (weight <= 0.) {
01009         ROOT::Math::Interpolator my(theEEGrid,theEEWeights,ROOT::Math::Interpolation::kAKIMA);
01010         weight = my.Eval(theEEEScale);
01011       }
01012     }
01013   }
01014   else if(det == DetId::Hcal) {
01015     HcalDetId hcalDetId(detId);
01016     HcalSubdetector subdet = hcalDetId.subdet();
01017     
01018     if(subdet == HcalBarrel) {
01019       threshold = theHBthreshold;
01020       weight = theHBweight;
01021       if (weight <= 0.) {
01022         ROOT::Math::Interpolator my(theHBGrid,theHBWeights,ROOT::Math::Interpolation::kAKIMA);
01023         weight = my.Eval(theHBEScale);
01024       }
01025     }
01026     
01027     else if(subdet == HcalEndcap) {
01028       // check if it's single or double tower
01029       if(hcalDetId.ietaAbs() < theHcalTopology->firstHEDoublePhiRing()) {
01030         threshold = theHESthreshold;
01031         weight = theHESweight;
01032         if (weight <= 0.) {
01033           ROOT::Math::Interpolator my(theHESGrid,theHESWeights,ROOT::Math::Interpolation::kAKIMA);
01034           weight = my.Eval(theHESEScale);
01035         }
01036       }
01037       else {
01038         threshold = theHEDthreshold;
01039         weight = theHEDweight;
01040         if (weight <= 0.) {
01041           ROOT::Math::Interpolator my(theHEDGrid,theHEDWeights,ROOT::Math::Interpolation::kAKIMA);
01042           weight = my.Eval(theHEDEScale);
01043         }
01044       }
01045     }
01046     
01047     else if(subdet == HcalOuter) {
01048       //check if it's ring 0 or +1 or +2 or -1 or -2
01049       if(hcalDetId.ietaAbs() <= 4) threshold = theHOthreshold0;
01050       else if(hcalDetId.ieta() < 0) {
01051         // set threshold for ring -1 or -2
01052         threshold = (hcalDetId.ietaAbs() <= 10) ?  theHOthresholdMinus1 : theHOthresholdMinus2;
01053       } else {
01054         // set threshold for ring +1 or +2
01055         threshold = (hcalDetId.ietaAbs() <= 10) ?  theHOthresholdPlus1 : theHOthresholdPlus2;
01056       }
01057       weight = theHOweight;
01058       if (weight <= 0.) {
01059         ROOT::Math::Interpolator my(theHOGrid,theHOWeights,ROOT::Math::Interpolation::kAKIMA);
01060         weight = my.Eval(theHOEScale);
01061       }
01062     } 
01063 
01064     else if(subdet == HcalForward) {
01065       if(hcalDetId.depth() == 1) {
01066         threshold = theHF1threshold;
01067         weight = theHF1weight;
01068         if (weight <= 0.) {
01069           ROOT::Math::Interpolator my(theHF1Grid,theHF1Weights,ROOT::Math::Interpolation::kAKIMA);
01070           weight = my.Eval(theHF1EScale);
01071         }
01072       } else {
01073         threshold = theHF2threshold;
01074         weight = theHF2weight;
01075         if (weight <= 0.) {
01076           ROOT::Math::Interpolator my(theHF2Grid,theHF2Weights,ROOT::Math::Interpolation::kAKIMA);
01077           weight = my.Eval(theHF2EScale);
01078         }
01079       }
01080     }
01081   }
01082   else {
01083     edm::LogError("CaloTowersCreationAlgo") << "Bad cell: " << det << std::endl;
01084   }
01085 }
01086 
01087 void CaloTowersCreationAlgo::setEBEScale(double scale){
01088   if (scale>0.00001) *&theEBEScale = scale;
01089   else *&theEBEScale = 50.;
01090 }
01091 
01092 void CaloTowersCreationAlgo::setEEEScale(double scale){
01093   if (scale>0.00001) *&theEEEScale = scale;
01094   else *&theEEEScale = 50.;
01095 }
01096 
01097 void CaloTowersCreationAlgo::setHBEScale(double scale){
01098   if (scale>0.00001) *&theHBEScale = scale;
01099   else *&theHBEScale = 50.;
01100 }
01101 
01102 void CaloTowersCreationAlgo::setHESEScale(double scale){
01103   if (scale>0.00001) *&theHESEScale = scale;
01104   else *&theHESEScale = 50.;
01105 }
01106 
01107 void CaloTowersCreationAlgo::setHEDEScale(double scale){
01108   if (scale>0.00001) *&theHEDEScale = scale;
01109   else *&theHEDEScale = 50.;
01110 }
01111 
01112 void CaloTowersCreationAlgo::setHOEScale(double scale){
01113   if (scale>0.00001) *&theHOEScale = scale;
01114   else *&theHOEScale = 50.;
01115 }
01116 
01117 void CaloTowersCreationAlgo::setHF1EScale(double scale){
01118   if (scale>0.00001) *&theHF1EScale = scale;
01119   else *&theHF1EScale = 50.;
01120 }
01121 
01122 void CaloTowersCreationAlgo::setHF2EScale(double scale){
01123   if (scale>0.00001) *&theHF2EScale = scale;
01124   else *&theHF2EScale = 50.;
01125 }
01126 
01127 
01128 GlobalPoint CaloTowersCreationAlgo::emCrystalShwrPos(DetId detId, float fracDepth) {
01129    const CaloCellGeometry* cellGeometry = theGeometry->getGeometry(detId);
01130    GlobalPoint point = cellGeometry->getPosition();  // face of the cell
01131 
01132    if      (fracDepth<0) fracDepth=0;
01133    else if (fracDepth>1) fracDepth=1;
01134 
01135    if (fracDepth>0.0) {
01136      CaloCellGeometry::CornersVec cv = cellGeometry->getCorners();
01137      GlobalPoint backPoint = GlobalPoint( 0.25*( cv[4].x() + cv[5].x() + cv[6].x() + cv[7].x() ),
01138                                           0.25*( cv[4].y() + cv[5].y() + cv[6].y() + cv[7].y() ),
01139                                           0.25*( cv[4].z() + cv[5].z() + cv[6].z() + cv[7].z() ) );
01140      point += fracDepth * (backPoint-point);
01141    }
01142 
01143    return point;
01144 }
01145 
01146 GlobalPoint CaloTowersCreationAlgo::hadSegmentShwrPos(DetId detId, float fracDepth) {
01147    const CaloCellGeometry* cellGeometry = theGeometry->getGeometry(detId);
01148    GlobalPoint point = cellGeometry->getPosition();  // face of the cell
01149 
01150    if      (fracDepth<0) fracDepth=0;
01151    else if (fracDepth>1) fracDepth=1;
01152 
01153    if (fracDepth>0.0) {
01154      CaloCellGeometry::CornersVec cv = cellGeometry->getCorners();
01155      GlobalPoint backPoint = GlobalPoint( 0.25*( cv[4].x() + cv[5].x() + cv[6].x() + cv[7].x() ),
01156                                           0.25*( cv[4].y() + cv[5].y() + cv[6].y() + cv[7].y() ),
01157                                           0.25*( cv[4].z() + cv[5].z() + cv[6].z() + cv[7].z() ) );
01158      point += fracDepth * (backPoint-point);
01159    }
01160 
01161    return point;
01162 }
01163 
01164 
01165 GlobalPoint CaloTowersCreationAlgo::hadShwrPos(const std::vector<std::pair<DetId,double> >& metaContains,
01166                                                float fracDepth, double hadE) {
01167                                                   
01168   // this is based on available RecHits, can lead to different actual depths if
01169   // hits in multi-depth towers are not all there
01170   if (hadE<=0) return GlobalPoint(0,0,0);
01171 
01172   double hadX = 0.0;
01173   double hadY = 0.0;
01174   double hadZ = 0.0;
01175 
01176   int nConst = 0;
01177 
01178   std::vector<std::pair<DetId,double> >::const_iterator mc_it = metaContains.begin();
01179   for (; mc_it!=metaContains.end(); ++mc_it) {
01180     if (mc_it->first.det() != DetId::Hcal) continue;
01181     // do not use HO for deirection calculations for now
01182     if (HcalDetId(mc_it->first).subdet() == HcalOuter) continue;
01183     ++nConst;
01184 
01185     GlobalPoint p = hadSegmentShwrPos(mc_it->first, fracDepth);
01186 
01187     // longitudinal segmentation: do not weight by energy,
01188     // get the geometrical position
01189     hadX += p.x();
01190     hadY += p.y();
01191     hadZ += p.z();
01192   }
01193 
01194    return GlobalPoint(hadX/nConst, hadY/nConst, hadZ/nConst);
01195 }
01196 
01197 
01198 GlobalPoint CaloTowersCreationAlgo::hadShwrPos(CaloTowerDetId towerId, float fracDepth) {
01199 
01200   // set depth using geometry of cells that are associated with the
01201   // tower (regardless if they have non-zero energies)
01202 
01203 //  if (hadE <= 0) return GlobalPoint(0, 0, 0);
01204 
01205   if (fracDepth < 0) fracDepth = 0;
01206   else if (fracDepth > 1) fracDepth = 1;
01207 
01208   GlobalPoint point(0,0,0);
01209 
01210   int iEta = towerId.ieta();
01211   int iPhi = towerId.iphi();
01212 
01213   HcalDetId frontCellId, backCellId;
01214 
01215   if (towerId.ietaAbs() <= 14) {
01216     // barrel, one depth only
01217     frontCellId = HcalDetId(HcalBarrel, iEta, iPhi, 1);
01218     backCellId  = HcalDetId(HcalBarrel, iEta, iPhi, 1);
01219   }
01220   else if (towerId.ietaAbs() == 15) {
01221     // barrel, two depths
01222     frontCellId = HcalDetId(HcalBarrel, iEta, iPhi, 1);
01223     backCellId  = HcalDetId(HcalBarrel, iEta, iPhi, 2);
01224   }
01225   else if (towerId.ietaAbs() == 16) {
01226     // barrel and endcap: two depths HB, one depth HE 
01227     frontCellId = HcalDetId(HcalBarrel, iEta, iPhi, 1);
01228     backCellId  = HcalDetId(HcalEndcap, iEta, iPhi, 3);  // this cell is in endcap!
01229   }
01230   else if (towerId.ietaAbs() == 17) {
01231     // endcap, one depth only
01232    frontCellId = HcalDetId(HcalEndcap, iEta, iPhi, 1);
01233    backCellId  = HcalDetId(HcalEndcap, iEta, iPhi, 1);
01234   }
01235   else if (towerId.ietaAbs() >= 18 && towerId.ietaAbs() <= 26) {
01236   // endcap: two depths
01237   frontCellId = HcalDetId(HcalEndcap, iEta, iPhi, 1);
01238   backCellId  = HcalDetId(HcalEndcap, iEta, iPhi, 2);
01239   }
01240   else if (towerId.ietaAbs() <= 29) {
01241   // endcap: three depths
01242   frontCellId = HcalDetId(HcalEndcap, iEta, iPhi, 1);
01243   // there is no iEta=29 for depth 3
01244   if (iEta ==  29) iEta =  28;
01245   if (iEta == -29) iEta = -28;
01246   backCellId  = HcalDetId(HcalEndcap, iEta, iPhi, 3);
01247   }
01248   else if (towerId.ietaAbs() >= 30) {
01249   // forward, take the goemetry for long fibers
01250   frontCellId = HcalDetId(HcalForward, iEta, iPhi, 1);
01251   backCellId  = HcalDetId(HcalForward, iEta, iPhi, 1);
01252   }
01253   else {
01254     // should not get here
01255     return point;
01256   }
01257 
01258   point = hadShwPosFromCells(DetId(frontCellId), DetId(backCellId), fracDepth);
01259 
01260   return point;
01261 }
01262 
01263 GlobalPoint CaloTowersCreationAlgo::hadShwPosFromCells(DetId frontCellId, DetId backCellId, float fracDepth) {
01264 
01265    // uses the "front" and "back" cells
01266    // to determine the axis. point set by the predefined depth.
01267 
01268     const CaloCellGeometry* frontCellGeometry = theGeometry->getGeometry(DetId(frontCellId));
01269     const CaloCellGeometry* backCellGeometry  = theGeometry->getGeometry(DetId(backCellId));
01270 
01271     GlobalPoint point = frontCellGeometry->getPosition();
01272 
01273     CaloCellGeometry::CornersVec cv = backCellGeometry->getCorners();
01274 
01275     GlobalPoint backPoint = GlobalPoint(0.25 * (cv[4].x() + cv[5].x() + cv[6].x() + cv[7].x()),
01276       0.25 * (cv[4].y() + cv[5].y() + cv[6].y() + cv[7].y()),
01277       0.25 * (cv[4].z() + cv[5].z() + cv[6].z() + cv[7].z()));
01278 
01279     point += fracDepth * (backPoint - point);
01280 
01281     return point;
01282 }
01283 
01284 
01285 GlobalPoint CaloTowersCreationAlgo::emShwrPos(const std::vector<std::pair<DetId,double> >& metaContains, 
01286                                               float fracDepth, double emE) {
01287 
01288   if (emE<=0) return GlobalPoint(0,0,0);
01289 
01290   double emX = 0.0;
01291   double emY = 0.0;
01292   double emZ = 0.0;
01293 
01294   double eSum = 0;
01295 
01296   std::vector<std::pair<DetId,double> >::const_iterator mc_it = metaContains.begin();
01297   for (; mc_it!=metaContains.end(); ++mc_it) {
01298     if (mc_it->first.det() != DetId::Ecal) continue;
01299     GlobalPoint p = emCrystalShwrPos(mc_it->first, fracDepth);
01300     double e = mc_it->second;
01301 
01302     if (e>0) {
01303       emX += p.x() * e;
01304       emY += p.y() * e;
01305       emZ += p.z() * e;
01306       eSum += e;
01307     }
01308 
01309   }
01310 
01311    return GlobalPoint(emX/eSum, emY/eSum, emZ/eSum);
01312 }
01313 
01314 
01315 GlobalPoint CaloTowersCreationAlgo::emShwrLogWeightPos(const std::vector<std::pair<DetId,double> >& metaContains, 
01316                                float fracDepth, double emE) {
01317 
01318   double emX = 0.0;
01319   double emY = 0.0;
01320   double emZ = 0.0;
01321 
01322   double weight = 0;
01323   double sumWeights = 0;
01324   double sumEmE = 0;  // add crystals with E/E_EM > 1.5%
01325   double crystalThresh = 0.015 * emE;
01326 
01327   std::vector<std::pair<DetId,double> >::const_iterator mc_it = metaContains.begin();
01328   for (; mc_it!=metaContains.end(); ++mc_it) {
01329     if (mc_it->second < 0) continue;
01330     if (mc_it->first.det() == DetId::Ecal && mc_it->second > crystalThresh) sumEmE += mc_it->second;
01331   }
01332 
01333   for (mc_it = metaContains.begin(); mc_it!=metaContains.end(); ++mc_it) {
01334     
01335     if (mc_it->first.det() != DetId::Ecal || mc_it->second < crystalThresh) continue;
01336     
01337     GlobalPoint p = emCrystalShwrPos(mc_it->first, fracDepth);
01338 
01339     weight = 4.2 + log(mc_it->second/sumEmE);
01340     sumWeights += weight;
01341       
01342     emX += p.x() * weight;
01343     emY += p.y() * weight;
01344     emZ += p.z() * weight;
01345   }
01346 
01347    return GlobalPoint(emX/sumWeights, emY/sumWeights, emZ/sumWeights);
01348 }
01349 
01350 
01351 
01352 
01353 
01354 int CaloTowersCreationAlgo::compactTime(float time) {
01355 
01356   const float timeUnit = 0.01; // discretization (ns)
01357 
01358   if (time>  300.0) return  30000;
01359   if (time< -300.0) return -30000;
01360 
01361   return int(time/timeUnit + 0.5);
01362 
01363 }
01364 
01365 
01366 
01367 //========================================================
01368 //
01369 // Bad/anomolous cell handling 
01370 
01371 
01372 
01373 
01374 void CaloTowersCreationAlgo::makeHcalDropChMap() {
01375 
01376   // This method fills the map of number of dead channels for the calotower,
01377   // The key of the map is CaloTowerDetId.
01378   // By definition these channels are not going to be in the RecHit collections.
01379   hcalDropChMap.clear();
01380   std::vector<DetId> allChanInStatusCont = theHcalChStatus->getAllChannels();
01381 
01382   for (std::vector<DetId>::iterator it = allChanInStatusCont.begin(); it!=allChanInStatusCont.end(); ++it) {
01383 
01384      const uint32_t dbStatusFlag = theHcalChStatus->getValues(*it)->getValue();
01385 
01386     if (theHcalSevLvlComputer->dropChannel(dbStatusFlag)) {
01387 
01388       CaloTowerDetId twrId = theTowerConstituentsMap->towerOf(*it);
01389       
01390       hcalDropChMap[twrId] +=1;
01391       
01392       // special case for tower 29: if HCAL hit is in depth 3 add to twr 29 as well
01393       if (HcalDetId(*it).subdet()==HcalEndcap &&
01394           HcalDetId(*it).depth()==3 &&
01395           HcalDetId(*it).ietaAbs()==28) {
01396         
01397         CaloTowerDetId twrId29(twrId.ieta()+twrId.zside(), twrId.iphi());
01398         hcalDropChMap[twrId29] +=1;
01399       }
01400 
01401     }
01402 
01403   }
01404 
01405   return;
01406 }
01407 
01408 
01409 
01411 
01412 unsigned int CaloTowersCreationAlgo::hcalChanStatusForCaloTower(const CaloRecHit* hit) {
01413 
01414   const DetId id = hit->detid();
01415 
01416   const uint32_t recHitFlag = hit->flags();
01417   const uint32_t dbStatusFlag = theHcalChStatus->getValues(id)->getValue();
01418   
01419   int severityLevel = theHcalSevLvlComputer->getSeverityLevel(id, recHitFlag, dbStatusFlag); 
01420   bool isRecovered  = theHcalSevLvlComputer->recoveredRecHit(id, recHitFlag);
01421 
01422 
01423   // For use with hits rejected in the default reconstruction
01424   if (useRejectedHitsOnly) {
01425     
01426     if (!isRecovered) {
01427 
01428       if (severityLevel <= int(theHcalAcceptSeverityLevel) ||
01429           severityLevel > int(theHcalAcceptSeverityLevelForRejectedHit)) return CaloTowersCreationAlgo::IgnoredChan;
01430       // this hit was either already accepted or is worse than 
01431     }    
01432     else {
01433       
01434       if (theRecoveredHcalHitsAreUsed || !useRejectedRecoveredHcalHits) {
01435         // skip recovered hits either because they were already used or because there was an explicit instruction
01436         return CaloTowersCreationAlgo::IgnoredChan;
01437       }
01438       else if (useRejectedRecoveredHcalHits) {
01439         return CaloTowersCreationAlgo::RecoveredChan;
01440       }  
01441   
01442     }  // recovered channels
01443 
01444     // clasify channels as problematic: no good hits are supposed to be present in the
01445     // extra rechit collections
01446     return CaloTowersCreationAlgo::ProblematicChan;
01447 
01448   }  // treatment of rejected hits
01449 
01450 
01451 
01452 
01453   // this is for the regular reconstruction sequence
01454 
01455   if (severityLevel == 0) return CaloTowersCreationAlgo::GoodChan;
01456 
01457   if (isRecovered) {
01458     return (theRecoveredHcalHitsAreUsed) ? 
01459       CaloTowersCreationAlgo::RecoveredChan : CaloTowersCreationAlgo::BadChan;
01460   }
01461   else {
01462     if (severityLevel > int(theHcalAcceptSeverityLevel)) {
01463       return CaloTowersCreationAlgo::BadChan;
01464     }
01465     else {
01466       return CaloTowersCreationAlgo::ProblematicChan;
01467     }
01468   }  
01469 
01470 }
01471 
01472 
01473 
01474 unsigned int CaloTowersCreationAlgo::ecalChanStatusForCaloTower(const CaloRecHit* hit) {
01475 
01476   // const DetId id = hit->detid();
01477 
01478   //  uint16_t dbStatus = theEcalChStatus->find(id)->getStatusCode();
01479   //  uint32_t rhFlags  = hit->flags();
01480   //  int severityLevel = theEcalSevLvlAlgo->severityLevel(rhFlags, dbStatus);
01481   // The methods above will become private and cannot be usef for flagging ecal spikes.
01482   // Use the recommended interface - we leave the parameters for spilke removal to be specified by ECAL.
01483 
01484 
01485   //  int severityLevel = 999;
01486 
01487   EcalRecHit const & rh = *reinterpret_cast<EcalRecHit const *>(hit);
01488   int severityLevel = theEcalSevLvlAlgo->severityLevel(rh);
01489 
01490 //  if      (id.subdetId() == EcalBarrel) severityLevel = theEcalSevLvlAlgo->severityLevel( id, *theEbHandle);//, *theEcalChStatus);
01491 //  else if (id.subdetId() == EcalEndcap) severityLevel = theEcalSevLvlAlgo->severityLevel( id, *theEeHandle);//, *theEcalChStatus);
01492 
01493   // there should be no other ECAL types used in this reconstruction
01494 
01495   // The definition of ECAL severity levels uses categories that
01496   // are similar to the defined for CaloTower. (However, the categorization
01497   // for CaloTowers depends on the specified maximum acceptabel severity and therefore cannnot
01498   // be exact correspondence between the two. ECAL has additional categories describing modes of failure.)
01499   // This approach is different from the initial idea and from
01500   // the implementation for HCAL. Still make the logic similar to HCAL so that one has the ability to 
01501   // exclude problematic channels as defined by ECAL.
01502   // For definitions of ECAL severity levels see RecoLocalCalo/EcalRecAlgos/interface/EcalSeverityLevelAlgo.h
01503 
01504 
01505   bool isRecovered = (severityLevel == EcalSeverityLevel::kRecovered);
01506 
01507   // check if the severity is compatible with our configuration
01508   // This applies to the "default" tower cleaning
01509   std::vector<int>::const_iterator sevit = std::find(theEcalSeveritiesToBeExcluded.begin(),
01510                                                      theEcalSeveritiesToBeExcluded.end(),
01511                                                      severityLevel);
01512   bool accepted = (sevit==theEcalSeveritiesToBeExcluded.end()) ;
01513 
01514   // For use with hits that were rejected in the regular reconstruction:
01515   // This is for creating calotowers with lower level of cleaning by merging
01516   // the information from the default towers and a collection of towers created from
01517   // bad rechits 
01518  
01519 
01520   if (useRejectedHitsOnly) {
01521     
01522     if (!isRecovered) {
01523 
01524       if (accepted  ||
01525           std::find(theEcalSeveritiesToBeUsedInBadTowers.begin(), theEcalSeveritiesToBeUsedInBadTowers.end(), severityLevel)
01526           == theEcalSeveritiesToBeUsedInBadTowers.end())
01527         return CaloTowersCreationAlgo::IgnoredChan;
01528       // this hit was either already accepted, or is not eligible for inclusion
01529     }    
01530     else {
01531       
01532       if (theRecoveredEcalHitsAreUsed || !useRejectedRecoveredEcalHits) {
01533         // skip recovered hits either because they were already used or because there was an explicit instruction
01534         return CaloTowersCreationAlgo::IgnoredChan;
01535       }
01536       else if (useRejectedRecoveredEcalHits) {
01537         return CaloTowersCreationAlgo::RecoveredChan;
01538       }  
01539   
01540     }  // recovered channels
01541 
01542     // clasify channels as problematic
01543     return CaloTowersCreationAlgo::ProblematicChan;
01544 
01545   }  // treatment of rejected hits
01546 
01547 
01548 
01549   // for normal reconstruction
01550   if (severityLevel == EcalSeverityLevel::kGood) return CaloTowersCreationAlgo::GoodChan;
01551 
01552   if (isRecovered) {
01553     return (theRecoveredEcalHitsAreUsed) ? 
01554       CaloTowersCreationAlgo::RecoveredChan : CaloTowersCreationAlgo::BadChan;
01555   }  
01556   else {
01557     if (!accepted) {
01558       return CaloTowersCreationAlgo::BadChan;
01559     }
01560     else {
01561       return CaloTowersCreationAlgo::ProblematicChan;
01562     }
01563   }
01564 
01565 
01566 }
01567