tau_reweight_lib.cxx

00001 #include "TauSpinner/tau_reweight_lib.h"
00002 #include "TauSpinner/nonSM.h"
00003 using namespace Tauolapp;
00004 
00005 namespace TauSpinner {
00006 
00007 /*****   GLOBAL VARIABLES   *****/
00008 
00009 // Center of mass system energy
00010 double CMSENE = 7000.0;
00011 
00012 // pp collisions
00013 bool   Ipp    = true;
00014 int    Ipol   = 1;     // Is original sample ( relevant for  Z/gamma case only) polarized?
00015 int    nonSM2 = 0;     // Turn nonSM calculations on/off
00016 int    nonSMN = 0;     // Turn on if calculating nonSM weight for shapes only
00017 int    relWTnonSM = 1; // 1: relWTnonSM is relative to SM or for 0: absolute
00018 double WTnonSM=1.0;    // nonSM weight
00019 double Polari =0.0;    // Helicity-equivalent  for the taus in Z/gamma* production only.
00020                        // Polari is always attributed for polarized states.
00021                        // may be should be available with getter only.
00022 bool IfHiggs=false;    // variable for sigborn
00023 double WTamplit=1;     // AMPLIT
00024 double WTamplitP=1;     // AMPLIT for tau+
00025 double WTamplitM=1;     // AMPLIT for tau-
00026 // Higgs parameters
00027   int    IfHsimple=0;  // switch for simple Higgs
00028 double XMH   = 125.0;  // mass
00029 double XGH   = 1.0;    // width
00030 double Xnorm = 0.15;   // normalization of higgs born
00031 
00032 /********************************/
00033 
00034 /**** To be replaced ****/
00035 double f(double x, int ID, double SS, double cmsene)
00036 // this represent set of PDFS; to be replaced.
00037 // x - fraction of parton momenta
00038 // ID flavour of incoming quark
00039 // SS scale of hard process
00040 // cmsene center of mass for pp collision.
00041 {
00042   // LHAPDF manual: http://projects.hepforge.org/lhapdf/manual
00043   //  double xfx(const double &x;, const double &Q;, int fl);
00044   // returns xf(x, Q) for flavour fl - this time the flavour encoding
00045   // is as in the LHAPDF manual...
00046   // -6..-1 = tbar,...,ubar, dbar
00047   // 1..6 = duscbt
00048   // 0 = g
00049   // xfx is the C++ wrapper for fortran evolvePDF(x,Q,f)
00050   // returns the PDF momentum densities f (i.e. x times PDF number density)
00051 
00052   // we return PDF number density so we divide by x
00053   return LHAPDF::xfx(x, SS, ID)/x;
00054 
00055   //return x*(1-x);
00056 
00057 }
00058 
00059 double sigborn(int ID, double SS, double costhe)
00060 {
00061   //  cout << "ID : " << ID << " HgsWTnonSM = " << HgsWTnonSM << " IfHsimple = " << IfHsimple << endl;
00062   // BORN x-section.
00063   // WARNING: overall sign of costheta must be fixed
00064   int tauID = 15;
00065 
00066   // WARNING: THIS WILL BE SEPARATED FUNCTION
00067     if (IfHiggs) {
00068       double SIGggHiggs=0.;
00069       if(ID==0){
00070         int IPOne =  1;
00071         int IMOne = -1;
00072         SIGggHiggs=disth_(&SS, &costhe, &IPOne, &IPOne)+disth_(&SS, &costhe, &IPOne, &IMOne)+
00073                    disth_(&SS, &costhe, &IMOne, &IPOne)+disth_(&SS, &costhe, &IMOne, &IMOne);
00074 
00075 
00076         double PI=3.14159265358979324;
00077         SIGggHiggs *=  XMH * XMH * XMH *XGH /PI/ ((SS-XMH*XMH)*(SS-XMH*XMH) + XGH*XGH*XMH*XMH);   
00078         //      cout << "JK: SIGggHiggs = " << SS << " " << XMH << " " << XGH << " " <<  XMH * XMH * XMH * XGH /PI/ ((SS-XMH*XMH)*(SS-XMH*XMH) + XGH*XGH*XMH*XMH) << " " << SIGggHiggs << endl;
00079 
00080         if(IfHsimple==1) SIGggHiggs =  Xnorm * XMH * XGH /PI/ ((SS-XMH*XMH)*(SS-XMH*XMH) +XGH*XGH*XMH*XMH);
00081         //      cout << "ZW: SIGggHiggs = " << SS << " " << costhe << " " << SIGggHiggs << endl;
00082       }
00083     return SIGggHiggs;
00084     }
00085   // WARNING: END OF FUTURE  SEPARATED FUNCTION
00086 
00087 
00088   if (ID==0) return 0.0 ;   // for the time being it is zero.
00089   if (ID>0) initwk_( &ID, &tauID, &SS);
00090   else
00091   {
00092     ID = -ID;
00093     initwk_( &ID, &tauID, &SS);
00094   }
00095 
00096   int    iZero = 0;
00097   double dOne  =  1.0;
00098   double dMOne = -1.0;
00099   // sum over all helicity configuration:
00100   return ( t_born_(&iZero, &SS, &costhe, &dOne , &dOne) + t_born_(&iZero, &SS, &costhe, &dOne , &dMOne)
00101            + t_born_(&iZero, &SS, &costhe, &dMOne, &dOne) + t_born_(&iZero, &SS, &costhe, &dMOne, &dMOne))/SS/123231.; 
00102 // overall norm. factor .../SS/123231  most probably it is alpha_QED**2/pi/2/SS is from comparison between Born we use and Born used in Warsaw group. 
00103 }
00104 
00105 /*******************************************************************************
00106   Initialize TauSpinner
00107 
00108   Print info and set global variables
00109 *******************************************************************************/
00110 void initialize_spinner(bool _Ipp, int _Ipol, int _nonSM2, int _nonSMN, double _CMSENE)
00111 {
00112   Ipp    = _Ipp;
00113   Ipol   = _Ipol;
00114   nonSM2 = _nonSM2;
00115   nonSMN = _nonSMN;
00116 
00117   CMSENE = _CMSENE;
00118 
00119   cout<<" ------------------------------------------------------"<<endl;
00120   cout<<" TauSpinner v1.3"<<endl;
00121   cout<<" ---------------"<<endl;
00122   cout<<"   20.Apr.2013  "<<endl;
00123   cout<<" by Z. Czyczula, T. Przedzinski and Z. Was"<<endl;
00124   cout<<" for extra coupling contribution "<<endl;
00125   cout<<" by J. Kalinowski and Wojciech Kotlarski"<<endl;
00126   cout<<" ------------------------------------------------------"<<endl;
00127   cout<<" Ipp - true for pp collision; otherwise polarization"<<endl;
00128   cout<<"       of individual taus from Z/gamma* is set to 0.0"<<endl;
00129   cout<<" Ipp    = "<<Ipp<<endl;
00130   cout<<" CMSENE - used in PDF calculations; only if Ipp = true"<<endl;
00131   cout<<"          and only for Z/gamma*"<<endl;
00132   cout<<" CMSENE = "<<CMSENE<<endl;
00133   cout<<" Ipol - relevant for Z/gamma* decays "<<endl;
00134   cout<<" 0 - events generated without spin effects                "<<endl;
00135   cout<<" 1 - events generated with all spin effects               "<<endl;
00136   cout<<" 2 - events generated with spin correlations and <pol>=0  "<<endl;
00137   cout<<" Ipol    = "<<Ipol<<endl;
00138   cout<<" Ipol - relevant for Z/gamma* decays "<<endl;
00139   cout<<" NOTE: For Ipol=0,1 algorithm is identical.               "<<endl;
00140   cout<<"       However in user program role of wt need change.    "<<endl;
00141   cout<<" nonSM2  = "<<nonSM2<<endl;
00142   cout<<" 1/0 extra term in cross section, density matrix on/off   "<<endl;
00143   cout<<" nonSMN  = "<<nonSMN<<endl;
00144   cout<<" 1/0 extra term in cross section, for shapes only? on/off "<<endl;
00145   cout<<" ------------------------------------------------------   "<<endl;
00146 }
00147 
00148 /*******************************************************************************
00149   Set flag for calculating relative(NONSM-SM)/absolute weight for X-section
00150   calculated as by product in longitudinal polarization method.
00151   1: relWTnonSM is relative to SM (default)
00152   0: absolute
00153 *******************************************************************************/
00154 void setRelWTnonSM(int _relWTnonSM)
00155 {
00156   relWTnonSM = _relWTnonSM;
00157 }
00158 
00159 /*******************************************************************************
00160   Set Higgs mass, width and normalization of Higgs born function
00161   Default is mass = 125, width = 1.0, normalization = 0.15
00162 *******************************************************************************/
00163   void setHiggsParameters(int jak, double mass, double width, double normalization)
00164 {
00165   IfHsimple=jak;
00166   XMH   = mass;
00167   XGH   = width;
00168   Xnorm = normalization;
00169 }
00170 
00171 /*******************************************************************************
00172   Get Higgs mass, width and normalization of Higgs born function
00173 *******************************************************************************/
00174 void getHiggsParameters(double *mass, double *width, double *normalization)
00175 {
00176   *mass          = XMH;
00177   *width         = XGH;
00178   *normalization = Xnorm;
00179 }
00180 
00181 /*******************************************************************************
00182   Set spin of sample
00183 *******************************************************************************/
00184 void setSpinOfSample(int _Ipol)
00185 {
00186   Ipol = _Ipol;
00187 }
00188 
00189 /*******************************************************************************
00190   Turn nonSM calculation on/off
00191 *******************************************************************************/
00192 void setNonSMkey(int _key)
00193 {
00194   nonSM2 = _key;
00195 }
00196 
00197 /*******************************************************************************
00198   Get nonSM weight
00199 *******************************************************************************/
00200 double getWtNonSM()
00201 {
00202   return WTnonSM;
00203 }
00204 /*******************************************************************************
00205   Get amplitude weight
00206 *******************************************************************************/
00207 double getWtamplitP(){return WTamplitP;}
00208 double getWtamplitM(){return WTamplitM;}
00209 /*******************************************************************************
00210   Get tau spin
00211   
00212   Used after sample is reweighted to obtain information about tau spin
00213 *******************************************************************************/
00214 double getTauSpin()
00215 {
00216   return Polari;
00217 }
00218 
00219 /*******************************************************************************
00220   Calculate weights.
00221 
00222   Determine decay channel and call polarization calculation function.
00223   Function for W+/- and H+/-
00224 *******************************************************************************/
00225 double calculateWeightFromParticlesWorHpn(SimpleParticle &sp_X, SimpleParticle &sp_tau, SimpleParticle &sp_nu_tau, vector<SimpleParticle> &sp_tau_daughters)
00226 {
00227   // Create Particles from SimpleParticles
00228 
00229   Particle X     (     sp_X.px(),      sp_X.py(),      sp_X.pz(),      sp_X.e(),      sp_X.pdgid() );
00230   Particle tau   (   sp_tau.px(),    sp_tau.py(),    sp_tau.pz(),    sp_tau.e(),    sp_tau.pdgid() );
00231   Particle nu_tau(sp_nu_tau.px(), sp_nu_tau.py(), sp_nu_tau.pz(), sp_nu_tau.e(), sp_nu_tau.pdgid() );
00232 
00233   vector<Particle> tau_daughters;
00234 
00235   // tau pdgid
00236   int tau_pdgid = sp_tau.pdgid();
00237 
00238   // Create list of tau daughters
00239   for(unsigned int i=0; i<sp_tau_daughters.size(); i++)
00240   {
00241     Particle pp(sp_tau_daughters[i].px(),
00242                 sp_tau_daughters[i].py(),
00243                 sp_tau_daughters[i].pz(),
00244                 sp_tau_daughters[i].e(),
00245                 sp_tau_daughters[i].pdgid() );
00246 
00247     tau_daughters.push_back(pp);
00248   }
00249 
00250   double phi2 = 0.0, theta2 = 0.0;
00251 
00252 
00253   //  Move decay kinematics first to tau rest frame  with z axis pointing along nu_tau direction
00254   //  later rotate again to have neutrino from tau decay along z axis: angles phi2, theta2
00255   prepareKinematicForHH   (tau, nu_tau, tau_daughters, &phi2, &theta2);
00256 
00257 
00258   //  Determine decay channel and then calculate polarimetric vector HH
00259   double *HH = calculateHH(tau_pdgid, tau_daughters, phi2, theta2);
00260  
00261   double sign = 1.0;  // tau from W is 100 % polarized, also from charged Higgs (but with opposite sign)
00262   if     ( abs(sp_X.pdgid()) == 24 ) { sign= 1.0; } 
00263   else if( abs(sp_X.pdgid()) == 37 ) { sign=-1.0; } 
00264   else
00265   {
00266     cout<<"wrong sp_W/H.pdgid()="<<sp_X.pdgid()<<endl;
00267     exit(-1);
00268   }
00269   if     (sp_X.pdgid() < 0 )   
00270     {WTamplitM = WTamplit;}   // tau-
00271   else
00272     {WTamplitP = WTamplit;}   // tau+
00273 
00274   double WT   = 1.0+sign*HH[2];     // [2] means 'pz' component
00275 
00276   // Print out some info about the channel
00277   DEBUG
00278   (
00279     cout<<tau_pdgid<<" -> ";
00280     for(unsigned int i=0;i<tau_daughters.size();i++) cout<<tau_daughters[i].pdgid()<<" ";
00281     cout<<" (HH: "<<HH[0]<<" "<<HH[1]<<" "<<HH[2]<<" "<<HH[3]<<") WT: "<<WT<<endl;
00282   )
00283 
00284   if( WT>2.0 || WT<0.0)
00285   {
00286     cout<<"ERROR: WT not in range [0,2]."<<endl;
00287     exit(-1);
00288   }
00289 
00290   delete HH;
00291   
00292   return WT;
00293 }
00294 
00295 /*******************************************************************************
00296   Calculate weights.
00297 
00298   Determine decay channel and call polarization calculation function.
00299   Function for H
00300 *******************************************************************************/
00301 double calculateWeightFromParticlesH(SimpleParticle &sp_X, SimpleParticle &sp_tau1, SimpleParticle &sp_tau2, vector<SimpleParticle> &sp_tau1_daughters, vector<SimpleParticle> &sp_tau2_daughters)
00302 {
00303   //  cout << "sp_tau1_daughters = " << sp_tau1_daughters.size() << endl;
00304   //  cout << "sp_tau2_daughters = " << sp_tau2_daughters.size() << endl;
00305   SimpleParticle         sp_tau;
00306   SimpleParticle         sp_nu_tau;
00307   vector<SimpleParticle> sp_tau_daughters;
00308   
00309   // First iteration is for tau plus, so the 'nu_tau' is tau minus
00310   if (sp_tau1.pdgid() == -15 )
00311   {
00312     sp_tau           = sp_tau1;
00313     sp_nu_tau        = sp_tau2;
00314     sp_tau_daughters = sp_tau1_daughters;
00315   }
00316   else
00317   {
00318     sp_tau           = sp_tau2;
00319     sp_nu_tau        = sp_tau1;
00320     sp_tau_daughters = sp_tau2_daughters;
00321   }
00322 
00323   double *HHp, *HHm;
00324   
00325   // We use this to separate namespace for tau+ and tau-
00326   if(true)
00327   {
00328     // Create Particles from SimpleParticles
00329     Particle X     (      sp_X.px(),      sp_X.py(),      sp_X.pz(),      sp_X.e(),      sp_X.pdgid() );
00330     Particle tau   (    sp_tau.px(),    sp_tau.py(),    sp_tau.pz(),    sp_tau.e(),    sp_tau.pdgid() );
00331     Particle nu_tau( sp_nu_tau.px(), sp_nu_tau.py(), sp_nu_tau.pz(), sp_nu_tau.e(), sp_nu_tau.pdgid() );
00332 
00333     vector<Particle> tau_daughters;
00334 
00335     // tau pdgid
00336     int tau_pdgid = sp_tau.pdgid();
00337 
00338     // Create list of tau daughters
00339     for(unsigned int i=0; i<sp_tau_daughters.size(); i++)
00340     {
00341       Particle pp(sp_tau_daughters[i].px(),
00342                   sp_tau_daughters[i].py(),
00343                   sp_tau_daughters[i].pz(),
00344                   sp_tau_daughters[i].e(),
00345                   sp_tau_daughters[i].pdgid() );
00346 
00347       tau_daughters.push_back(pp);
00348     }
00349 
00350     double phi2 = 0.0, theta2 = 0.0;
00351 
00352 
00353     //  Move decay kinematics first to tau rest frame  with z axis pointing along nu_tau direction
00354     //  later rotate again to have neutrino from tau decay along z axis: angles phi2, theta2
00355     prepareKinematicForHH   (tau, nu_tau, tau_daughters, &phi2, &theta2);
00356 
00357 
00358     //  Determine decay channel and then calculate polarimetric vector HH
00359     HHp = calculateHH(tau_pdgid, tau_daughters, phi2, theta2);
00360 
00361     DEBUG
00362     (
00363       cout<<tau_pdgid<<" -> ";
00364       for(unsigned int i=0;i<tau_daughters.size();i++) cout<<tau_daughters[i].pdgid()<<" ";
00365       cout<<" (HHp: "<<HHp[0]<<" "<<HHp[1]<<" "<<HHp[2]<<" "<<HHp[3]<<") ";
00366       cout<<endl;
00367     )
00368 
00369     WTamplitP = WTamplit;
00370   } // end of tau+
00371 
00372   // Second iteration is for tau minus, so the 'nu_tau' is tau minus
00373   if(sp_tau1.pdgid() == 15 )
00374   {
00375     sp_tau           = sp_tau1;
00376     sp_nu_tau        = sp_tau2;
00377     sp_tau_daughters = sp_tau1_daughters;
00378   }
00379   else
00380   {
00381     sp_tau           = sp_tau2;
00382     sp_nu_tau        = sp_tau1;
00383     sp_tau_daughters = sp_tau2_daughters;
00384   }
00385   
00386   // We use this to separate namespace for tau+ and tau-
00387   if(true)
00388   {
00389     // Create Particles from SimpleParticles
00390     Particle X     (      sp_X.px(),      sp_X.py(),      sp_X.pz(),      sp_X.e(),      sp_X.pdgid() );
00391     Particle tau   (    sp_tau.px(),    sp_tau.py(),    sp_tau.pz(),    sp_tau.e(),    sp_tau.pdgid() );
00392     Particle nu_tau( sp_nu_tau.px(), sp_nu_tau.py(), sp_nu_tau.pz(), sp_nu_tau.e(), sp_nu_tau.pdgid() );
00393 
00394     vector<Particle> tau_daughters;
00395 
00396     // tau pdgid
00397     int tau_pdgid = sp_tau.pdgid();
00398 
00399     // Create list of tau daughters
00400     for(unsigned int i=0; i<sp_tau_daughters.size(); i++)
00401     {
00402       Particle pp(sp_tau_daughters[i].px(),
00403                   sp_tau_daughters[i].py(),
00404                   sp_tau_daughters[i].pz(),
00405                   sp_tau_daughters[i].e(),
00406                   sp_tau_daughters[i].pdgid() );
00407 
00408       tau_daughters.push_back(pp);
00409     }
00410 
00411     double phi2 = 0.0, theta2 = 0.0;
00412 
00413 
00414     //  Move decay kinematics first to tau rest frame  with z axis pointing along nu_tau direction
00415     //  later rotate again to have neutrino from tau decay along z axis: angles phi2, theta2
00416     prepareKinematicForHH   (tau, nu_tau, tau_daughters, &phi2, &theta2);
00417 
00418 
00419     //  Determine decay channel and then calculate polarimetric vector HH
00420     HHm = calculateHH(tau_pdgid, tau_daughters, phi2, theta2);
00421 
00422     DEBUG
00423     (
00424       cout<<tau_pdgid<<" -> ";
00425       for(unsigned int i=0;i<tau_daughters.size();i++) cout<<tau_daughters[i].pdgid()<<" ";
00426       cout<<" (HHm: "<<HHm[0]<<" "<<HHm[1]<<" "<<HHm[2]<<" "<<HHm[3]<<") ";
00427       cout<<endl;
00428     )
00429 
00430     WTamplitM = WTamplit; 
00431   } // end of tau-
00432 
00433   double sign = 1.0; // longitudinal spin correlation for gamma* or even Z/gamma* (just that this is vector)
00434   if(sp_X.pdgid() == 25) { sign=-1.0; } 
00435   if(sp_X.pdgid() == 36) { sign=-1.0; }
00436 
00437   double WT = 0.0;
00438   Polari = 0.0;
00439   
00440   if(sign == -1.0) // Case of Higgs 
00441   {
00442     double S = sp_X.e()*sp_X.e() - sp_X.px()*sp_X.px() - sp_X.py()*sp_X.py() - sp_X.pz()*sp_X.pz();
00443     IfHiggs=true;
00444     double pol = getLongitudinalPolarization(S, sp_tau, sp_nu_tau);
00445 
00446     if(nonSM2==1)
00447       {
00448      
00449       double corrX2;
00450       double polX2;
00451 
00452       // NOTE: in this case, sp_nu_tau is the 2nd tau
00453       //      nonSMHcorrPol(S, sp_tau, sp_nu_tau, &corrX2, &polX2); // for future use
00454       //                                                          WARNING: may be for polX2*HHm[2] we need to fix sign!
00455       polX2=pol;
00456       corrX2=-sign; // if X2 is of spin-2, spin correlation like for Z
00457       
00458       WT = 1.0+corrX2*HHp[2]*HHm[2]+polX2*HHp[2]+polX2*HHm[2];
00459       // we separate cross section into helicity +- and -+ parts
00460       double RRR = Tauola::randomDouble();  
00461       Polari=1.0;
00462       if (RRR<(1.0+polX2)*(1.0+corrX2*HHp[2]*HHm[2]+HHp[2]+HHm[2])/(2.0+2.0*corrX2*HHp[2]*HHm[2]+2.0*polX2*HHp[2]+2.0*polX2*HHm[2])) Polari=-1.0;    }
00463     else
00464     {
00465       WT = 1.0+sign*HHp[2]*HHm[2];     // [2] means 'pz' component
00466       // we separate cross section into helicity +- and -+ parts
00467       double RRR = Tauola::randomDouble();  
00468       Polari=1.0;
00469       if (RRR<(1.0+sign*HHp[2]*HHm[2]+HHp[2]-HHm[2])/(2.0+2.0*sign*HHp[2]*HHm[2])) Polari=-1.0;
00470     }
00471   }
00472   else   // Case of Z/gamma*
00473   { 
00474 
00475     double S = sp_X.e()*sp_X.e() - sp_X.px()*sp_X.px() - sp_X.py()*sp_X.py() - sp_X.pz()*sp_X.pz();
00476 
00477     // Get Z polarization
00478     // ( Variable names are misleading! sp_tau is tau+ and sp_nu_tau is tau- )
00479 
00480     IfHiggs=false;
00481     double pol = getLongitudinalPolarization(S, sp_tau, sp_nu_tau);
00482 
00483     // we separate cross section into helicity ++ and -- parts
00484     double RRR = Tauola::randomDouble();  
00485     WT = 1.0+sign*HHp[2]*HHm[2]+pol*HHp[2]+pol*HHm[2]; 
00486     // we need extra factor for wt which is
00487     //     F=PLWEIGHT(IDE,IDF,SVAR,COSTHE,1)
00488 
00489 
00490     if(Ipol==2) WT = WT/(1.0+sign*HHp[2]*HHm[2]); // extra term in wt
00491     // to correct sample when only corr. are in, but no pol.
00492 
00493       Polari=1.0;
00494       if (RRR<(1.0+pol)*(1.0+sign*HHp[2]*HHm[2]+HHp[2]+HHm[2])/(2.0+2.0*sign*HHp[2]*HHm[2]+2.0*pol*HHp[2]+2.0*pol*HHm[2])) Polari=-1.0; 
00495   }
00496 
00497   // Print out some info about the channel
00498   DEBUG( cout<<" WT: "<<WT<<endl; )
00499 
00500   if (WT<0.0) {
00501     WT = 0.0; // SwB:23Feb2013
00502     cout << "Setting WT to be 0.0" << endl;
00503    }
00504 
00505   if (WT>4.0) {
00506     WT = 4.0; // SwB:23Feb2013
00507     cout << "Setting WT to be 4.0" << endl;
00508   }
00509 
00510   if( WT>4.0 || WT<0.0)
00511   {
00512     cout<<"ERROR: Z/gamma* or H, and WT not in range [0,4]."<<endl;
00513     exit(-1);
00514   }
00515 
00516   if (sign==-1.0) {
00517     if (WT>2.0) {
00518       WT = 2.0; // SwB:26Feb2013
00519       cout << "Setting WT to be 2.0" << endl;
00520     }
00521   }
00522 
00523   if( sign==-1.0 && (WT>2.0 || WT<0.0) )
00524   {
00525     cout<<"ERROR: H and WT not in range [0,2]."<<endl;
00526     exit(-1);
00527   }
00528 
00529   delete[] HHp;
00530   delete[] HHm;
00531   
00532   return WT;
00533 }
00534 
00535 /*******************************************************************************
00536   Prepare kinematics for HH calculation
00537   
00538   Boost particles to effective bozon rest frame, and rotate them so that tau is on Z axis.
00539   Then rotate again with theta2 phi2 so neutrino from tau decay is along Z.
00540 *******************************************************************************/
00541 void prepareKinematicForHH(Particle &tau, Particle &nu_tau, vector<Particle> &tau_daughters, double *phi2, double *theta2)
00542 {
00543   Particle P_QQ( tau.px()+nu_tau.px(), tau.py()+nu_tau.py(), tau.pz()+nu_tau.pz(), tau.e()+nu_tau.e(), 0 );
00544 
00545   //cout<<endl<<"START: "<<endl;
00546   //print(P_QQ,nu_tau,tau,tau_daughters);
00547   
00548   // 1) boost tau, nu_tau and tau daughters to rest frame of P_QQ
00549 
00550   tau.boostToRestFrame(P_QQ);
00551   nu_tau.boostToRestFrame(P_QQ);
00552 
00553   for(unsigned int i=0; i<tau_daughters.size();i++)
00554     tau_daughters[i].boostToRestFrame(P_QQ);
00555 
00556   //cout<<endl<<"AFTER 1: "<<endl;
00557   //print(P_QQ,nu_tau,tau,tau_daughters);
00558 
00559   // 2) Rotate tau, nu_tau~, tau daughters to frame where tau is along Z
00560   //    We set accompanying neutino in direction of Z+
00561 
00562   double phi = tau.getAnglePhi();
00563 
00564   tau.rotateXY(-phi);
00565 
00566   double theta   = tau.getAngleTheta();
00567 
00568   tau.rotateXZ(M_PI-theta);
00569 
00570   nu_tau.rotateXY(-phi  );
00571   nu_tau.rotateXZ(M_PI-theta);
00572 
00573   for(unsigned int i=0; i<tau_daughters.size();i++)
00574   {
00575     tau_daughters[i].rotateXY(-phi  );
00576     tau_daughters[i].rotateXZ(M_PI-theta);
00577   }
00578 
00579   //cout<<endl<<"AFTER 2: "<<endl;
00580   //print(P_QQ,nu_tau,tau,tau_daughters);
00581 
00582   // 3) boost tau_daughters along Z to rest frame of tau
00583 
00584   for(unsigned int i=0; i<tau_daughters.size();i++)
00585     tau_daughters[i].boostAlongZ(-tau.pz(),tau.e());
00586 
00587   //cout<<endl<<"AFTER 3: "<<endl;
00588   //print(P_QQ,nu_tau,tau,tau_daughters);
00589 
00590   // 4) Now rotate tau daughters second time
00591   //    so that nu_tau (from tau daughters list) is on Z axis
00592 
00593   *phi2     = tau_daughters[0].getAnglePhi();
00594 
00595   tau_daughters[0].rotateXY( -(*phi2)   );
00596 
00597   *theta2   = tau_daughters[0].getAngleTheta();
00598 
00599   tau_daughters[0].rotateXZ( -(*theta2) );
00600 
00601   for(unsigned int i=1; i<tau_daughters.size();i++)
00602   {
00603     tau_daughters[i].rotateXY( -(*phi2)   );
00604     tau_daughters[i].rotateXZ( -(*theta2) );
00605   }
00606 
00607   //cout<<endl<<"AFTER 4: "<<endl;
00608   //print(P_QQ,nu_tau,tau,tau_daughters);
00609 }
00610 
00611 /*******************************************************************************
00612   Calculate polarization vector.
00613 
00614   We use FORTRAN metdods to calculate HH.
00615   First decide what is the channel. After that, 4-vectors
00616   are moved to tau rest frame of tau.
00617   Polarimetric vector HH is then rotated using angles phi and theta.
00618 
00619   Order of the particles does not matter. 
00620 *******************************************************************************/
00621 double* calculateHH(int tau_pdgid, vector<Particle> &tau_daughters, double phi, double theta)
00622 {
00623   int    channel = 0;
00624   double *HH     = new double[4];
00625 
00626   HH[0]=HH[1]=HH[2]=HH[3]=0.0;
00627 
00628   vector<int>  pdgid;
00629 
00630   // Create list of tau daughters
00631   for(unsigned int i=0; i<tau_daughters.size(); i++)
00632     pdgid.push_back( tau_daughters[i].pdgid() );
00633 
00634   // tau^- --> pi^- nu_tau
00635   // tau^+ --> pi^+ anti_nu_tau
00636   // tau^- --> K^-  nu_tau
00637   // tau^+ --> K^+  anti_nu_tau
00638   if( pdgid.size()==2 &&
00639       (
00640         ( tau_pdgid== 15 && channelMatch(tau_daughters, 16,-211) ) ||
00641         ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 211) ) ||
00642         ( tau_pdgid== 15 && channelMatch(tau_daughters, 16,-321) ) ||
00643         ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 321) )
00644       )
00645     ) {
00646     channel = 3;
00647     if(abs(pdgid[1])==321) channel = 6;
00648     DEBUG( cout<<"Channel "<<channel<<"  : "; )
00649     //        PXQ=AMTAU*EPI
00650     //        PXN=AMTAU*ENU
00651     //        QXN=PPI(4)*PNU(4)-PPI(1)*PNU(1)-PPI(2)*PNU(2)-PPI(3)*PNU(3)
00652 
00653     //        BRAK=(GV**2+GA**2)*(2*PXQ*QXN-AMPI**2*PXN)
00654     //        HV(I)=-ISGN*2*GA*GV*AMTAU*(2*PPI(I)*QXN-PNU(I)*AMPI**2)/BRAK
00655 
00656     const double AMTAU = 1.777;
00657     double AMPI  = sqrt(tau_daughters[1].e() *tau_daughters[1].e()
00658                        -tau_daughters[1].px()*tau_daughters[1].px()
00659                        -tau_daughters[1].py()*tau_daughters[1].py()
00660                        -tau_daughters[1].pz()*tau_daughters[1].pz());
00661 
00662     double PXQ=AMTAU*tau_daughters[1].e();
00663     double PXN=AMTAU*tau_daughters[0].e();
00664     double QXN=tau_daughters[1].e()*tau_daughters[0].e()-tau_daughters[1].px()*tau_daughters[0].px()-tau_daughters[1].py()*tau_daughters[0].py()-tau_daughters[1].pz()*tau_daughters[0].pz();
00665     double BRAK=(2*PXQ*QXN-AMPI*AMPI*PXN);
00666 
00667     WTamplit = (1.16637E-5)*(1.16637E-5)*BRAK/2.;//AMPLIT=(GFERMI)**2*BRAK/2.
00668     HH[0] = AMTAU*(2*tau_daughters[1].px()*QXN-tau_daughters[0].px()*AMPI*AMPI)/BRAK;
00669     HH[1] = AMTAU*(2*tau_daughters[1].py()*QXN-tau_daughters[0].py()*AMPI*AMPI)/BRAK;
00670     HH[2] = AMTAU*(2*tau_daughters[1].pz()*QXN-tau_daughters[0].pz()*AMPI*AMPI)/BRAK;
00671     HH[3] = 1.0;
00672   }
00673 
00674   // tau^- --> pi^- pi^0 nu_tau
00675   // tau^+ --> pi^+ pi^0 anti_nu_tau
00676   // tau^- --> K^-  pi^0 nu_tau
00677   // tau^+ --> K^+  pi^0 anti_nu_tau
00678   // tau^- --> pi^- K_S0 nu_tau
00679   // tau^+ --> pi^+ K_S0 anti_nu_tau
00680   // tau^- --> pi^- K_L0 nu_tau
00681   // tau^+ --> pi^+ K_L0 anti_nu_tau
00682   else if( pdgid.size()==3 &&
00683            (
00684              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16,-211, 111) ) ||
00685              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 211, 111) ) ||
00686              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16,-211, 130) ) ||
00687              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 211, 130) ) ||
00688              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16,-211, 310) ) ||
00689              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 211, 310) ) ||
00690              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16,-321, 111) ) ||
00691              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 321, 111) )
00692            )
00693          ) {
00694 
00695     channel = 4;
00696     if(abs(pdgid[1])==321 || abs(pdgid[2])==130 || abs(pdgid[2])==310) channel = 7;
00697     DEBUG( cout<<"Channel "<<channel<<"  : "; )
00698     //      PRODPQ=PT(4)*QQ(4)
00699     //      PRODNQ=PN(4)*QQ(4)-PN(1)*QQ(1)-PN(2)*QQ(2)-PN(3)*QQ(3)
00700     //      PRODPN=PT(4)*PN(4)
00701     //      BRAK=(GV**2+GA**2)*(2*PRODPQ*PRODNQ-PRODPN*QQ2)
00702     //      HV(I)=2*GV*GA*AMTAU*(2*PRODNQ*QQ(I)-QQ2*PN(I))/BRAK
00703 
00704     const double AMTAU = 1.777;
00705 
00706     double QQ[4];
00707     QQ[0]=tau_daughters[1].e() -tau_daughters[2].e() ;
00708       QQ[1]=tau_daughters[1].px()-tau_daughters[2].px();
00709       QQ[2]=tau_daughters[1].py()-tau_daughters[2].py();
00710       QQ[3]=tau_daughters[1].pz()-tau_daughters[2].pz();
00711 
00712     double PKS[4];
00713     PKS[0]=tau_daughters[1].e() +tau_daughters[2].e() ;
00714       PKS[1]=tau_daughters[1].px()+tau_daughters[2].px();
00715       PKS[2]=tau_daughters[1].py()+tau_daughters[2].py();
00716       PKS[3]=tau_daughters[1].pz()+tau_daughters[2].pz();
00717 
00718        // orthogonalization of QQ wr. to PKS
00719     double PKSD=PKS[0]*PKS[0]-PKS[1]*PKS[1]-PKS[2]*PKS[2]-PKS[3]*PKS[3];
00720     double QQPKS=QQ[0]*PKS[0]-QQ[1]*PKS[1]-QQ[2]*PKS[2]-QQ[3]*PKS[3];
00721 
00722     QQ[0]=QQ[0]-PKS[0]*QQPKS/PKSD;
00723       QQ[1]=QQ[1]-PKS[1]*QQPKS/PKSD;
00724       QQ[2]=QQ[2]-PKS[2]*QQPKS/PKSD;
00725       QQ[3]=QQ[3]-PKS[3]*QQPKS/PKSD;
00726 
00727     double PRODPQ=AMTAU*QQ[0];
00728     double PRODNQ=tau_daughters[0].e() *QQ[0]
00729                  -tau_daughters[0].px()*QQ[1]
00730                  -tau_daughters[0].py()*QQ[2]
00731                  -tau_daughters[0].pz()*QQ[3];
00732     double PRODPN=AMTAU*tau_daughters[0].e();
00733     double QQ2   =QQ[0]*QQ[0]-QQ[1]*QQ[1]-QQ[2]*QQ[2]-QQ[3]*QQ[3];
00734 
00735     double BRAK=(2*PRODPQ*PRODNQ-PRODPN*QQ2);
00736 
00737     WTamplit = (1.16637E-5)*(1.16637E-5)*BRAK/2.;//AMPLIT=(GFERMI)**2*BRAK/2.
00738     HH[0]=AMTAU*(2*PRODNQ*QQ[1]-QQ2*tau_daughters[0].px())/BRAK;
00739     HH[1]=AMTAU*(2*PRODNQ*QQ[2]-QQ2*tau_daughters[0].py())/BRAK;
00740     HH[2]=AMTAU*(2*PRODNQ*QQ[3]-QQ2*tau_daughters[0].pz())/BRAK;
00741     HH[3]=1.0;
00742   }
00743 
00744   // tau^- --> e^- anti_nu_e      nu_tau
00745   // tau^+ --> e^+      nu_e anti_nu_tau
00746   else if( pdgid.size()==3 &&
00747            (
00748              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16, 11,-12) ) ||
00749              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16,-11, 12) )
00750            )
00751          ) {
00752     DEBUG( cout<<"Channel 1  : "; )
00753     channel = 1;
00754     //  ITDKRC=0,XK0DEC=0.01 XK[4]={0},XA[4] nu_e, QP[4] e, XN[4] neutrino tauowe, AMPLIT, HH[4]
00755     //      SUBROUTINE DAMPRY(ITDKRC,XK0DEC,XK,XA,QP,XN,AMPLIT,HV)
00756 
00757     int    ITDKRC = 0;
00758     double XK0DEC = 0.01;
00759     double XK[4] = { 0.0 };
00760     double XA[4] = { tau_daughters[2].px(), tau_daughters[2].py(), tau_daughters[2].pz(), tau_daughters[2].e() };
00761     double QP[4] = { tau_daughters[1].px(), tau_daughters[1].py(), tau_daughters[1].pz(), tau_daughters[1].e() };
00762     double XN[4] = { tau_daughters[0].px(), tau_daughters[0].py(), tau_daughters[0].pz(), tau_daughters[0].e() };
00763     double AMPLIT = 0.0;
00764     double HV[4] = { 0.0 };
00765 
00766     // Fix 4-momenta of electron and electron neutrino
00767     // Since electrons have small mass, they are prone to rounding errors
00768     QP[3] = sqrt( QP[0]*QP[0] + QP[1]*QP[1] + QP[2]*QP[2] + 0.511e-3*0.511e-3);
00769     XA[3] = sqrt( XA[0]*XA[0] + XA[1]*XA[1] + XA[2]*XA[2] );
00770 
00771     dampry_( &ITDKRC, &XK0DEC, XK, XA, QP, XN, &AMPLIT, HV );
00772 
00773     WTamplit = AMPLIT;
00774     HH[0] = -HV[0];
00775     HH[1] = -HV[1];
00776     HH[2] = -HV[2];
00777     HH[3] =  HV[3];
00778   }
00779 
00780   // tau^- --> e^- anti_nu_e      nu_tau + gamma
00781   // tau^+ --> e^+      nu_e anti_nu_tau + gamma
00782   else if( pdgid.size()==4 &&
00783            (
00784              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16, 11,-12, 22) ) ||
00785              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16,-11, 12, 22) )
00786            )
00787          ) {
00788     DEBUG( cout<<"Channel 1b : "; )
00789     channel = 1;
00790     //  ITDKRC=0,XK0DEC=0.01 XK[4]  gamma, XA[4] nu_e, QP[4] e, XN[4] neutrino tau , AMPLIT, HH[4]
00791     //      SUBROUTINE DAMPRY(ITDKRC,XK0DEC,XK,XA,QP,XN,AMPLIT,HV)
00792 
00793     int    ITDKRC = 1;
00794     double XK0DEC = 0.01;
00795     double XK[4] = { tau_daughters[3].px(), tau_daughters[3].py(), tau_daughters[3].pz(), tau_daughters[3].e() };
00796     double XA[4] = { tau_daughters[2].px(), tau_daughters[2].py(), tau_daughters[2].pz(), tau_daughters[2].e() };
00797     double QP[4] = { tau_daughters[1].px(), tau_daughters[1].py(), tau_daughters[1].pz(), tau_daughters[1].e() };
00798     double XN[4] = { tau_daughters[0].px(), tau_daughters[0].py(), tau_daughters[0].pz(), tau_daughters[0].e() };
00799     double AMPLIT = 0.0;
00800     double HV[4] = { 0.0 };
00801     
00802     // Fix 4-momenta of electron and electron neutrino and photon
00803     // Since electrons have small mass, they are prone to rounding errors
00804     QP[3] = sqrt( QP[0]*QP[0] + QP[1]*QP[1] + QP[2]*QP[2] + 0.511e-3*0.511e-3);
00805     XA[3] = sqrt( XA[0]*XA[0] + XA[1]*XA[1] + XA[2]*XA[2] );
00806     XK[3] = sqrt( XK[0]*XK[0] + XK[1]*XK[1] + XK[2]*XK[2] );
00807     // XK0DEC must be smaller in TauSpinner  than what was used in generation. We do not use virt. corr anyway.
00808     if(XK0DEC > XK[3]/(XK[3]+XA[3]+QP[3]+XN[3]))  XK0DEC=0.5*XK[3]/(XK[3]+XA[3]+QP[3]+XN[3]);
00809     
00810     dampry_( &ITDKRC, &XK0DEC, XK, XA, QP, XN, &AMPLIT, HV );
00811 
00812     WTamplit = AMPLIT;
00813     HH[0] = -HV[0];
00814     HH[1] = -HV[1];
00815     HH[2] = -HV[2];
00816     HH[3] =  HV[3];
00817   }
00818 
00819   // tau^- --> mu^- antui_nu_mu      nu_tau
00820   // tau^+ --> mu^+       nu_mu anti_nu_tau
00821   else if( pdgid.size()==3 &&
00822            (
00823              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16, 13,-14) ) ||
00824              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16,-13, 14) )
00825            )
00826          ) {
00827 
00828     DEBUG( cout<<"Channel 2  : "; )
00829     channel = 2;
00830     //  ITDKRC=0,XK0DEC=0.01 XK[4]={0},XA[4] nu_mu, QP[4] mu, XN[4] neutrino tauowe, AMPLIT, HH[4]
00831     //      SUBROUTINE DAMPRY(ITDKRC,XK0DEC,XK,XA,QP,XN,AMPLIT,HV)
00832 
00833     int    ITDKRC = 0;
00834     double XK0DEC = 0.01;
00835     double XK[4] = { 0.0 };
00836     double XA[4] = { tau_daughters[2].px(), tau_daughters[2].py(), tau_daughters[2].pz(), tau_daughters[2].e() };
00837     double QP[4] = { tau_daughters[1].px(), tau_daughters[1].py(), tau_daughters[1].pz(), tau_daughters[1].e() };
00838     double XN[4] = { tau_daughters[0].px(), tau_daughters[0].py(), tau_daughters[0].pz(), tau_daughters[0].e() };
00839     double AMPLIT = 0.0;
00840     double HV[4] = { 0.0 };
00841 
00842     // Fix 4-momenta of muon and muon neutrino
00843     // Since muon have small mass, they are prone to rounding errors
00844     QP[3] = sqrt( QP[0]*QP[0] + QP[1]*QP[1] + QP[2]*QP[2] + 0.105659*0.105659);
00845     XA[3] = sqrt( XA[0]*XA[0] + XA[1]*XA[1] + XA[2]*XA[2] );
00846     
00847     dampry_( &ITDKRC, &XK0DEC, XK, XA, QP, XN, &AMPLIT, HV );
00848 
00849     WTamplit = AMPLIT;
00850     HH[0] = -HV[0];
00851     HH[1] = -HV[1];
00852     HH[2] = -HV[2];
00853     HH[3] =  HV[3];
00854   }
00855 
00856   // tau^- --> mu^- antui_nu_mu      nu_tau + gamma
00857   // tau^+ --> mu^+       nu_mu anti_nu_tau + gamma
00858   else if( pdgid.size()==4 &&
00859            (
00860              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16, 13,-14, 22) ) ||
00861              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16,-13, 14, 22) )
00862            )
00863          ) {
00864 
00865     DEBUG( cout<<"Channel 2b : "; )
00866     channel = 2;
00867     //  ITDKRC=0,XK0DEC=0.01 XK[4]  gamma, XA[4] nu_mu, QP[4] mu, XN[4] neutrino tau, AMPLIT, HH[4]
00868     //      SUBROUTINE DAMPRY(ITDKRC,XK0DEC,XK,XA,QP,XN,AMPLIT,HV)
00869 
00870     int    ITDKRC = 1;
00871     double XK0DEC = 0.01;
00872     double XK[4] = { tau_daughters[3].px(), tau_daughters[3].py(), tau_daughters[3].pz(), tau_daughters[3].e() };
00873     double XA[4] = { tau_daughters[2].px(), tau_daughters[2].py(), tau_daughters[2].pz(), tau_daughters[2].e() };
00874     double QP[4] = { tau_daughters[1].px(), tau_daughters[1].py(), tau_daughters[1].pz(), tau_daughters[1].e() };
00875     double XN[4] = { tau_daughters[0].px(), tau_daughters[0].py(), tau_daughters[0].pz(), tau_daughters[0].e() };
00876     double AMPLIT = 0.0;
00877     double HV[4] = { 0.0 };
00878 
00879     // Fix 4-momenta of muon and muon neutrino and photon
00880     // Since muons have small mass, they are prone to rounding errors
00881     QP[3] = sqrt( QP[0]*QP[0] + QP[1]*QP[1] + QP[2]*QP[2] + 0.105659*0.105659);
00882     XA[3] = sqrt( XA[0]*XA[0] + XA[1]*XA[1] + XA[2]*XA[2] );
00883     XK[3] = sqrt( XK[0]*XK[0] + XK[1]*XK[1] + XK[2]*XK[2] );
00884     // XK0DEC must be smaller in TauSpinner  than what was used in generation. We do not use virt. corr anyway.
00885     if(XK0DEC > XK[3]/(XK[3]+XA[3]+QP[3]+XN[3]))  XK0DEC=0.5*XK[3]/(XK[3]+XA[3]+QP[3]+XN[3]);
00886 
00887 
00888     dampry_( &ITDKRC, &XK0DEC, XK, XA, QP, XN, &AMPLIT, HV );
00889 
00890     WTamplit = AMPLIT;
00891     HH[0] = -HV[0];
00892     HH[1] = -HV[1];
00893     HH[2] = -HV[2];
00894     HH[3] =  HV[3];
00895   }
00896 
00897   // tau^- --> pi^- pi^0 pi^0 nu_tau
00898   // tau^+ --> pi^+ pi^0 pi^0 anti_nu_tau
00899   else if( pdgid.size()==4 &&
00900            (
00901              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16, 111, 111,-211) ) ||
00902              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 111, 111, 211) )
00903            )
00904          ) {
00905     DEBUG( cout<<"Channel 5  : "; )
00906     channel = 5;
00907     //  MNUM=0, PT[4] tau, PN[4] neutrino, pi0[4], pi0[4], pi[4], AMPLIT, HH[4]
00908     //        CALL DAMPPK(MNUM,PT,PN,PIM1,PIM2,PIPL,AMPLIT,HH)
00909     jaki_.ktom = 1 ; // jaki_.ktom = (tau_pdgid==15) ? -1 : 1 ;
00910 
00911     const double AMTAU = 1.777;
00912     int   MNUM = 0;
00913     float PT[4]   = { 0.0, 0.0, 0.0, (float)AMTAU };
00914     float PN[4]   = { (float)tau_daughters[0].px(), (float)tau_daughters[0].py(), (float)tau_daughters[0].pz(), (float)tau_daughters[0].e() };
00915     float PIM1[4] = { (float)tau_daughters[1].px(), (float)tau_daughters[1].py(), (float)tau_daughters[1].pz(), (float)tau_daughters[1].e() };
00916     float PIM2[4] = { (float)tau_daughters[2].px(), (float)tau_daughters[2].py(), (float)tau_daughters[2].pz(), (float)tau_daughters[2].e() };
00917     float PIPL[4] = { (float)tau_daughters[3].px(), (float)tau_daughters[3].py(), (float)tau_daughters[3].pz(), (float)tau_daughters[3].e() };
00918     float AMPLIT = 0.0;
00919     float HV[4]  = { 0.0 };
00920 
00921     damppk_( &MNUM, PT, PN, PIM1, PIM2, PIPL, &AMPLIT, HV );
00922 
00923     WTamplit = AMPLIT;
00924     HH[0] = -HV[0];
00925     HH[1] = -HV[1];
00926     HH[2] = -HV[2];
00927     HH[3] =  HV[3];
00928   }
00929 
00930   // tau^- --> pi^+ pi^- pi^- nu_tau
00931   // tau^+ --> pi^- pi^+ pi^+ anti_nu_tau
00932   else if( pdgid.size()==4 &&
00933            (
00934              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16,-211,-211, 211) ) ||
00935              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 211, 211,-211) )
00936            )
00937          ) {
00938     DEBUG( cout<<"Channel 5  : "; )
00939     channel = 5;
00940     //  MNUM=0, PT[4] tau, PN[4] neutrino, pi[4], pi[4], pi[4], AMPLIT, HH[4]
00941     //        CALL DAMPPK(MNUM,PT,PN,PIM1,PIM2,PIPL,AMPLIT,HH)
00942     jaki_.ktom = 1 ; // jaki_.ktom = (tau_pdgid==15) ? -1 : 1 ;
00943 
00944     const double AMTAU = 1.777;
00945     int   MNUM = 0;
00946     float PT[4]   = { 0.0, 0.0, 0.0, (float)AMTAU };
00947     float PN[4]   = { (float)tau_daughters[0].px(), (float)tau_daughters[0].py(), (float)tau_daughters[0].pz(), (float)tau_daughters[0].e() };
00948     float PIM1[4] = { (float)tau_daughters[1].px(), (float)tau_daughters[1].py(), (float)tau_daughters[1].pz(), (float)tau_daughters[1].e() };
00949     float PIM2[4] = { (float)tau_daughters[2].px(), (float)tau_daughters[2].py(), (float)tau_daughters[2].pz(), (float)tau_daughters[2].e() };
00950     float PIPL[4] = { (float)tau_daughters[3].px(), (float)tau_daughters[3].py(), (float)tau_daughters[3].pz(), (float)tau_daughters[3].e() };
00951     float AMPLIT = 0.0;
00952     float HV[4] = { 0.0 };
00953 
00954     damppk_( &MNUM, PT, PN, PIM1, PIM2, PIPL, &AMPLIT, HV );
00955 
00956     WTamplit = AMPLIT;
00957     HH[0] = -HV[0];
00958     HH[1] = -HV[1];
00959     HH[2] = -HV[2];
00960     HH[3] =  HV[3];
00961   }
00962   // tau^- --> pi^+ pi^+ pi^0 pi^- nu_tau
00963   // tau^+ --> pi^- pi^- pi^0 pi^+ anti_nu_tau
00964   else if( pdgid.size()==5 &&
00965            (
00966              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16,-211,-211, 211, 111) ) ||
00967              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 211, 211,-211, 111) )
00968            )
00969          ) {
00970     DEBUG( cout<<"Channel 8  : "; )
00971     channel = 8;
00972 
00973     jaki_.ktom = 1 ; // jaki_.ktom = (tau_pdgid==15) ? -1 : 1 ;
00974 
00975     const double AMTAU = 1.777;
00976     int   MNUM = 1;
00977     float PT[4]   = { 0.0, 0.0, 0.0, (float)AMTAU };
00978     float PN[4]   = { (float)tau_daughters[0].px(), (float)tau_daughters[0].py(), (float)tau_daughters[0].pz(), (float)tau_daughters[0].e() };
00979     float PIM1[4] = { (float)tau_daughters[1].px(), (float)tau_daughters[1].py(), (float)tau_daughters[1].pz(), (float)tau_daughters[1].e() };
00980     float PIM2[4] = { (float)tau_daughters[2].px(), (float)tau_daughters[2].py(), (float)tau_daughters[2].pz(), (float)tau_daughters[2].e() };
00981     float PIZ [4] = { (float)tau_daughters[4].px(), (float)tau_daughters[4].py(), (float)tau_daughters[4].pz(), (float)tau_daughters[4].e() };
00982     float PIPL[4] = { (float)tau_daughters[3].px(), (float)tau_daughters[3].py(), (float)tau_daughters[3].pz(), (float)tau_daughters[3].e() };
00983     float AMPLIT = 0.0;
00984     float HV[4] = { 0.0 };
00985 
00986     dam4pi_( &MNUM, PT, PN, PIM1, PIM2, PIZ, PIPL, &AMPLIT, HV );
00987 
00988     WTamplit = AMPLIT;
00989     HH[0] = -HV[0];
00990     HH[1] = -HV[1];
00991     HH[2] = -HV[2];
00992     HH[3] =  HV[3];
00993   }
00994   // tau^- --> pi^0 pi^0 pi^0 pi^- nu_tau
00995   // tau^+ --> pi^0 pi^0 pi^0 pi^+ anti_nu_tau
00996   else if( pdgid.size()==5 &&
00997            (
00998              ( tau_pdgid== 15 && channelMatch(tau_daughters, 16, 111, 111, 111,-211) ) ||
00999              ( tau_pdgid==-15 && channelMatch(tau_daughters,-16, 111, 111, 111, 211) )
01000            )
01001          ) {
01002     DEBUG( cout<<"Channel 9  : "; )
01003     channel = 9;
01004 
01005     jaki_.ktom = 1 ; // jaki_.ktom = (tau_pdgid==15) ? -1 : 1 ;
01006 
01007     const double AMTAU = 1.777;
01008     int   MNUM = 2;
01009     float PT[4]   = { 0.0, 0.0, 0.0, (float)AMTAU };
01010     float PN[4]   = { (float)tau_daughters[0].px(), (float)tau_daughters[0].py(), (float)tau_daughters[0].pz(), (float)tau_daughters[0].e() };
01011     float PIM1[4] = { (float)tau_daughters[1].px(), (float)tau_daughters[1].py(), (float)tau_daughters[1].pz(), (float)tau_daughters[1].e() };
01012     float PIM2[4] = { (float)tau_daughters[2].px(), (float)tau_daughters[2].py(), (float)tau_daughters[2].pz(), (float)tau_daughters[2].e() };
01013     float PIZ [4] = { (float)tau_daughters[3].px(), (float)tau_daughters[3].py(), (float)tau_daughters[3].pz(), (float)tau_daughters[3].e() };
01014     float PIPL[4] = { (float)tau_daughters[4].px(), (float)tau_daughters[4].py(), (float)tau_daughters[4].pz(), (float)tau_daughters[4].e() };
01015     float AMPLIT = 0.0;
01016     float HV[4] = { 0.0 };
01017 
01018     dam4pi_( &MNUM, PT, PN, PIM1, PIM2, PIZ, PIPL, &AMPLIT, HV );
01019 
01020     WTamplit = AMPLIT;
01021     HH[0] = -HV[0];
01022     HH[1] = -HV[1];
01023     HH[2] = -HV[2];
01024     HH[3] =  HV[3];
01025   }
01026   else {
01027 
01028     DEBUG( cout<<tau_daughters.size()<<"-part  ???: "; )
01029 
01030   }
01031 
01032   // Now rotate vector HH using angles phi and theta
01033   Particle HHbuf(HH[0], HH[1], HH[2], HH[3], 0);
01034   
01035   HHbuf.rotateXZ(theta);
01036   HHbuf.rotateXY(phi);
01037   
01038   HH[0] = HHbuf.px();
01039   HH[1] = HHbuf.py();
01040   HH[2] = HHbuf.pz();
01041   HH[3] = HHbuf.e ();
01042 
01043   return HH;
01044 }
01045 
01046 /*******************************************************************************
01047  Get Z polarization
01048  
01049  Returns longitudinal polarization in Z/gamma* -> tau+ tau- averaged over
01050  incoming configurations
01051  S: invariant mass^2 of the bozon
01052 *******************************************************************************/
01053 double getLongitudinalPolarization(double S, SimpleParticle &sp_tau, SimpleParticle &sp_nu_tau)
01054 {
01055   // tau+ and tau- in lab frame
01056   Particle tau_plus (    sp_tau.px(),    sp_tau.py(),    sp_tau.pz(),    sp_tau.e(),    sp_tau.pdgid() );
01057   Particle tau_minus( sp_nu_tau.px(), sp_nu_tau.py(), sp_nu_tau.pz(), sp_nu_tau.e(), sp_nu_tau.pdgid() );
01058 
01059   // P_QQ = sum of tau+ and tau- in lab frame
01060   Particle P_QQ( tau_plus.px()+tau_minus.px(), tau_plus.py()+tau_minus.py(), tau_plus.pz()+tau_minus.pz(), tau_plus.e()+tau_minus.e(), 0 );
01061   
01062   Particle P_B1(0, 0, 1, 1, 0);
01063   Particle P_B2(0, 0,-1, 1, 0);
01064 
01065   tau_plus. boostToRestFrame(P_QQ);
01066   tau_minus.boostToRestFrame(P_QQ);
01067   P_B1.     boostToRestFrame(P_QQ);
01068   P_B2.     boostToRestFrame(P_QQ);
01069   
01070   double costheta1 = (tau_plus.px()*P_B1.px()    +tau_plus.py()*P_B1.py()    +tau_plus.pz()*P_B1.pz()    ) /
01071                  sqrt(tau_plus.px()*tau_plus.px()+tau_plus.py()*tau_plus.py()+tau_plus.pz()*tau_plus.pz()) /
01072                  sqrt(P_B1.px()    *P_B1.px()    +P_B1.py()    *P_B1.py()    +P_B1.pz()    *P_B1.pz()    );
01073 
01074   double costheta2 = (tau_minus.px()*P_B2.px()    +tau_minus.py()*P_B2.py()    +tau_minus.pz()*P_B2.pz()    ) /
01075                  sqrt(tau_minus.px()*tau_minus.px()+tau_minus.py()*tau_minus.py()+tau_minus.pz()*tau_minus.pz()) /
01076                  sqrt(P_B2.px()    *P_B2.px()    +P_B2.py()    *P_B2.py()    +P_B2.pz()    *P_B2.pz()    );
01077                
01078   double sintheta1 = sqrt(1-costheta1*costheta1);
01079   double sintheta2 = sqrt(1-costheta2*costheta2);
01080   
01081   // Cosine of hard scattering
01082   double costhe = (costheta1*sintheta2 + costheta2*sintheta1) / (sintheta1 + sintheta2);
01083   
01084   // Invariant mass of tau+tau- pair
01085   double SS     = S; // other option is for tests: P_QQ.recalculated_mass()*P_QQ.recalculated_mass();
01086   
01087   /*
01088     We need to fix sign of costhe and attribute ID. 
01089     calculate x1,x2;  // x1*x2 = SS/CMSENE/CMSENE; // (x1-x2)/(x1+x2)=P_QQ/CMSENE*2 in lab; 
01090     calculate weight WID[]=sig(ID,SS,+/-costhe)* f(x1,+/-ID,SS) * f(x2,-/+ID,SS) ; respectively for u d c s b 
01091     f(x,ID,SS,CMSENE)=x*(1-x) // for the start it will invoke library
01092     on the basis of this generate ID and set sign for costhe. 
01093     then we calculate polarization averaging over incoming states.
01094   */
01095   
01096   double x1x2  = SS/CMSENE/CMSENE;
01097   double x1Mx2 = P_QQ.pz()/CMSENE*2;
01098   
01099   double x1 = (  x1Mx2 + sqrt(x1Mx2*x1Mx2 + 4*x1x2) )/2;
01100   double x2 = ( -x1Mx2 + sqrt(x1Mx2*x1Mx2 + 4*x1x2) )/2;
01101   
01102   double WID[11];
01103   WID[0] = f(x1, 0,SS,CMSENE)*f(x2, 0,SS,CMSENE) * sigborn(0,SS, costhe);
01104   WID[1] = f(x1, 1,SS,CMSENE)*f(x2,-1,SS,CMSENE) * sigborn(1,SS, costhe);
01105   WID[2] = f(x1,-1,SS,CMSENE)*f(x2, 1,SS,CMSENE) * sigborn(1,SS,-costhe);
01106   WID[3] = f(x1, 2,SS,CMSENE)*f(x2,-2,SS,CMSENE) * sigborn(2,SS, costhe);
01107   WID[4] = f(x1,-2,SS,CMSENE)*f(x2, 2,SS,CMSENE) * sigborn(2,SS,-costhe);
01108   WID[5] = f(x1, 3,SS,CMSENE)*f(x2,-3,SS,CMSENE) * sigborn(1,SS, costhe);
01109   WID[6] = f(x1,-3,SS,CMSENE)*f(x2, 3,SS,CMSENE) * sigborn(1,SS,-costhe);
01110   WID[7] = f(x1, 4,SS,CMSENE)*f(x2,-4,SS,CMSENE) * sigborn(2,SS, costhe);
01111   WID[8] = f(x1,-4,SS,CMSENE)*f(x2, 4,SS,CMSENE) * sigborn(2,SS,-costhe);
01112   WID[9] = f(x1, 5,SS,CMSENE)*f(x2,-5,SS,CMSENE) * sigborn(1,SS, costhe);
01113   WID[10]= f(x1,-5,SS,CMSENE)*f(x2, 5,SS,CMSENE) * sigborn(1,SS,-costhe);
01114   
01115   double sum = 0.0;  // normalize
01116   for(int i=0;i<=10;i++) sum+=WID[i];
01117   
01118   WTnonSM=1.0;
01119   if(relWTnonSM==0)  WTnonSM=sum;
01120   if(nonSM2==1)
01121   {
01122     double WID2[11];
01123     WID2[0] = f(x1, 0,SS,CMSENE)*f(x2, 0,SS,CMSENE) * sigborn(0,SS, costhe) * plweight(0,SS, costhe);
01124     WID2[1] = f(x1, 1,SS,CMSENE)*f(x2,-1,SS,CMSENE) * sigborn(1,SS, costhe) * plweight(1,SS, costhe);
01125     WID2[2] = f(x1,-1,SS,CMSENE)*f(x2, 1,SS,CMSENE) * sigborn(1,SS,-costhe) * plweight(1,SS,-costhe);
01126     WID2[3] = f(x1, 2,SS,CMSENE)*f(x2,-2,SS,CMSENE) * sigborn(2,SS, costhe) * plweight(2,SS, costhe);
01127     WID2[4] = f(x1,-2,SS,CMSENE)*f(x2, 2,SS,CMSENE) * sigborn(2,SS,-costhe) * plweight(2,SS,-costhe);
01128     WID2[5] = f(x1, 3,SS,CMSENE)*f(x2,-3,SS,CMSENE) * sigborn(1,SS, costhe) * plweight(1,SS, costhe);
01129     WID2[6] = f(x1,-3,SS,CMSENE)*f(x2, 3,SS,CMSENE) * sigborn(1,SS,-costhe) * plweight(1,SS,-costhe);
01130     WID2[7] = f(x1, 4,SS,CMSENE)*f(x2,-4,SS,CMSENE) * sigborn(2,SS, costhe) * plweight(2,SS, costhe);
01131     WID2[8] = f(x1,-4,SS,CMSENE)*f(x2, 4,SS,CMSENE) * sigborn(2,SS,-costhe) * plweight(2,SS,-costhe);
01132     WID2[9] = f(x1, 5,SS,CMSENE)*f(x2,-5,SS,CMSENE) * sigborn(1,SS, costhe) * plweight(1,SS, costhe);
01133     WID2[10]= f(x1,-5,SS,CMSENE)*f(x2, 5,SS,CMSENE) * sigborn(1,SS,-costhe) * plweight(1,SS,-costhe);
01134     
01135     double sum2 = 0.0;  // normalize
01136     for(int i=0;i<=10;i++) sum2+=WID2[i];
01137 
01138     WTnonSM=sum2/sum ; 
01139     if(relWTnonSM==0)  WTnonSM=sum2;
01140     }
01141   
01142   double pol = 0.0;
01143   
01144   if(IfHiggs && nonSM2==1) {   // we ssume that only glue glue process contributes for Higgs
01145     double polp = plzap2(0,15,S,costhe);
01146     pol += (2*(1-polp)-1);
01147      return pol;
01148   }
01149   if(IfHiggs) return NAN;
01150 
01151   // caze of Z/gamma 
01152   for(int i=0;i<=10;i++) WID[i]/=sum;
01153 
01154 
01155   
01156   int ICC = -1;
01157   
01158   for(int i=1;i<=10;i++)
01159   {
01160 
01161     ICC = i;
01162     double cost = costhe;
01163     // first beam quark or antiquark
01164 
01165     if( ICC==2 || ICC==4 || ICC==6 || ICC==8 || ICC==10 )  cost = -cost;
01166 
01167     // ID of incoming quark (up or down type)
01168     int ID = 2;          
01169 
01170     if( ICC==1 || ICC==2 || ICC==5 || ICC==6 || ICC==9 || ICC==10 ) ID = 1;
01171 
01172     int tau_pdgid = 15;
01173 
01174     double polp = plzap2(ID,tau_pdgid,S,cost);
01175     pol += (2*(1-polp)-1)*WID[i];
01176   }
01177   
01178   // Calculations are prepared only for pp collision.
01179   // Otherwise pol = 0.0
01180   if(!Ipp) pol=0.0;
01181 
01182   return pol;
01183 }
01184 
01185 /*******************************************************************************
01186   Check if the list of particles match the list of pdgid
01187 
01188   Returns true if 'particles' contain all of the listed pdgid-s.
01189   If it does - 'particles' will be rearranged so thath they have
01190   the same order as listed pdgid-s.
01191 
01192   It is done so the order of particles is the same as the order used by
01193   TAUOLA Fortran routines.
01194 *******************************************************************************/
01195 bool channelMatch(vector<Particle> &particles, int p1, int p2, int p3, int p4, int p5, int p6)
01196 {
01197   // Copy pdgid-s of all particles
01198   vector<int> list;
01199   
01200   for(unsigned int i=0;i<particles.size();i++) list.push_back(particles[i].pdgid());
01201   
01202   // Create array out of pdgid-s
01203   int p[6] = { p1, p2, p3, p4, p5, p6 };
01204 
01205   // 1) Check if 'particles' contain all pdgid-s on the list 'p'
01206   
01207   for(int i=0;i<6;i++)
01208   {
01209     // if the pdgid is zero - finish
01210     if(p[i]==0) break;
01211     
01212     bool found = false;
01213     
01214     for(unsigned int j=0;j<list.size(); j++)
01215     {
01216       // if pdgid is found - erese it from the list and search for the next one
01217       if(list[j]==p[i])
01218       {
01219         found = true;
01220         list.erase(list.begin()+j);
01221         break;
01222       }
01223     }
01224     
01225     if(!found) return false;
01226   }
01227   
01228   // if there are more particles on the list - there is no match
01229   if(list.size()!=0) return false;
01230 
01231   
01232   // 2) Rearrange particles to match the order of pdgid-s listed in array 'p'
01233 
01234   vector<Particle> newList;
01235   
01236   for(int i=0;i<6;i++)
01237   {
01238     // if the pdgid is zero - finish
01239     if(p[i]==0) break;
01240     
01241     for(unsigned int j=0;j<particles.size(); j++)
01242     {
01243       // if pdgid is found - copy it to new list and erese from the old one
01244       if(particles[j].pdgid()==p[i])
01245       {
01246         newList.push_back(particles[j]);
01247         particles.erase(particles.begin()+j);
01248         break;
01249       }
01250     }
01251   }
01252   
01253   particles = newList;
01254 
01255   return true;
01256 }
01257 
01258 /*******************************************************************************
01259  Prints out two vertices:
01260    W   -> tau, nu_tau
01261    tau -> tau_daughters
01262 *******************************************************************************/
01263 void print(Particle &W, Particle &nu_tau, Particle &tau, vector<Particle> &tau_daughters) {
01264 
01265   nu_tau.print();
01266   tau   .print();
01267 
01268   double px=nu_tau.px()+tau.px();
01269   double py=nu_tau.py()+tau.py();
01270   double pz=nu_tau.pz()+tau.pz();
01271   double e =nu_tau.e ()+tau.e ();
01272 
01273   // Print out sum and W for comparison
01274   cout<<"--------------------------------------------------------------------------------------------------------"<<endl;
01275   Particle sum1(px,py,pz,e,0);
01276   sum1.print();
01277   W   .print();
01278 
01279   cout<<endl;
01280 
01281   // Print out tau daughters
01282   for(unsigned int i=0; i<tau_daughters.size();i++) tau_daughters[i].print();
01283 
01284   // Print out sum and tau for comparison
01285   cout<<"--------------------------------------------------------------------------------------------------------"<<endl;
01286   Particle *sum2 = vector_sum(tau_daughters);
01287   sum2->print();
01288   tau.print();
01289   cout<<endl;
01290   
01291   delete sum2;
01292 }
01293 
01294 /*******************************************************************************
01295  Sums all 4-vectors of the particles on the list
01296 *******************************************************************************/
01297 Particle *vector_sum(vector<Particle> &x) {
01298 
01299   double px=0.0,py=0.0,pz=0.0,e=0.0;
01300 
01301   for(unsigned int i=0; i<x.size();i++)
01302   {
01303     px+=x[i].px();
01304     py+=x[i].py();
01305     pz+=x[i].pz();
01306     e +=x[i].e();
01307   }
01308 
01309   Particle *sum = new Particle(px,py,pz,e,0);
01310   return sum;
01311 }
01312 
01313 } // namespace TauSpinner
01314 
Generated on Sun Oct 20 20:24:10 2013 for C++InterfacetoTauola by  doxygen 1.6.3