CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/TrackingTools/TrackAssociator/src/TrackDetectorAssociator.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    TrackAssociator
00004 // Class:      TrackDetectorAssociator
00005 // 
00006 /*
00007 
00008  Description: <one line class summary>
00009 
00010  Implementation:
00011      <Notes on implementation>
00012 */
00013 //
00014 // Original Author:  Dmytro Kovalskyi
00015 //         Created:  Fri Apr 21 10:59:41 PDT 2006
00016 // $Id: TrackDetectorAssociator.cc,v 1.51 2012/09/20 15:06:07 wdd Exp $
00017 //
00018 //
00019 
00020 #include "Geometry/Records/interface/CaloGeometryRecord.h"
00021 #include "TrackingTools/TrackAssociator/interface/TrackDetectorAssociator.h"
00022 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00023 
00024 // user include files
00025 #include "FWCore/Framework/interface/Frameworkfwd.h"
00026 
00027 #include "FWCore/Framework/interface/Event.h"
00028 #include "FWCore/Framework/interface/EventSetup.h"
00029 #include "FWCore/Framework/interface/MakerMacros.h"
00030 #include "DataFormats/Common/interface/Handle.h"
00031 #include "FWCore/Framework/interface/ESHandle.h"
00032 #include "DataFormats/Common/interface/OrphanHandle.h"
00033 
00034 #include "DataFormats/TrackReco/interface/Track.h"
00035 #include "DataFormats/TrackReco/interface/TrackExtra.h"
00036 #include "DataFormats/CaloTowers/interface/CaloTower.h"
00037 #include "DataFormats/CaloTowers/interface/CaloTowerCollection.h"
00038 #include "DataFormats/HcalRecHit/interface/HcalRecHitCollections.h"
00039 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
00040 #include "DataFormats/DTRecHit/interface/DTRecHitCollection.h"
00041 #include "DataFormats/EcalDetId/interface/EBDetId.h"
00042 #include "DataFormats/DetId/interface/DetId.h"
00043 
00044 // calorimeter info
00045 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
00046 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00047 #include "Geometry/CaloGeometry/interface/CaloCellGeometry.h"
00048 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00049 #include "DataFormats/HcalDetId/interface/HcalSubdetector.h"
00050 #include "DataFormats/EcalRecHit/interface/EcalRecHitCollections.h"
00051 
00052 #include "Geometry/DTGeometry/interface/DTLayer.h"
00053 #include "Geometry/DTGeometry/interface/DTGeometry.h"
00054 #include "Geometry/Records/interface/MuonGeometryRecord.h"
00055 
00056 #include "Geometry/CSCGeometry/interface/CSCGeometry.h"
00057 #include "Geometry/CSCGeometry/interface/CSCChamberSpecs.h"
00058 
00059 #include "DataFormats/GeometrySurface/interface/Cylinder.h"
00060 #include "DataFormats/GeometrySurface/interface/Plane.h"
00061 
00062 #include "Geometry/CommonDetUnit/interface/GeomDetUnit.h"
00063 
00064 
00065 #include "MagneticField/Engine/interface/MagneticField.h"
00066 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00067 
00068 #include "TrackPropagation/SteppingHelixPropagator/interface/SteppingHelixPropagator.h"
00069 #include "Utilities/Timing/interface/TimingReport.h"
00070 #include <stack>
00071 #include <set>
00072 
00073 #include "DataFormats/Math/interface/LorentzVector.h"
00074 #include "Math/VectorUtil.h"
00075 #include <algorithm>
00076 
00077 #include "TrackingTools/TrackAssociator/interface/DetIdAssociator.h"
00078 #include "TrackingTools/TrackAssociator/interface/DetIdInfo.h"
00079 // #include "TrackingTools/TrackAssociator/interface/CaloDetIdAssociator.h"
00080 // #include "TrackingTools/TrackAssociator/interface/EcalDetIdAssociator.h"
00081 // #include "TrackingTools/TrackAssociator/interface/PreshowerDetIdAssociator.h"
00082 // #include "Utilities/Timing/interface/TimerStack.h"
00083 
00084 #include "DataFormats/DTRecHit/interface/DTRecSegment4DCollection.h"
00085 #include "DataFormats/DTRecHit/interface/DTRecSegment2D.h"
00086 #include "DataFormats/CSCRecHit/interface/CSCSegmentCollection.h"
00087 #include "DataFormats/GeometryCommonDetAlgo/interface/ErrorFrameTransformer.h"
00088 
00089 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
00090 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
00091 #include "SimDataFormats/Track/interface/SimTrack.h"
00092 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
00093 #include "SimDataFormats/Vertex/interface/SimVertex.h"
00094 #include "SimDataFormats/Vertex/interface/SimVertexContainer.h"
00095 #include "SimDataFormats/CaloHit/interface/PCaloHit.h"
00096 #include "SimDataFormats/CaloHit/interface/PCaloHitContainer.h"
00097 
00098 #include "TrackingTools/Records/interface/DetIdAssociatorRecord.h"
00099 
00100 using namespace reco;
00101 
00102 TrackDetectorAssociator::TrackDetectorAssociator() 
00103 {
00104    ivProp_ = 0;
00105    defProp_ = 0;
00106    useDefaultPropagator_ = false;
00107 }
00108 
00109 TrackDetectorAssociator::~TrackDetectorAssociator()
00110 {
00111    if (defProp_) delete defProp_;
00112 }
00113 
00114 void TrackDetectorAssociator::setPropagator( const Propagator* ptr)
00115 {
00116    ivProp_ = ptr;
00117    cachedTrajectory_.setPropagator(ivProp_);
00118 }
00119 
00120 void TrackDetectorAssociator::useDefaultPropagator()
00121 {
00122    useDefaultPropagator_ = true;
00123 }
00124 
00125 
00126 void TrackDetectorAssociator::init( const edm::EventSetup& iSetup )
00127 {
00128    // access the calorimeter geometry
00129    iSetup.get<CaloGeometryRecord>().get(theCaloGeometry_);
00130    if (!theCaloGeometry_.isValid()) 
00131      throw cms::Exception("FatalError") << "Unable to find CaloGeometryRecord in event!\n";
00132    
00133    // get the tracking Geometry
00134    iSetup.get<GlobalTrackingGeometryRecord>().get(theTrackingGeometry_);
00135    if (!theTrackingGeometry_.isValid()) 
00136      throw cms::Exception("FatalError") << "Unable to find GlobalTrackingGeometryRecord in event!\n";
00137    
00138    if (useDefaultPropagator_ && (! defProp_ || theMagneticFeildWatcher_.check(iSetup) ) ) {
00139       // setup propagator
00140       edm::ESHandle<MagneticField> bField;
00141       iSetup.get<IdealMagneticFieldRecord>().get(bField);
00142       
00143       SteppingHelixPropagator* prop  = new SteppingHelixPropagator(&*bField,anyDirection);
00144       prop->setMaterialMode(false);
00145       prop->applyRadX0Correction(true);
00146       // prop->setDebug(true); // tmp
00147       defProp_ = prop;
00148       setPropagator(defProp_);
00149    }
00150 
00151    iSetup.get<DetIdAssociatorRecord>().get("EcalDetIdAssociator", ecalDetIdAssociator_);
00152    iSetup.get<DetIdAssociatorRecord>().get("HcalDetIdAssociator", hcalDetIdAssociator_);
00153    iSetup.get<DetIdAssociatorRecord>().get("HODetIdAssociator", hoDetIdAssociator_);
00154    iSetup.get<DetIdAssociatorRecord>().get("CaloDetIdAssociator", caloDetIdAssociator_);
00155    iSetup.get<DetIdAssociatorRecord>().get("MuonDetIdAssociator", muonDetIdAssociator_);
00156    iSetup.get<DetIdAssociatorRecord>().get("PreshowerDetIdAssociator", preshowerDetIdAssociator_);
00157 }
00158 
00159 TrackDetMatchInfo TrackDetectorAssociator::associate( const edm::Event& iEvent,
00160                                               const edm::EventSetup& iSetup,
00161                                               const FreeTrajectoryState& fts,
00162                                               const AssociatorParameters& parameters )
00163 {
00164    return associate(iEvent,iSetup,parameters,&fts);
00165 }
00166 
00167 TrackDetMatchInfo TrackDetectorAssociator::associate( const edm::Event& iEvent,
00168                                                       const edm::EventSetup& iSetup,
00169                                                       const AssociatorParameters& parameters,
00170                                                       const FreeTrajectoryState* innerState,
00171                                                       const FreeTrajectoryState* outerState)
00172 {
00173    TrackDetMatchInfo info;
00174    if (! parameters.useEcal && ! parameters.useCalo && ! parameters.useHcal &&
00175        ! parameters.useHO && ! parameters.useMuon && !parameters.usePreshower)
00176      throw cms::Exception("ConfigurationError") << 
00177      "Configuration error! No subdetector was selected for the track association.";
00178    // TimerStack timers;
00179    // timers.push("TrackDetectorAssociator::associate",TimerStack::DetailedMonitoring);
00180    
00181    SteppingHelixStateInfo trackOrigin(*innerState);
00182    info.stateAtIP = *innerState;
00183    cachedTrajectory_.setStateAtIP(trackOrigin);
00184    
00185    init( iSetup );
00186    // get track trajectory
00187    // timers.push("TrackDetectorAssociator::fillEcal::propagation");
00188    // ECAL points (EB+EE)
00189    // If the phi angle between a track entrance and exit points is more
00190    // than 2 crystals, it is possible that the track will cross 3 crystals
00191    // and therefore one has to check at least 3 points along the track
00192    // trajectory inside ECAL. In order to have a chance to cross 4 crystalls
00193    // in the barrel, a track should have P_t as low as 3 GeV or smaller
00194    // If it's necessary, number of points along trajectory can be increased
00195    
00196    info.setCaloGeometry(theCaloGeometry_);
00197    
00198    // timers.push("TrackDetectorAssociator::associate::getTrajectories");
00199    cachedTrajectory_.reset_trajectory();
00200    // estimate propagation outer boundaries based on 
00201    // requested sub-detector information. For now limit
00202    // propagation region only if muon matching is not 
00203    // requested.
00204    double HOmaxR = hoDetIdAssociator_->volume().maxR();
00205    double HOmaxZ = hoDetIdAssociator_->volume().maxZ();
00206    double minR = ecalDetIdAssociator_->volume().minR();
00207    double minZ = preshowerDetIdAssociator_->volume().minZ();
00208    cachedTrajectory_.setMaxHORadius(HOmaxR);
00209    cachedTrajectory_.setMaxHOLength(HOmaxZ*2.);
00210    cachedTrajectory_.setMinDetectorRadius(minR);
00211    cachedTrajectory_.setMinDetectorLength(minZ*2.);
00212 
00213    double maxR(0);
00214    double maxZ(0);
00215 
00216    if (parameters.useMuon) {
00217      maxR = muonDetIdAssociator_->volume().maxR();
00218      maxZ = muonDetIdAssociator_->volume().maxZ();
00219      cachedTrajectory_.setMaxDetectorRadius(maxR);
00220      cachedTrajectory_.setMaxDetectorLength(maxZ*2.);
00221    }
00222    else {
00223      maxR = HOmaxR;
00224      maxZ = HOmaxZ;
00225      cachedTrajectory_.setMaxDetectorRadius(HOmaxR);
00226      cachedTrajectory_.setMaxDetectorLength(HOmaxZ*2.);
00227    }
00228    
00229    // If track extras exist and outerState is before HO maximum, then use outerState
00230    if (outerState) {
00231      if (outerState->position().perp()<HOmaxR && fabs(outerState->position().z())<HOmaxZ) {
00232        LogTrace("TrackAssociator") << "Using outerState as trackOrigin at Rho=" << outerState->position().perp()
00233              << "  Z=" << outerState->position().z() << "\n";
00234        trackOrigin = SteppingHelixStateInfo(*outerState);
00235      }
00236      else if(innerState) {
00237        LogTrace("TrackAssociator") << "Using innerState as trackOrigin at Rho=" << innerState->position().perp()
00238              << "  Z=" << innerState->position().z() << "\n";
00239        trackOrigin = SteppingHelixStateInfo(*innerState);
00240      }
00241    }
00242 
00243    if ( ! cachedTrajectory_.propagateAll(trackOrigin) ) return info;
00244    
00245    // get trajectory in calorimeters
00246    cachedTrajectory_.findEcalTrajectory( ecalDetIdAssociator_->volume() );
00247    cachedTrajectory_.findHcalTrajectory( hcalDetIdAssociator_->volume() );
00248    cachedTrajectory_.findHOTrajectory( hoDetIdAssociator_->volume() );
00249    cachedTrajectory_.findPreshowerTrajectory( preshowerDetIdAssociator_->volume() );
00250 
00251    info.trkGlobPosAtEcal = getPoint( cachedTrajectory_.getStateAtEcal().position() );
00252    info.trkGlobPosAtHcal = getPoint( cachedTrajectory_.getStateAtHcal().position() );
00253    info.trkGlobPosAtHO  = getPoint( cachedTrajectory_.getStateAtHO().position() );
00254    
00255    info.trkMomAtEcal = cachedTrajectory_.getStateAtEcal().momentum();
00256    info.trkMomAtHcal = cachedTrajectory_.getStateAtHcal().momentum();
00257    info.trkMomAtHO   = cachedTrajectory_.getStateAtHO().momentum();
00258    
00259    // timers.pop_and_push("TrackDetectorAssociator::associate::fillInfo");
00260      
00261    if (parameters.useEcal) fillEcal( iEvent, info, parameters);
00262    if (parameters.useCalo) fillCaloTowers( iEvent, info, parameters);
00263    if (parameters.useHcal) fillHcal( iEvent, info, parameters);
00264    if (parameters.useHO)   fillHO( iEvent, info, parameters);
00265    if (parameters.usePreshower) fillPreshower( iEvent, info, parameters);
00266    if (parameters.useMuon) fillMuon( iEvent, info, parameters);
00267    if (parameters.truthMatch) fillCaloTruth( iEvent, info, parameters);
00268    
00269    return info;
00270 }
00271 
00272 void TrackDetectorAssociator::fillEcal( const edm::Event& iEvent,
00273                                 TrackDetMatchInfo& info,
00274                                 const AssociatorParameters& parameters)
00275 {
00276    // TimerStack timers;
00277    // timers.push("TrackDetectorAssociator::fillEcal");
00278    
00279    const std::vector<SteppingHelixStateInfo>& trajectoryStates = cachedTrajectory_.getEcalTrajectory();
00280    
00281    for(std::vector<SteppingHelixStateInfo>::const_iterator itr = trajectoryStates.begin();
00282        itr != trajectoryStates.end(); itr++) 
00283      LogTrace("TrackAssociator") << "ECAL trajectory point (rho, z, phi): " << itr->position().perp() <<
00284      ", " << itr->position().z() << ", " << itr->position().phi();
00285 
00286    std::vector<GlobalPoint> coreTrajectory;
00287    for(std::vector<SteppingHelixStateInfo>::const_iterator itr = trajectoryStates.begin();
00288        itr != trajectoryStates.end(); itr++) coreTrajectory.push_back(itr->position());
00289    
00290    if(coreTrajectory.empty()) {
00291       LogTrace("TrackAssociator") << "ECAL track trajectory is empty; moving on\n";
00292       info.isGoodEcal = 0;
00293       return;
00294    }
00295    info.isGoodEcal = 1;
00296 
00297    // Find ECAL crystals
00298    // timers.push("TrackDetectorAssociator::fillEcal::access::EcalBarrel");
00299    edm::Handle<EBRecHitCollection> EBRecHits;
00300    iEvent.getByLabel( parameters.theEBRecHitCollectionLabel, EBRecHits );
00301    if (!EBRecHits.isValid()) throw cms::Exception("FatalError") << "Unable to find EBRecHitCollection in the event!\n";
00302 
00303    // timers.pop_and_push("TrackDetectorAssociator::fillEcal::access::EcalEndcaps");
00304    edm::Handle<EERecHitCollection> EERecHits;
00305    iEvent.getByLabel( parameters.theEERecHitCollectionLabel, EERecHits );
00306    if (!EERecHits.isValid()) throw cms::Exception("FatalError") << "Unable to find EERecHitCollection in event!\n";
00307 
00308    // timers.pop_and_push("TrackDetectorAssociator::fillEcal::matching");
00309    // timers.push("TrackDetectorAssociator::fillEcal::matching::region");
00310    std::set<DetId> ecalIdsInRegion;
00311    if (parameters.accountForTrajectoryChangeCalo){
00312       // get trajectory change with respect to initial state
00313       DetIdAssociator::MapRange mapRange = getMapRange(cachedTrajectory_.trajectoryDelta(CachedTrajectory::IpToEcal),
00314                                                        parameters.dREcalPreselection);
00315       ecalIdsInRegion = ecalDetIdAssociator_->getDetIdsCloseToAPoint(coreTrajectory[0],mapRange);
00316    } else ecalIdsInRegion = ecalDetIdAssociator_->getDetIdsCloseToAPoint(coreTrajectory[0], parameters.dREcalPreselection);
00317    // timers.pop_and_push("TrackDetectorAssociator::fillEcal::matching::cone");
00318    LogTrace("TrackAssociator") << "ECAL hits in the region: " << ecalIdsInRegion.size();
00319    if (parameters.dREcalPreselection > parameters.dREcal)
00320      ecalIdsInRegion =  ecalDetIdAssociator_->getDetIdsInACone(ecalIdsInRegion, coreTrajectory, parameters.dREcal);
00321    LogTrace("TrackAssociator") << "ECAL hits in the cone: " << ecalIdsInRegion.size();
00322    std::vector<DetId> crossedEcalIds =  
00323      ecalDetIdAssociator_->getCrossedDetIds(ecalIdsInRegion, coreTrajectory);
00324    LogTrace("TrackAssociator") << "ECAL crossed hits " << crossedEcalIds.size();
00325    
00326    info.crossedEcalIds = crossedEcalIds;
00327    
00328    // add EcalRecHits
00329    // timers.pop_and_push("TrackDetectorAssociator::fillEcal::addCrossedHits");
00330    for(std::vector<DetId>::const_iterator itr=crossedEcalIds.begin(); itr!=crossedEcalIds.end();itr++)
00331    {
00332       std::vector<EcalRecHit>::const_iterator ebHit = (*EBRecHits).find(*itr);
00333       std::vector<EcalRecHit>::const_iterator eeHit = (*EERecHits).find(*itr);
00334       if(ebHit != (*EBRecHits).end()) 
00335          info.crossedEcalRecHits.push_back(&*ebHit);
00336       else if(eeHit != (*EERecHits).end()) 
00337          info.crossedEcalRecHits.push_back(&*eeHit);
00338       else  
00339          LogTrace("TrackAssociator") << "Crossed EcalRecHit is not found for DetId: " << itr->rawId();
00340    }
00341    // timers.pop_and_push("TrackDetectorAssociator::fillEcal::addHitsInTheRegion");
00342    for(std::set<DetId>::const_iterator itr=ecalIdsInRegion.begin(); itr!=ecalIdsInRegion.end();itr++)
00343    {
00344       std::vector<EcalRecHit>::const_iterator ebHit = (*EBRecHits).find(*itr);
00345       std::vector<EcalRecHit>::const_iterator eeHit = (*EERecHits).find(*itr);
00346       if(ebHit != (*EBRecHits).end()) 
00347          info.ecalRecHits.push_back(&*ebHit);
00348       else if(eeHit != (*EERecHits).end()) 
00349          info.ecalRecHits.push_back(&*eeHit);
00350       else 
00351          LogTrace("TrackAssociator") << "EcalRecHit from the cone is not found for DetId: " << itr->rawId();
00352    }
00353 }
00354 
00355 void TrackDetectorAssociator::fillCaloTowers( const edm::Event& iEvent,
00356                                       TrackDetMatchInfo& info,
00357                                       const AssociatorParameters& parameters)
00358 {
00359    // TimerStack timers;
00360    // timers.push("TrackDetectorAssociator::fillCaloTowers");
00361 
00362    // use ECAL and HCAL trajectories to match a tower. (HO isn't used for matching).
00363    std::vector<GlobalPoint> trajectory;
00364    const std::vector<SteppingHelixStateInfo>& ecalTrajectoryStates = cachedTrajectory_.getEcalTrajectory();
00365    const std::vector<SteppingHelixStateInfo>& hcalTrajectoryStates = cachedTrajectory_.getHcalTrajectory();
00366    for(std::vector<SteppingHelixStateInfo>::const_iterator itr = ecalTrajectoryStates.begin();
00367        itr != ecalTrajectoryStates.end(); itr++) trajectory.push_back(itr->position());
00368    for(std::vector<SteppingHelixStateInfo>::const_iterator itr = hcalTrajectoryStates.begin();
00369        itr != hcalTrajectoryStates.end(); itr++) trajectory.push_back(itr->position());
00370    
00371    if(trajectory.empty()) {
00372       LogTrace("TrackAssociator") << "HCAL trajectory is empty; moving on\n";
00373       info.isGoodCalo = 0;
00374       return;
00375    }
00376    info.isGoodCalo = 1;
00377    
00378    // find crossed CaloTowers
00379    // timers.push("TrackDetectorAssociator::fillCaloTowers::access::CaloTowers");
00380    edm::Handle<CaloTowerCollection> caloTowers;
00381 
00382    iEvent.getByLabel( parameters.theCaloTowerCollectionLabel, caloTowers );
00383    if (!caloTowers.isValid())  throw cms::Exception("FatalError") << "Unable to find CaloTowers in event!\n";
00384    
00385    // timers.pop_and_push("TrackDetectorAssociator::fillCaloTowers::matching");
00386    std::set<DetId> caloTowerIdsInRegion;
00387    if (parameters.accountForTrajectoryChangeCalo){
00388       // get trajectory change with respect to initial state
00389       DetIdAssociator::MapRange mapRange = getMapRange(cachedTrajectory_.trajectoryDelta(CachedTrajectory::IpToHcal),
00390                                                        parameters.dRHcalPreselection);
00391       caloTowerIdsInRegion = caloDetIdAssociator_->getDetIdsCloseToAPoint(trajectory[0],mapRange);
00392    } else caloTowerIdsInRegion = caloDetIdAssociator_->getDetIdsCloseToAPoint(trajectory[0], parameters.dRHcalPreselection);
00393    
00394    LogTrace("TrackAssociator") << "Towers in the region: " << caloTowerIdsInRegion.size();
00395    std::set<DetId> caloTowerIdsInACone = caloDetIdAssociator_->getDetIdsInACone(caloTowerIdsInRegion, trajectory, parameters.dRHcal);
00396    LogTrace("TrackAssociator") << "Towers in the cone: " << caloTowerIdsInACone.size();
00397    std::vector<DetId> crossedCaloTowerIds = caloDetIdAssociator_->getCrossedDetIds(caloTowerIdsInRegion, trajectory);
00398    LogTrace("TrackAssociator") << "Towers crossed: " << crossedCaloTowerIds.size();
00399    
00400    info.crossedTowerIds = crossedCaloTowerIds;
00401    
00402    // add CaloTowers
00403    // timers.pop_and_push("TrackDetectorAssociator::fillCaloTowers::addCrossedTowers");
00404    for(std::vector<DetId>::const_iterator itr=crossedCaloTowerIds.begin(); itr!=crossedCaloTowerIds.end();itr++)
00405      {
00406         CaloTowerCollection::const_iterator tower = (*caloTowers).find(*itr);
00407         if(tower != (*caloTowers).end()) 
00408           info.crossedTowers.push_back(&*tower);
00409         else
00410           LogTrace("TrackAssociator") << "Crossed CaloTower is not found for DetId: " << (*itr).rawId();
00411      }
00412    
00413    // timers.pop_and_push("TrackDetectorAssociator::fillCaloTowers::addTowersInTheRegion");
00414    for(std::set<DetId>::const_iterator itr=caloTowerIdsInACone.begin(); itr!=caloTowerIdsInACone.end();itr++)
00415      {
00416         CaloTowerCollection::const_iterator tower = (*caloTowers).find(*itr);
00417         if(tower != (*caloTowers).end()) 
00418           info.towers.push_back(&*tower);
00419         else 
00420           LogTrace("TrackAssociator") << "CaloTower from the cone is not found for DetId: " << (*itr).rawId();
00421      }
00422    
00423 }
00424 
00425 void TrackDetectorAssociator::fillPreshower( const edm::Event& iEvent,
00426                                              TrackDetMatchInfo& info,
00427                                              const AssociatorParameters& parameters)
00428 {
00429    std::vector<GlobalPoint> trajectory;
00430    const std::vector<SteppingHelixStateInfo>& trajectoryStates = cachedTrajectory_.getPreshowerTrajectory();
00431    for(std::vector<SteppingHelixStateInfo>::const_iterator itr = trajectoryStates.begin();
00432        itr != trajectoryStates.end(); itr++) trajectory.push_back(itr->position());
00433    
00434    if(trajectory.empty()) {
00435       LogTrace("TrackAssociator") << "Preshower trajectory is empty; moving on\n";
00436       return;
00437    }
00438    
00439    std::set<DetId> idsInRegion = 
00440      preshowerDetIdAssociator_->getDetIdsCloseToAPoint(trajectory[0], 
00441                                                        parameters.dRPreshowerPreselection);
00442    
00443    LogTrace("TrackAssociator") << "Number of Preshower Ids in the region: " << idsInRegion.size();
00444    std::vector<DetId> crossedIds = preshowerDetIdAssociator_->getCrossedDetIds(idsInRegion, trajectory);
00445    LogTrace("TrackAssociator") << "Number of Preshower Ids in crossed: " << crossedIds.size();
00446    info.crossedPreshowerIds = crossedIds;
00447 }
00448 
00449 
00450 void TrackDetectorAssociator::fillHcal( const edm::Event& iEvent,
00451                                 TrackDetMatchInfo& info,
00452                                 const AssociatorParameters& parameters)
00453 {
00454    // TimerStack timers;
00455    // timers.push("TrackDetectorAssociator::fillHcal");
00456 
00457    const std::vector<SteppingHelixStateInfo>& trajectoryStates = cachedTrajectory_.getHcalTrajectory();
00458 
00459    std::vector<GlobalPoint> coreTrajectory;
00460    for(std::vector<SteppingHelixStateInfo>::const_iterator itr = trajectoryStates.begin();
00461        itr != trajectoryStates.end(); itr++) coreTrajectory.push_back(itr->position());   
00462    
00463    if(coreTrajectory.empty()) {
00464       LogTrace("TrackAssociator") << "HCAL trajectory is empty; moving on\n";
00465       info.isGoodHcal = 0;
00466       return;
00467    }
00468    info.isGoodHcal = 1;
00469    
00470    // find crossed Hcals
00471    // timers.push("TrackDetectorAssociator::fillHcal::access::Hcal");
00472    edm::Handle<HBHERecHitCollection> collection;
00473 
00474    iEvent.getByLabel( parameters.theHBHERecHitCollectionLabel, collection );
00475    if ( ! collection.isValid() ) throw cms::Exception("FatalError") << "Unable to find HBHERecHits in event!\n";
00476    
00477    // timers.pop_and_push("TrackDetectorAssociator::fillHcal::matching");
00478    std::set<DetId> idsInRegion;
00479    if (parameters.accountForTrajectoryChangeCalo){
00480       // get trajectory change with respect to initial state
00481       DetIdAssociator::MapRange mapRange = getMapRange(cachedTrajectory_.trajectoryDelta(CachedTrajectory::IpToHcal),
00482                                                        parameters.dRHcalPreselection);
00483       idsInRegion = hcalDetIdAssociator_->getDetIdsCloseToAPoint(coreTrajectory[0], mapRange);
00484    } else idsInRegion = hcalDetIdAssociator_->getDetIdsCloseToAPoint(coreTrajectory[0], parameters.dRHcalPreselection);
00485    
00486    LogTrace("TrackAssociator") << "HCAL hits in the region: " << idsInRegion.size() << "\n" << DetIdInfo::info(idsInRegion);
00487    std::set<DetId> idsInACone = hcalDetIdAssociator_->getDetIdsInACone(idsInRegion, coreTrajectory, parameters.dRHcal);
00488    LogTrace("TrackAssociator") << "HCAL hits in the cone: " << idsInACone.size() << "\n" << DetIdInfo::info(idsInACone);
00489    std::vector<DetId> crossedIds = 
00490      hcalDetIdAssociator_->getCrossedDetIds(idsInRegion, coreTrajectory);
00491    LogTrace("TrackAssociator") << "HCAL hits crossed: " << crossedIds.size() << "\n" << DetIdInfo::info(crossedIds);
00492    
00493    info.crossedHcalIds = crossedIds;
00494    // timers.pop_and_push("TrackDetectorAssociator::fillHcal::addCrossedHits");
00495    // add Hcal
00496    // timers.push("TrackDetectorAssociator::fillHcal::addHcal");
00497    for(std::vector<DetId>::const_iterator itr=crossedIds.begin(); itr!=crossedIds.end();itr++)
00498      {
00499         HBHERecHitCollection::const_iterator hit = (*collection).find(*itr);
00500         if( hit != (*collection).end() ) 
00501           info.crossedHcalRecHits.push_back(&*hit);
00502         else
00503           LogTrace("TrackAssociator") << "Crossed HBHERecHit is not found for DetId: " << itr->rawId();
00504      }
00505    // timers.pop_and_push("TrackDetectorAssociator::fillHcal::addHitsInTheRegion");
00506    for(std::set<DetId>::const_iterator itr=idsInACone.begin(); itr!=idsInACone.end();itr++)
00507      {
00508         HBHERecHitCollection::const_iterator hit = (*collection).find(*itr);
00509         if( hit != (*collection).end() ) 
00510           info.hcalRecHits.push_back(&*hit);
00511         else 
00512           LogTrace("TrackAssociator") << "HBHERecHit from the cone is not found for DetId: " << itr->rawId();
00513      }
00514 }
00515 
00516 void TrackDetectorAssociator::fillHO( const edm::Event& iEvent,
00517                               TrackDetMatchInfo& info,
00518                               const AssociatorParameters& parameters)
00519 {
00520    // TimerStack timers;
00521    // timers.push("TrackDetectorAssociator::fillHO");
00522 
00523    const std::vector<SteppingHelixStateInfo>& trajectoryStates = cachedTrajectory_.getHOTrajectory();
00524 
00525    std::vector<GlobalPoint> coreTrajectory;
00526    for(std::vector<SteppingHelixStateInfo>::const_iterator itr = trajectoryStates.begin();
00527        itr != trajectoryStates.end(); itr++) coreTrajectory.push_back(itr->position());
00528 
00529    if(coreTrajectory.empty()) {
00530       LogTrace("TrackAssociator") << "HO trajectory is empty; moving on\n";
00531       info.isGoodHO = 0;
00532       return;
00533    }
00534    info.isGoodHO = 1;
00535    
00536    // find crossed HOs
00537    // timers.pop_and_push("TrackDetectorAssociator::fillHO::access::HO");
00538    edm::Handle<HORecHitCollection> collection;
00539 
00540    iEvent.getByLabel( parameters.theHORecHitCollectionLabel, collection );
00541    if ( ! collection.isValid() ) throw cms::Exception("FatalError") << "Unable to find HORecHits in event!\n";
00542    
00543    // timers.pop_and_push("TrackDetectorAssociator::fillHO::matching");
00544    std::set<DetId> idsInRegion;
00545    if (parameters.accountForTrajectoryChangeCalo){
00546       // get trajectory change with respect to initial state
00547       DetIdAssociator::MapRange mapRange = getMapRange(cachedTrajectory_.trajectoryDelta(CachedTrajectory::IpToHO),
00548                                                        parameters.dRHcalPreselection);
00549       idsInRegion = hoDetIdAssociator_->getDetIdsCloseToAPoint(coreTrajectory[0], mapRange);
00550    } else idsInRegion = hoDetIdAssociator_->getDetIdsCloseToAPoint(coreTrajectory[0], parameters.dRHcalPreselection);
00551    
00552    LogTrace("TrackAssociator") << "idsInRegion.size(): " << idsInRegion.size();
00553    std::set<DetId> idsInACone = hoDetIdAssociator_->getDetIdsInACone(idsInRegion, coreTrajectory, parameters.dRHcal);
00554    LogTrace("TrackAssociator") << "idsInACone.size(): " << idsInACone.size();
00555    std::vector<DetId> crossedIds =
00556      hoDetIdAssociator_->getCrossedDetIds(idsInRegion, coreTrajectory);
00557    
00558    info.crossedHOIds = crossedIds;
00559    
00560    // add HO
00561    // timers.pop_and_push("TrackDetectorAssociator::fillHO::addCrossedHits");
00562    for(std::vector<DetId>::const_iterator itr=crossedIds.begin(); itr!=crossedIds.end();itr++)
00563      {
00564         HORecHitCollection::const_iterator hit = (*collection).find(*itr);
00565         if( hit != (*collection).end() ) 
00566           info.crossedHORecHits.push_back(&*hit);
00567         else
00568           LogTrace("TrackAssociator") << "Crossed HORecHit is not found for DetId: " << itr->rawId();
00569      }
00570 
00571    // timers.pop_and_push("TrackDetectorAssociator::fillHO::addHitsInTheRegion");
00572    for(std::set<DetId>::const_iterator itr=idsInACone.begin(); itr!=idsInACone.end();itr++)
00573      {
00574         HORecHitCollection::const_iterator hit = (*collection).find(*itr);
00575         if( hit != (*collection).end() ) 
00576           info.hoRecHits.push_back(&*hit);
00577         else 
00578           LogTrace("TrackAssociator") << "HORecHit from the cone is not found for DetId: " << itr->rawId();
00579      }
00580 }
00581 
00582 FreeTrajectoryState TrackDetectorAssociator::getFreeTrajectoryState( const edm::EventSetup& iSetup, 
00583                                                                             const SimTrack& track, 
00584                                                                             const SimVertex& vertex )
00585 {
00586    GlobalVector vector( track.momentum().x(), track.momentum().y(), track.momentum().z() );
00587    GlobalPoint point( vertex.position().x(), vertex.position().y(), vertex.position().z() );
00588 
00589    int charge = track.type( )> 0 ? -1 : 1; // lepton convention
00590    if ( abs(track.type( )) == 211 || // pion
00591         abs(track.type( )) == 321 || // kaon
00592         abs(track.type( )) == 2212 )
00593      charge = track.type( )< 0 ? -1 : 1;
00594    return getFreeTrajectoryState(iSetup, vector, point, charge);
00595 }
00596 
00597 FreeTrajectoryState TrackDetectorAssociator::getFreeTrajectoryState( const edm::EventSetup& iSetup,
00598                                                                             const GlobalVector& momentum, 
00599                                                                             const GlobalPoint& vertex,
00600                                                                             const int charge)
00601 {
00602    edm::ESHandle<MagneticField> bField;
00603    iSetup.get<IdealMagneticFieldRecord>().get(bField);
00604    
00605    GlobalTrajectoryParameters tPars(vertex, momentum, charge, &*bField);
00606    
00607    ROOT::Math::SMatrixIdentity id;
00608    AlgebraicSymMatrix66 covT(id); covT *= 1e-6; // initialize to sigma=1e-3
00609    CartesianTrajectoryError tCov(covT);
00610    
00611    return FreeTrajectoryState(tPars, tCov);
00612 }
00613 
00614 
00615 FreeTrajectoryState TrackDetectorAssociator::getFreeTrajectoryState( const edm::EventSetup& iSetup,
00616                                                                             const reco::Track& track )
00617 {
00618    edm::ESHandle<MagneticField> bField;
00619    iSetup.get<IdealMagneticFieldRecord>().get(bField);
00620    
00621    GlobalVector vector( track.momentum().x(), track.momentum().y(), track.momentum().z() );
00622 
00623    GlobalPoint point( track.vertex().x(), track.vertex().y(),  track.vertex().z() );
00624 
00625    GlobalTrajectoryParameters tPars(point, vector, track.charge(), &*bField);
00626    
00627    // FIX THIS !!!
00628    // need to convert from perigee to global or helix (curvilinear) frame
00629    // for now just an arbitrary matrix.
00630    ROOT::Math::SMatrixIdentity id;
00631    AlgebraicSymMatrix66 covT(id); covT *= 1e-6; // initialize to sigma=1e-3
00632    CartesianTrajectoryError tCov(covT);
00633    
00634    return FreeTrajectoryState(tPars, tCov);
00635 }
00636 
00637 DetIdAssociator::MapRange TrackDetectorAssociator::getMapRange( const std::pair<float,float>& delta,
00638                                                                 const float dR )
00639 {
00640    DetIdAssociator::MapRange mapRange;
00641    mapRange.dThetaPlus = dR;
00642    mapRange.dThetaMinus = dR;
00643    mapRange.dPhiPlus = dR;
00644    mapRange.dPhiMinus = dR;
00645    if ( delta.first > 0 ) 
00646      mapRange.dThetaPlus += delta.first;
00647    else
00648      mapRange.dThetaMinus += fabs(delta.first);
00649    if ( delta.second > 0 ) 
00650      mapRange.dPhiPlus += delta.second;
00651    else
00652      mapRange.dPhiMinus += fabs(delta.second);
00653    LogTrace("TrackAssociator") << "Selection range: (dThetaPlus, dThetaMinus, dPhiPlus, dPhiMinus, dRPreselection): " <<
00654      mapRange.dThetaPlus << ", " << mapRange.dThetaMinus << ", " << 
00655      mapRange.dPhiPlus << ", " << mapRange.dPhiMinus << ", " << dR;
00656    return mapRange;
00657 }
00658 
00659 void TrackDetectorAssociator::getTAMuonChamberMatches(std::vector<TAMuonChamberMatch>& matches,
00660                                                     const AssociatorParameters& parameters)
00661 {
00662    // Strategy:
00663    //    Propagate through the whole detector, estimate change in eta and phi 
00664    //    along the trajectory, add this to dRMuon and find DetIds around this 
00665    //    direction using the map. Then propagate fast to each surface and apply 
00666    //    final matching criteria.
00667 
00668    // TimerStack timers(TimerStack::Disableable);
00669    // timers.push("MuonDetIdAssociator::getTrajectoryInMuonDetector");
00670    // timers.push("MuonDetIdAssociator::getTrajectoryInMuonDetector::propagation",TimerStack::FastMonitoring);
00671    // timers.pop();
00672    // get the direction first
00673    SteppingHelixStateInfo trajectoryPoint = cachedTrajectory_.getStateAtHcal();
00674    // If trajectory point at HCAL is not valid, try to use the outer most state of the
00675    // trajectory instead.
00676    if(! trajectoryPoint.isValid() ) trajectoryPoint = cachedTrajectory_.getOuterState();
00677    if(! trajectoryPoint.isValid() ) {
00678       LogTrace("TrackAssociator") << 
00679         "trajectory position at HCAL is not valid. Assume the track cannot reach muon detectors and skip it";
00680       return;
00681    }
00682 
00683    GlobalVector direction = trajectoryPoint.momentum().unit();
00684    LogTrace("TrackAssociator") << "muon direction: " << direction << "\n\t and corresponding point: " <<
00685      trajectoryPoint.position() <<"\n";
00686    
00687    DetIdAssociator::MapRange mapRange = getMapRange(cachedTrajectory_.trajectoryDelta(CachedTrajectory::FullTrajectory),
00688                                                     parameters.dRMuonPreselection);
00689      
00690    // and find chamber DetIds
00691 
00692    // timers.push("MuonDetIdAssociator::getTrajectoryInMuonDetector::getDetIdsCloseToAPoint",TimerStack::FastMonitoring);
00693    std::set<DetId> muonIdsInRegion = 
00694      muonDetIdAssociator_->getDetIdsCloseToAPoint(trajectoryPoint.position(), mapRange);
00695    // timers.pop_and_push("MuonDetIdAssociator::getTrajectoryInMuonDetector::matching",TimerStack::FastMonitoring);
00696    LogTrace("TrackAssociator") << "Number of chambers to check: " << muonIdsInRegion.size();
00697    for(std::set<DetId>::const_iterator detId = muonIdsInRegion.begin(); detId != muonIdsInRegion.end(); detId++)
00698    {
00699       const GeomDet* geomDet = muonDetIdAssociator_->getGeomDet(*detId);
00700       // timers.push("MuonDetIdAssociator::getTrajectoryInMuonDetector::matching::localPropagation",TimerStack::FastMonitoring);
00701       TrajectoryStateOnSurface stateOnSurface = cachedTrajectory_.propagate( &geomDet->surface() );
00702       if (! stateOnSurface.isValid()) {
00703          LogTrace("TrackAssociator") << "Failed to propagate the track; moving on\n\t"<<
00704            "Element is not crosssed: " << DetIdInfo::info(*detId) << "\n";
00705          continue;
00706       }
00707       // timers.pop_and_push("MuonDetIdAssociator::getTrajectoryInMuonDetector::matching::geometryAccess",TimerStack::FastMonitoring);
00708       LocalPoint localPoint = geomDet->surface().toLocal(stateOnSurface.freeState()->position());
00709       LocalError localError = stateOnSurface.localError().positionError();
00710       float distanceX = 0;
00711       float distanceY = 0;
00712       float sigmaX = 0.0;
00713       float sigmaY = 0.0;
00714       if(const CSCChamber* cscChamber = dynamic_cast<const CSCChamber*>(geomDet) ) {
00715          const CSCChamberSpecs* chamberSpecs = cscChamber->specs();
00716          if(! chamberSpecs) {
00717             LogTrace("TrackAssociator") << "Failed to get CSCChamberSpecs from CSCChamber; moving on\n";
00718             continue;
00719          }
00720          const CSCLayerGeometry* layerGeometry = chamberSpecs->oddLayerGeometry(1);
00721          if(! layerGeometry) {
00722             LogTrace("TrackAssociator") << "Failed to get CSCLayerGeometry from CSCChamberSpecs; moving on\n";
00723             continue;
00724          }
00725          const CSCWireTopology* wireTopology = layerGeometry->wireTopology();
00726          if(! wireTopology) {
00727             LogTrace("TrackAssociator") << "Failed to get CSCWireTopology from CSCLayerGeometry; moving on\n";
00728             continue;
00729          }
00730 
00731          float wideWidth      = wireTopology->wideWidthOfPlane();
00732          float narrowWidth    = wireTopology->narrowWidthOfPlane();
00733          float length         = wireTopology->lengthOfPlane();
00734          // If slanted, there is no y offset between local origin and symmetry center of wire plane
00735          float yOfFirstWire   = fabs(wireTopology->wireAngle())>1.E-06 ? -0.5*length : wireTopology->yOfWire(1);
00736          // y offset between local origin and symmetry center of wire plane
00737          float yCOWPOffset    = yOfFirstWire+0.5*length;
00738 
00739          // tangent of the incline angle from inside the trapezoid
00740          float tangent = (wideWidth-narrowWidth)/(2.*length);
00741          // y position wrt bottom of trapezoid
00742          float yPrime  = localPoint.y()+fabs(yOfFirstWire);
00743          // half trapezoid width at y' is 0.5 * narrowWidth + x side of triangle with the above tangent and side y'
00744          float halfWidthAtYPrime = 0.5*narrowWidth+yPrime*tangent;
00745          distanceX = fabs(localPoint.x()) - halfWidthAtYPrime;
00746          distanceY = fabs(localPoint.y()-yCOWPOffset) - 0.5*length;
00747          sigmaX = distanceX/sqrt(localError.xx());
00748          sigmaY = distanceY/sqrt(localError.yy());
00749       } else {
00750          distanceX = fabs(localPoint.x()) - geomDet->surface().bounds().width()/2.;
00751          distanceY = fabs(localPoint.y()) - geomDet->surface().bounds().length()/2.;
00752          sigmaX = distanceX/sqrt(localError.xx());
00753          sigmaY = distanceY/sqrt(localError.yy());
00754       }
00755       // timers.pop_and_push("MuonDetIdAssociator::getTrajectoryInMuonDetector::matching::checking",TimerStack::FastMonitoring);
00756       if ( (distanceX < parameters.muonMaxDistanceX && distanceY < parameters.muonMaxDistanceY) ||
00757            (sigmaX < parameters.muonMaxDistanceSigmaX && sigmaY < parameters.muonMaxDistanceSigmaY) ) {
00758         LogTrace("TrackAssociator") << "found a match: " << DetIdInfo::info(*detId) << "\n";
00759          TAMuonChamberMatch match;
00760          match.tState = stateOnSurface;
00761          match.localDistanceX = distanceX;
00762          match.localDistanceY = distanceY;
00763          match.id = *detId;
00764          matches.push_back(match);
00765       } else {
00766         LogTrace("TrackAssociator") << "chamber is too far: " << 
00767           DetIdInfo::info(*detId) << "\n\tdistanceX: " << distanceX << "\t distanceY: " << distanceY <<
00768           "\t sigmaX: " << sigmaX << "\t sigmaY: " << sigmaY << "\n";
00769       } 
00770       //timers.pop();
00771    }
00772    //timers.pop();
00773    
00774 }
00775 
00776 void TrackDetectorAssociator::fillMuon( const edm::Event& iEvent,
00777                                         TrackDetMatchInfo& info,
00778                                         const AssociatorParameters& parameters)
00779 {
00780    // TimerStack timers;
00781    // timers.push("TrackDetectorAssociator::fillMuon");
00782 
00783    // Get the segments from the event
00784    // timers.push("TrackDetectorAssociator::fillMuon::access");
00785    edm::Handle<DTRecSegment4DCollection> dtSegments;
00786    iEvent.getByLabel( parameters.theDTRecSegment4DCollectionLabel, dtSegments );
00787    if (! dtSegments.isValid()) 
00788      throw cms::Exception("FatalError") << "Unable to find DTRecSegment4DCollection in event!\n";
00789    
00790    edm::Handle<CSCSegmentCollection> cscSegments;
00791    iEvent.getByLabel( parameters.theCSCSegmentCollectionLabel, cscSegments );
00792    if (! cscSegments.isValid()) 
00793      throw cms::Exception("FatalError") << "Unable to find CSCSegmentCollection in event!\n";
00794 
00796    
00797    // check the map of available segments
00798    // if there is no segments in a given direction at all,
00799    // then there is no point to fly there.
00800    // 
00801    // MISSING
00802    // Possible solution: quick search for presence of segments 
00803    // for the set of DetIds
00804 
00805    // timers.pop_and_push("TrackDetectorAssociator::fillMuon::matchChembers");
00806    
00807    // get a set of matches corresponding to muon chambers
00808    std::vector<TAMuonChamberMatch> matchedChambers;
00809    LogTrace("TrackAssociator") << "Trying to Get ChamberMatches" << std::endl;
00810    getTAMuonChamberMatches(matchedChambers, parameters);
00811    LogTrace("TrackAssociator") << "Chambers matched: " << matchedChambers.size() << "\n";
00812    
00813    // Iterate over all chamber matches and fill segment matching 
00814    // info if it's available
00815    // timers.pop_and_push("TrackDetectorAssociator::fillMuon::findSemgents");
00816    for(std::vector<TAMuonChamberMatch>::iterator matchedChamber = matchedChambers.begin(); 
00817        matchedChamber != matchedChambers.end(); matchedChamber++)
00818      {
00819         const GeomDet* geomDet = muonDetIdAssociator_->getGeomDet((*matchedChamber).id);
00820         // DT chamber
00821         if(const DTChamber* chamber = dynamic_cast<const DTChamber*>(geomDet) ) {
00822            // Get the range for the corresponding segments
00823            DTRecSegment4DCollection::range  range = dtSegments->get(chamber->id());
00824            // Loop over the segments of this chamber
00825            for (DTRecSegment4DCollection::const_iterator segment = range.first; segment!=range.second; segment++) {
00826              if (addTAMuonSegmentMatch(*matchedChamber, &(*segment), parameters)) {
00827                 matchedChamber->segments.back().dtSegmentRef = DTRecSegment4DRef(dtSegments, segment - dtSegments->begin());
00828              }
00829            }
00830         }else{
00831            // CSC Chamber
00832            if(const CSCChamber* chamber = dynamic_cast<const CSCChamber*>(geomDet) ) {
00833               // Get the range for the corresponding segments
00834               CSCSegmentCollection::range  range = cscSegments->get(chamber->id());
00835               // Loop over the segments
00836               for (CSCSegmentCollection::const_iterator segment = range.first; segment!=range.second; segment++) {
00837                  if (addTAMuonSegmentMatch(*matchedChamber, &(*segment), parameters)) {
00838                      matchedChamber->segments.back().cscSegmentRef = CSCSegmentRef(cscSegments, segment - cscSegments->begin());
00839                  }
00840               }
00841            }else{
00842              // throw cms::Exception("FatalError") << "Failed to cast GeomDet object to either DTChamber or CSCChamber. Who is this guy anyway?\n";
00843            }
00844         }
00845         info.chambers.push_back(*matchedChamber);
00846      }
00847 }
00848 
00849 
00850 bool TrackDetectorAssociator::addTAMuonSegmentMatch(TAMuonChamberMatch& matchedChamber,
00851                                           const RecSegment* segment,
00852                                           const AssociatorParameters& parameters)
00853 {
00854    LogTrace("TrackAssociator")
00855      << "Segment local position: " << segment->localPosition() << "\n"
00856      << std::hex << segment->geographicalId().rawId() << "\n";
00857    
00858    const GeomDet* chamber = muonDetIdAssociator_->getGeomDet(matchedChamber.id);
00859    TrajectoryStateOnSurface trajectoryStateOnSurface = matchedChamber.tState;
00860    GlobalPoint segmentGlobalPosition = chamber->toGlobal(segment->localPosition());
00861 
00862    LogTrace("TrackAssociator")
00863      << "Segment global position: " << segmentGlobalPosition << " \t (R_xy,eta,phi): "
00864      << segmentGlobalPosition.perp() << "," << segmentGlobalPosition.eta() << "," << segmentGlobalPosition.phi() << "\n";
00865 
00866    LogTrace("TrackAssociator")
00867      << "\teta hit: " << segmentGlobalPosition.eta() << " \tpropagator: " << trajectoryStateOnSurface.freeState()->position().eta() << "\n"
00868      << "\tphi hit: " << segmentGlobalPosition.phi() << " \tpropagator: " << trajectoryStateOnSurface.freeState()->position().phi() << std::endl;
00869    
00870    bool isGood = false;
00871    bool isDTWithoutY = false;
00872    const DTRecSegment4D* dtseg = dynamic_cast<const DTRecSegment4D*>(segment);
00873    if ( dtseg && (! dtseg->hasZed()) )
00874       isDTWithoutY = true;
00875 
00876    double deltaPhi(fabs(segmentGlobalPosition.phi()-trajectoryStateOnSurface.freeState()->position().phi()));
00877    if(deltaPhi>M_PI) deltaPhi = fabs(deltaPhi-M_PI*2.);
00878 
00879    if( isDTWithoutY )
00880      {
00881         isGood = deltaPhi < parameters.dRMuon;
00882         // Be in chamber
00883         isGood &= fabs(segmentGlobalPosition.eta()-trajectoryStateOnSurface.freeState()->position().eta()) < .3;
00884      } else isGood = sqrt( pow(segmentGlobalPosition.eta()-trajectoryStateOnSurface.freeState()->position().eta(),2) + 
00885                            deltaPhi*deltaPhi) < parameters.dRMuon;
00886 
00887    if(isGood) {
00888       TAMuonSegmentMatch muonSegment;
00889       muonSegment.segmentGlobalPosition = getPoint(segmentGlobalPosition);
00890       muonSegment.segmentLocalPosition = getPoint( segment->localPosition() );
00891       muonSegment.segmentLocalDirection = getVector( segment->localDirection() );
00892       muonSegment.segmentLocalErrorXX = segment->localPositionError().xx();
00893       muonSegment.segmentLocalErrorYY = segment->localPositionError().yy();
00894       muonSegment.segmentLocalErrorXY = segment->localPositionError().xy();
00895       muonSegment.segmentLocalErrorDxDz = segment->localDirectionError().xx();
00896       muonSegment.segmentLocalErrorDyDz = segment->localDirectionError().yy();
00897       
00898       // DANGEROUS - compiler cannot guaranty parameters ordering
00899       // AlgebraicSymMatrix segmentCovMatrix = segment->parametersError();
00900       // muonSegment.segmentLocalErrorXDxDz = segmentCovMatrix[2][0];
00901       // muonSegment.segmentLocalErrorYDyDz = segmentCovMatrix[3][1];
00902       muonSegment.segmentLocalErrorXDxDz = -999;
00903       muonSegment.segmentLocalErrorYDyDz = -999;
00904       muonSegment.hasZed = true;
00905       muonSegment.hasPhi = true;
00906       
00907       // timing information
00908       muonSegment.t0 = 0;
00909       if ( dtseg ) {
00910         if ( (dtseg->hasPhi()) && (! isDTWithoutY) ) {
00911           int phiHits = dtseg->phiSegment()->specificRecHits().size();
00912           //      int zHits = dtseg->zSegment()->specificRecHits().size();
00913           int hits=0;
00914           double t0=0.;
00915           // TODO: cuts on hit numbers not optimized in any way yet...
00916           if (phiHits>5 && dtseg->phiSegment()->ist0Valid()) {
00917             t0+=dtseg->phiSegment()->t0()*phiHits;
00918             hits+=phiHits;
00919             LogTrace("TrackAssociator") << " Phi t0: " << dtseg->phiSegment()->t0() << " hits: " << phiHits;
00920           }
00921           // the z segments seem to contain little useful information...
00922 //        if (zHits>3) {
00923 //          t0+=s->zSegment()->t0()*zHits;
00924 //          hits+=zHits;
00925 //          std::cout << "   Z t0: " << s->zSegment()->t0() << " hits: " << zHits << std::endl;
00926 //        }
00927           if (hits) muonSegment.t0 = t0/hits;
00928 //        std::cout << " --- t0: " << muonSegment.t0 << std::endl;
00929         } else {
00930            // check and set dimensionality
00931            if (isDTWithoutY) muonSegment.hasZed = false;
00932            if (! dtseg->hasPhi()) muonSegment.hasPhi = false;
00933         }
00934       }
00935       matchedChamber.segments.push_back(muonSegment);
00936    }
00937 
00938    return isGood;
00939 }
00940 
00941 //********************** NON-CORE CODE ******************************//
00942 
00943 void TrackDetectorAssociator::fillCaloTruth( const edm::Event& iEvent,
00944                                              TrackDetMatchInfo& info,
00945                                              const AssociatorParameters& parameters)
00946 {
00947    // get list of simulated tracks and their vertices
00948    using namespace edm;
00949    Handle<SimTrackContainer> simTracks;
00950    iEvent.getByLabel<SimTrackContainer>("g4SimHits", simTracks);
00951    if (! simTracks.isValid() ) throw cms::Exception("FatalError") << "No simulated tracks found\n";
00952    
00953    Handle<SimVertexContainer> simVertices;
00954    iEvent.getByLabel<SimVertexContainer>("g4SimHits", simVertices);
00955    if (! simVertices.isValid() ) throw cms::Exception("FatalError") << "No simulated vertices found\n";
00956    
00957    // get sim calo hits
00958    Handle<PCaloHitContainer> simEcalHitsEB;
00959    iEvent.getByLabel("g4SimHits","EcalHitsEB",simEcalHitsEB);
00960    if (! simEcalHitsEB.isValid() ) throw cms::Exception("FatalError") << "No simulated ECAL EB hits found\n";
00961 
00962    Handle<PCaloHitContainer> simEcalHitsEE;
00963    iEvent.getByLabel("g4SimHits","EcalHitsEE",simEcalHitsEE);
00964    if (! simEcalHitsEE.isValid() ) throw cms::Exception("FatalError") << "No simulated ECAL EE hits found\n";
00965 
00966    Handle<PCaloHitContainer> simHcalHits;
00967    iEvent.getByLabel("g4SimHits","HcalHits",simHcalHits);
00968    if (! simHcalHits.isValid() ) throw cms::Exception("FatalError") << "No simulated HCAL hits found\n";
00969 
00970    // find truth partner
00971    SimTrackContainer::const_iterator simTrack = simTracks->begin();
00972    for( ; simTrack != simTracks->end(); ++simTrack){
00973       math::XYZVector simP3( simTrack->momentum().x(), simTrack->momentum().y(), simTrack->momentum().z() );
00974       math::XYZVector recoP3( info.stateAtIP.momentum().x(), info.stateAtIP.momentum().y(), info.stateAtIP.momentum().z() );
00975       if ( ROOT::Math::VectorUtil::DeltaR(recoP3, simP3) < 0.1 ) break;
00976    }
00977    if ( simTrack != simTracks->end() ) {
00978       info.simTrack = &(*simTrack);
00979       double ecalTrueEnergy(0);
00980       double hcalTrueEnergy(0);
00981       
00982       // loop over calo hits
00983       for( PCaloHitContainer::const_iterator hit = simEcalHitsEB->begin(); hit != simEcalHitsEB->end(); ++hit )
00984         if ( hit->geantTrackId() == info.simTrack->genpartIndex() ) ecalTrueEnergy += hit->energy();
00985       
00986       for( PCaloHitContainer::const_iterator hit = simEcalHitsEE->begin(); hit != simEcalHitsEE->end(); ++hit )
00987         if ( hit->geantTrackId() == info.simTrack->genpartIndex() ) ecalTrueEnergy += hit->energy();
00988       
00989       for( PCaloHitContainer::const_iterator hit = simHcalHits->begin(); hit != simHcalHits->end(); ++hit )
00990         if ( hit->geantTrackId() == info.simTrack->genpartIndex() ) hcalTrueEnergy += hit->energy();
00991       
00992       info.ecalTrueEnergy = ecalTrueEnergy;
00993       info.hcalTrueEnergy = hcalTrueEnergy;
00994       info.hcalTrueEnergyCorrected = hcalTrueEnergy;
00995       if ( fabs(info.trkGlobPosAtHcal.eta()) < 1.3 )
00996         info.hcalTrueEnergyCorrected = hcalTrueEnergy*113.2;
00997       else 
00998         if ( fabs(info.trkGlobPosAtHcal.eta()) < 3.0 )
00999           info.hcalTrueEnergyCorrected = hcalTrueEnergy*167.2;
01000    }
01001 }
01002 
01003 TrackDetMatchInfo TrackDetectorAssociator::associate( const edm::Event& iEvent,
01004                                                       const edm::EventSetup& iSetup,
01005                                                       const reco::Track& track,
01006                                                       const AssociatorParameters& parameters,
01007                                                       Direction direction /*= Any*/ )
01008 {
01009    double currentStepSize = cachedTrajectory_.getPropagationStep();
01010    
01011    edm::ESHandle<MagneticField> bField;
01012    iSetup.get<IdealMagneticFieldRecord>().get(bField);
01013 
01014    if(track.extra().isNull()) {
01015       if ( direction != InsideOut ) 
01016         throw cms::Exception("FatalError") << 
01017         "No TrackExtra information is available and association is done with something else than InsideOut track.\n" <<
01018         "Either change the parameter or provide needed data!\n";
01019      LogTrace("TrackAssociator") << "Track Extras not found\n";
01020      FreeTrajectoryState initialState = trajectoryStateTransform::initialFreeState(track,&*bField);
01021      return associate(iEvent, iSetup, parameters, &initialState); // 5th argument is null pointer
01022    }
01023    
01024    LogTrace("TrackAssociator") << "Track Extras found\n";
01025    FreeTrajectoryState innerState = trajectoryStateTransform::innerFreeState(track,&*bField);
01026    FreeTrajectoryState outerState = trajectoryStateTransform::outerFreeState(track,&*bField);
01027    FreeTrajectoryState referenceState = trajectoryStateTransform::initialFreeState(track,&*bField);
01028    
01029    LogTrace("TrackAssociator") << "inner track state (rho, z, phi):" << 
01030      track.innerPosition().Rho() << ", " << track.innerPosition().z() <<
01031      ", " << track.innerPosition().phi() << "\n";
01032    LogTrace("TrackAssociator") << "innerFreeState (rho, z, phi):" << 
01033      innerState.position().perp() << ", " << innerState.position().z() <<
01034      ", " << innerState.position().phi() << "\n";
01035    
01036    LogTrace("TrackAssociator") << "outer track state (rho, z, phi):" << 
01037      track.outerPosition().Rho() << ", " << track.outerPosition().z() <<
01038      ", " << track.outerPosition().phi() << "\n";
01039    LogTrace("TrackAssociator") << "outerFreeState (rho, z, phi):" << 
01040      outerState.position().perp() << ", " << outerState.position().z() <<
01041      ", " << outerState.position().phi() << "\n";
01042    
01043    // InsideOut first
01044    if ( crossedIP( track ) ) {
01045       switch ( direction ) {
01046        case InsideOut:
01047        case Any:
01048          return associate(iEvent, iSetup, parameters, &referenceState, &outerState);
01049          break;
01050        case OutsideIn:
01051            {
01052               cachedTrajectory_.setPropagationStep( -fabs(currentStepSize) );
01053               TrackDetMatchInfo result = associate(iEvent, iSetup, parameters, &innerState, &referenceState);
01054               cachedTrajectory_.setPropagationStep( currentStepSize );
01055               return result;
01056               break;
01057            }
01058       }
01059    } else {
01060       switch ( direction ) {
01061        case InsideOut:
01062          return associate(iEvent, iSetup, parameters, &innerState, &outerState);
01063          break;
01064        case OutsideIn:
01065            {
01066               cachedTrajectory_.setPropagationStep( -fabs(currentStepSize) );
01067               TrackDetMatchInfo result = associate(iEvent, iSetup, parameters, &outerState, &innerState);
01068               cachedTrajectory_.setPropagationStep( currentStepSize );
01069               return result;
01070               break;
01071            }
01072        case Any:
01073            {
01074               // check if we deal with clear outside-in case
01075               if ( track.innerPosition().Dot( track.innerMomentum() ) < 0 &&
01076                    track.outerPosition().Dot( track.outerMomentum() ) < 0 )
01077                 {
01078                    cachedTrajectory_.setPropagationStep( -fabs(currentStepSize) );
01079                    TrackDetMatchInfo result;
01080                    if ( track.innerPosition().R() < track.outerPosition().R() )
01081                      result = associate(iEvent, iSetup, parameters, &innerState, &outerState);
01082                    else
01083                      result = associate(iEvent, iSetup, parameters, &outerState, &innerState);
01084                    cachedTrajectory_.setPropagationStep( currentStepSize );
01085                    return result;
01086                 }
01087            }
01088       }
01089    }
01090         
01091    // all other cases  
01092    return associate(iEvent, iSetup, parameters, &innerState, &outerState);
01093 }
01094 
01095 TrackDetMatchInfo TrackDetectorAssociator::associate( const edm::Event& iEvent,
01096                                                       const edm::EventSetup& iSetup,
01097                                                       const SimTrack& track,
01098                                                       const SimVertex& vertex,
01099                                                       const AssociatorParameters& parameters)
01100 {
01101    return associate(iEvent, iSetup, getFreeTrajectoryState(iSetup, track, vertex), parameters);
01102 }
01103 
01104 TrackDetMatchInfo TrackDetectorAssociator::associate( const edm::Event& iEvent,
01105                                                       const edm::EventSetup& iSetup,
01106                                                       const GlobalVector& momentum,
01107                                                       const GlobalPoint& vertex,
01108                                                       const int charge,
01109                                                       const AssociatorParameters& parameters)
01110 {
01111    return associate(iEvent, iSetup, getFreeTrajectoryState(iSetup, momentum, vertex, charge), parameters);
01112 }
01113 
01114 bool TrackDetectorAssociator::crossedIP( const reco::Track& track )
01115 {
01116    bool crossed = true;
01117    crossed &= (track.innerPosition().rho() > 3 ); // something close to active volume
01118    crossed &= (track.outerPosition().rho() > 3 ); // something close to active volume
01119    crossed &=  ( ( track.innerPosition().x()*track.innerMomentum().x() +
01120                    track.innerPosition().y()*track.innerMomentum().y() < 0 ) !=
01121                  ( track.outerPosition().x()*track.outerMomentum().x() + 
01122                    track.outerPosition().y()*track.outerMomentum().y() < 0 ) );
01123    return crossed;
01124 }