CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/FastSimulation/Tracking/plugins/TrajectorySeedProducer.cc

Go to the documentation of this file.
00001 #include <memory>
00002 
00003 #include "FWCore/Framework/interface/Event.h"
00004 #include "FWCore/Framework/interface/EventSetup.h"
00005 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00006 #include "FWCore/Framework/interface/ESHandle.h"
00007 
00008 #include "DataFormats/Common/interface/Handle.h"
00009 #include "DataFormats/Common/interface/OwnVector.h"
00010 #include "DataFormats/TrackerRecHit2D/interface/SiTrackerGSRecHit2DCollection.h" 
00011 #include "DataFormats/TrackerRecHit2D/interface/SiTrackerGSMatchedRecHit2DCollection.h" 
00012 #include "DataFormats/TrajectorySeed/interface/TrajectorySeedCollection.h"
00013 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00014 #include "DataFormats/VertexReco/interface/Vertex.h"
00015 
00016 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00017 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00018 
00019 #include "FastSimulation/ParticlePropagator/interface/MagneticFieldMapRecord.h"
00020 
00021 #include "FastSimulation/Tracking/plugins/TrajectorySeedProducer.h"
00022 #include "FastSimulation/Tracking/interface/TrackerRecHit.h"
00023 
00024 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
00025 #include "SimDataFormats/Vertex/interface/SimVertexContainer.h"
00026 
00027 #include "TrackingTools/TrajectoryParametrization/interface/CurvilinearTrajectoryError.h"
00028 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00029 #include "TrackingTools/TrajectoryState/interface/FreeTrajectoryState.h"
00030 
00031 #include "Geometry/CommonDetUnit/interface/GeomDetUnit.h"
00032 #include "DataFormats/DetId/interface/DetId.h"
00033 
00034 #include "FastSimulation/BaseParticlePropagator/interface/BaseParticlePropagator.h"
00035 #include "FastSimulation/ParticlePropagator/interface/ParticlePropagator.h"
00036 
00037 //Propagator withMaterial
00038 #include "TrackingTools/MaterialEffects/interface/PropagatorWithMaterial.h"
00039 //analyticalpropagator
00040 //#include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
00041 
00042 
00043 //
00044 
00045 //for debug only 
00046 //#define FAMOS_DEBUG
00047 
00048 TrajectorySeedProducer::TrajectorySeedProducer(const edm::ParameterSet& conf) :thePropagator(0)
00049 {  
00050 
00051   // The input tag for the beam spot
00052   theBeamSpot = conf.getParameter<edm::InputTag>("beamSpot");
00053 
00054   // The name of the TrajectorySeed Collections
00055   seedingAlgo = conf.getParameter<std::vector<std::string> >("seedingAlgo");
00056   for ( unsigned i=0; i<seedingAlgo.size(); ++i )
00057     produces<TrajectorySeedCollection>(seedingAlgo[i]);
00058 
00059   // The smallest true pT for a track candidate
00060   pTMin = conf.getParameter<std::vector<double> >("pTMin");
00061   if ( pTMin.size() != seedingAlgo.size() ) 
00062     throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00063       << " WARNING : pTMin does not have the proper size "
00064       << std::endl;
00065 
00066   for ( unsigned i=0; i<pTMin.size(); ++i )
00067     pTMin[i] *= pTMin[i];  // Cut is done of perp2() - CPU saver
00068   
00069   // The smallest number of Rec Hits for a track candidate
00070   minRecHits = conf.getParameter<std::vector<unsigned int> >("minRecHits");
00071   if ( minRecHits.size() != seedingAlgo.size() ) 
00072     throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00073       << " WARNING : minRecHits does not have the proper size "
00074       << std::endl;
00075   // Set the overall number hits to be checked
00076   absMinRecHits = 0;
00077   for ( unsigned ialgo=0; ialgo<minRecHits.size(); ++ialgo ) 
00078     if ( minRecHits[ialgo] > absMinRecHits ) absMinRecHits = minRecHits[ialgo];
00079 
00080   // The smallest true impact parameters (d0 and z0) for a track candidate
00081   maxD0 = conf.getParameter<std::vector<double> >("maxD0");
00082   if ( maxD0.size() != seedingAlgo.size() ) 
00083     throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00084       << " WARNING : maxD0 does not have the proper size "
00085       << std::endl;
00086 
00087   maxZ0 = conf.getParameter<std::vector<double> >("maxZ0");
00088   if ( maxZ0.size() != seedingAlgo.size() ) 
00089     throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00090       << " WARNING : maxZ0 does not have the proper size "
00091       << std::endl;
00092 
00093   // The name of the hit producer
00094   hitProducer = conf.getParameter<edm::InputTag>("HitProducer");
00095 
00096   // The cuts for seed cleaning
00097   seedCleaning = conf.getParameter<bool>("seedCleaning");
00098 
00099   // Number of hits needed for a seed
00100   numberOfHits = conf.getParameter<std::vector<unsigned int> >("numberOfHits");
00101   if ( numberOfHits.size() != seedingAlgo.size() ) 
00102     throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00103       << " WARNING : numberOfHits does not have the proper size "
00104       << std::endl;
00105 
00106   // Seeding based on muons
00107   selectMuons = conf.getParameter<bool>("selectMuons");
00108 
00109   // Layers
00110   newSyntax = conf.getParameter<bool>("newSyntax");
00111   if (newSyntax) {
00112     layerList = conf.getParameter<std::vector<std::string> >("layerList");
00113     // (AG)  for (unsigned i=0; i<layerList.size();i++) std::cout << "------- Layers = " << layerList[i] << std::endl;
00114   } else {
00115     // TO BE DELETED (AG)
00116     firstHitSubDetectorNumber = 
00117       conf.getParameter<std::vector<unsigned int> >("firstHitSubDetectorNumber");
00118     if ( firstHitSubDetectorNumber.size() != seedingAlgo.size() ) 
00119       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00120         << " WARNING : firstHitSubDetectorNumber does not have the proper size "
00121         << std::endl;
00122     
00123     std::vector<unsigned int> firstSubDets = 
00124       conf.getParameter<std::vector<unsigned int> >("firstHitSubDetectors");
00125     unsigned isub1 = 0;
00126     unsigned check1 = 0;
00127     firstHitSubDetectors.resize(seedingAlgo.size());
00128     for ( unsigned ialgo=0; ialgo<firstHitSubDetectorNumber.size(); ++ialgo ) { 
00129       check1 += firstHitSubDetectorNumber[ialgo];
00130       for ( unsigned idet=0; idet<firstHitSubDetectorNumber[ialgo]; ++idet ) { 
00131         firstHitSubDetectors[ialgo].push_back(firstSubDets[isub1++]);
00132       }
00133     }
00134     if ( firstSubDets.size() != check1 ) 
00135       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00136         << " WARNING : firstHitSubDetectors does not have the proper size (should be " << check1 << ")"
00137         << std::endl;
00138     
00139     
00140     secondHitSubDetectorNumber = 
00141       conf.getParameter<std::vector<unsigned int> >("secondHitSubDetectorNumber");
00142     if ( secondHitSubDetectorNumber.size() != seedingAlgo.size() ) 
00143       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00144         << " WARNING : secondHitSubDetectorNumber does not have the proper size "
00145         << std::endl;
00146     
00147     std::vector<unsigned int> secondSubDets = 
00148       conf.getParameter<std::vector<unsigned int> >("secondHitSubDetectors");
00149     unsigned isub2 = 0;
00150     unsigned check2 = 0;
00151     secondHitSubDetectors.resize(seedingAlgo.size());
00152     for ( unsigned ialgo=0; ialgo<secondHitSubDetectorNumber.size(); ++ialgo ) { 
00153       check2 += secondHitSubDetectorNumber[ialgo];
00154       for ( unsigned idet=0; idet<secondHitSubDetectorNumber[ialgo]; ++idet ) { 
00155         secondHitSubDetectors[ialgo].push_back(secondSubDets[isub2++]);
00156       }
00157     }
00158     if ( secondSubDets.size() != check2 ) 
00159       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00160         << " WARNING : secondHitSubDetectors does not have the proper size (should be " << check2 << ")"
00161         << std::endl;
00162     
00163     thirdHitSubDetectorNumber = 
00164       conf.getParameter<std::vector<unsigned int> >("thirdHitSubDetectorNumber");
00165     if ( thirdHitSubDetectorNumber.size() != seedingAlgo.size() ) 
00166       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00167         << " WARNING : thirdHitSubDetectorNumber does not have the proper size "
00168         << std::endl;
00169     
00170     std::vector<unsigned int> thirdSubDets = 
00171       conf.getParameter<std::vector<unsigned int> >("thirdHitSubDetectors");
00172     unsigned isub3 = 0;
00173     unsigned check3 = 0;
00174     thirdHitSubDetectors.resize(seedingAlgo.size());
00175     for ( unsigned ialgo=0; ialgo<thirdHitSubDetectorNumber.size(); ++ialgo ) { 
00176       check3 += thirdHitSubDetectorNumber[ialgo];
00177       for ( unsigned idet=0; idet<thirdHitSubDetectorNumber[ialgo]; ++idet ) { 
00178         thirdHitSubDetectors[ialgo].push_back(thirdSubDets[isub3++]);
00179       }
00180     }
00181     if ( thirdSubDets.size() != check3 ) 
00182       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00183         << " WARNING : thirdHitSubDetectors does not have the proper size (should be " << check3 << ")"
00184         << std::endl;
00185     
00186     originRadius = conf.getParameter<std::vector<double> >("originRadius");
00187     if ( originRadius.size() != seedingAlgo.size() ) 
00188       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00189         << " WARNING : originRadius does not have the proper size "
00190         << std::endl;
00191     
00192     originHalfLength = conf.getParameter<std::vector<double> >("originHalfLength");
00193     if ( originHalfLength.size() != seedingAlgo.size() ) 
00194       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00195         << " WARNING : originHalfLength does not have the proper size "
00196         << std::endl;
00197     
00198     originpTMin = conf.getParameter<std::vector<double> >("originpTMin");
00199     if ( originpTMin.size() != seedingAlgo.size() ) 
00200       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00201         << " WARNING : originpTMin does not have the proper size "
00202         << std::endl;
00203     
00204     primaryVertices = conf.getParameter<std::vector<edm::InputTag> >("primaryVertices");
00205     if ( primaryVertices.size() != seedingAlgo.size() ) 
00206       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00207         << " WARNING : primaryVertices does not have the proper size "
00208         << std::endl;
00209     
00210     zVertexConstraint = conf.getParameter<std::vector<double> >("zVertexConstraint");
00211     if ( zVertexConstraint.size() != seedingAlgo.size() ) 
00212       throw cms::Exception("FastSimulation/TrajectorySeedProducer ") 
00213         << " WARNING : zVertexConstraint does not have the proper size "
00214         << std::endl;
00215   }
00216 
00217 }
00218 
00219   
00220 // Virtual destructor needed.
00221 TrajectorySeedProducer::~TrajectorySeedProducer() {
00222   
00223   if(thePropagator) delete thePropagator;
00224 
00225   // do nothing
00226 #ifdef FAMOS_DEBUG
00227   std::cout << "TrajectorySeedProducer destructed" << std::endl;
00228 #endif
00229 
00230 } 
00231  
00232 void 
00233 TrajectorySeedProducer::beginRun(edm::Run const&, const edm::EventSetup & es) {
00234 
00235   //services
00236   //  es.get<TrackerRecoGeometryRecord>().get(theGeomSearchTracker);
00237 
00238   edm::ESHandle<MagneticField>          magField;
00239   edm::ESHandle<TrackerGeometry>        geometry;
00240   edm::ESHandle<MagneticFieldMap>       magFieldMap;
00241 
00242 
00243   es.get<IdealMagneticFieldRecord>().get(magField);
00244   es.get<TrackerDigiGeometryRecord>().get(geometry);
00245   es.get<MagneticFieldMapRecord>().get(magFieldMap);
00246 
00247   theMagField = &(*magField);
00248   theGeometry = &(*geometry);
00249   theFieldMap = &(*magFieldMap);
00250 
00251   thePropagator = new PropagatorWithMaterial(alongMomentum,0.105,&(*theMagField)); 
00252 
00253   const GlobalPoint g(0.,0.,0.);
00254 
00255 }
00256   
00257   // Functions that gets called by framework every event
00258 void 
00259 TrajectorySeedProducer::produce(edm::Event& e, const edm::EventSetup& es) {        
00260 
00261 
00262   //  if( seedingAlgo[0] ==  "FourthPixelLessPairs") std::cout << "Seed producer in 4th iteration " << std::endl;
00263 
00264 #ifdef FAMOS_DEBUG
00265   std::cout << "################################################################" << std::endl;
00266   std::cout << " TrajectorySeedProducer produce init " << std::endl;
00267 #endif
00268 
00269   //Retrieve tracker topology from geometry
00270   edm::ESHandle<TrackerTopology> tTopoHand;
00271   es.get<IdealGeometryRecord>().get(tTopoHand);
00272   const TrackerTopology *tTopo=tTopoHand.product();
00273 
00274 
00275   unsigned nSimTracks = 0;
00276   unsigned nTracksWithHits = 0;
00277   unsigned nTracksWithPT = 0;
00278   unsigned nTracksWithD0Z0 = 0;
00279   //  unsigned nTrackCandidates = 0;
00280   PTrajectoryStateOnDet initialState;
00281   
00282   // Output
00283   std::vector<TrajectorySeedCollection*>
00284     output(seedingAlgo.size(),static_cast<TrajectorySeedCollection*>(0));
00285   for ( unsigned ialgo=0; ialgo<seedingAlgo.size(); ++ialgo ) { 
00286     //    std::auto_ptr<TrajectorySeedCollection> p(new TrajectorySeedCollection );
00287     output[ialgo] = new TrajectorySeedCollection;
00288   }
00289   
00290   // Beam spot
00291   edm::Handle<reco::BeamSpot> recoBeamSpotHandle;
00292   e.getByLabel(theBeamSpot,recoBeamSpotHandle); 
00293   math::XYZPoint BSPosition_ = recoBeamSpotHandle->position();
00294 
00295   //not used anymore. take the value from the py
00296 
00297   //double sigmaZ=recoBeamSpotHandle->sigmaZ();
00298   //double sigmaZ0Error=recoBeamSpotHandle->sigmaZ0Error();
00299   //double sigmaz0=sqrt(sigmaZ*sigmaZ+sigmaZ0Error*sigmaZ0Error);
00300   x0 = BSPosition_.X();
00301   y0 = BSPosition_.Y();
00302   z0 = BSPosition_.Z();
00303 
00304   // SimTracks and SimVertices
00305   edm::Handle<edm::SimTrackContainer> theSimTracks;
00306   e.getByLabel("famosSimHits",theSimTracks);
00307   
00308   edm::Handle<edm::SimVertexContainer> theSimVtx;
00309   e.getByLabel("famosSimHits",theSimVtx);
00310 
00311 #ifdef FAMOS_DEBUG
00312   std::cout << " Step A: SimTracks found " << theSimTracks->size() << std::endl;
00313 #endif
00314   
00315   //  edm::Handle<SiTrackerGSRecHit2DCollection> theGSRecHits;
00316   edm::Handle<SiTrackerGSMatchedRecHit2DCollection> theGSRecHits;
00317   e.getByLabel(hitProducer, theGSRecHits);
00318   
00319   // No tracking attempted if no hits (but put an empty collection in the event)!
00320 #ifdef FAMOS_DEBUG
00321   std::cout << " Step B: Full GS RecHits found " << theGSRecHits->size() << std::endl;
00322 #endif
00323   if(theGSRecHits->size() == 0) {
00324     for ( unsigned ialgo=0; ialgo<seedingAlgo.size(); ++ialgo ) {
00325       std::auto_ptr<TrajectorySeedCollection> p(output[ialgo]);
00326       e.put(p,seedingAlgo[ialgo]);
00327     }
00328     return;
00329   }
00330   
00331   // Primary vertices
00332   vertices = std::vector<const reco::VertexCollection*>
00333     (seedingAlgo.size(),static_cast<const reco::VertexCollection*>(0));
00334   for ( unsigned ialgo=0; ialgo<seedingAlgo.size(); ++ialgo ) { 
00335     //PAT Attempt!!!! 
00336 
00337    //originHalfLength[ialgo] = 3.*sigmaz0; // Overrides the configuration
00338     edm::Handle<reco::VertexCollection> aHandle;
00339     bool isVertexCollection = e.getByLabel(primaryVertices[ialgo],aHandle);
00340     if (!isVertexCollection ) continue;
00341     vertices[ialgo] = &(*aHandle);
00342   }
00343   
00344 #ifdef FAMOS_DEBUG
00345   std::cout << " Step C: Loop over the RecHits, track by track " << std::endl;
00346 #endif
00347 
00348   // The vector of simTrack Id's carrying GSRecHits
00349   const std::vector<unsigned> theSimTrackIds = theGSRecHits->ids();
00350 
00351   // loop over SimTrack Id's
00352   for ( unsigned tkId=0;  tkId != theSimTrackIds.size(); ++tkId ) {
00353 
00354 #ifdef FAMOS_DEBUG
00355     std::cout << "Track number " << tkId << std::endl;
00356 #endif
00357 
00358     ++nSimTracks;
00359     unsigned simTrackId = theSimTrackIds[tkId];
00360     const SimTrack& theSimTrack = (*theSimTracks)[simTrackId]; 
00361 #ifdef FAMOS_DEBUG
00362     std::cout << "Pt = " << std::sqrt(theSimTrack.momentum().Perp2()) 
00363               << " eta " << theSimTrack.momentum().Eta()
00364               << " pdg ID " << theSimTrack.type()
00365               << std::endl;
00366 #endif
00367 
00368     // Select only muons, if requested
00369     if (selectMuons && abs(theSimTrack.type()) != 13) continue;
00370     
00371     // Check that the sim track comes from the main vertex (loose cut)
00372     int vertexIndex = theSimTrack.vertIndex();
00373     const SimVertex& theSimVertex = (*theSimVtx)[vertexIndex]; 
00374 #ifdef FAMOS_DEBUG
00375     std::cout << " o SimTrack " << theSimTrack << std::endl;
00376     std::cout << " o SimVertex " << theSimVertex << std::endl;
00377 #endif
00378     
00379     BaseParticlePropagator theParticle = 
00380       BaseParticlePropagator( 
00381          RawParticle(XYZTLorentzVector(theSimTrack.momentum().px(),
00382                                        theSimTrack.momentum().py(),
00383                                        theSimTrack.momentum().pz(),
00384                                        theSimTrack.momentum().e()),
00385                      XYZTLorentzVector(theSimVertex.position().x(),
00386                                        theSimVertex.position().y(),
00387                                        theSimVertex.position().z(),
00388                                        theSimVertex.position().t())),
00389                      0.,0.,4.);
00390     theParticle.setCharge((*theSimTracks)[simTrackId].charge());
00391 
00392     SiTrackerGSMatchedRecHit2DCollection::range theRecHitRange = theGSRecHits->get(simTrackId);
00393     SiTrackerGSMatchedRecHit2DCollection::const_iterator theRecHitRangeIteratorBegin = theRecHitRange.first;
00394     SiTrackerGSMatchedRecHit2DCollection::const_iterator theRecHitRangeIteratorEnd   = theRecHitRange.second;
00395     SiTrackerGSMatchedRecHit2DCollection::const_iterator iterRecHit;
00396     SiTrackerGSMatchedRecHit2DCollection::const_iterator iterRecHit1;
00397     SiTrackerGSMatchedRecHit2DCollection::const_iterator iterRecHit2;
00398     SiTrackerGSMatchedRecHit2DCollection::const_iterator iterRecHit3;
00399 
00400     // Check the number of layers crossed
00401     unsigned numberOfRecHits = 0;
00402     TrackerRecHit previousHit, currentHit;
00403     for ( iterRecHit = theRecHitRangeIteratorBegin; 
00404           iterRecHit != theRecHitRangeIteratorEnd; 
00405           ++iterRecHit) { 
00406       previousHit = currentHit;
00407       currentHit = TrackerRecHit(&(*iterRecHit),theGeometry,tTopo);
00408       if ( currentHit.isOnTheSameLayer(previousHit) ) continue;
00409       ++numberOfRecHits;
00410       if ( numberOfRecHits == absMinRecHits ) break;
00411     }
00412 
00413     // Loop on the successive seedings
00414     for ( unsigned int ialgo = 0; ialgo < seedingAlgo.size(); ++ialgo ) { 
00415 
00416 #ifdef FAMOS_DEBUG
00417       std::cout << "Algo " << seedingAlgo[ialgo] << std::endl;
00418 #endif
00419 
00420       // Request a minimum number of RecHits for the track to give a seed.
00421 #ifdef FAMOS_DEBUG
00422       std::cout << "The number of RecHits = " << numberOfRecHits << std::endl;
00423 #endif
00424       if ( numberOfRecHits < minRecHits[ialgo] ) continue;
00425       ++nTracksWithHits;
00426 
00427       // Request a minimum pT for the sim track
00428       if ( theSimTrack.momentum().Perp2() < pTMin[ialgo] ) continue;
00429       ++nTracksWithPT;
00430       
00431       // Cut on sim track impact parameters
00432       if ( theParticle.xyImpactParameter(x0,y0) > maxD0[ialgo] ) continue;
00433       if ( fabs( theParticle.zImpactParameter(x0,y0) - z0 ) > maxZ0[ialgo] ) continue;
00434       ++nTracksWithD0Z0;
00435       
00436       std::vector<TrackerRecHit > 
00437         theSeedHits(numberOfHits[ialgo],
00438                     static_cast<TrackerRecHit >(TrackerRecHit()));
00439       TrackerRecHit& theSeedHits0 = theSeedHits[0];
00440       TrackerRecHit& theSeedHits1 = theSeedHits[1];
00441       TrackerRecHit& theSeedHits2 = theSeedHits[2];
00442       bool compatible = false;
00443       for ( iterRecHit1 = theRecHitRangeIteratorBegin; iterRecHit1 != theRecHitRangeIteratorEnd; ++iterRecHit1) {
00444         theSeedHits[0] = TrackerRecHit(&(*iterRecHit1),theGeometry,tTopo);
00445 #ifdef FAMOS_DEBUG
00446         std::cout << "The first hit position = " << theSeedHits0.globalPosition() << std::endl;
00447         std::cout << "The first hit subDetId = " << theSeedHits0.subDetId() << std::endl;
00448         std::cout << "The first hit layer    = " << theSeedHits0.layerNumber() << std::endl;
00449 #endif
00450 
00451         // Check if inside the requested detectors
00452         bool isInside = true;
00453         if (!selectMuons) {
00454           if (newSyntax) 
00455             isInside = true; // AG placeholder
00456           else
00457             isInside = theSeedHits0.subDetId() < firstHitSubDetectors[ialgo][0];
00458           //    bool isInside = theSeedHits0.subDetId() < firstHitSubDetectors[ialgo][0];
00459           if ( isInside ) continue;
00460         }
00461 
00462         // Check if on requested detectors
00463         //      bool isOndet =  theSeedHits0.isOnRequestedDet(firstHitSubDetectors[ialgo]);
00464         bool isOndet = true;
00465         if (!selectMuons) {
00466           if (newSyntax) 
00467             isOndet = theSeedHits0.isOnRequestedDet(layerList);
00468           else
00469             isOndet = theSeedHits0.isOnRequestedDet(firstHitSubDetectors[ialgo], seedingAlgo[ialgo]);
00470           //    bool isOndet =  theSeedHits0.isOnRequestedDet(firstHitSubDetectors[ialgo], seedingAlgo[ialgo]);
00471           //    if ( !isOndet ) break;
00472           if ( !isOndet ) continue;
00473         }
00474 
00475 #ifdef FAMOS_DEBUG
00476         std::cout << "Apparently the first hit is on the requested detector! " << std::endl;
00477 #endif
00478         for ( iterRecHit2 = iterRecHit1+1; iterRecHit2 != theRecHitRangeIteratorEnd; ++iterRecHit2) {
00479           theSeedHits[1] = TrackerRecHit(&(*iterRecHit2),theGeometry,tTopo);
00480 #ifdef FAMOS_DEBUG
00481           std::cout << "The second hit position = " << theSeedHits1.globalPosition() << std::endl;
00482           std::cout << "The second hit subDetId = " << theSeedHits1.subDetId() << std::endl;
00483           std::cout << "The second hit layer    = " << theSeedHits1.layerNumber() << std::endl;
00484 #endif
00485 
00486           if (!selectMuons) {
00487             // Check if inside the requested detectors
00488             if (newSyntax) 
00489               isInside = true; // AG placeholder
00490             else
00491               isInside = theSeedHits1.subDetId() < secondHitSubDetectors[ialgo][0];
00492             if ( isInside ) continue;
00493 
00494             // Check if on requested detectors
00495             if (newSyntax) 
00496               isOndet = theSeedHits1.isOnRequestedDet(layerList);
00497             else
00498               isOndet =  theSeedHits1.isOnRequestedDet(secondHitSubDetectors[ialgo], seedingAlgo[ialgo]);
00499             if ( !isOndet ) break;
00500           }
00501 
00502           // Check if on the same layer as previous hit
00503           if ( theSeedHits1.isOnTheSameLayer(theSeedHits0) ) continue;
00504 
00505 #ifdef FAMOS_DEBUG
00506           std::cout << "Apparently the second hit is on the requested detector! " << std::endl;
00507 #endif
00508           GlobalPoint gpos1 = theSeedHits0.globalPosition();
00509           GlobalPoint gpos2 = theSeedHits1.globalPosition();
00510           bool forward = theSeedHits0.isForward();
00511           double error = std::sqrt(theSeedHits0.largerError()+theSeedHits1.largerError());
00512           //      compatible = compatibleWithVertex(gpos1,gpos2,ialgo);
00513           //added out of desperation    
00514           if(seedingAlgo[0] == "PixelLess" ||  seedingAlgo[0] ==  "TobTecLayerPairs"){
00515             compatible = true;
00516             //std::cout << "Algo " << seedingAlgo[0] << "Det/layer = " << theSeedHits0.subDetId() << "/" <<  theSeedHits0.layerNumber() << std::endl;
00517           } else {
00518             compatible = compatibleWithBeamAxis(gpos1,gpos2,error,forward,ialgo);
00519           }
00520           
00521 #ifdef FAMOS_DEBUG
00522           std::cout << "Algo" << seedingAlgo[0] << "\t Are the two hits compatible with the PV? " << compatible << std::endl;
00523 #endif
00524 
00525           if (!selectMuons) {
00526             // Check if the pair is on the requested dets
00527             if ( numberOfHits[ialgo] == 2 ) {
00528               
00529               if ( seedingAlgo[0] ==  "ThirdMixedPairs" ){
00530                 compatible = compatible && theSeedHits[0].makesAPairWith3rd(theSeedHits[1]);
00531               } else {
00532                 compatible = compatible && theSeedHits[0].makesAPairWith(theSeedHits[1]);
00533                 //check
00534                 /*
00535                   if((seedingAlgo[0] == "PixelLess" ||  seedingAlgo[0] ==  "TobTecLayerPairs") && !compatible) 
00536                   std::cout << "NOT Compatible " <<  seedingAlgo[0] 
00537                   <<  "Hit 1 Det/layer/ring = " << theSeedHits0.subDetId() << "/" <<  theSeedHits0.layerNumber() << "/" << theSeedHits0.ringNumber() 
00538                   <<  "\tHit 2 Det/layer/ring = " << theSeedHits1.subDetId() << "/" <<  theSeedHits1.layerNumber() << "/" << theSeedHits1.ringNumber() <<  std::endl;
00539                 */
00540               }
00541             }   
00542           }    
00543           
00544           // Reject non suited pairs
00545           if ( !compatible ) continue;
00546 
00547 #ifdef FAMOS_DEBUG
00548           std::cout << "Pair kept! " << std::endl;
00549 #endif
00550 
00551           // Leave here if only two hits are required.
00552           if ( numberOfHits[ialgo] == 2 ) break; 
00553           
00554           compatible = false;
00555           // Check if there is a third satisfying hit otherwise
00556           for ( iterRecHit3 = iterRecHit2+1; iterRecHit3 != theRecHitRangeIteratorEnd; ++iterRecHit3) {
00557             theSeedHits[2] = TrackerRecHit(&(*iterRecHit3),theGeometry,tTopo);
00558 #ifdef FAMOS_DEBUG
00559             std::cout << "The third hit position = " << theSeedHits2.globalPosition() << std::endl;
00560             std::cout << "The third hit subDetId = " << theSeedHits2.subDetId() << std::endl;
00561             std::cout << "The third hit layer    = " << theSeedHits2.layerNumber() << std::endl;
00562 #endif
00563 
00564             if (!selectMuons) {
00565               // Check if inside the requested detectors
00566               if (newSyntax) 
00567                 isInside = true; // AG placeholder
00568               else 
00569                 isInside = theSeedHits2.subDetId() < thirdHitSubDetectors[ialgo][0];
00570               if ( isInside ) continue;
00571             
00572               // Check if on requested detectors
00573               if (newSyntax) 
00574                 isOndet = theSeedHits2.isOnRequestedDet(layerList);
00575               else 
00576                 isOndet =  theSeedHits2.isOnRequestedDet(thirdHitSubDetectors[ialgo], seedingAlgo[ialgo]);
00577               //            if ( !isOndet ) break;
00578               if ( !isOndet ) continue;
00579             }
00580 
00581             // Check if on the same layer as previous hit
00582             compatible = !(theSeedHits2.isOnTheSameLayer(theSeedHits1));
00583 
00584             // Check if the triplet is on the requested det combination
00585             if (!selectMuons) compatible = compatible && theSeedHits[0].makesATripletWith(theSeedHits[1],theSeedHits[2]);
00586 
00587 #ifdef FAMOS_DEBUG
00588             if ( compatible ) 
00589               std::cout << "Apparently the third hit is on the requested detector! " << std::endl;
00590 #endif
00591 
00592             if ( compatible ) break;      
00593 
00594           }
00595 
00596           if ( compatible ) break;
00597 
00598         }
00599 
00600         if ( compatible ) break;
00601 
00602       }
00603 
00604       // There is no compatible seed for this track with this seeding algorithm 
00605       // Go to next algo
00606       if ( !compatible ) continue;
00607 #ifdef FAMOS_DEBUG
00608       if ( compatible ) 
00609         std::cout << "@@@ There is at least a compatible seed" << std::endl;
00610       else
00611         std::cout << "@@@ There is no compatible seed" << std::endl;
00612 #endif
00613       
00614 
00615 #ifdef FAMOS_DEBUG
00616       std::cout << "Preparing to create the TrajectorySeed" << std::endl;
00617 #endif
00618       // The seed is validated -> include in the collection
00619       // 1) Create the vector of RecHits
00620       edm::OwnVector<TrackingRecHit> recHits;
00621       for ( unsigned ih=0; ih<theSeedHits.size(); ++ih ) {
00622         TrackingRecHit* aTrackingRecHit = theSeedHits[ih].hit()->clone();
00623         recHits.push_back(aTrackingRecHit);
00624       }
00625 #ifdef FAMOS_DEBUG
00626       std::cout << "with " << recHits.size() << " hits." << std::endl;
00627 #endif
00628 
00629       // 2) Create the initial state
00630       //   a) origin vertex
00631       GlobalPoint  position((*theSimVtx)[vertexIndex].position().x(),
00632                             (*theSimVtx)[vertexIndex].position().y(),
00633                             (*theSimVtx)[vertexIndex].position().z());
00634       
00635       //   b) initial momentum
00636       GlobalVector momentum( (*theSimTracks)[simTrackId].momentum().x() , 
00637                              (*theSimTracks)[simTrackId].momentum().y() , 
00638                              (*theSimTracks)[simTrackId].momentum().z() );
00639       //   c) electric charge
00640       float        charge   = (*theSimTracks)[simTrackId].charge();
00641       //  -> inital parameters
00642       GlobalTrajectoryParameters initialParams(position,momentum,(int)charge,theMagField);
00643       //  -> large initial errors
00644       AlgebraicSymMatrix55 errorMatrix= AlgebraicMatrixID();      
00645       // errorMatrix = errorMatrix * 10;
00646 
00647       //this line help the fit succeed in the case of pixelless tracks (4th and 5th iteration)
00648       //for the future: probably the best thing is to use the mini-kalmanFilter
00649       if(theSeedHits0.subDetId() !=1 || theSeedHits0.subDetId() !=2) errorMatrix = errorMatrix * 0.0000001;
00650 
00651 
00652 
00653 #ifdef FAMOS_DEBUG
00654       std::cout << "TrajectorySeedProducer: SimTrack parameters " << std::endl;
00655       std::cout << "\t\t pT  = " << (*theSimTracks)[simTrackId].momentum().Pt() << std::endl;
00656       std::cout << "\t\t eta = " << (*theSimTracks)[simTrackId].momentum().Eta()  << std::endl;
00657       std::cout << "\t\t phi = " << (*theSimTracks)[simTrackId].momentum().Phi()  << std::endl;
00658       std::cout << "TrajectorySeedProducer: AlgebraicSymMatrix " << errorMatrix << std::endl;
00659 #endif
00660       CurvilinearTrajectoryError initialError(errorMatrix);
00661       // -> initial state
00662       FreeTrajectoryState initialFTS(initialParams, initialError);      
00663 #ifdef FAMOS_DEBUG
00664       std::cout << "TrajectorySeedProducer: FTS momentum " << initialFTS.momentum() << std::endl;
00665 #endif
00666       // const GeomDetUnit* initialLayer = theGeometry->idToDetUnit( recHits.front().geographicalId() );
00667       const GeomDet* initialLayer = theGeometry->idToDet( recHits.front().geographicalId() );
00668 
00669       //this is wrong because the FTS is defined at vertex, and it need to be properly propagated.
00670       //      const TrajectoryStateOnSurface initialTSOS(initialFTS, initialLayer->surface());      
00671 
00672       const TrajectoryStateOnSurface initialTSOS = thePropagator->propagate(initialFTS,initialLayer->surface()) ;
00673       if (!initialTSOS.isValid()) continue; 
00674 
00675 #ifdef FAMOS_DEBUG
00676       std::cout << "TrajectorySeedProducer: TSOS global momentum "    << initialTSOS.globalMomentum() << std::endl;
00677       std::cout << "\t\t\tpT = "                                     << initialTSOS.globalMomentum().perp() << std::endl;
00678       std::cout << "\t\t\teta = "                                    << initialTSOS.globalMomentum().eta() << std::endl;
00679       std::cout << "\t\t\tphi = "                                    << initialTSOS.globalMomentum().phi() << std::endl;
00680       std::cout << "TrajectorySeedProducer: TSOS local momentum "     << initialTSOS.localMomentum()  << std::endl;
00681       std::cout << "TrajectorySeedProducer: TSOS local error "        << initialTSOS.localError().positionError() << std::endl;
00682       std::cout << "TrajectorySeedProducer: TSOS local error matrix " << initialTSOS.localError().matrix() << std::endl;
00683       std::cout << "TrajectorySeedProducer: TSOS surface side "       << initialTSOS.surfaceSide()    << std::endl;
00684 #endif
00685       stateOnDet(initialTSOS, 
00686                  recHits.front().geographicalId().rawId(),
00687                  initialState);
00688       // Create a new Trajectory Seed    
00689       output[ialgo]->push_back(TrajectorySeed(initialState, recHits, alongMomentum));
00690 #ifdef FAMOS_DEBUG
00691       std::cout << "Trajectory seed created ! " << std::endl;
00692 #endif
00693       break;
00694       // End of the loop over seeding algorithms
00695     }
00696     // End on the loop over simtracks
00697   }
00698 
00699   for ( unsigned ialgo=0; ialgo<seedingAlgo.size(); ++ialgo ) { 
00700     std::auto_ptr<TrajectorySeedCollection> p(output[ialgo]);
00701     e.put(p,seedingAlgo[ialgo]);
00702   }
00703 
00704 }
00705 
00706 // This is a copy of a method in 
00707 // TrackingTools/TrajectoryState/src/TrajectoryStateTransform.cc
00708 // but it does not return a pointer (thus avoiding a memory leak)
00709 // In addition, it's also CPU more efficient, because 
00710 // ts.localError().matrix() is not copied
00711 void 
00712 TrajectorySeedProducer::stateOnDet(const TrajectoryStateOnSurface& ts,
00713                                    unsigned int detid,
00714                                    PTrajectoryStateOnDet& pts) const
00715 {
00716 
00717   const AlgebraicSymMatrix55& m = ts.localError().matrix();
00718   
00719   int dim = 5; 
00720 
00721   float localErrors[15];
00722   int k = 0;
00723   for (int i=0; i<dim; ++i) {
00724     for (int j=0; j<=i; ++j) {
00725       localErrors[k++] = m(i,j);
00726     }
00727   }
00728   int surfaceSide = static_cast<int>(ts.surfaceSide());
00729 
00730   pts = PTrajectoryStateOnDet( ts.localParameters(),
00731                                localErrors, detid,
00732                                surfaceSide);
00733 }
00734 
00735 bool
00736 TrajectorySeedProducer::compatibleWithBeamAxis(GlobalPoint& gpos1, 
00737                                                GlobalPoint& gpos2,
00738                                                double error,
00739                                                bool forward,
00740                                                unsigned algo) const {
00741 
00742   if ( !seedCleaning ) return true;
00743 
00744   // The hits 1 and 2 positions, in HepLorentzVector's
00745   XYZTLorentzVector thePos1(gpos1.x(),gpos1.y(),gpos1.z(),0.);
00746   XYZTLorentzVector thePos2(gpos2.x(),gpos2.y(),gpos2.z(),0.);
00747 #ifdef FAMOS_DEBUG
00748   std::cout << "ThePos1 = " << thePos1 << std::endl;
00749   std::cout << "ThePos2 = " << thePos2 << std::endl;
00750 #endif
00751 
00752 
00753   // Create new particles that pass through the second hit with pT = ptMin 
00754   // and charge = +/-1
00755   
00756   // The momentum direction is by default joining the two hits 
00757   XYZTLorentzVector theMom2 = (thePos2-thePos1);
00758 
00759   // The corresponding RawParticle, with an (irrelevant) electric charge
00760   // (The charge is determined in the next step)
00761   ParticlePropagator myPart(theMom2,thePos2,1.,theFieldMap);
00762 
00766   bool intersect = myPart.propagateToBeamCylinder(thePos1,originRadius[algo]*1.);
00767   if ( !intersect ) return false;
00768 
00769 #ifdef FAMOS_DEBUG
00770   std::cout << "MyPart R = " << myPart.R() << "\t Z = " << myPart.Z() 
00771             << "\t pT = " << myPart.Pt() << std::endl;
00772 #endif
00773 
00774   // Check if the constraints are satisfied
00775   // 1. pT at cylinder with radius originRadius
00776   if ( myPart.Pt() < originpTMin[algo] ) return false;
00777 
00778   // 2. Z compatible with beam spot size
00779   if ( fabs(myPart.Z()-z0) > originHalfLength[algo] ) return false;
00780 
00781   // 3. Z compatible with one of the primary vertices (always the case if no primary vertex)
00782   const reco::VertexCollection* theVertices = vertices[algo];
00783   if (!theVertices) return true;
00784   unsigned nVertices = theVertices->size();
00785   if ( !nVertices || zVertexConstraint[algo] < 0. ) return true;
00786   // Radii of the two hits with respect to the beam spot position
00787   double R1 = std::sqrt ( (thePos1.X()-x0)*(thePos1.X()-x0) 
00788                         + (thePos1.Y()-y0)*(thePos1.Y()-y0) );
00789   double R2 = std::sqrt ( (thePos2.X()-x0)*(thePos2.X()-x0) 
00790                         + (thePos2.Y()-y0)*(thePos2.Y()-y0) );
00791   // Loop on primary vertices
00792   for ( unsigned iv=0; iv<nVertices; ++iv ) { 
00793     // Z position of the primary vertex
00794     double zV = (*theVertices)[iv].z();
00795     // Constraints on the inner hit
00796     double checkRZ1 = forward ?
00797       (thePos1.Z()-zV+zVertexConstraint[algo]) / (thePos2.Z()-zV+zVertexConstraint[algo]) * R2 : 
00798       -zVertexConstraint[algo] + R1/R2*(thePos2.Z()-zV+zVertexConstraint[algo]);
00799     double checkRZ2 = forward ?
00800       (thePos1.Z()-zV-zVertexConstraint[algo])/(thePos2.Z()-zV-zVertexConstraint[algo]) * R2 :
00801       +zVertexConstraint[algo] + R1/R2*(thePos2.Z()-zV-zVertexConstraint[algo]);
00802     double checkRZmin = std::min(checkRZ1,checkRZ2)-3.*error;
00803     double checkRZmax = std::max(checkRZ1,checkRZ2)+3.*error;
00804     // Check if the innerhit is within bounds
00805     bool compat = forward ?
00806       checkRZmin < R1 && R1 < checkRZmax : 
00807       checkRZmin < thePos1.Z()-zV && thePos1.Z()-zV < checkRZmax; 
00808     // If it is, just return ok
00809     if ( compat ) return compat;
00810   }
00811   // Otherwise, return not ok
00812   return false;
00813 
00814 }  
00815