00001
00002
00003
00004
00005
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <memory>
00023 #include <map>
00024
00025
00026 #include "FWCore/Framework/interface/Frameworkfwd.h"
00027 #include "FWCore/Framework/interface/EDProducer.h"
00028
00029 #include "FWCore/Framework/interface/Event.h"
00030 #include "FWCore/Framework/interface/MakerMacros.h"
00031
00032 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00033 #include "FWCore/Framework/interface/ESHandle.h"
00034
00035 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00036
00037
00038 #include "DataFormats/EgammaReco/interface/BasicCluster.h"
00039 #include "DataFormats/EgammaReco/interface/BasicClusterFwd.h"
00040 #include "DataFormats/EgammaReco/interface/SuperCluster.h"
00041 #include "DataFormats/EgammaReco/interface/SuperClusterFwd.h"
00042 #include "DataFormats/CaloRecHit/interface/CaloCluster.h"
00043
00044 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00045
00046
00047 #include "DataFormats/TrackReco/interface/TrackFwd.h"
00048 #include "DataFormats/TrackReco/interface/Track.h"
00049
00050 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00051 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00052 #include "DataFormats/TrajectoryState/interface/PTrajectoryStateOnDet.h"
00053 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00054 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00055 #include "Geometry/CommonDetUnit/interface/GeomDetUnit.h"
00056 #include "DataFormats/GeometrySurface/interface/BoundCylinder.h"
00057 #include "DataFormats/GeometrySurface/interface/BoundDisk.h"
00058 #include "DataFormats/GeometrySurface/interface/SimpleCylinderBounds.h"
00059 #include "DataFormats/GeometrySurface/interface/SimpleDiskBounds.h"
00060
00061 #include "MagneticField/Engine/interface/MagneticField.h"
00062 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00063 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00064 #include "TrackingTools/MaterialEffects/interface/PropagatorWithMaterial.h"
00065 #include "DataFormats/TrackingRecHit/interface/TrackingRecHit.h"
00066 #include "DataFormats/EcalDetId/interface/EcalSubdetector.h"
00067
00068 #include "TrackingTools/TransientTrack/interface/TrackTransientTrack.h"
00069 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00070
00071 #include "DataFormats/VertexReco/interface/Vertex.h"
00072 #include "DataFormats/VertexReco/interface/VertexFwd.h"
00073
00074 #include "TrackingTools/TransientTrack/interface/TransientTrackBuilder.h"
00075 #include "TrackingTools/Records/interface/TransientTrackRecord.h"
00076 #include "TrackingTools/TransientTrack/interface/TransientTrack.h"
00077
00078
00079
00080
00081
00082 #include "DataFormats/EgammaCandidates/interface/Photon.h"
00083 #include "DataFormats/EgammaCandidates/interface/PhotonFwd.h"
00084 #include "DataFormats/EgammaCandidates/interface/Conversion.h"
00085 #include "DataFormats/EgammaCandidates/interface/ConversionFwd.h"
00086
00087 using namespace edm;
00088 using namespace reco;
00089 using namespace std;
00090
00091
00092
00093
00094
00095 inline const GeomDet * recHitDet( const TrackingRecHit & hit, const TrackingGeometry * geom ) {
00096 return geom->idToDet( hit.geographicalId() );
00097 }
00098
00099 inline const BoundPlane & recHitSurface( const TrackingRecHit & hit, const TrackingGeometry * geom ) {
00100 return recHitDet( hit, geom )->surface();
00101 }
00102
00103 inline LocalVector toLocal( const Track::Vector & v, const Surface & s ) {
00104 return s.toLocal( GlobalVector( v.x(), v.y(), v.z() ) );
00105 }
00106
00107 inline double map_phi2(double phi) {
00108
00109 double result = phi;
00110 if ( result < 1.0*Geom::pi() ) result = result + Geom::twoPi();
00111 if ( result >= Geom::pi()) result = result - Geom::twoPi();
00112 return result;
00113 }
00114
00115 class TrackerOnlyConversionProducer : public edm::EDProducer {
00116 public:
00117 explicit TrackerOnlyConversionProducer(const edm::ParameterSet&);
00118 ~TrackerOnlyConversionProducer();
00119
00120 private:
00121 virtual void beginJob(const edm::EventSetup&) ;
00122 virtual void produce(edm::Event&, const edm::EventSetup&);
00123 virtual void endJob() ;
00124 virtual void beginRun(const edm::Run&, const edm::EventSetup&);
00125 virtual void endRun(const edm::Run&, const edm::EventSetup&);
00126
00127
00128 typedef math::XYZPointD Point;
00129 typedef std::vector<Point> PointCollection;
00130
00131 std::vector<edm::InputTag> src_;
00132
00133 edm::InputTag bcBarrelCollection_;
00134 edm::InputTag bcEndcapCollection_;
00135 std::string ConvertedPhotonCollection_;
00136
00137 double halfWayEta_, halfWayPhi_;
00138
00139 double energyBC_;
00140 double dEtaTkBC_, dPhiTkBC_;
00141
00142 double maxChi2Left_, maxChi2Right_;
00143 double maxHitsLeft_, maxHitsRight_;
00144
00145 double deltaCotTheta_, deltaPhi_;
00146
00147 bool allowSingleLeg_;
00148
00149 };
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 TrackerOnlyConversionProducer::TrackerOnlyConversionProducer(const edm::ParameterSet& iConfig)
00164 {
00165 src_ = iConfig.getParameter<std::vector<edm::InputTag> >("src");
00166
00167
00168 bcBarrelCollection_ = iConfig.getParameter<edm::InputTag>("bcBarrelCollection");
00169 bcEndcapCollection_ = iConfig.getParameter<edm::InputTag>("bcEndcapCollection");
00170
00171 halfWayEta_ = iConfig.getParameter<double>("HalfwayEta");
00172
00173
00174 dEtaTkBC_ = iConfig.getParameter<double>("dEtaTrackBC");
00175 dPhiTkBC_ = iConfig.getParameter<double>("dPhiTrackBC");
00176
00177 energyBC_ = iConfig.getParameter<double>("EnergyBC");
00178
00179
00180
00181
00182 maxChi2Left_ = iConfig.getParameter<double>("MaxChi2Left");
00183 maxChi2Right_ = iConfig.getParameter<double>("MaxChi2Right");
00184 maxHitsLeft_ = iConfig.getParameter<int>("MaxHitsLeft");
00185 maxHitsRight_ = iConfig.getParameter<int>("MaxHitsRight");
00186
00187
00188 deltaCotTheta_ = iConfig.getParameter<double>("DeltaCotTheta");
00189 deltaPhi_ = iConfig.getParameter<double>("DeltaPhi");
00190
00191
00192 allowSingleLeg_ = iConfig.getParameter<bool>("AllowSingleLeg");
00193
00194
00195 ConvertedPhotonCollection_ = iConfig.getParameter<std::string>("convertedPhotonCollection");
00196
00197 produces< reco::ConversionCollection >(ConvertedPhotonCollection_);
00198
00199 }
00200
00201
00202 TrackerOnlyConversionProducer::~TrackerOnlyConversionProducer()
00203 {
00204
00205
00206
00207
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 void
00217 TrackerOnlyConversionProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup)
00218 {
00219 using namespace edm;
00220
00221 reco::ConversionCollection outputConvPhotonCollection;
00222 std::auto_ptr<reco::ConversionCollection> outputConvPhotonCollection_p(new reco::ConversionCollection);
00223
00224
00225 std::vector<const reco::TrackCollection*> trackCollections;
00226 std::vector<edm::Handle<reco::TrackCollection> > trackCollectionHandles;
00227 for (unsigned ii = 0; ii<src_.size(); ++ii){
00228 edm::Handle<reco::TrackCollection> temp_handle;
00229 if(iEvent.getByLabel(src_[ii],temp_handle)){
00230 trackCollectionHandles.push_back(temp_handle);
00231 } else {
00232 edm::LogWarning("TrackerOnlyConversionProducer") << "Collection reco::TrackCollection with label " << src_[ii] << " cannot be found, using empty collection of same type";
00233 }
00234 }
00235 edm::Handle<edm::View<reco::CaloCluster> > bcBarrelHandle;
00236 iEvent.getByLabel( bcBarrelCollection_, bcBarrelHandle);
00237
00238 edm::Handle<edm::View<reco::CaloCluster> > bcEndcapHandle;
00239 iEvent.getByLabel( bcEndcapCollection_, bcEndcapHandle);
00240
00241 edm::ESHandle<TrackerGeometry> trackerGeomHandle;
00242 edm::ESHandle<MagneticField> magFieldHandle;
00243
00244 iSetup.get<TrackerDigiGeometryRecord>().get( trackerGeomHandle );
00245 iSetup.get<IdealMagneticFieldRecord>().get( magFieldHandle );
00246
00247 const TrackerGeometry* trackerGeom = trackerGeomHandle.product();
00248 const MagneticField* magField = magFieldHandle.product();;
00249
00250
00251
00252
00253 reco::TrackRefVector allTracks;
00254 int total_tracks = 0;
00255 for (unsigned int ii = 0; ii<trackCollectionHandles.size(); ++ii)
00256 total_tracks += trackCollectionHandles[ii]->size();
00257 allTracks.reserve(total_tracks);
00258
00259 for (unsigned int ii = 0; ii<trackCollectionHandles.size(); ++ii){
00260 if (!trackCollectionHandles[ii]->empty()){
00261 for (unsigned int jj = 0; jj<trackCollectionHandles[ii]->size(); ++jj){
00262 edm::Ref<reco::TrackCollection> ref(trackCollectionHandles[ii], jj);
00263 if (ref.isNonnull()){
00264 allTracks.push_back(ref);
00265 }
00266 }
00267 }
00268 }
00269
00270
00271 std::multimap<double, reco::CaloClusterPtr> basicClusterPtrs;
00272 edm::Handle<edm::View<reco::CaloCluster> > bcHandle = bcBarrelHandle;
00273 for (unsigned jj = 0; jj < 2; ++jj ){
00274 for (unsigned ii = 0; ii < bcHandle->size(); ++ii ) {
00275 if (bcHandle->ptrAt(ii)->energy()>energyBC_)
00276 basicClusterPtrs.insert(std::make_pair(bcHandle->ptrAt(ii)->position().eta(), bcHandle->ptrAt(ii)));
00277 }
00278 bcHandle = bcEndcapHandle;
00279 }
00280
00281 std::vector<math::XYZPoint> trackImpactPosition;
00282 trackImpactPosition.reserve(allTracks.size());
00283 std::vector<bool> trackValidECAL;
00284 trackValidECAL.assign(allTracks.size(), false);
00285
00286 std::vector<reco::CaloClusterPtr> trackMatchedBC;
00287 reco::CaloClusterPtr empty_bc;
00288 trackMatchedBC.assign(allTracks.size(), empty_bc);
00289
00290 std::multimap<double, int> trackInnerEta;
00291
00292
00293
00294 for (reco::TrackRefVector::const_iterator ref = allTracks.begin(); ref != allTracks.end(); ++ref){
00295 const TrackRef& tk_ref = *ref;
00296
00297 if (tk_ref->normalizedChi2() > maxChi2Left_ || tk_ref->found() < maxHitsLeft_
00298 ) continue;
00299
00300
00301 trackInnerEta.insert(std::make_pair(tk_ref->innerMomentum().eta(), ref-allTracks.begin()));
00302
00303 PropagatorWithMaterial propag( alongMomentum, 0.000511, magField );
00304 TrajectoryStateTransform transformer;
00305 ReferenceCountingPointer<Surface> ecalWall(
00306 new BoundCylinder( GlobalPoint(0.,0.,0.), TkRotation<float>(),
00307 SimpleCylinderBounds( 129, 129, -320.5, 320.5 ) ) );
00308 const float epsilon = 0.001;
00309 Surface::RotationType rot;
00310 const float barrelRadius = 129.f;
00311 const float barrelHalfLength = 270.9f;
00312 const float endcapRadius = 171.1f;
00313 const float endcapZ = 320.5f;
00314 ReferenceCountingPointer<BoundCylinder> theBarrel_(new BoundCylinder( Surface::PositionType(0,0,0), rot,
00315 SimpleCylinderBounds( barrelRadius-epsilon, barrelRadius+epsilon, -barrelHalfLength, barrelHalfLength)));
00316 ReferenceCountingPointer<BoundDisk> theNegativeEtaEndcap_(
00317 new BoundDisk( Surface::PositionType( 0, 0, -endcapZ), rot,
00318 SimpleDiskBounds( 0, endcapRadius, -epsilon, epsilon)));
00319 ReferenceCountingPointer<BoundDisk> thePositiveEtaEndcap_(
00320 new BoundDisk( Surface::PositionType( 0, 0, endcapZ), rot,
00321 SimpleDiskBounds( 0, endcapRadius, -epsilon, epsilon)));
00322
00323
00324 const TrajectoryStateOnSurface myTSOS = transformer.outerStateOnSurface(*tk_ref, *trackerGeom, magField);
00325 TrajectoryStateOnSurface stateAtECAL;
00326 stateAtECAL = propag.propagate(myTSOS, *theBarrel_);
00327 if (!stateAtECAL.isValid() || ( stateAtECAL.isValid() && fabs(stateAtECAL.globalPosition().eta() ) >1.479 ) ) {
00328
00329 if (myTSOS.globalPosition().eta() > 0.) {
00330 stateAtECAL = propag.propagate(myTSOS, *thePositiveEtaEndcap_);
00331 } else {
00332 stateAtECAL = propag.propagate(myTSOS, *theNegativeEtaEndcap_);
00333 }
00334 }
00335 math::XYZPoint ew;
00336 if (stateAtECAL.isValid()){
00337 ew = stateAtECAL.globalPosition();
00338 }
00339 trackImpactPosition.push_back(ew);
00340 if (!stateAtECAL.isValid()){ continue;}
00341
00342 const double track_eta = ew.eta();
00343 const double track_phi = ew.phi();
00344
00345
00346 reco::CaloClusterPtr closest_bc;
00347 double min_eta = 999., min_phi = 999.;
00348 for (std::multimap<double, reco::CaloClusterPtr>::iterator bc = basicClusterPtrs.lower_bound(track_eta - halfWayEta_);
00349 bc != basicClusterPtrs.upper_bound(track_eta + halfWayEta_); ++bc){
00350 const reco::CaloClusterPtr& ebc = bc->second;
00351 const double delta_eta = track_eta-(ebc->position().eta());
00352 const double delta_phi = map_phi2(track_phi-(ebc->position().phi()));
00353 if (fabs(delta_eta)<dEtaTkBC_ && fabs(delta_phi)<dPhiTkBC_){
00354 if (fabs(min_eta)>fabs(delta_eta) && fabs(min_phi)>fabs(delta_phi)){
00355 min_eta = delta_eta;
00356 min_phi = delta_phi;
00357 closest_bc = bc->second;
00358
00359 }
00360 }
00361 }
00362 if (min_eta < 999.){
00363 trackMatchedBC[ref-allTracks.begin()] = closest_bc;
00364 trackValidECAL[ref-allTracks.begin()] = true;
00365 }
00366 }
00367
00368
00369 reco::VertexCollection vertexs;
00370 std::vector<bool> isPaired;
00371 isPaired.assign(allTracks.size(), false);
00373 for( reco::TrackRefVector::const_iterator ll = allTracks.begin(); ll != allTracks.end(); ++ ll ) {
00374
00375 if (!trackValidECAL[ll-allTracks.begin()]
00376 || (*ll)->d0()*(*ll)->charge()<0.
00377 || isPaired[ll-allTracks.begin()])
00378 continue;
00379 const double left_eta = (*ll)->innerMomentum().eta();
00380 bool found_right = false;
00381 std::map<double, int> right_candidates;
00382
00383
00384 for (std::multimap<double, int>::iterator rr = trackInnerEta.lower_bound(left_eta - halfWayEta_);
00385 rr != trackInnerEta.upper_bound(left_eta + halfWayEta_); ++rr){
00386
00387
00388 const edm::Ref<reco::TrackCollection> & right = allTracks[rr->second];
00389
00390 if (right->normalizedChi2() > maxChi2Right_ || right->found() < maxHitsRight_
00391 || isPaired[rr->second]
00392
00393 || right->d0()*right->charge()<0.
00394 || ((*ll)->charge())*(right->charge()) > 0)
00395 continue;
00396
00397 const double theta_l = (*ll)->innerMomentum().Theta();
00398 const double theta_r = right->innerMomentum().Theta();
00399 const double dCotTheta = 1./tan(theta_l) - 1./tan(theta_r) ;
00400
00401 if (fabs(dCotTheta) > deltaCotTheta_) continue;
00402
00403 const double phi_l = (*ll)->innerMomentum().phi();
00404 const double phi_r = right->innerMomentum().phi();
00405 const double dPhi = phi_l - phi_r;
00406
00407 if (fabs(dPhi) > deltaPhi_) continue;
00408
00409
00410
00411 right_candidates.insert(std::pair<double, int>(theta_r, rr->second));
00412 }
00413
00414 double min_theta = 999.;
00415 edm::Ref<reco::TrackCollection> right;
00416 int right_index = -1;
00417 for (std::map<double, int>::iterator rr = right_candidates.begin(); rr != right_candidates.end(); ++rr){
00418 const double theta_l = (*ll)->innerMomentum().Theta();
00419 const double dCotTheta = 1./tan(theta_l) - 1./tan(rr->first);
00420 if (fabs(min_theta) > fabs(dCotTheta)){
00421 min_theta = dCotTheta;
00422 right_index = rr->second;
00423 right = allTracks[right_index];
00424 }
00425 }
00426 if (min_theta <999.){
00427
00428 std::vector<edm::Ref<reco::TrackCollection> > trackPairRef;
00429 trackPairRef.push_back((*ll));
00430 trackPairRef.push_back(right);
00431
00432 reco::CaloClusterPtrVector scPtrVec;
00433 reco::Vertex theConversionVertex;
00434 std::vector<math::XYZPoint> trkPositionAtEcal;
00435 std::vector<reco::CaloClusterPtr> matchingBC;
00436
00437 trkPositionAtEcal.push_back(trackImpactPosition[ll-allTracks.begin()]);
00438 if (trackValidECAL[right_index])
00439 trkPositionAtEcal.push_back(trackImpactPosition[right_index]);
00440
00441 matchingBC.push_back(trackMatchedBC[ll-allTracks.begin()]);
00442 scPtrVec.push_back(trackMatchedBC[ll-allTracks.begin()]);
00443 if (trackValidECAL[right_index]){
00444 matchingBC.push_back(trackMatchedBC[right_index]);
00445 scPtrVec.push_back(trackMatchedBC[right_index]);
00446 }
00447
00448
00449
00450
00451
00452 reco::Conversion newCandidate(scPtrVec, trackPairRef, trkPositionAtEcal, theConversionVertex, matchingBC);
00453 outputConvPhotonCollection.push_back(newCandidate);
00454
00455 found_right = true;
00456 isPaired[ll-allTracks.begin()] = true;
00457 isPaired[right_index] = true;
00458 break;
00459 }
00460 if (!found_right && allowSingleLeg_){
00461 std::vector<edm::Ref<reco::TrackCollection> > trackPairRef;
00462 trackPairRef.push_back((*ll));
00463
00464 reco::CaloClusterPtrVector scPtrVec;
00465 reco::Vertex theConversionVertex;
00466 std::vector<math::XYZPoint> trkPositionAtEcal;
00467 std::vector<reco::CaloClusterPtr> matchingBC;
00468
00469 trkPositionAtEcal.push_back(trackImpactPosition[ll-allTracks.begin()]);
00470
00471 matchingBC.push_back(trackMatchedBC[ll-allTracks.begin()]);
00472 scPtrVec.push_back(trackMatchedBC[ll-allTracks.begin()]);
00473
00474 reco::Conversion newCandidate(scPtrVec, trackPairRef, trkPositionAtEcal, theConversionVertex, matchingBC);
00475 outputConvPhotonCollection.push_back(newCandidate);
00476
00477 isPaired[ll-allTracks.begin()] = true;
00478 }
00479 }
00480
00481
00482 outputConvPhotonCollection_p->assign(outputConvPhotonCollection.begin(), outputConvPhotonCollection.end());
00483
00484 iEvent.put( outputConvPhotonCollection_p, ConvertedPhotonCollection_);
00485
00486
00487
00488 }
00489
00490
00491 void
00492 TrackerOnlyConversionProducer::beginJob(const edm::EventSetup&)
00493 {
00494 }
00495
00496
00497 void
00498 TrackerOnlyConversionProducer::endJob() {
00499 }
00500
00501 void
00502 TrackerOnlyConversionProducer::beginRun(const edm::Run& run, const edm::EventSetup& iSetup ) {
00503 }
00504
00505 void
00506 TrackerOnlyConversionProducer::endRun(const edm::Run & run, const edm::EventSetup & iSetup){
00507 }
00508
00509
00510 DEFINE_FWK_MODULE(TrackerOnlyConversionProducer);