00001 #include "RecoEgamma/EgammaPhotonAlgos/interface/OutInConversionSeedFinder.h"
00002 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionBarrelEstimator.h"
00003 #include "RecoEgamma/EgammaPhotonAlgos/interface/ConversionForwardEstimator.h"
00004
00005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00006
00007 #include "MagneticField/Engine/interface/MagneticField.h"
00008
00009 #include "DataFormats/CLHEP/interface/AlgebraicObjects.h"
00010
00011 #include "Geometry/Records/interface/IdealGeometryRecord.h"
00012 #include "Geometry/CaloGeometry/interface/CaloSubdetectorGeometry.h"
00013
00014 #include "TrackingTools/TrajectoryParametrization/interface/GlobalTrajectoryParameters.h"
00015 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00016 #include "TrackingTools/DetLayers/interface/DetLayer.h"
00017 #include "TrackingTools/MeasurementDet/interface/LayerMeasurements.h"
00018
00019 #include "RecoTracker/TkDetLayers/interface/GeometricSearchTracker.h"
00020 #include "RecoTracker/MeasurementDet/interface/MeasurementTracker.h"
00021
00022
00023 #include "CLHEP/Units/PhysicalConstants.h"
00024 #include "CLHEP/Geometry/Point3D.h"
00025 #include <cfloat>
00026
00027
00028 OutInConversionSeedFinder::OutInConversionSeedFinder( const edm::ParameterSet& conf ): ConversionSeedFinder( conf ), conf_(conf)
00029 {
00030
00031 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder CTOR " << "\n";
00032
00033
00034 the2ndHitdphi_ = 0.03;
00035 the2ndHitdzConst_ = 5.;
00036 the2ndHitdznSigma_ = 2.;
00037 maxNumberOfOutInSeedsPerBC_=50;
00038
00039
00040 }
00041
00042
00043
00044
00045 OutInConversionSeedFinder::~OutInConversionSeedFinder() {
00046 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder DTOR " << "\n";
00047
00048 }
00049
00050
00051
00052 void OutInConversionSeedFinder::makeSeeds( const edm::Handle<edm::View<reco::CaloCluster> > & allBC ) const {
00053
00054
00055 theSeeds_.clear();
00056
00057
00058
00059
00060
00061
00062
00063
00064 findLayers();
00065
00066
00067
00068
00069 float theSCPhi=theSCPosition_.phi();
00070 float theSCEta=theSCPosition_.eta();
00071
00072
00073
00074
00075 reco::CaloClusterCollection::const_iterator bcItr;
00076 LogDebug("OutInConversionSeedFinder") << " OutInConversionSeedFinder::makeSeeds() All BC in the event " << "\n";
00077 for (unsigned i = 0; i < allBC->size(); ++i ) {
00078
00079
00080 nSeedsPerBC_=0;
00081
00082 theBCEnergy_=allBC->ptrAt(i)->energy();
00083 theBCPosition_ = GlobalPoint(allBC->ptrAt(i)->position().x(), allBC->ptrAt(i)->position().y(), allBC->ptrAt(i)->position().z() ) ;
00084 float theBcEta= theBCPosition_.eta();
00085 float theBcPhi= theBCPosition_.phi();
00086 float dPhi= theBcPhi-theSCPhi;
00087
00088
00089
00090 if ( theBCEnergy_ < 1.5 ) continue;
00091
00092 LogDebug("OutInConversionSeedFinder") << " OutInConversionSeedFinder::makeSeeds() Passing the >=1.5 GeV cut BC eta " << theBcEta << " phi " << theBcPhi << " BC energy " << theBCEnergy_ << "\n";
00093
00094 if ( fabs(theBcEta-theSCEta) < 0.015 && fabs(theBcPhi-theSCPhi) < 0.25 ) {
00095 LogDebug("OutInConversionSeedFinder") << " OutInConversionSeedFinder::makeSeeds() in et and phi range passed to the analysis " << "\n";
00096 fillClusterSeeds( allBC->ptrAt(i) );
00097 }
00098
00099
00100 }
00101
00102
00103
00104
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 }
00142
00143
00144
00145 void OutInConversionSeedFinder::makeSeeds( const reco::CaloClusterPtr& aBC ) const {
00146
00147 theSeeds_.clear();
00148
00149 findLayers();
00150
00151 float theSCPhi=theSCPosition_.phi();
00152 float theSCEta=theSCPosition_.eta();
00153
00154 nSeedsPerBC_=0;
00155
00156 theBCEnergy_=aBC->energy();
00157 theBCPosition_ = GlobalPoint(aBC->position().x(), aBC->position().y(), aBC->position().z() ) ;
00158 float theBcEta= theBCPosition_.eta();
00159 float theBcPhi= theBCPosition_.phi();
00160 float dPhi= theBcPhi-theSCPhi;
00161
00162 if ( theBCEnergy_ < 1.5 ) return;
00163
00164 if ( fabs(theBcEta-theSCEta) < 0.015 && fabs(theBcPhi-theSCPhi) < 0.25 ) {
00165 fillClusterSeeds( aBC);
00166 }
00167
00168 }
00169
00170
00171
00172
00173
00174 void OutInConversionSeedFinder::fillClusterSeeds(const reco::CaloClusterPtr& bc) const {
00175
00176
00177 theFirstMeasurements_.clear();
00178 FreeTrajectoryState fts;
00179
00181 if ( makeTrackState(-1).second ) {
00182 fts = makeTrackState(-1).first;
00183 startSeed(fts);
00184 }
00186
00187 if ( makeTrackState(1).second ) {
00188 fts = makeTrackState(1).first;
00189 startSeed(fts);
00190 }
00191
00192 }
00193
00194
00195
00196 std::pair<FreeTrajectoryState,bool> OutInConversionSeedFinder::makeTrackState(int charge) const {
00197
00198 std::pair<FreeTrajectoryState,bool> result;
00199 result.second=false;
00200
00201
00202
00203
00204
00205
00206
00207 GlobalPoint gpOrigine(0.,0.,0.);
00208 GlobalVector gvBcRadius = theBCPosition_ - gpOrigine ;
00209 HepPoint3D radiusBc(gvBcRadius.x(),gvBcRadius.y(),gvBcRadius.z()) ;
00210 HepPoint3D momentumWithoutCurvature = radiusBc.unit() * theBCEnergy_ ;
00211
00212
00213 double curvature = theMF_->inTesla(theBCPosition_).z() * c_light * 1.e-3 / momentumWithoutCurvature.perp() ;
00214 curvature /= 100. ;
00215
00216 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::makeTrackState gpOrigine " << gpOrigine.x() << " " << gpOrigine.y() << " " << gpOrigine.z() << " momentumWithoutCurvature " << momentumWithoutCurvature.mag() << " curvature " << curvature << "\n";
00217
00218
00219 float R = theBCPosition_.perp();
00220 float r = gpOrigine.perp();
00221 float rho = 1./curvature;
00222
00223
00224 float d = sqrt(r*r+rho*rho);
00225 float u = rho + rho/d/d*(R*R-rho*rho) - r/d/d*sqrt((R*R-r*r+2*rho*R)*(R*R-r*r+2*rho*R));
00226
00227 if ( u <=R ) result.second=true;
00228
00229 double sinAlpha = 0.5*u/R;
00230 if ( sinAlpha>(1.-10*DBL_EPSILON) ) sinAlpha = 1.-10*DBL_EPSILON;
00231 else if ( sinAlpha<-(1.-10*DBL_EPSILON) ) sinAlpha = -(1.-10*DBL_EPSILON);
00232
00233 double newdphi = charge * asin( sinAlpha) ;
00234
00235 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::makeTrackState charge " << charge << " R " << R << " u/R " << u/R << " asin(0.5*u/R) " << asin(sinAlpha) << "\n";
00236
00237 HepTransform3D rotation = HepRotate3D(newdphi, HepVector3D(0., 0. ,1.));
00238
00239
00240 HepPoint3D momentumInTracker = momentumWithoutCurvature.transform(rotation) ;
00241 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::makeTrackState R " << R << " r " << r << " rho " << rho << " d " << d << " u " << u << " newdphi " << newdphi << " momentumInTracker " << momentumInTracker << "\n";
00242
00243 HepPoint3D hepStartingPoint(gpOrigine.x(), gpOrigine.y(), gpOrigine.z()) ;
00244
00245 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::makeTrackState hepStartingPoint " << hepStartingPoint << "\n";
00246
00247 hepStartingPoint.transform(rotation);
00248
00249 GlobalPoint startingPoint(hepStartingPoint.x(), hepStartingPoint.y(), hepStartingPoint.z());
00250
00251 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::makeTrackState startingPoint " << startingPoint << " calo position " << theBCPosition_ << "\n";
00252 GlobalVector gvTracker(momentumInTracker.x(), momentumInTracker.y(), momentumInTracker.z());
00253 GlobalTrajectoryParameters gtp(startingPoint, gvTracker, charge, &(*theMF_) );
00254
00255 AlgebraicSymMatrix55 m = AlgebraicMatrixID();
00256 m(0,0) = 0.1; m(1,1) = 0.1 ; m(2,2) = 0.1 ;
00257 m(3,3) = 0.1 ; m(4,4) = 0.1;
00258
00259
00260
00261 result.first= FreeTrajectoryState(gtp, CurvilinearTrajectoryError(m) ) ;
00262 return result;
00263
00264 }
00265
00266
00267 void OutInConversionSeedFinder::startSeed(const FreeTrajectoryState & fts) const {
00268
00269
00270
00271
00272
00273 std::vector<const DetLayer*> myLayers=layerList();
00274 if ( myLayers.size() > 3 ) {
00275
00276 for(unsigned int ilayer = myLayers.size()-1; ilayer >= myLayers.size()-2; --ilayer) {
00277 const DetLayer * layer = myLayers[ilayer];
00278
00279
00280
00281
00282
00283 float dphi = 0.030;
00284
00285 MeasurementEstimator * newEstimator = makeEstimator(layer, dphi);
00286
00287
00288 PropagatorWithMaterial thePropagatorWithMaterial_ (alongMomentum, 0.000511, &(*theMF_) );
00289
00290
00291
00292
00293 TSOS tsos(fts, layer->surface() );
00294
00295 LogDebug("OutInConversionSeedFinder") << "OutInSeedFinder::startSeed after TSOS tsos(fts, layer->surface() ) " << "\n";
00296
00297 LayerMeasurements theLayerMeasurements_(this->getMeasurementTracker() );
00298 theFirstMeasurements_ = theLayerMeasurements_.measurements( *layer, tsos, thePropagatorWithMaterial_, *newEstimator);
00299
00300
00301
00302 if(theFirstMeasurements_.size() > 1)
00303 LogDebug("OutInConversionSeedFinder") << " Found " << theFirstMeasurements_.size()-1 << " 1st hits in seed" << "\n";
00304
00305 delete newEstimator;
00306
00307 LogDebug("OutInConversionSeedFinder") << "OutInSeedFinder::startSeed Layer " << ilayer << " theFirstMeasurements_.size " << theFirstMeasurements_.size() << "\n";
00308
00309 for(unsigned int i = 0; i < theFirstMeasurements_.size(); ++i) {
00310 TrajectoryMeasurement m1 = theFirstMeasurements_[i];
00311 if(m1.recHit()->isValid()) {
00312
00313
00314
00315 GlobalPoint hitPoint = m1.recHit()->globalPosition();
00316 LogDebug("OutInConversionSeedFinder") << " Valid hit at R " << m1.recHit()->globalPosition().perp() << " Z " << m1.recHit()->globalPosition().z() << " eta " << m1.recHit()->globalPosition().eta() << " phi " << m1.recHit()->globalPosition().phi() << " xyz " << m1.recHit()->globalPosition() << "\n";
00317
00318
00319 FreeTrajectoryState newfts = trackStateFromClusters(fts.charge(), hitPoint, alongMomentum, 0.8);
00320 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::startSeed newfts " << newfts << "\n";
00321
00322 PropagatorWithMaterial thePropagatorWithMaterial_ (oppositeToMomentum, 0.000511, &(*theMF_) );
00323
00324
00325
00326 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::startSeed propagationDirection after switching " << int(thePropagatorWithMaterial_.propagationDirection() ) << "\n";
00327
00328
00329 completeSeed(m1, newfts, &thePropagatorWithMaterial_, ilayer-1);
00330
00331 if(ilayer == myLayers.size()-1) {
00332 completeSeed(m1, newfts, &thePropagatorWithMaterial_, ilayer-2);
00333 }
00334 }
00335 }
00336
00337 }
00338 }
00339
00340
00341
00342
00343 }
00344
00345
00346
00347 MeasurementEstimator * OutInConversionSeedFinder::makeEstimator(const DetLayer * layer, float dphi) const {
00348
00349
00350
00351 MeasurementEstimator * newEstimator=0;
00352
00353 if (layer->location() == GeomDetEnumerators::barrel ) {
00354
00355 const BarrelDetLayer * barrelLayer = dynamic_cast<const BarrelDetLayer*>(layer);
00356 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::makeEstimator Barrel r = " << barrelLayer->specificSurface().radius() << " " << "\n";
00357 float r = barrelLayer->specificSurface().radius();
00358 float zrange = 15.* (1.-r/theBCPosition_.perp());
00359 newEstimator = new ConversionBarrelEstimator(-dphi, dphi, -zrange, zrange);
00360 }
00361
00362
00363
00364 if (layer->location() == GeomDetEnumerators::endcap ) {
00365
00366 const ForwardDetLayer * forwardLayer = dynamic_cast<const ForwardDetLayer*>(layer);
00367 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::makeEstimator Endcap r = " << forwardLayer->specificSurface().innerRadius() << " R " << forwardLayer->specificSurface().outerRadius() << " Z " << forwardLayer->specificSurface().position().z() << "\n";
00368
00369 float zc = fabs(theBCPosition_.z());
00370 float z = fabs(forwardLayer->surface().position().z());
00371
00372 float rrange = 15. * theBCPosition_.perp() * (zc - z) / (zc*zc - 15.*zc);
00373 newEstimator = new ConversionForwardEstimator(-dphi, dphi, rrange);
00374 }
00375
00376
00377
00378
00379 return newEstimator;
00380 }
00381
00382
00383
00384
00385 void OutInConversionSeedFinder::completeSeed(const TrajectoryMeasurement & m1,
00386 FreeTrajectoryState & fts,
00387 const Propagator* propagator, int ilayer) const {
00388
00389
00390
00391 MeasurementEstimator * newEstimator=0;
00392 const DetLayer * layer = theLayerList_[ilayer];
00393
00394
00395 if ( layer->location() == GeomDetEnumerators::barrel ) {
00396
00397 LogDebug("OutInConversionSeedFinder") << " Barrel OutInConversionSeedFinder::completeSeed " << the2ndHitdznSigma_ << " " << the2ndHitdzConst_ << " " << the2ndHitdphi_ << "\n";
00398 float dz = sqrt(the2ndHitdznSigma_*the2ndHitdznSigma_*m1.recHit()->globalPositionError().czz()
00399 + the2ndHitdzConst_*the2ndHitdzConst_);
00400 newEstimator =
00401 new ConversionBarrelEstimator(-the2ndHitdphi_, the2ndHitdphi_, -dz, dz);
00402 }
00403 else {
00404 LogDebug("OutInConversionSeedFinder") << " EndCap OutInConversionSeedFinder::completeSeed " << the2ndHitdznSigma_ << " " << the2ndHitdzConst_ << " " << the2ndHitdphi_ << "\n";
00405
00406
00407 float m1dr = sqrt(m1.recHit()->localPositionError().yy());
00408 float dr = sqrt(the2ndHitdznSigma_*the2ndHitdznSigma_*m1dr*m1dr
00409 + the2ndHitdzConst_*the2ndHitdznSigma_);
00410
00411 newEstimator =
00412 new ConversionForwardEstimator(-the2ndHitdphi_, the2ndHitdphi_, dr);
00413 }
00414
00415 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::completeSeed ilayer " << ilayer << "\n";
00416
00417
00418 TSOS tsos(fts, layer->surface() );
00419 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::completeSeed propagationDirection " << int(propagator->propagationDirection() ) << "\n";
00420 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::completeSeed pointer to estimator " << newEstimator << "\n";
00421
00422 LayerMeasurements theLayerMeasurements_(this->getMeasurementTracker() );
00423 std::vector<TrajectoryMeasurement> measurements = theLayerMeasurements_.measurements( *layer, tsos, *propagator, *newEstimator);
00424
00425 delete newEstimator;
00426
00427 for(unsigned int i = 0; i < measurements.size(); ++i) {
00428 if( measurements[i].recHit()->isValid() ) {
00429 createSeed(m1, measurements[i]);
00430 }
00431 }
00432
00433
00434
00435
00436 }
00437
00438
00439
00440 void OutInConversionSeedFinder::createSeed(const TrajectoryMeasurement & m1,
00441 const TrajectoryMeasurement & m2) const {
00442
00443
00444
00445
00446 FreeTrajectoryState fts = createSeedFTS(m1, m2);
00447
00448
00449 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::createSeed First point errors " <<m1.recHit()->parametersError() << "\n";
00450 LogDebug("OutInConversionSeedFinder") << "original cluster FTS " << fts <<"\n";
00451
00452
00453 PropagatorWithMaterial thePropagatorWithMaterial_ (oppositeToMomentum, 0.000511, &(*theMF_) );
00454
00455 TrajectoryStateOnSurface state1 = thePropagatorWithMaterial_.propagate(fts, m1.recHit()->det()->surface());
00456
00457
00458
00459
00460
00461
00462 if ( state1.isValid() ) {
00463 TrajectoryStateOnSurface updatedState1 = theUpdator_.update(state1, *m1.recHit() );
00464
00465 if ( updatedState1.isValid() ) {
00466 TrajectoryStateOnSurface state2 = thePropagatorWithMaterial_.propagate(*updatedState1.freeTrajectoryState(), m2.recHit()->det()->surface());
00467
00468 if ( state2.isValid() ) {
00469
00470 TrajectoryStateOnSurface updatedState2 = theUpdator_.update(state2, *m2.recHit() );
00471 TrajectoryMeasurement meas1(state1, updatedState1, m1.recHit() , m1.estimate(), m1.layer());
00472 TrajectoryMeasurement meas2(state2, updatedState2, m2.recHit() , m2.estimate(), m2.layer());
00473
00474 edm::OwnVector<TrackingRecHit> myHits;
00475 myHits.push_back(meas1.recHit()->hit()->clone());
00476 myHits.push_back(meas2.recHit()->hit()->clone());
00477
00478 if ( nSeedsPerBC_ >= maxNumberOfOutInSeedsPerBC_ ) return;
00479
00480 TrajectoryStateTransform tsTransform;
00481 PTrajectoryStateOnDet* ptsod= tsTransform.persistentState(state2, meas2.recHit()->hit()->geographicalId().rawId() );
00482
00483 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::createSeed new seed from state " << state2.globalPosition() << "\n";
00484 LogDebug("OutInConversionSeedFinder") << "OutInConversionSeedFinder::createSeed new seed ptsod " << ptsod->parameters().position() << " R " << ptsod->parameters().position().perp() << " phi " << ptsod->parameters().position().phi() << " eta " << ptsod->parameters().position().eta() << "\n" ;
00485
00486
00487
00488 theSeeds_.push_back(TrajectorySeed( *ptsod, myHits, oppositeToMomentum ));
00489 nSeedsPerBC_++;
00490
00491 delete ptsod;
00492
00493
00494 }
00495 }
00496 }
00497
00498
00499
00500
00501
00502 }
00503
00504
00505
00506
00507
00508 FreeTrajectoryState OutInConversionSeedFinder::createSeedFTS(const TrajectoryMeasurement & m1,
00509 const TrajectoryMeasurement & m2) const {
00510
00511
00512
00513 GlobalPoint xmeas = fixPointRadius(m1);
00514 GlobalPoint xvert = fixPointRadius(m2);
00515
00516
00517 float pt = theSCenergy_ * sin(theSCPosition_.theta());
00518 float pz = theSCenergy_ * cos(theSCPosition_.theta());
00519
00520
00521
00522
00523
00524
00525 int charge = m2.predictedState().charge();
00526
00527 double BInTesla = theMF_->inTesla(xmeas).z();
00528 GlobalVector xdiff = xmeas -xvert;
00529
00530 double phi= xdiff.phi();
00531 double pxOld = pt*cos(phi);
00532 double pyOld = pt*sin(phi);
00533 double RadCurv = 100*pt/(BInTesla*0.29979);
00534 double alpha = asin(0.5*xdiff.perp()/RadCurv);
00535 float ca = cos(charge*alpha);
00536 float sa = sin(charge*alpha);
00537 double pxNew = ca*pxOld + sa*pyOld;
00538 double pyNew = -sa*pxOld + ca*pyOld;
00539 GlobalVector pNew(pxNew, pyNew, pz);
00540
00541 GlobalTrajectoryParameters gp(xmeas, pNew, charge, &(*theMF_) );
00542
00543 AlgebraicSymMatrix55 m = AlgebraicMatrixID();
00544 m(0,0) = 0.05; m(1,1) = 0.02 ; m(2,2) = 0.007 ;
00545 m(3,3) = 10. ; m(4,4) = 10. ;
00546 return FreeTrajectoryState(gp, CurvilinearTrajectoryError(m));
00547
00548
00549 }
00550
00551
00552
00553
00554 GlobalPoint OutInConversionSeedFinder::fixPointRadius(const TrajectoryMeasurement& m1) const {
00555 GlobalPoint p1 = m1.recHit()->globalPosition();
00556 GlobalPoint p2;
00557 if(m1.layer()->location() == GeomDetEnumerators::barrel) {
00558 p2 = p1;
00559 } else {
00560 float z = p1.z();
00561 float phi = p1.phi();
00562 float theta = theSCPosition_.theta();
00563 float r = p1.z() * tan(theta);
00564 p2 = GlobalPoint(r*cos(phi), r*sin(phi), z);
00565
00566 }
00567 return p2;
00568 }
00569
00570
00571
00572
00573