CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_1/src/RecoTracker/ConversionSeedGenerators/src/SeedForPhotonConversionFromQuadruplets.cc

Go to the documentation of this file.
00001 #include "RecoTracker/ConversionSeedGenerators/interface/SeedForPhotonConversionFromQuadruplets.h"
00002 
00003 #include "RecoTracker/ConversionSeedGenerators/interface/Conv4HitsReco2.h"
00004 
00005 
00006 #include "TrackingTools/KalmanUpdators/interface/KFUpdator.h"
00007 #include "RecoTracker/TkSeedGenerator/interface/FastHelix.h"
00008 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
00009 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
00010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00011 #include "MagneticField/Engine/interface/MagneticField.h"
00012 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
00013 #include "TrackingTools/Records/interface/TrackingComponentsRecord.h"
00014 #include "TrackingTools/Records/interface/TransientRecHitRecord.h"
00015 #include "TrackingTools/MaterialEffects/interface/PropagatorWithMaterial.h"
00016 #include "FWCore/Framework/interface/ESHandle.h"
00017 #include "TrackingTools/GeomPropagators/interface/PropagationExceptions.h"
00018 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateTransform.h"
00019 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
00020 #include "RecoTracker/TransientTrackingRecHit/interface/TSiStripRecHit2DLocalPos.h"
00021 //ClusterShapeIncludes
00022 #include "RecoTracker/TkTrackingRegions/interface/OrderedHitsGenerator.h"
00023 #include "RecoTracker/TkTrackingRegions/interface/TrackingRegion.h"
00024 #include "RecoTracker/TkSeedingLayers/interface/SeedComparitor.h"
00025 #include "RecoTracker/TkSeedGenerator/interface/SeedCreator.h"
00026 #include "RecoTracker/TkSeedingLayers/interface/SeedComparitorFactory.h"
00027 #include "RecoTracker/TkSeedGenerator/interface/SeedCreatorFactory.h"
00028 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateClosestToBeamLine.h"
00029 #include "TrackingTools/PatternTools/interface/TSCBLBuilderNoMaterial.h"
00030 #include "DataFormats/BeamSpot/interface/BeamSpot.h"
00031 
00032 //#define mydebug_knuenz
00033 //#define mydebug_sguazz
00034 //#define quadDispLine
00035 template <class T> T sqr( T t) {return t*t;}
00036 
00037 const TrajectorySeed * SeedForPhotonConversionFromQuadruplets::trajectorySeed(
00038     TrajectorySeedCollection & seedCollection,
00039     const SeedingHitSet & phits,
00040     const SeedingHitSet & mhits,
00041     const TrackingRegion & region,
00042     const edm::EventSetup& es,
00043     std::stringstream& ss,
00044     std::vector<Quad>& quadV,
00045     edm::ParameterSet& SeedComparitorPSet,
00046     edm::ParameterSet& QuadCutPSet)
00047 {
00048 
00049 
00051 
00052 
00053         bool rejectAllQuads=QuadCutPSet.getParameter<bool>("rejectAllQuads");
00054         if(rejectAllQuads) return 0;
00055 
00056         bool applyDeltaPhiCuts=QuadCutPSet.getParameter<bool>("apply_DeltaPhiCuts");
00057     bool ClusterShapeFiltering=QuadCutPSet.getParameter<bool>("apply_ClusterShapeFilter");
00058     bool applyArbitration=QuadCutPSet.getParameter<bool>("apply_Arbitration");
00059     bool applydzCAcut=QuadCutPSet.getParameter<bool>("apply_zCACut");
00060     double CleaningmaxRadialDistance=QuadCutPSet.getParameter<double>("Cut_DeltaRho");//cm
00061     double BeamPipeRadiusCut=QuadCutPSet.getParameter<double>("Cut_BeamPipeRadius");//cm
00062     double CleaningMinLegPt = QuadCutPSet.getParameter<double>("Cut_minLegPt"); //GeV
00063     double maxLegPt = QuadCutPSet.getParameter<double>("Cut_maxLegPt"); //GeV
00064     double dzcut=QuadCutPSet.getParameter<double>("Cut_zCA");//cm
00065 
00066     double toleranceFactorOnDeltaPhiCuts=0.1;
00067 
00068   //  return 0; //FIXME, remove this line to make the code working.
00069 
00070   pss = &ss;
00071 
00072   if ( phits.size() < 2) return 0;
00073   if ( mhits.size() < 2) return 0;
00074 
00075   //PUT HERE THE QUADRUPLET ALGORITHM, AND IN CASE USE THE METHODS ALREADY DEVELOPED, ADAPTING THEM
00076 
00077   //
00078   // Rozzo ma efficace (per ora)
00079   //
00080 
00081 #ifdef mydebug_sguazz
00082   std::cout << " --------------------------------------------------------------------------" << "\n";
00083   std::cout << "  Starting a hit quad fast reco " << "\n";
00084   std::cout << " --------------------------------------------------------------------------" << "\n";
00085 #endif
00086 
00087   //
00088   // Let's build the 4 hits
00089   TransientTrackingRecHit::ConstRecHitPointer ptth1 = phits[0];
00090   TransientTrackingRecHit::ConstRecHitPointer ptth2 = phits[1];
00091   TransientTrackingRecHit::ConstRecHitPointer mtth1 = mhits[0];
00092   TransientTrackingRecHit::ConstRecHitPointer mtth2 = mhits[1];
00093 
00094   GlobalPoint vHit[4];
00095   vHit[0]=ptth2->globalPosition();
00096   vHit[1]=ptth1->globalPosition();
00097   vHit[2]=mtth1->globalPosition();
00098   vHit[3]=mtth2->globalPosition();
00099 
00100   //Photon source vertex primary vertex
00101   GlobalPoint vgPhotVertex=region.origin();
00102   math::XYZVector vPhotVertex(vgPhotVertex.x(), vgPhotVertex.y(), vgPhotVertex.z());
00103 
00104   math::XYZVector h1(vHit[0].x(),vHit[0].y(),vHit[0].z());
00105   math::XYZVector h2(vHit[1].x(),vHit[1].y(),vHit[1].z());
00106   math::XYZVector h3(vHit[2].x(),vHit[2].y(),vHit[2].z());
00107   math::XYZVector h4(vHit[3].x(),vHit[3].y(),vHit[3].z());
00108 
00109 // At this point implement cleaning cuts before building the seed:::
00110 
00111 /*
00112   Notes:
00113 
00114 h1, h2: positron
00115 h3, h4: electron
00116 
00117 P1, P2: positron, ordered with radius
00118 M1, M2: electron, ordered with radius
00119 
00120 Evan's notation:
00121 V1=P1
00122 V2=M1
00123 V3=P2
00124 V4=M2
00125 
00126 */
00127 
00128   math::XYZVector P1;
00129   math::XYZVector P2;
00130   math::XYZVector M1;
00131   math::XYZVector M2;
00132 
00133   if(h1.x()*h1.x()+h1.y()*h1.y() < h2.x()*h2.x()+h2.y()*h2.y()){
00134           P1=h1;
00135           P2=h2;
00136   }
00137   else{
00138           P1=h2;
00139           P2=h1;
00140   }
00141 
00142   if(h3.x()*h3.x()+h3.y()*h3.y() < h4.x()*h4.x()+h4.y()*h4.y()){
00143           M1=h3;
00144           M2=h4;
00145   }
00146   else{
00147           M1=h4;
00148           M2=h3;
00149   }
00150 
00152 // Intersection-point:::
00154 /*
00155 Calculate the intersection point of the lines P2-P1 and M2-M1.
00156 If this point is in the beam pipe, or if the distance of this
00157 point to the layer of the most inner hit of the seed is less
00158 than CleaningmaxRadialDistance cm, the combination is rejected.
00159 */
00160 
00161 
00162   math::XYZVector IP(0,0,0);
00163 
00164   //Line1:
00165   double kP=(P1.y()-P2.y())/(P1.x()-P2.x());
00166   double dP=P1.y()-kP*P1.x();
00167   //Line2:
00168   double kM=(M1.y()-M2.y())/(M1.x()-M2.x());
00169   double dM=M1.y()-kM*M1.x();
00170   //Intersection:
00171   double IPx=(dM-dP)/(kP-kM);
00172   double IPy=kP*IPx+dP;
00173 
00174   IP.SetXYZ(IPx,IPy,0);
00175 
00176   double IPrho=std::sqrt(IP.x()*IP.x()+IP.y()*IP.y());
00177   double P1rho2=P1.x()*P1.x()+P1.y()*P1.y();
00178   double M1rho2=M1.x()*M1.x()+M1.y()*M1.y();
00179   double maxIPrho2=IPrho+CleaningmaxRadialDistance; maxIPrho2*=maxIPrho2;
00180 
00181   if( IPrho<BeamPipeRadiusCut || P1rho2>maxIPrho2 || M1rho2>maxIPrho2){
00182           return 0;
00183   }
00184 
00185   if(applyDeltaPhiCuts) {
00186 
00187   kPI_ = std::atan(1.0)*4;
00188   
00189   edm::ESHandle<MagneticField> bfield;
00190   es.get<IdealMagneticFieldRecord>().get(bfield);
00191   math::XYZVector QuadMean(0,0,0);
00192   QuadMean.SetXYZ((M1.x()+M2.x()+P1.x()+P2.x())/4.,(M1.y()+M2.y()+P1.y()+P2.y())/4.,(M1.z()+M2.z()+P1.z()+P2.z())/4.);
00193 
00194   double fBField = bfield->inTesla(GlobalPoint(QuadMean.x(),QuadMean.y(),QuadMean.z())).z();
00195 
00196   double rMax=CleaningMinLegPt/(0.01*0.3*fBField);
00197   double rMax_squared=rMax*rMax;
00198   double Mx=M1.x();
00199   double My=M1.y();
00200 
00201   math::XYZVector B(0,0,0);
00202   math::XYZVector C(0,0,0);
00203 
00204   if(rMax_squared*4. > Mx*Mx+My*My){
00205 
00207 // Cleaning P1 points:::
00209 
00210           //Cx, Cy = Coordinates of circle center
00211           //C_=line that contains the circle center
00212 
00213   //C_=k*x+d
00214   double k=-Mx/My;
00215   double d=My/2.-k*Mx/2.;
00216 
00217 #ifdef mydebug_knuenz
00218 std::cout << "k" << k << std::endl;
00219 std::cout << "d" << d << std::endl;
00220 #endif
00221 
00222   //Cx1,2 and Cy1,2 are the two points that have a distance of rMax to 0,0
00223   double CsolutionPart1=-2*k*d;
00224   double CsolutionPart2=std::sqrt(4*k*k*d*d-4*(1+k*k)*(d*d-rMax_squared));
00225   double CsolutionPart3=2*(1+k*k);
00226   double Cx1=(CsolutionPart1+CsolutionPart2)/CsolutionPart3;
00227   double Cx2=(CsolutionPart1-CsolutionPart2)/CsolutionPart3;
00228   double Cy1=k*Cx1+d;
00229   double Cy2=k*Cx2+d;
00230 
00231 
00232   // Decide between solutions: phi(C) > phi(P)
00233   double Cx,Cy;
00234   math::XYZVector C1(Cx1,Cy1,0);
00235   if(C1.x()*M1.y()-C1.y()*M1.x()<0){
00236           Cx=Cx1;
00237           Cy=Cy1;
00238   }
00239   else{
00240           Cx=Cx2;
00241           Cy=Cy2;
00242   }
00243   C.SetXYZ(Cx,Cy,0);
00244 
00245 #ifdef mydebug_knuenz
00246         std::cout << "Cx1" << Cx1 << std::endl;
00247         std::cout << "Cx2" << Cx2 << std::endl;
00248         std::cout << "Cy1" << Cy1 << std::endl;
00249         std::cout << "Cy2" << Cy2 << std::endl;
00250         std::cout << "Cx" << Cx << std::endl;
00251         std::cout << "Cy" << Cy << std::endl;
00252 #endif
00253 
00254 // Find Tangent at 0,0 to minPtCircle and point (Bx,By) on the first layer which bisects the allowed angle
00255   k=-Cx/Cy;
00256   d=0;
00257   double Bx1=std::sqrt(Mx*Mx+My*My/(1+k*k));
00258   double Bx2=-Bx1;
00259   double By1=k*Bx1+d;
00260   double By2=k*Bx2+d;
00261 
00262 #ifdef mydebug_knuenz
00263         std::cout << "k" << k << std::endl;
00264         std::cout << "d" << d << std::endl;
00265 #endif
00266 
00267 // Decide between solutions: phi(B) < phi(P)
00268   double Bx,By;
00269   math::XYZVector B1(Bx1,By1,0);
00270   if(M1.x()*B1.y()-M1.y()*B1.x()<0){
00271           Bx=Bx1;
00272           By=By1;
00273   }
00274   else{
00275           Bx=Bx2;
00276           By=By2;
00277   }
00278   B.SetXYZ(Bx,By,0);
00279 
00280 #ifdef mydebug_knuenz
00281         std::cout << "Bx1" << Bx1 << std::endl;
00282         std::cout << "Bx2" << Bx2 << std::endl;
00283         std::cout << "By1" << By1 << std::endl;
00284         std::cout << "By2" << By2 << std::endl;
00285         std::cout << "Bx" << Bx << std::endl;
00286         std::cout << "By" << By << std::endl;
00287 #endif
00288 
00289   double DeltaPhiMaxM1P1=DeltaPhiManual(M1,B)*2;
00290 
00291 #ifdef mydebug_knuenz
00292     std::cout << "DeltaPhiMaxM1P1 " << DeltaPhiMaxM1P1 << std::endl;
00293         std::cout << "M1.DeltaPhi(P1) " << DeltaPhiManual(M1,P1) << std::endl;
00294     std::cout << "rho P1: " << std::sqrt(P1.x()*P1.x()+P1.y()*P1.y()) <<  "phi P1: " << P1.Phi() << std::endl;
00295     std::cout << "rho M1: " << std::sqrt(M1.x()*M1.x()+M1.y()*M1.y()) <<  "phi M1: " << M1.Phi() << std::endl;
00296 #endif
00297 
00298 //Finally Cut on DeltaPhi of P1 and M1
00299 
00300     double tol_DeltaPhiMaxM1P1=DeltaPhiMaxM1P1*toleranceFactorOnDeltaPhiCuts;
00301     double DeltaPhiManualM1P1=DeltaPhiManual(M1,P1);
00302 
00303 if(DeltaPhiManualM1P1>DeltaPhiMaxM1P1+tol_DeltaPhiMaxM1P1 || DeltaPhiManualM1P1<0-tol_DeltaPhiMaxM1P1){
00304         return 0;
00305 }
00306 
00307   }//if rMax > rLayerM1
00308 
00309 
00311 // Cleaning M2 points:::
00313 
00314 //  if(B.DeltaPhi(P1)>0){//normal algo (with minPt circle)
00315 
00316           double rM2_squared=M2.x()*M2.x()+M2.y()*M2.y();
00317           if(rMax_squared*4. > rM2_squared){//if minPt circle is smaller than 2*M2-layer radius, algo makes no sense
00318 
00319                   //Chordales equation (line containing the two intersection points of the two circles)
00320                   double k=-C.x()/C.y();
00321                   double d=(rM2_squared-rMax_squared+C.x()*C.x()+C.y()*C.y())/(2*C.y());
00322 
00323                   double M2solutionPart1=-2*k*d;
00324                   double M2solutionPart2=std::sqrt(4*k*k*d*d-4*(1+k*k)*(d*d-rM2_squared));
00325                   double M2solutionPart3=2+2*k*k;
00326                   double M2xMax1=(M2solutionPart1+M2solutionPart2)/M2solutionPart3;
00327                   double M2xMax2=(M2solutionPart1-M2solutionPart2)/M2solutionPart3;
00328                   double M2yMax1=k*M2xMax1+d;
00329                   double M2yMax2=k*M2xMax2+d;
00330 
00331                   //double M2xMax,M2yMax;
00332                   math::XYZVector M2MaxVec1(M2xMax1,M2yMax1,0);
00333                   math::XYZVector M2MaxVec2(M2xMax2,M2yMax2,0);
00334                   math::XYZVector M2MaxVec(0,0,0);
00335                   if(M2MaxVec1.x()*M2MaxVec2.y()-M2MaxVec1.y()*M2MaxVec2.x()<0){
00336                           M2MaxVec.SetXYZ(M2xMax2,M2yMax2,0);
00337                   }
00338                   else{
00339                           M2MaxVec.SetXYZ(M2xMax1,M2yMax1,0);
00340                   }
00341 
00342                   double DeltaPhiMaxM2=DeltaPhiManual(M2MaxVec,M1);
00343 
00344 #ifdef mydebug_knuenz
00345                         std::cout << "C.x() " << C.x() << std::endl;
00346                         std::cout << "C.y() " << C.y() << std::endl;
00347                         std::cout << "M1.x() " << M1.x() << std::endl;
00348                         std::cout << "M1.y() " << M1.y() << std::endl;
00349                         std::cout << "M2.x() " << M2.x() << std::endl;
00350                         std::cout << "M2.y() " << M2.y() << std::endl;
00351                         std::cout << "k " << k << std::endl;
00352                         std::cout << "d " << d << std::endl;
00353                         std::cout << "M2xMax1 " << M2xMax1 << std::endl;
00354                         std::cout << "M2xMax2 " << M2xMax2 << std::endl;
00355                         std::cout << "M2yMax1 " << M2yMax1 << std::endl;
00356                         std::cout << "M2yMax2 " << M2yMax2 << std::endl;
00357                         std::cout << "M2xMax " << M2MaxVec.x() << std::endl;
00358                         std::cout << "M2yMax " << M2MaxVec.y() << std::endl;
00359                         std::cout << "rM2_squared " << rM2_squared << std::endl;
00360                         std::cout << "rMax " << rMax << std::endl;
00361                         std::cout << "DeltaPhiMaxM2 " << DeltaPhiMaxM2 << std::endl;
00362 #endif
00363 
00364 
00365                     double tol_DeltaPhiMaxM2=DeltaPhiMaxM2*toleranceFactorOnDeltaPhiCuts;
00366                     double DeltaPhiManualM2M1=DeltaPhiManual(M2,M1);
00367 
00368                   if(DeltaPhiManualM2M1>DeltaPhiMaxM2+tol_DeltaPhiMaxM2 || DeltaPhiManualM2M1<0-tol_DeltaPhiMaxM2){
00369                           return 0;
00370                   }
00371 
00372                   //Using the lazy solution for P2: DeltaPhiMaxP2=DeltaPhiMaxM2
00373                   double DeltaPhiManualP1P2=DeltaPhiManual(P1,P2);
00374                   if(DeltaPhiManualP1P2>DeltaPhiMaxM2+tol_DeltaPhiMaxM2 || DeltaPhiManualP1P2<0-tol_DeltaPhiMaxM2){
00375                         return 0;
00376                   }
00377 
00378           }
00379 
00380 }
00381 
00382 //  }
00383 
00384 //  if(B.DeltaPhi(P1)<0){//different algo (without minPt circle)
00385 
00386 //  }
00387 
00388 // End of pre-seed cleaning
00389 
00390           
00391           
00392   Conv4HitsReco2 quad(vPhotVertex, h1, h2, h3, h4);
00393   quad.SetMaxNumberOfIterations(100);
00394 #ifdef mydebug_sguazz
00395   quad.Dump();
00396 #endif
00397   math::XYZVector candVtx;
00398   double candPtPlus, candPtMinus;
00399   //double rPlus, rMinus;
00400   int nite = quad.ConversionCandidate(candVtx, candPtPlus, candPtMinus);
00401 
00402   if ( ! (nite && abs(nite) < 25 && nite != -1000 && nite != -2000) ) return 0;
00403 
00404 //  math::XYZVector plusCenter = quad.GetPlusCenter(rPlus);
00405 //  math::XYZVector minusCenter = quad.GetMinusCenter(rMinus);
00406 
00407 #ifdef mydebug_sguazz
00408     std::cout << " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << "\n";
00409     std::cout << " >>>>>>>>>>> Conv Cand: " << " Vertex X: " << candVtx.X() << " [cm] Y: " << candVtx.Y() << " [cm] pt+: " << candPtPlus<< " [GeV] pt-: " << candPtMinus << " [GeV]; #its: " << nite << "\n";
00410 #endif
00411 
00412     //Add here cuts
00413     double minLegPt = CleaningMinLegPt;
00414     double maxRadialDistance = CleaningmaxRadialDistance;
00415 
00416     //
00417     // Cut on leg's transverse momenta
00418     if ( candPtPlus < minLegPt ) return 0;
00419     if ( candPtMinus < minLegPt ) return 0;
00420     //
00421     if ( candPtPlus > maxLegPt ) return 0;
00422     if ( candPtMinus > maxLegPt ) return 0;
00423     //
00424     // Cut on radial distance between estimated conversion vertex and inner hits
00425     double cr = std::sqrt(candVtx.Perp2());
00426     double maxr2 = (maxRadialDistance + cr); maxr2*=maxr2;
00427     if (h2.Perp2() > maxr2) return 0;
00428     if (h3.Perp2() > maxr2) return 0;
00429 
00430 
00431 // At this point implement cleaning cuts after building the seed
00432 
00433     //ClusterShapeFilter_knuenz:::
00434     std::string comparitorName = SeedComparitorPSet.getParameter<std::string>("ComponentName");
00435     SeedComparitor * theComparitor = (comparitorName == "none") ? 0 :  SeedComparitorFactory::get()->create( comparitorName, SeedComparitorPSet);
00436 
00437     if(ClusterShapeFiltering){
00438           if (theComparitor) theComparitor->init(es);
00439 
00440                   GlobalTrajectoryParameters pkine;
00441                   GlobalTrajectoryParameters mkine;
00442 
00443                   TransientTrackingRecHit::ConstRecHitPointer ptth1 = phits[0];
00444                   TransientTrackingRecHit::ConstRecHitPointer ptth2 = phits[1];
00445                   TransientTrackingRecHit::ConstRecHitPointer mtth1 = mhits[0];
00446                   TransientTrackingRecHit::ConstRecHitPointer mtth2 = mhits[1];
00447 
00448                   GlobalPoint vertexPos(candVtx.x(),candVtx.y(),candVtx.z());
00449 
00450                   float ptMinReg=0.1;
00451                   GlobalTrackingRegion region(ptMinReg,vertexPos,0,0,true);
00452 
00453                   FastHelix phelix(ptth2->globalPosition(), mtth1->globalPosition(), vertexPos, es, vertexPos);
00454                   pkine = phelix.stateAtVertex().parameters();
00455                   FastHelix mhelix(mtth2->globalPosition(), mtth1->globalPosition(), vertexPos, es, vertexPos);
00456                   mkine = mhelix.stateAtVertex().parameters();
00457 
00458                   if(theComparitor&&!theComparitor->compatible(phits, pkine, phelix, region)) { return 0; }
00459                   if(theComparitor&&!theComparitor->compatible(mhits, mkine, mhelix, region)) { return 0; }
00460     }
00461 
00462 
00463     //Do a very simple fit to estimate the slope
00464     double quadPhotCotTheta = 0.;
00465     double quadZ0 = 0.;
00466     simpleGetSlope(ptth2, ptth1, mtth1, mtth2, region, quadPhotCotTheta, quadZ0);
00467 
00468     double quadPhotPhi = (candVtx-vPhotVertex).Phi();
00469 
00470     math::XYZVector fittedPrimaryVertex(vgPhotVertex.x(), vgPhotVertex.y(),quadZ0);
00471 
00472     candVtx.SetZ(std::sqrt(candVtx.Perp2())*quadPhotCotTheta+quadZ0);
00473     GlobalPoint convVtxGlobalPoint(candVtx.X(),candVtx.Y(),candVtx.Z());
00474 
00475     //
00476     // Comparing new quad with old quad
00477     //
00478     //Arbitration
00479 
00480     Quad thisQuad;
00481     thisQuad.x = candVtx.X();
00482     thisQuad.y = candVtx.Y();
00483     thisQuad.z = candVtx.Z();
00484     thisQuad.ptPlus = candPtPlus;
00485     thisQuad.ptMinus = candPtMinus;
00486     thisQuad.cot = quadPhotCotTheta;
00487         if ( similarQuadExist(thisQuad, quadV) && applyArbitration ) return 0;
00488 
00489     // not able to get the mag field... doing the dirty way
00490     //
00491     // Plus
00492     FastHelix helixPlus(ptth2->globalPosition(), ptth1->globalPosition(), convVtxGlobalPoint, es, convVtxGlobalPoint);
00493     GlobalTrajectoryParameters kinePlus = helixPlus.stateAtVertex().parameters();
00494     kinePlus = GlobalTrajectoryParameters(convVtxGlobalPoint,
00495                                           GlobalVector(candPtPlus*cos(quadPhotPhi),candPtPlus*sin(quadPhotPhi),candPtPlus*quadPhotCotTheta),
00496                                           1,//1
00497                                           & kinePlus.magneticField()
00498                                           );
00499 
00500     //
00501     // Minus
00502     FastHelix helixMinus(mtth2->globalPosition(), mtth1->globalPosition(), convVtxGlobalPoint, es, convVtxGlobalPoint);
00503     GlobalTrajectoryParameters kineMinus = helixMinus.stateAtVertex().parameters();
00504     kineMinus = GlobalTrajectoryParameters(convVtxGlobalPoint,
00505                                           GlobalVector(candPtMinus*cos(quadPhotPhi),candPtMinus*sin(quadPhotPhi),candPtMinus*quadPhotCotTheta),
00506                                           -1,//-1
00507                                           & kineMinus.magneticField()
00508                                           );
00509 
00510     float sinThetaPlus = sin(kinePlus.momentum().theta());
00511     float sinThetaMinus = sin(kineMinus.momentum().theta());
00512     float ptmin = region.ptMin();
00513     //vertexBounds da region
00514     GlobalVector vertexBounds(region.originRBound(),region.originRBound(),region.originZBound());
00515 
00516     CurvilinearTrajectoryError errorPlus = initialError(vertexBounds, ptmin,  sinThetaPlus);
00517     CurvilinearTrajectoryError errorMinus = initialError(vertexBounds, ptmin,  sinThetaMinus);
00518     FreeTrajectoryState ftsPlus(kinePlus, errorPlus);
00519     FreeTrajectoryState ftsMinus(kineMinus, errorMinus);
00520 
00521     //FIXME: here probably you want to go in parallel with phits and mhits
00522     //NB: the seedCollection is filled (the important thing) the return of the last TrajectorySeed is not used, but is needed
00523     //to maintain the inheritance
00524 
00525 #ifdef quadDispLine
00526     double vError = region.originZBound();
00527     if ( vError > 15. ) vError = 1.;
00528     std::cout << "QuadDispLine "
00529               << vgPhotVertex.x() << " " << vgPhotVertex.y() << " " << vgPhotVertex.z() << " " << vError << " "
00530               << vHit[0].x() << " " << vHit[0].y() << " " << vHit[0].z() << " " << sqrt(getSqrEffectiveErrorOnZ(ptth2, region)) << " "
00531               << vHit[1].x() << " " << vHit[1].y() << " " << vHit[1].z() << " " << sqrt(getSqrEffectiveErrorOnZ(ptth1, region)) << " "
00532               << vHit[2].x() << " " << vHit[2].y() << " " << vHit[2].z() << " " << sqrt(getSqrEffectiveErrorOnZ(mtth1, region)) << " "
00533               << vHit[3].x() << " " << vHit[3].y() << " " << vHit[3].z() << " " << sqrt(getSqrEffectiveErrorOnZ(mtth2, region)) << " "
00534               << candVtx.X() << " " << candVtx.Y() << " " << candVtx.Z() << " "
00535               << fittedPrimaryVertex.X() << " " << fittedPrimaryVertex.Y() << " " << fittedPrimaryVertex.Z() << " "
00536 //            << candPtPlus  << " " << rPlus << " " << plusCenter.X() << " " << plusCenter.Y() << " "
00537 //            << candPtMinus << " " << rMinus << " " << minusCenter.X() << " " << minusCenter.Y() << " "
00538               << nite << " " << chi2 << "\n";
00539 #endif
00540 #ifdef mydebug_sguazz
00541     std::cout << " >>>>> Hit quad fast reco done >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << "\n";
00542     uint32_t detid;
00543     std::cout << "[SeedForPhotonConversionFromQuadruplets]\n ptth1 " ;
00544     detid=ptth1->geographicalId().rawId();
00545     //    po.print(std::cout , detid );
00546     std::cout << " \t " << detid << " " << ptth1->localPosition()  << " " << ptth1->globalPosition()    ;
00547     detid=ptth2->geographicalId().rawId();
00548     std::cout << " \n\t ptth2 ";
00549     //    po.print(std::cout , detid );
00550     std::cout << " \t " << detid << " " << ptth2->localPosition()  << " " << ptth2->globalPosition()
00551               << "\nhelix momentum " << kinePlus.momentum() << " pt " << kinePlus.momentum().perp() << " radius " << 1/kinePlus.transverseCurvature() << " q " << kinePlus.charge();
00552     std::cout << " \n\t mtth1 ";
00553     detid=mtth1->geographicalId().rawId();
00554     std::cout << " \t " << detid << " " << mtth1->localPosition()  << " " << mtth1->globalPosition()    ;
00555     std::cout << " \n\t mtth2 ";
00556     detid=mtth2->geographicalId().rawId();
00557     //    po.print(std::cout , detid );
00558     std::cout << " \t " << detid << " " << mtth2->localPosition()  << " " << mtth2->globalPosition()
00559               << "\nhelix momentum " << kineMinus.momentum() << " pt " << kineMinus.momentum().perp() << " radius " << 1/kineMinus.transverseCurvature() << " q " << kineMinus.charge();
00560     std::cout << "\n <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << "\n";
00561 #endif
00562 
00563     
00564 
00565     bool buildSeedBoolPos = buildSeedBool(seedCollection,phits,ftsPlus,es,applydzCAcut,region, dzcut);
00566     bool buildSeedBoolNeg = buildSeedBool(seedCollection,mhits,ftsMinus,es,applydzCAcut,region, dzcut);
00567 
00568     
00569     
00570     if( buildSeedBoolPos && buildSeedBoolNeg ){
00571         buildSeed(seedCollection,phits,ftsPlus,es,false,region);
00572         buildSeed(seedCollection,mhits,ftsMinus,es,false,region);
00573         }
00574 
00575     return 0;
00576 
00577 }
00578 
00579 
00580 GlobalTrajectoryParameters SeedForPhotonConversionFromQuadruplets::initialKinematic(
00581       const SeedingHitSet & hits,
00582       const GlobalPoint & vertexPos,
00583       const edm::EventSetup& es,
00584       const float cotTheta) const
00585 {
00586   GlobalTrajectoryParameters kine;
00587 
00588   TransientTrackingRecHit::ConstRecHitPointer tth1 = hits[0];
00589   TransientTrackingRecHit::ConstRecHitPointer tth2 = hits[1];
00590 
00591 
00592   FastHelix helix(tth2->globalPosition(), tth1->globalPosition(), vertexPos, es, vertexPos);
00593   kine = helix.stateAtVertex().parameters();
00594 
00595   //force the pz/pt equal to the measured one
00596   if(fabs(cotTheta)<cotTheta_Max)
00597     kine = GlobalTrajectoryParameters(kine.position(),
00598                                       GlobalVector(kine.momentum().x(),kine.momentum().y(),kine.momentum().perp()*cotTheta),
00599                                       kine.charge(),
00600                                       & kine.magneticField()
00601                                       );
00602   else
00603     kine = GlobalTrajectoryParameters(kine.position(),
00604                                       GlobalVector(kine.momentum().x(),kine.momentum().y(),kine.momentum().perp()*cotTheta_Max),
00605                                       kine.charge(),
00606                                       & kine.magneticField()
00607                                       );
00608 
00609 #ifdef mydebug_seed
00610   uint32_t detid;
00611   (*pss) << "[SeedForPhotonConversionFromQuadruplets] initialKinematic tth1 " ;
00612   detid=tth1->geographicalId().rawId();
00613   po.print(*pss, detid );
00614   (*pss) << " \t " << detid << " " << tth1->localPosition()  << " " << tth1->globalPosition()    ;
00615   detid= tth2->geographicalId().rawId();
00616   (*pss) << " \n\t tth2 ";
00617   po.print(*pss, detid );
00618   (*pss) << " \t " << detid << " " << tth2->localPosition()  << " " << tth2->globalPosition()
00619          << "\nhelix momentum " << kine.momentum() << " pt " << kine.momentum().perp() << " radius " << 1/kine.transverseCurvature();
00620 #endif
00621 
00622   edm::ESHandle<MagneticField> bfield;
00623   es.get<IdealMagneticFieldRecord>().get(bfield);
00624   bool isBOFF = ( std::abs(bfield->inTesla(GlobalPoint(0,0,0)).z()) < 1e-3 );
00625   if (isBOFF && (theBOFFMomentum > 0)) {
00626     kine = GlobalTrajectoryParameters(kine.position(),
00627                               kine.momentum().unit() * theBOFFMomentum,
00628                               kine.charge(),
00629                               &*bfield);
00630   }
00631   return kine;
00632 }
00633 
00634 
00635 
00636 CurvilinearTrajectoryError SeedForPhotonConversionFromQuadruplets::
00637 initialError(
00638              const GlobalVector& vertexBounds,
00639              float ptMin,
00640              float sinTheta) const
00641 {
00642   // Set initial uncertainty on track parameters, using only P.V. constraint and no hit
00643   // information.
00644   GlobalError vertexErr( sqr(vertexBounds.x()), 0,
00645                          sqr(vertexBounds.y()), 0, 0,
00646                          sqr(vertexBounds.z())
00647                          );
00648 
00649 
00650   AlgebraicSymMatrix55 C = ROOT::Math::SMatrixIdentity();
00651 
00652 // FIXME: minC00. Prevent apriori uncertainty in 1/P from being too small,
00653 // to avoid instabilities.
00654 // N.B. This parameter needs optimising ...
00655   float sin2th = sqr(sinTheta);
00656   float minC00 = 1.0;
00657   C[0][0] = std::max(sin2th/sqr(ptMin), minC00);
00658   float zErr = vertexErr.czz();
00659   float transverseErr = vertexErr.cxx(); // assume equal cxx cyy
00660   C[3][3] = transverseErr;
00661   C[4][4] = zErr*sin2th + transverseErr*(1-sin2th);
00662 
00663   return CurvilinearTrajectoryError(C);
00664 }
00665 
00666 const TrajectorySeed * SeedForPhotonConversionFromQuadruplets::buildSeed(
00667     TrajectorySeedCollection & seedCollection,
00668     const SeedingHitSet & hits,
00669     const FreeTrajectoryState & fts,
00670     const edm::EventSetup& es,
00671     bool apply_dzCut,
00672     const TrackingRegion & region) const
00673 {
00674   // get tracker
00675   edm::ESHandle<TrackerGeometry> tracker;
00676   es.get<TrackerDigiGeometryRecord>().get(tracker);
00677 
00678   // get propagator
00679   edm::ESHandle<Propagator>  propagatorHandle;
00680   es.get<TrackingComponentsRecord>().get(thePropagatorLabel, propagatorHandle);
00681   const Propagator*  propagator = &(*propagatorHandle);
00682 
00683   // get updator
00684   KFUpdator  updator;
00685 
00686   // Now update initial state track using information from seed hits.
00687 
00688   TrajectoryStateOnSurface updatedState;
00689   edm::OwnVector<TrackingRecHit> seedHits;
00690 
00691   const TrackingRecHit* hit = 0;
00692   for ( unsigned int iHit = 0; iHit < hits.size() && iHit<2; iHit++) {
00693     hit = hits[iHit]->hit();
00694     TrajectoryStateOnSurface state = (iHit==0) ?
00695       propagator->propagate(fts,tracker->idToDet(hit->geographicalId())->surface())
00696       : propagator->propagate(updatedState, tracker->idToDet(hit->geographicalId())->surface());
00697 
00698     TransientTrackingRecHit::ConstRecHitPointer tth = hits[iHit];
00699 
00700     TransientTrackingRecHit::RecHitPointer newtth =  refitHit( tth, state);
00701 
00702     updatedState =  updator.update(state, *newtth);
00703 
00704     seedHits.push_back(newtth->hit()->clone());
00705 #ifdef mydebug_seed
00706     uint32_t detid = hit->geographicalId().rawId();
00707     (*pss) << "\n[SeedForPhotonConversionFromQuadruplets] hit " << iHit;
00708     po.print(*pss, detid);
00709     (*pss) << " "  << detid << "\t lp " << hit->localPosition()
00710            << " tth " << tth->localPosition() << " newtth " << newtth->localPosition() << " state " << state.globalMomentum().perp();
00711 #endif
00712   }
00713 
00714   PTrajectoryStateOnDet const &  PTraj =
00715       trajectoryStateTransform::persistentState(updatedState, hit->geographicalId().rawId());
00716 
00717 
00718   seedCollection.push_back( TrajectorySeed(PTraj,seedHits,alongMomentum));
00719   return &seedCollection.back();
00720 }
00721 
00722 
00723 
00724 
00725 
00726 bool SeedForPhotonConversionFromQuadruplets::buildSeedBool(
00727     TrajectorySeedCollection & seedCollection,
00728     const SeedingHitSet & hits,
00729     const FreeTrajectoryState & fts,
00730     const edm::EventSetup& es,
00731     bool apply_dzCut,
00732     const TrackingRegion & region,
00733     double dzcut) const
00734 {
00735   // get tracker
00736   edm::ESHandle<TrackerGeometry> tracker;
00737   es.get<TrackerDigiGeometryRecord>().get(tracker);
00738 
00739   // get propagator
00740   edm::ESHandle<Propagator>  propagatorHandle;
00741   es.get<TrackingComponentsRecord>().get(thePropagatorLabel, propagatorHandle);
00742   const Propagator*  propagator = &(*propagatorHandle);
00743 
00744   // get updator
00745   KFUpdator  updator;
00746 
00747   // Now update initial state track using information from seed hits.
00748 
00749   TrajectoryStateOnSurface updatedState;
00750   edm::OwnVector<TrackingRecHit> seedHits;
00751 
00752   const TrackingRecHit* hit = 0;
00753   for ( unsigned int iHit = 0; iHit < hits.size() && iHit<2; iHit++) {
00754     hit = hits[iHit]->hit();
00755     TrajectoryStateOnSurface state = (iHit==0) ?
00756       propagator->propagate(fts,tracker->idToDet(hit->geographicalId())->surface())
00757       : propagator->propagate(updatedState, tracker->idToDet(hit->geographicalId())->surface());
00758     if (!state.isValid()) {
00759         return false;}
00760 
00761     TransientTrackingRecHit::ConstRecHitPointer tth = hits[iHit];
00762 
00763     TransientTrackingRecHit::RecHitPointer newtth =  refitHit( tth, state);
00764 
00765 
00766     if (!checkHit(state,newtth,es)){
00767                 return false;
00768     }
00769     
00770     updatedState =  updator.update(state, *newtth);
00771     if (!updatedState.isValid()){
00772         return false;
00773     }
00774 
00775     seedHits.push_back(newtth->hit()->clone());
00776   }
00777 
00778   if(apply_dzCut){
00780 
00781   double zCA;
00782 
00783   math::XYZVector EstMomGam(updatedState.globalMomentum().x(),updatedState.globalMomentum().y(),updatedState.globalMomentum().z());
00784   math::XYZVector EstPosGam(updatedState.globalPosition().x(),updatedState.globalPosition().y(),updatedState.globalPosition().z());
00785 
00786   double EstMomGamLength=std::sqrt(EstMomGam.x()*EstMomGam.x()+EstMomGam.y()*EstMomGam.y()+EstMomGam.z()*EstMomGam.z());
00787   math::XYZVector EstMomGamNorm(EstMomGam.x()/EstMomGamLength,EstMomGam.y()/EstMomGamLength,EstMomGam.z()/EstMomGamLength);
00788 
00789   //Calculate dz of point of closest approach of the two lines (WA approach) -> cut on dz
00790   
00791           
00792   const GlobalPoint EstPosGamGlobalPoint(updatedState.globalPosition().x(),updatedState.globalPosition().y(),updatedState.globalPosition().z());
00793   const GlobalVector EstMomGamGlobalVector(updatedState.globalMomentum().x(),updatedState.globalMomentum().y(),updatedState.globalMomentum().z());
00794 
00795 
00796   edm::ESHandle<MagneticField> bfield;
00797   es.get<IdealMagneticFieldRecord>().get(bfield);
00798   const MagneticField* magField = bfield.product();
00799   TrackCharge qCharge = 0;
00800   
00801   const GlobalTrajectoryParameters myGlobalTrajectoryParameter(EstPosGamGlobalPoint, EstMomGamGlobalVector, qCharge, magField);
00802   
00803   AlgebraicSymMatrix66 aCovarianceMatrix;
00804   
00805   for (int i =0;i<6;++i)
00806      for (int j =0;j<6;++j)
00807          aCovarianceMatrix(i, j) = 1e-4;
00808  
00809   CartesianTrajectoryError myCartesianError (aCovarianceMatrix);
00810  
00811   const FreeTrajectoryState stateForProjectionToBeamLine(myGlobalTrajectoryParameter,myCartesianError);
00812 
00813   const GlobalPoint BeamSpotGlobalPoint(0,0,0);
00814 
00815   const reco::BeamSpot::Point BeamSpotPoint(region.origin().x(),region.origin().y(),region.origin().z());
00816 
00817   TSCBLBuilderNoMaterial tscblBuilder;
00818   
00819   double CovMatEntry=0.;
00820   reco::BeamSpot::CovarianceMatrix cov;
00821   for (int i=0;i<3;++i) {
00822           cov(i,i) = CovMatEntry;
00823   }
00824    reco::BeamSpot::BeamType BeamType_=reco::BeamSpot::Unknown;
00825 
00826   reco::BeamSpot myBeamSpot(BeamSpotPoint, 0.,0.,0.,0., cov,BeamType_);
00827        
00828   TrajectoryStateClosestToBeamLine tscbl = tscblBuilder(stateForProjectionToBeamLine,myBeamSpot);
00829   if (tscbl.isValid()==false) {
00830           zCA=0;
00831   }
00832   else{
00833           GlobalPoint v = tscbl.trackStateAtPCA().position(); // Position of closest approach to BS
00834           zCA=v.z();
00835   }
00836   
00837 /*  //Calculate dz of point of closest approach of the two lines -> cut on dz
00838 
00839   double newX,newY,newR;
00840   double Rbuff=std::sqrt(EstPosGam.x()*EstPosGam.x()+EstPosGam.y()*EstPosGam.y());
00841   double deltas,s,sbuff;
00842   double rMin=1e9;
00843 
00844   double InitXp=EstPosGam.x()+1*EstMomGamNorm.x();
00845   double InitXm=EstPosGam.x()-1*EstMomGamNorm.x();
00846   double InitYp=EstPosGam.y()+1*EstMomGamNorm.y();
00847   double InitYm=EstPosGam.y()-1*EstMomGamNorm.y();
00848 
00849   if(InitXp*InitXp+InitYp*InitYp < InitXm*InitXm+InitYm*InitYm)  {s=5; deltas=5;}
00850   else {s=-5; deltas=-5;}
00851 
00852   int nTurns=0;
00853   int nIterZ=0;
00854   for (int i_dz=0;i_dz<1000;i_dz++){
00855   newX=EstPosGam.x()+s*EstMomGamNorm.x();
00856   newY=EstPosGam.y()+s*EstMomGamNorm.y();
00857   newR=std::sqrt(newX*newX+newY*newY);
00858   if(newR>Rbuff) {deltas=-1*deltas/10;nTurns++;}
00859   else {Rbuff=newR;}
00860   if(newR<rMin) {rMin=newR; sbuff=s;}
00861   s=s+deltas;
00862   nIterZ++;
00863   if(nTurns>1) break;
00864   }
00865 
00866   zCA=EstPosGam.z()+sbuff*EstMomGamNorm.z();
00867 */
00868   
00869 #ifdef mydebug_knuenz
00870   std::cout<< "zCA: " << zCA <<std::endl;
00871 #endif
00872 
00873   if(std::fabs(zCA)>dzcut) return false;
00874 
00875 
00876   }
00877 
00878 
00879   return true;
00880 }
00881 
00882 
00883 
00884 TransientTrackingRecHit::RecHitPointer SeedForPhotonConversionFromQuadruplets::refitHit(
00885       const TransientTrackingRecHit::ConstRecHitPointer &hit,
00886       const TrajectoryStateOnSurface &state) const
00887 {
00888   //const TransientTrackingRecHit* a= hit.get();
00889   //return const_cast<TransientTrackingRecHit*> (a);
00890   //This was modified otherwise the rechit will have just the local x component and local y=0
00891   // To understand how to modify for pixels
00892 
00893   //const TSiStripRecHit2DLocalPos* b = dynamic_cast<const TSiStripRecHit2DLocalPos*>(a);
00894   //return const_cast<TSiStripRecHit2DLocalPos*>(b);
00895   return hit->clone(state);
00896 }
00897 
00898 //
00899 // Below: stupid utils method by sguazz
00900 //
00901 //
00902 void SeedForPhotonConversionFromQuadruplets::
00903 stupidPrint(std::string s,float* d){
00904   (*pss) << "\n" << s << "\t";
00905   for(size_t i=0;i<2;++i)
00906       (*pss) << std::setw (60)  << d[i] << std::setw(1) << " | ";
00907 }
00908 
00909 void SeedForPhotonConversionFromQuadruplets::
00910 stupidPrint(std::string s,double* d){
00911   (*pss) << "\n" << s << "\t";
00912   for(size_t i=0;i<2;++i)
00913       (*pss) << std::setw (60) << d[i] << std::setw(1) << " | ";
00914 }
00915 
00916 void SeedForPhotonConversionFromQuadruplets::
00917 stupidPrint(const char* s,GlobalPoint* d){
00918   (*pss) << "\n" << s << "\t";
00919   for(size_t i=0;i<2;++i)
00920     (*pss) << std::setw(20) << d[i] << " r " << d[i].perp() << " phi " << d[i].phi() << " | ";
00921 }
00922 
00923 void SeedForPhotonConversionFromQuadruplets::
00924 stupidPrint(const char* s, GlobalPoint* d, int n){
00925   (*pss) << "\n" << s << "\n";
00926   for(int i=0;i<n;++i)
00927     (*pss) << std::setw(20) << d[i] << " r " << d[i].perp() << " phi " << d[i].phi() << "\n";
00928 }
00929 
00930 #include "DataFormats/Math/interface/deltaPhi.h"
00931 
00932 void SeedForPhotonConversionFromQuadruplets::
00933 bubbleSortVsPhi(GlobalPoint arr[], int n, GlobalPoint vtx) {
00934   bool swapped = true;
00935   int j = 0;
00936   GlobalPoint tmp;
00937   while (swapped) {
00938     swapped = false;
00939     j++;
00940     for (int i = 0; i < n - j; i++) {
00941       if ( reco::deltaPhi( (arr[i]-vtx).phi(), (arr[i + 1]-vtx).phi() ) > 0. ) {
00942         tmp = arr[i];
00943         arr[i] = arr[i + 1];
00944         arr[i + 1] = tmp;
00945         swapped = true;
00946       }
00947     }
00948   }
00949 }
00950 
00951 void SeedForPhotonConversionFromQuadruplets::
00952 bubbleReverseSortVsPhi(GlobalPoint arr[], int n, GlobalPoint vtx) {
00953   bool swapped = true;
00954   int j = 0;
00955   GlobalPoint tmp;
00956   while (swapped) {
00957     swapped = false;
00958     j++;
00959     for (int i = 0; i < n - j; i++) {
00960       if ( reco::deltaPhi( (arr[i]-vtx).phi(), (arr[i + 1]-vtx).phi() ) < 0. ) {
00961         tmp = arr[i];
00962         arr[i] = arr[i + 1];
00963         arr[i + 1] = tmp;
00964         swapped = true;
00965       }
00966     }
00967   }
00968 }
00969 
00970 
00971 double SeedForPhotonConversionFromQuadruplets::
00972 simpleGetSlope(const TransientTrackingRecHit::ConstRecHitPointer &ohit, const TransientTrackingRecHit::ConstRecHitPointer &nohit, const TransientTrackingRecHit::ConstRecHitPointer &ihit, const TransientTrackingRecHit::ConstRecHitPointer &nihit, const TrackingRegion & region, double & cotTheta, double & z0){
00973 
00974   double x[5], y[5], e2y[5];
00975 
00976   //The fit is done filling x with r values, y with z values of the four hits and the vertex
00977   //
00978   //Hits
00979   x[0] = ohit->globalPosition().perp();
00980   y[0] = ohit->globalPosition().z();
00981   e2y[0] = getSqrEffectiveErrorOnZ(ohit, region);
00982   //
00983   x[1] = nohit->globalPosition().perp();
00984   y[1] = nohit->globalPosition().z();
00985   e2y[1] = getSqrEffectiveErrorOnZ(nohit, region);
00986   //
00987   x[2] = nihit->globalPosition().perp();
00988   y[2] = nihit->globalPosition().z();
00989   e2y[2] = getSqrEffectiveErrorOnZ(nihit, region);
00990   //
00991   x[3] = ihit->globalPosition().perp();
00992   y[3] = ihit->globalPosition().z();
00993   e2y[3] = getSqrEffectiveErrorOnZ(ihit, region);
00994   //
00995   //Vertex
00996   x[4] = region.origin().perp();
00997   y[4] = region.origin().z();
00998   double vError = region.originZBound();
00999   if ( vError > 15. ) vError = 1.;
01000   e2y[4] = sqr(vError);
01001 
01002   double e2z0;
01003   double chi2 = verySimpleFit(5, x, y, e2y, z0, e2z0, cotTheta);
01004 
01005   return chi2;
01006 
01007 }
01008 
01009 double SeedForPhotonConversionFromQuadruplets::verySimpleFit(int size, double* ax, double* ay, double* e2y, double& p0, double& e2p0, double& p1){
01010 
01011   //#include "RecoTracker/ConversionSeedGenerators/interface/verySimpleFit.icc"
01012   return 0;
01013 }
01014 
01015 double SeedForPhotonConversionFromQuadruplets::getSqrEffectiveErrorOnZ(const TransientTrackingRecHit::ConstRecHitPointer &hit, const TrackingRegion & region){
01016 
01017   //
01018   //Fit-wise the effective error on Z is the sum in quadrature of the error on Z
01019   //and the error on R correctly projected by using hit-vertex direction
01020 
01021   double sqrProjFactor = sqr((hit->globalPosition().z()-region.origin().z())/(hit->globalPosition().perp()-region.origin().perp()));
01022   return (hit->globalPositionError().czz()+sqrProjFactor*hit->globalPositionError().rerr(hit->globalPosition()));
01023 
01024 }
01025 
01026 bool SeedForPhotonConversionFromQuadruplets::similarQuadExist(Quad & thisQuad, std::vector<Quad>& quadV){
01027 
01028   BOOST_FOREACH( Quad quad, quadV )
01029     {
01030       double dx = thisQuad.x-quad.x;
01031       double dy = thisQuad.y-quad.y;
01032       //double dz = abs(thisQuad.z-quad.z);
01033       //std::cout<<"thisQuad.x="<<thisQuad.x<<"  "<<"quad.x="<<quad.x<<"  "<<"thisQuad.y="<<thisQuad.y<<"  "<<"quad.y="<<quad.y<<"  "<<"thisQuad.z"<<thisQuad.z<<"  "<<"quad.z="<<quad.z<<"  "<<"thisQuad.ptPlus"<<thisQuad.ptPlus<<"  "<<"quad.ptPlus="<<quad.ptPlus<<"  "<<"thisQuad.ptMinus="<<thisQuad.ptMinus<<"  "<<"quad.ptMinus="<<quad.ptMinus<<"  "<<"thisQuad.cot="<<thisQuad.cot<<"  "<<"quad.cot="<<quad.cot<<std::endl; //ValDebug
01034       //std::cout<<"x1-x2="<<dx<<"y1-y2="<<dy<<"dx*dx+dy*dy="<<dx*dx+dy*dy<<std::endl; //ValDebug
01035       //std::cout<<"thisQuad.ptPlus-quad.ptPlus="<<thisQuad.ptPlus-quad.ptPlus<<"abs(thisQuad.ptPlus-quad.ptPlus)="<<abs(thisQuad.ptPlus-quad.ptPlus)<<std::endl; //ValDebug
01036       //std::cout <<sqrt(dx*dx+dy*dy)<<" <1? "<<dz<<" <3? "<<abs(thisQuad.ptPlus-quad.ptPlus)<<" <0.5? "<<abs(thisQuad.ptMinus-quad.ptMinus)<<" <0.5? "<<abs(thisQuad.cot-quad.cot)<<" <0.3? "<<std::endl; //ValDebug
01037       //if ( sqrt(dx*dx+dy*dy)<1.)
01038           //      std::cout <<sqrt(dx*dx+dy*dy)<<" <1? "<<dz<<" <3? "<<abs(thisQuad.ptPlus-quad.ptPlus)<<" <"<<0.5*quad.ptPlus<<"? "<<abs(thisQuad.ptMinus-quad.ptMinus)<<" <"<<0.5*quad.ptMinus<<"? "<<abs(thisQuad.cot-quad.cot)<<" <"<<0.3*quad.cot<<"? "<<std::endl; //ValDebug
01039     // ( sqrt(dx*dx+dy*dy)<1. &&
01040         //z<3. &&
01041         //bs(thisQuad.ptPlus-quad.ptPlus)<0.5*quad.ptPlus &&
01042         //bs(thisQuad.ptMinus-quad.ptMinus)<0.5*quad.ptMinus &&
01043         //bs(thisQuad.cot-quad.cot)<0.3*quad.cot
01044         //
01045     //  {
01046     //  //std::cout<<"Seed rejected due to arbitration"<<std::endl;
01047     //  return true;
01048     //  }
01049       if ( sqrt(dx*dx+dy*dy)<1. &&
01050            fabs(thisQuad.ptPlus-quad.ptPlus)<0.5*quad.ptPlus &&
01051            fabs(thisQuad.ptMinus-quad.ptMinus)<0.5*quad.ptMinus
01052            )
01053           {
01054           //std::cout<<"Seed rejected due to arbitration"<<std::endl;
01055           return true;
01056           }
01057     }
01058   quadV.push_back(thisQuad);
01059   return false;
01060 
01061 }
01062 
01063 double SeedForPhotonConversionFromQuadruplets::DeltaPhiManual(math::XYZVector v1, math::XYZVector v2){
01064 
01065         double  kTWOPI     = 2.*kPI_;
01066         double DeltaPhiMan=v1.Phi()-v2.Phi();
01067         while (DeltaPhiMan >= kPI_) DeltaPhiMan -= kTWOPI;
01068         while (DeltaPhiMan < -kPI_) DeltaPhiMan += kTWOPI;
01069 
01070         return DeltaPhiMan;
01071 
01072 }