CMS 3D CMS Logo

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