CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_6/src/TopQuarkAnalysis/TopTools/interface/TopologyWorker.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:    TopTools
00004 // Class:      TopologyWorker
00005 // 
00014 #ifndef __TOPTOOLSTOPOLOGYWORKER__
00015 #define __TOPTOOLSTOPOLOGYWORKER__
00016 
00017 #warning The TopologyWorker class is currently not supported anymore! There might be issues in its implementation.
00018 #warning If you are still using it or planned to do so, please contact the admins of the corresponding CMSSW package.
00019 #warning You can find their e-mail adresses in: cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/TopQuarkAnalysis/TopTools/.admin/
00020 
00021 #include "TF1.h"
00022 #include "TMath.h"
00023 #include "TClass.h"
00024 #include "TString.h"
00025 #include "TRandom.h"
00026 #include "TMatrixD.h"
00027 #include "TLorentzVector.h"
00028 
00029 #include <cmath>
00030 #include <iostream>
00031 
00032 class TopologyWorker
00033 {
00034 public:
00035   TopologyWorker(){;}
00036   TopologyWorker(bool boost);
00037   virtual ~TopologyWorker(){;}
00038 
00039   void clear(void){m_np=0;m_np2=0;return;}
00040   
00041   void setPartList(TObjArray* e1, TObjArray* e2);
00042   void setVerbose(bool loud){m_verbose=loud; return;}
00043   
00044   void     setThMomPower(double tp);
00045   double   getThMomPower();
00046   void     setFast(int nf);
00047   int      getFast();
00048   
00049   TVector3 thrustAxis();
00050   TVector3 majorAxis();
00051   TVector3 minorAxis();
00052   
00053   TVector3 thrust(); 
00054   // thrust :: Corresponding thrust, major, and minor value.
00055   
00056   double oblateness();
00057   double get_sphericity();
00058   double get_aplanarity();
00059   double get_h10();
00060   double get_h20();
00061   double get_h30();
00062   double get_h40();
00063   double get_h50();
00064   double get_h60();
00065 
00066 
00067   void planes_sphe(double& pnorm,double& p2, double& p3);
00068   void planes_sphe_wei(double& pnorm,double& p2, double& p3);
00069   void planes_thrust(double& pnorm,double& p2, double& p3);
00070   void sumangles(float& sdeta, float& sdr);
00071   
00072   double get_ht() {return m_ht;}
00073   double get_ht3() {return m_ht3;}
00074   double get_et0() {return m_et0;}
00075   double get_sqrts() {return m_sqrts;}
00076   double get_njetW() {return m_njetsweighed;}
00077   double get_et56() {return m_et56;}
00078   double get_centrality() { return m_centrality;}
00079   
00080 private:        
00081   bool m_verbose;
00082   void getetaphi(double px, double py, double pz, double& eta, double& phi);
00083   double ulAngle(double x, double y);
00084   double sign(double a, double b);
00085   void     ludbrb(TMatrix *mom, 
00086                   double the, 
00087                   double phi, 
00088                   double bx, 
00089                   double by,
00090                   double bz);
00091   
00092   int iPow(int man, int exp);
00093   
00094   double m_dSphMomPower; 
00095   // PARU(41): Power of momentum dependence in sphericity finder.
00096   
00097   double m_dDeltaThPower;
00098   // PARU(42): Power of momentum dependence in thrust finder.   
00099   
00100   int m_iFast; 
00101   // MSTU(44): # of initial fastest particles choosen to start search.
00102   
00103   double m_dConv;
00104   // PARU(48): Convergence criteria for axis maximization.
00105   
00106   int m_iGood;
00107   // MSTU(45): # different starting configurations that must
00108   // converge before axis is accepted as correct.       
00109   
00110   TMatrix m_dAxes;
00111   // data: results
00112   // m_dAxes[1] is the Thrust axis.
00113   // m_dAxes[2] is the Major axis.
00114   // m_dAxes[3] is the Minor axis.
00115   
00116   TVector3 m_ThrustAxis;
00117   TVector3 m_MajorAxis;
00118   TVector3 m_MinorAxis;
00119   TVector3 m_Thrust;
00120   
00121   TRandom m_random;
00122   
00123   TMatrix m_mom;
00124   TMatrix m_mom2;
00125   
00126   double m_dThrust[4];
00127   double m_dOblateness;
00128   int m_np;
00129   int m_np2;
00130   bool m_sanda_called;
00131   bool m_fowo_called;
00132   bool m_boost;
00133   bool m_sumangles_called;
00134   double m_sph;
00135   double m_apl;
00136   double m_h10;
00137   double m_h20;
00138   double m_h30;
00139   double m_h40;
00140   double m_h50;
00141   double m_h60;
00142   double m_ht;
00143   double m_ht3;
00144   double m_et0;
00145   double m_sqrts;
00146   double m_njetsweighed;
00147   double m_et56;
00148   double m_centrality;
00149   
00150   void sanda();
00151   void fowo();
00152   static int m_maxpart;
00153   
00154   void CalcWmul();
00155   void CalcSqrts();
00156   void CalcHTstuff();
00157   double CalcPt(int i) { return sqrt(pow(m_mom(i,1),2)+pow(m_mom(i,2),2));}
00158   double CalcPt2(int i)  { return sqrt(pow(m_mom2(i,1),2)+pow(m_mom2(i,2),2));}
00159   double CalcEta(int i) {double eta, phi;getetaphi(m_mom(i,1),m_mom(i,2),m_mom(i,3),eta,phi); return eta;}
00160   double CalcEta2(int i) {double eta, phi; getetaphi(m_mom2(i,1),m_mom2(i,2),m_mom2(i,3),eta,phi); return eta;}
00161   
00162 };
00163 
00164 class LessThan {
00165    public :
00166      // retrieve tru info MC stuff
00167   bool operator () (const TLorentzVector & tl1, const TLorentzVector &
00168                     tl2)
00169     const {
00170     return tl2.Pt() < tl1.Pt();
00171   }
00172 };
00173 
00174 Int_t TopologyWorker::m_maxpart = 1000;
00175 
00176 TopologyWorker::TopologyWorker(bool boost):
00177   m_dSphMomPower(2.0),m_dDeltaThPower(0),
00178   m_iFast(4),m_dConv(0.0001),m_iGood(2)
00179 {
00180   m_dAxes.ResizeTo(4,4);
00181   m_mom.ResizeTo(m_maxpart,6);
00182   m_mom2.ResizeTo(m_maxpart,6);
00183   m_np=-1;
00184   m_np2=-1;
00185   m_sanda_called=false;
00186   m_fowo_called=false;
00187   m_sumangles_called=false;
00188   m_verbose=false;
00189   m_boost=boost;
00190   m_sph=-1;
00191   m_apl=-1;
00192   m_h10=-1;
00193   m_h20=-1;
00194   m_h30=-1;
00195   m_h40=-1;
00196   m_sqrts=0;
00197   m_ht=0;
00198   m_ht3=0;
00199   m_et56=0;
00200   m_njetsweighed=0;
00201   m_et0=0;
00202 }
00203 //______________________________________________________________
00204 
00205 
00206 // Input the particle 3(4)-vector list
00207 // e: 3-vector  TVector3       ..(px,py,pz) or
00208 //    4-vector  TLorentzVector ..(px,py,pz,E) 
00209 // Even input the TLorentzVector, we don't use Energy 
00210 // 
00211 void TopologyWorker::setPartList(TObjArray* e1, TObjArray* e2)
00212 {       
00213   //To make this look like normal physics notation the
00214   //zeroth element of each array, mom[i][0], will be ignored
00215   //and operations will be on elements 1,2,3...
00216   TMatrix mom(m_maxpart,6);
00217   TMatrix mom2(m_maxpart,6);
00218   double tmax = 0;
00219   double phi = 0.;
00220   double the = 0.;
00221   double sgn;
00222   TMatrix fast(m_iFast + 1,6);
00223   TMatrix work(11,6);
00224   double tdi[4] = {0.,0.,0.,0.};
00225   double tds;
00226   double tpr[4] = {0.,0.,0.,0.};
00227   double thp;
00228   double thps;
00229   double pxtot=0;
00230   double pytot=0;
00231   double pztot=0;
00232   double etot=0;
00233 
00234   TMatrix temp(3,5);
00235   Int_t np = 0;
00236   Int_t numElements = e1->GetEntries();
00237   Int_t numElements2 = e2->GetEntries();
00238 
00239   // trying to sort...
00240   
00241   
00242 
00243   m_np=0;
00244   for(Int_t elem=0;elem<numElements;elem++) {
00245     if(m_verbose){
00246       std::cout << "looping over array, element " << elem << std::endl;
00247     }
00248     TObject* o = (TObject*) e1->At(elem);    
00249     if(m_verbose){
00250       std::cerr << "TopologyWorker:SetPartList(): adding jet " << elem  << "." << std::endl; 
00251     }
00252     if (np >= m_maxpart) { 
00253         printf("Too many particles input to TopologyWorker");
00254         return;
00255     }
00256     if(m_verbose){
00257       std::cout << "getting name of object..." << std::endl;
00258     }
00259     TString nam(o->IsA()->GetName());
00260     if(m_verbose){
00261       std::cout << "TopologyWorker::setPartList(): object is of type " << nam << std::endl;
00262     }
00263     if (nam.Contains("TVector3")) {
00264       TVector3 v(((TVector3 *) o)->X(),
00265                  ((TVector3 *) o)->Y(),
00266                  ((TVector3 *) o)->Z());
00267       mom(np,1) = v.X();
00268       mom(np,2) = v.Y();
00269       mom(np,3) = v.Z();
00270       mom(np,4) = v.Mag();
00271     }
00272     else if (nam.Contains("TLorentzVector")) {
00273       TVector3 v(((TLorentzVector *) o)->X(),
00274                  ((TLorentzVector *) o)->Y(),
00275                  ((TLorentzVector *) o)->Z());
00276       mom(np,1) = v.X();
00277       mom(np,2) = v.Y();
00278       mom(np,3) = v.Z();
00279       mom(np,4) = ((TLorentzVector *) o)->T();
00280     }
00281     else {
00282       printf("TopologyWorker::setEvent input is not a TVector3 or a TLorentzVector\n");
00283       continue;
00284     }
00285     
00286 
00287     if ( TMath::Abs( m_dDeltaThPower ) <= 0.001 ) {
00288       mom(np,5) = 1.0;
00289     }
00290     else {
00291       mom(np,5) = TMath::Power(mom(np,4),m_dDeltaThPower);
00292     }
00293     tmax = tmax + mom(np,4)*mom(np,5);
00294     pxtot+=mom(np,1);
00295     pytot+=mom(np,2);
00296     pztot+=mom(np,3);
00297     etot+=mom(np,4);
00298     np++;
00299     m_np=np;
00300   }
00301   Int_t np2=0;
00302   // second jet array.... only use some values here.
00303   for(Int_t elem=0;elem<numElements2;elem++) {
00304     //cout << elem << endl;
00305     TObject* o = (TObject*) e2->At(elem);    
00306     if (np2 >= m_maxpart) { 
00307         printf("Too many particles input to TopologyWorker");
00308         return;
00309     }
00310 
00311     TString nam(o->IsA()->GetName());
00312     if (nam.Contains("TVector3")) {
00313       TVector3 v(((TVector3 *) o)->X(),
00314                  ((TVector3 *) o)->Y(),
00315                  ((TVector3 *) o)->Z());
00316       mom2(np2,1) = v.X();
00317       mom2(np2,2) = v.Y();
00318       mom2(np2,3) = v.Z();
00319       mom2(np2,4) = v.Mag();
00320     }
00321     else if (nam.Contains("TLorentzVector")) {
00322       TVector3 v(((TLorentzVector *) o)->X(),
00323                  ((TLorentzVector *) o)->Y(),
00324                  ((TLorentzVector *) o)->Z());
00325       mom2(np2,1) = v.X();
00326       mom2(np2,2) = v.Y();
00327       mom2(np2,3) = v.Z();
00328       mom2(np2,4) = ((TLorentzVector *) o)->T();
00329       //      cout << "mom2: " << mom2(np2,1) << ", " << mom2(np2,2)<<", " << mom2(np2,3)<<", " << mom2(np2,4)<< endl;
00330     }
00331     else {
00332       printf("TopologyWorker::setEvent Second vector input is not a TVector3 or a TLorentzVector\n");
00333       continue;
00334     }
00335     np2++;
00336     m_np2=np2;
00337   }
00338   m_mom2=mom2;
00339 
00340   if (m_boost && m_np>1) {
00341     printf("TopologyWorker::setEvent Only boosting first vector so watch out when you do this!!!");
00342     TVector3 booze(-pxtot/etot,-pytot/etot,-pztot/etot);
00343     TLorentzVector l1;
00344     for (int k=0; k<m_np ; k++) {
00345       l1.SetPx(mom(k,1));
00346       l1.SetPy(mom(k,2)); 
00347       l1.SetPz(mom(k,3));
00348       l1.SetE(mom(k,4));
00349       l1.Boost(booze);
00350       mom(k,1)=l1.Px();
00351       mom(k,2)=l1.Py();
00352       mom(k,3)=l1.Pz();
00353       mom(k,4)=l1.E();
00354     }
00355   }
00356   
00357   m_sanda_called=false; 
00358   m_fowo_called=false; 
00359   for (int ip=0;ip<m_maxpart;ip++) {
00360     for (int id=0;id<6;id++) {
00361       m_mom(ip,id)=mom(ip,id);
00362     }
00363   }
00364 
00365   if ( np < 2 ) {
00366     m_dThrust[1] = -1.0;
00367     m_dOblateness = -1.0;
00368     return;
00369   }
00370   // for pass = 1: find thrust axis.
00371   // for pass = 2: find major axis.
00372   for ( Int_t pass=1; pass < 3; pass++) {
00373     if ( pass == 2 ) {
00374       phi = ulAngle(m_dAxes(1,1), m_dAxes(1,2));
00375       ludbrb( &mom, 0, -phi, 0., 0., 0. );
00376       for ( Int_t i = 0; i < 3; i++ ) {
00377         for ( Int_t j = 1; j < 4; j++ ) {
00378           temp(i,j) = m_dAxes(i+1,j);
00379         }
00380         temp(i,4) = 0;
00381       }
00382       ludbrb(&temp,0.,-phi,0.,0.,0.);
00383       for ( Int_t ib = 0; ib < 3; ib++ ) {
00384         for ( Int_t j = 1; j < 4; j++ ) {
00385           m_dAxes(ib+1,j) = temp(ib,j);
00386         }
00387       }
00388       the = ulAngle( m_dAxes(1,3), m_dAxes(1,1) );
00389       ludbrb( &mom, -the, 0., 0., 0., 0. );
00390       for ( Int_t ic = 0; ic < 3; ic++ ) {
00391         for ( Int_t j = 1; j < 4; j++ ) {
00392           temp(ic,j) = m_dAxes(ic+1,j);
00393         }
00394         temp(ic,4) = 0;
00395       }
00396       ludbrb(&temp,-the,0.,0.,0.,0.);
00397       for ( Int_t id = 0; id < 3; id++ ) {      
00398         for ( Int_t j = 1; j < 4; j++ ) {
00399           m_dAxes(id+1,j) = temp(id,j);
00400         }
00401       }
00402     }
00403     for ( Int_t ifas = 0; ifas < m_iFast + 1 ; ifas++ ) {
00404       fast(ifas,4) = 0.;
00405     }
00406     // Find the m_iFast highest momentum particles and
00407     // put the highest in fast[0], next in fast[1],....fast[m_iFast-1].
00408     // fast[m_iFast] is just a workspace.
00409     for ( Int_t i = 0; i < np; i++ ) {
00410       if ( pass == 2 ) {
00411         mom(i,4) = TMath::Sqrt( mom(i,1)*mom(i,1) 
00412                               + mom(i,2)*mom(i,2) ); 
00413       }
00414       for ( Int_t ifas = m_iFast - 1; ifas > -1; ifas-- ) {
00415         if ( mom(i,4) > fast(ifas,4) ) {
00416           for ( Int_t j = 1; j < 6; j++ ) {
00417             fast(ifas+1,j) = fast(ifas,j);
00418             if ( ifas == 0 ) fast(ifas,j) = mom(i,j);       
00419           }
00420         }
00421         else {
00422           for ( Int_t j = 1; j < 6; j++ ) {
00423             fast(ifas+1,j) = mom(i,j);
00424           }
00425           break;
00426         }
00427       }
00428     }
00429     // Find axis with highest thrust (case 1)/ highest major (case 2).
00430     for ( Int_t ie = 0; ie < work.GetNrows(); ie++ ) {
00431       work(ie,4) = 0.;
00432     }
00433     Int_t p = TMath::Min( m_iFast, np ) - 1;
00434     // Don't trust Math.pow to give right answer always.
00435     // Want nc = 2**p.
00436     Int_t nc = iPow(2,p); 
00437     for ( Int_t n = 0; n < nc; n++ ) {
00438       for ( Int_t j = 1; j < 4; j++ ) {
00439         tdi[j] = 0.;
00440       }
00441       for ( Int_t i = 0; i < TMath::Min(m_iFast,n); i++ ) {
00442         sgn = fast(i,5);
00443         if (iPow(2,(i+1))*((n+iPow(2,i))/iPow(2,(i+1))) >= i+1){
00444           sgn = -sgn;
00445         }
00446         for ( Int_t j = 1; j < 5-pass; j++ ) {
00447           tdi[j] = tdi[j] + sgn*fast(i,j);
00448         }
00449       }
00450       tds = tdi[1]*tdi[1] + tdi[2]*tdi[2] + tdi[3]*tdi[3];
00451       for ( Int_t iw = TMath::Min(n,9); iw > -1; iw--) {
00452         if( tds > work(iw,4) ) {
00453           for ( Int_t j = 1; j < 5; j++ ) {
00454             work(iw+1,j) = work(iw,j);
00455             if ( iw == 0 ) {
00456               if ( j < 4 ) {
00457                 work(iw,j) = tdi[j];
00458               }
00459               else {
00460                 work(iw,j) = tds;
00461               }
00462             }
00463           }
00464         }
00465         else {
00466           for ( Int_t j = 1; j < 4; j++ ) {
00467             work(iw+1,j) = tdi[j];
00468           }
00469           work(iw+1,4) = tds;
00470         }
00471       }
00472     }
00473     // Iterate direction of axis until stable maximum.
00474     m_dThrust[pass] = 0;
00475     thp = -99999.;
00476     Int_t nagree = 0;
00477     for ( Int_t iw = 0; 
00478           iw < TMath::Min(nc,10) && nagree < m_iGood; iw++ ){
00479       thp = 0.;
00480       thps = -99999.;
00481       while ( thp > thps + m_dConv ) {
00482         thps = thp;
00483         for ( Int_t j = 1; j < 4; j++ ) {
00484           if ( thp <= 1E-10 ) {
00485             tdi[j] = work(iw,j);
00486           }
00487           else {
00488             tdi[j] = tpr[j];
00489             tpr[j] = 0;
00490           }
00491         }
00492         for ( Int_t i = 0; i < np; i++ ) {
00493           sgn = sign(mom(i,5), 
00494                      tdi[1]*mom(i,1) + 
00495                      tdi[2]*mom(i,2) + 
00496                      tdi[3]*mom(i,3));
00497           for ( Int_t j = 1; j < 5 - pass; j++ ){
00498             tpr[j] = tpr[j] + sgn*mom(i,j);
00499           }
00500         }
00501         thp = TMath::Sqrt(tpr[1]*tpr[1] 
00502                           + tpr[2]*tpr[2] 
00503                           + tpr[3]*tpr[3])/tmax;
00504       }
00505       // Save good axis. Try new initial axis until enough
00506       // tries agree.
00507       if ( thp < m_dThrust[pass] - m_dConv ) {
00508         break;
00509       }
00510       if ( thp > m_dThrust[pass] + m_dConv ) {
00511         nagree = 0;
00512         sgn = iPow( -1, (Int_t)TMath::Nint(m_random.Rndm()) );
00513         for ( Int_t j = 1; j < 4; j++ ) {
00514           m_dAxes(pass,j) = sgn*tpr[j]/(tmax*thp);
00515         }
00516         m_dThrust[pass] = thp;
00517       }
00518       nagree = nagree + 1;
00519     }
00520   }
00521   // Find minor axis and value by orthogonality.
00522   sgn = iPow( -1, (Int_t)TMath::Nint(m_random.Rndm()));
00523   m_dAxes(3,1) = -sgn*m_dAxes(2,2);
00524   m_dAxes(3,2) = sgn*m_dAxes(2,1);
00525   m_dAxes(3,3) = 0.;
00526   thp = 0.;
00527   for ( Int_t i = 0; i < np; i++ ) {
00528     thp += mom(i,5)*TMath::Abs(m_dAxes(3,1)*mom(i,1) + 
00529                                m_dAxes(3,2)*mom(i,2));
00530   }
00531   m_dThrust[3] = thp/tmax;
00532   // Rotate back to original coordinate system.
00533   for ( Int_t i6 = 0; i6 < 3; i6++ ) {
00534     for ( Int_t j = 1; j < 4; j++ ) {
00535       temp(i6,j) = m_dAxes(i6+1,j);
00536     }
00537     temp(i6,4) = 0;
00538   }
00539   ludbrb(&temp,the,phi,0.,0.,0.);
00540   for ( Int_t i7 = 0; i7 < 3; i7++ ) {
00541     for ( Int_t j = 1; j < 4; j++ ) {
00542       m_dAxes(i7+1,j) = temp(i7,j);
00543     }
00544   }
00545   m_dOblateness = m_dThrust[2] - m_dThrust[3];
00546   
00547   // more stuff:
00548   
00549   // calculate weighed jet multiplicity();
00550   CalcWmul();
00551   CalcHTstuff();
00552   CalcSqrts();
00553  
00554 }
00555 //______________________________________________________________
00556         
00557 // Setting and getting parameters.
00558         
00559 void TopologyWorker::setThMomPower(double tp)
00560 {
00561   // Error if sp not positive.
00562   if ( tp > 0. ) m_dDeltaThPower = tp - 1.0;
00563   return;
00564 }
00565 //______________________________________________________________
00566 
00567 double TopologyWorker::getThMomPower()
00568 {
00569   return 1.0 + m_dDeltaThPower;
00570 }
00571 //______________________________________________________________
00572 
00573 void TopologyWorker::setFast(Int_t nf)
00574 {
00575   // Error if sp not positive.
00576   if ( nf > 3 ) m_iFast = nf;
00577   return;
00578 }
00579 //______________________________________________________________
00580 
00581 Int_t TopologyWorker::getFast()
00582 {
00583   return m_iFast;
00584 }
00585 //______________________________________________________________
00586 
00587 // Returning results
00588 
00589 TVector3 TopologyWorker::thrustAxis() {
00590   TVector3 m_ThrustAxis(m_dAxes(1,1),m_dAxes(1,2),m_dAxes(1,3));
00591   return m_ThrustAxis;
00592 }
00593 //______________________________________________________________
00594 
00595 TVector3 TopologyWorker::majorAxis() {
00596   TVector3 m_MajorAxis(m_dAxes(2,1),m_dAxes(2,2),m_dAxes(2,3));
00597   return m_MajorAxis;
00598 }
00599 //______________________________________________________________
00600 
00601 TVector3 TopologyWorker::minorAxis() {
00602   TVector3 m_MinorAxis(m_dAxes(3,1),m_dAxes(3,2),m_dAxes(3,3));
00603   return m_MinorAxis;
00604 }
00605 //______________________________________________________________
00606 
00607 TVector3 TopologyWorker::thrust() {
00608   TVector3 m_Thrust(m_dThrust[1],m_dThrust[2],m_dThrust[3]);
00609   return m_Thrust;
00610 }
00611 //______________________________________________________________
00612 
00613 double TopologyWorker::oblateness() {
00614   return m_dOblateness;
00615 }
00616 //______________________________________________________________
00617 
00618 // utilities(from Jetset):
00619 double TopologyWorker::ulAngle(double x, double y)
00620 {
00621   double ulangl = 0;
00622   double r = TMath::Sqrt(x*x + y*y);
00623   if ( r < 1.0E-20 ) {
00624     return ulangl; 
00625   }
00626   if ( TMath::Abs(x)/r < 0.8 ) {
00627     ulangl = sign(TMath::ACos(x/r),y);
00628   }
00629   else {
00630     ulangl = TMath::ASin(y/r);
00631     if ( x < 0. && ulangl >= 0. ) {
00632       ulangl = TMath::Pi() - ulangl;
00633     }
00634     else if ( x < 0. ) {
00635       ulangl = -TMath::Pi() - ulangl;
00636     }
00637   }
00638   return ulangl;
00639 }
00640 //______________________________________________________________
00641 
00642 double TopologyWorker::sign(double a, double b) {
00643   if ( b < 0 ) {
00644     return -TMath::Abs(a);
00645   }
00646   else {
00647     return TMath::Abs(a);
00648   }
00649 }
00650 //______________________________________________________________
00651 
00652 void TopologyWorker::ludbrb(TMatrix* mom, 
00653                         double the, 
00654                         double phi, 
00655                         double bx, 
00656                         double by,
00657                         double bz)
00658 {
00659   // Ignore "zeroth" elements in rot,pr,dp.
00660   // Trying to use physics-like notation.
00661   TMatrix rot(4,4);
00662   double pr[4];
00663   double dp[5];
00664   Int_t np = mom->GetNrows();
00665   if ( the*the + phi*phi > 1.0E-20 )
00666     {
00667       rot(1,1) = TMath::Cos(the)*TMath::Cos(phi);
00668       rot(1,2) = -TMath::Sin(phi);
00669       rot(1,3) = TMath::Sin(the)*TMath::Cos(phi);
00670       rot(2,1) = TMath::Cos(the)*TMath::Sin(phi);
00671       rot(2,2) = TMath::Cos(phi);
00672       rot(2,3) = TMath::Sin(the)*TMath::Sin(phi);
00673       rot(3,1) = -TMath::Sin(the);
00674       rot(3,2) = 0.0;
00675       rot(3,3) = TMath::Cos(the);
00676       for ( Int_t i = 0; i < np; i++ )
00677         {
00678           for ( Int_t j = 1; j < 4; j++ )
00679             {
00680               pr[j] = (*mom)(i,j);
00681               (*mom)(i,j) = 0;
00682             }
00683           for ( Int_t jb = 1; jb < 4; jb++)
00684             {
00685               for ( Int_t k = 1; k < 4; k++)
00686                 {
00687                   (*mom)(i,jb) = (*mom)(i,jb) + rot(jb,k)*pr[k];
00688                 }
00689             }
00690         }
00691       double beta = TMath::Sqrt( bx*bx + by*by + bz*bz );
00692       if ( beta*beta > 1.0E-20 )
00693         {
00694           if ( beta >  0.99999999 )
00695             {
00696                          //send message: boost too large, resetting to <~1.0.
00697               bx = bx*(0.99999999/beta);
00698               by = by*(0.99999999/beta);
00699               bz = bz*(0.99999999/beta);
00700               beta =   0.99999999;
00701             }
00702           double gamma = 1.0/TMath::Sqrt(1.0 - beta*beta);
00703           for ( Int_t i = 0; i < np; i++ )
00704             {
00705               for ( Int_t j = 1; j < 5; j++ )
00706                 {
00707                   dp[j] = (*mom)(i,j);
00708                 }
00709               double bp = bx*dp[1] + by*dp[2] + bz*dp[3];
00710               double gbp = gamma*(gamma*bp/(1.0 + gamma) + dp[4]);
00711               (*mom)(i,1) = dp[1] + gbp*bx;
00712               (*mom)(i,2) = dp[2] + gbp*by;
00713               (*mom)(i,3) = dp[3] + gbp*bz;
00714               (*mom)(i,4) = gamma*(dp[4] + bp);
00715             }
00716         }
00717     }
00718   return;
00719 }
00720 
00721 
00722 
00723 // APLANARITY and SPHERICITY
00724 
00725 void TopologyWorker::sanda() {
00726       float SPH=-1;
00727       float APL=-1;
00728       m_sanda_called=true;
00729   //=======================================================================
00730   // By M.Vreeswijk, (core was fortran, stolen from somewhere)
00731   // Purpose: to perform sphericity tensor analysis to give sphericity 
00732   // and aplanarity. 
00733   //
00734   // Needs: Array (standard from root-tuples): GTRACK_px, py, pz 
00735   //        The number of tracks in these arrays: GTRACK_ijet
00736   //        In addition: Array GTRACK_ijet contains a jet number 'ijet'
00737   //        (if you wish to change this, simply change code)
00738   //
00739   // Uses: TVector3 and TLorentzVector classes
00740   // 
00741   // Output: Sphericity SPH and Aplanarity APL
00742   //=======================================================================
00743 // C...Calculate matrix to be diagonalized.
00744       float P[1000][6];
00745       double SM[4][4],SV[4][4];
00746       double PA,PWT,PS,SQ,SR,SP,SMAX,SGN;
00747       int NP;
00748       int J, J1, J2, I, N, JA, JB, J3, JC, JB1, JB2;
00749       JA=JB=JC=0;
00750       double RL;
00751       float rlu,rlu1;
00752       //
00753       // --- get the input form GTRACK arrays
00754       //
00755       N=m_np;
00756       NP=0;
00757       for (I=1;I<N+1;I++){
00758            NP++; // start at one
00759            P[NP][1]=m_mom(I-1,1) ;
00760            P[NP][2]=m_mom(I-1,2) ;
00761            P[NP][3]=m_mom(I-1,3) ;
00762            P[NP][4]=m_mom(I-1,4) ;
00763            P[NP][5]=0;
00764        }
00765       //
00766       //---
00767       //
00768        N=NP;
00769 
00770       for (J1=1;J1<4;J1++) {
00771         for (J2=J1;J2<4;J2++) {
00772           SM[J1][J2]=0.;
00773         }
00774       }
00775       PS=0.;
00776       for (I=1;I<N+1;I++) { // 140
00777          PA=sqrt(pow(P[I][1],2)+pow(P[I][2],2)+pow(P[I][3],2)); 
00778          PWT=1.;
00779          for (J1=1;J1<4;J1++) { // 130
00780             for (J2=J1;J2<4;J2++) { // 120
00781                SM[J1][J2]=SM[J1][J2]+PWT*P[I][J1]*P[I][J2];
00782             }
00783          } // 130
00784          PS=PS+PWT*PA*PA;
00785        } //140
00786 // C...Very low multiplicities (0 or 1) not considered.
00787       if(NP<2) {
00788         SPH=-1.;
00789         APL=-1.;
00790         return; 
00791       }
00792       for (J1=1;J1<4;J1++) { // 160
00793          for (J2=J1;J2<4;J2++) { // 150
00794             SM[J1][J2]=SM[J1][J2]/PS;
00795          }
00796       } // 160
00797 // C...Find eigenvalues to matrix (third degree equation).
00798       SQ=(SM[1][1]*SM[2][2]+SM[1][1]*SM[3][3]+SM[2][2]*SM[3][3]
00799           -pow(SM[1][2],2)
00800           -pow(SM[1][3],2)-pow(SM[2][3],2))/3.-1./9.;
00801       SR=-0.5*(SQ+1./9.+SM[1][1]*pow(SM[2][3],2)+SM[2][2]*pow(SM[1][3],2)+SM[3][3]*
00802      pow(SM[1][2],2)-SM[1][1]*SM[2][2]*SM[3][3])+SM[1][2]*SM[1][3]*SM[2][3]+1./27.;
00803 
00804       SP=TMath::Cos(TMath::ACos(TMath::Max(TMath::Min(SR/TMath::Sqrt(-pow(SQ,3)),1.),-1.))/3.);
00805 
00806  P[N+1][4]=1./3.+TMath::Sqrt(-SQ)*TMath::Max(2.*SP,TMath::Sqrt(3.*(1.-SP*SP))-SP);
00807       P[N+3][4]=1./3.+TMath::Sqrt(-SQ)*TMath::Min(2.*SP,-TMath::Sqrt(3.*(1.-SP*SP))-SP);
00808       P[N+2][4]=1.-P[N+1][4]-P[N+3][4];
00809       if (P[N+2][4]> 1E-5) {
00810  
00811 // C...Find first and last eigenvector by solving equation system.
00812       for (I=1;I<4;I=I+2) { // 240
00813          for (J1=1;J1<4;J1++) { // 180
00814             SV[J1][J1]=SM[J1][J1]-P[N+I][4];
00815             for (J2=J1+1;J2<4;J2++) { // 170
00816                SV[J1][J2]=SM[J1][J2];
00817                SV[J2][J1]=SM[J1][J2];
00818             }
00819           } // 180
00820          SMAX=0.;
00821          for (J1=1;J1<4;J1++) { // 200
00822             for (J2=1;J2<4;J2++) { // 190
00823               if(std::fabs(SV[J1][J2])>SMAX) { // 190
00824                  JA=J1;
00825                  JB=J2;
00826                  SMAX=std::fabs(SV[J1][J2]);
00827               }
00828             } // 190
00829           } // 200
00830           SMAX=0.;
00831           for (J3=JA+1;J3<JA+3;J3++) { // 220
00832              J1=J3-3*((J3-1)/3);
00833              RL=SV[J1][JB]/SV[JA][JB];
00834              for (J2=1;J2<4;J2++) { // 210
00835                 SV[J1][J2]=SV[J1][J2]-RL*SV[JA][J2];
00836                 if (std::fabs(SV[J1][J2])>SMAX) { // GOTO 210
00837                    JC=J1;
00838                    SMAX=std::fabs(SV[J1][J2]);
00839                  }
00840                } // 210
00841             }  // 220 
00842             JB1=JB+1-3*(JB/3);
00843             JB2=JB+2-3*((JB+1)/3);
00844             P[N+I][JB1]=-SV[JC][JB2];
00845             P[N+I][JB2]=SV[JC][JB1];
00846             P[N+I][JB]=-(SV[JA][JB1]*P[N+I][JB1]+SV[JA][JB2]*P[N+I][JB2])/
00847                   SV[JA][JB];
00848             PA=TMath::Sqrt(pow(P[N+I][1],2)+pow(P[N+I][2],2)+pow(P[N+I][3],2));
00849 // make a random number
00850             float pa=P[N-1][I];
00851             rlu=std::fabs(pa)-std::fabs(int(pa)*1.);
00852             rlu1=std::fabs(pa*pa)-std::fabs(int(pa*pa)*1.);
00853             SGN=pow((-1.),1.*int(rlu+0.5));
00854             for (J=1;J<4;J++) { // 230
00855                P[N+I][J]=SGN*P[N+I][J]/PA;
00856             } // 230
00857       } // 240
00858  
00859 // C...Middle axis orthogonal to other two. Fill other codes.      
00860       SGN=pow((-1.),1.*int(rlu1+0.5));
00861       P[N+2][1]=SGN*(P[N+1][2]*P[N+3][3]-P[N+1][3]*P[N+3][2]);
00862       P[N+2][2]=SGN*(P[N+1][3]*P[N+3][1]-P[N+1][1]*P[N+3][3]);
00863       P[N+2][3]=SGN*(P[N+1][1]*P[N+3][2]-P[N+1][2]*P[N+3][1]);
00864  
00865 // C...Calculate sphericity and aplanarity. Select storing option.
00866       SPH=1.5*(P[N+2][4]+P[N+3][4]);
00867       APL=1.5*P[N+3][4];
00868 
00869       } // check 1
00870 
00871       m_sph=SPH;
00872       m_apl=APL;
00873       return;
00874 } // end sanda
00875 
00876 
00877 
00878 
00879 void TopologyWorker::planes_sphe(double& pnorm, double& p2, double& p3) {
00880   //float SPH=-1; //FIXME: commented out since gcc461 complained that this variable is set but unused
00881   //float APL=-1; //FIXME: commented out since gcc461 complained that this variable is set but unused
00882 // C...Calculate matrix to be diagonalized.
00883       float P[1000][6];
00884       double SM[4][4],SV[4][4];
00885       double PA,PWT,PS,SQ,SR,SP,SMAX,SGN;
00886       int NP;
00887       int J, J1, J2, I, N, JA, JB, J3, JC, JB1, JB2;
00888       JA=JB=JC=0;
00889       double RL;
00890       float rlu,rlu1;
00891       //
00892       // --- get the input form GTRACK arrays
00893       //
00894       N=m_np;
00895       NP=0;
00896       for (I=1;I<N+1;I++){
00897            NP++; // start at one
00898            P[NP][1]=m_mom(I-1,1) ;
00899            P[NP][2]=m_mom(I-1,2) ;
00900            P[NP][3]=m_mom(I-1,3) ;
00901            P[NP][4]=m_mom(I-1,4) ;
00902            P[NP][5]=0;
00903        }
00904       //
00905       //---
00906       //
00907        N=NP;
00908 
00909       for (J1=1;J1<4;J1++) {
00910         for (J2=J1;J2<4;J2++) {
00911           SM[J1][J2]=0.;
00912         }
00913       }
00914       PS=0.;
00915       for (I=1;I<N+1;I++) { // 140
00916          PA=sqrt(pow(P[I][1],2)+pow(P[I][2],2)+pow(P[I][3],2)); 
00917          double eta,phi;
00918          getetaphi(P[I][1],P[I][2],P[I][3],eta,phi);
00919          PWT=exp(-std::fabs(eta));
00920          PWT=1.;
00921          for (J1=1;J1<4;J1++) { // 130
00922             for (J2=J1;J2<4;J2++) { // 120
00923                SM[J1][J2]=SM[J1][J2]+PWT*P[I][J1]*P[I][J2];
00924             }
00925          } // 130
00926          PS=PS+PWT*PA*PA;
00927        } //140
00928 // C...Very low multiplicities (0 or 1) not considered.
00929       if(NP<2) {
00930         //SPH=-1.; //FIXME: commented out since gcc461 complained that this variable is set but unused
00931         //APL=-1.; //FIXME: commented out since gcc461 complained that this variable is set but unused
00932         return; 
00933       }
00934       for (J1=1;J1<4;J1++) { // 160
00935          for (J2=J1;J2<4;J2++) { // 150
00936             SM[J1][J2]=SM[J1][J2]/PS;
00937          }
00938       } // 160
00939 // C...Find eigenvalues to matrix (third degree equation).
00940       SQ=(SM[1][1]*SM[2][2]+SM[1][1]*SM[3][3]+SM[2][2]*SM[3][3]
00941           -pow(SM[1][2],2)
00942           -pow(SM[1][3],2)-pow(SM[2][3],2))/3.-1./9.;
00943       SR=-0.5*(SQ+1./9.+SM[1][1]*pow(SM[2][3],2)+SM[2][2]*pow(SM[1][3],2)+SM[3][3]*
00944      pow(SM[1][2],2)-SM[1][1]*SM[2][2]*SM[3][3])+SM[1][2]*SM[1][3]*SM[2][3]+1./27.;
00945 
00946       SP=TMath::Cos(TMath::ACos(TMath::Max(TMath::Min(SR/TMath::Sqrt(-pow(SQ,3)),1.),-1.))/3.);
00947 
00948  P[N+1][4]=1./3.+TMath::Sqrt(-SQ)*TMath::Max(2.*SP,TMath::Sqrt(3.*(1.-SP*SP))-SP);
00949       P[N+3][4]=1./3.+TMath::Sqrt(-SQ)*TMath::Min(2.*SP,-TMath::Sqrt(3.*(1.-SP*SP))-SP);
00950       P[N+2][4]=1.-P[N+1][4]-P[N+3][4];
00951       if (P[N+2][4]> 1E-5) {
00952  
00953 // C...Find first and last eigenvector by solving equation system.
00954       for (I=1;I<4;I=I+2) { // 240
00955          for (J1=1;J1<4;J1++) { // 180
00956             SV[J1][J1]=SM[J1][J1]-P[N+I][4];
00957             for (J2=J1+1;J2<4;J2++) { // 170
00958                SV[J1][J2]=SM[J1][J2];
00959                SV[J2][J1]=SM[J1][J2];
00960             }
00961           } // 180
00962          SMAX=0.;
00963          for (J1=1;J1<4;J1++) { // 200
00964             for (J2=1;J2<4;J2++) { // 190
00965               if(std::fabs(SV[J1][J2])>SMAX) { // 190
00966                  JA=J1;
00967                  JB=J2;
00968                  SMAX=std::fabs(SV[J1][J2]);
00969               }
00970             } // 190
00971           } // 200
00972           SMAX=0.;
00973           for (J3=JA+1;J3<JA+3;J3++) { // 220
00974              J1=J3-3*((J3-1)/3);
00975              RL=SV[J1][JB]/SV[JA][JB];
00976              for (J2=1;J2<4;J2++) { // 210
00977                 SV[J1][J2]=SV[J1][J2]-RL*SV[JA][J2];
00978                 if (std::fabs(SV[J1][J2])>SMAX) { // GOTO 210
00979                    JC=J1;
00980                    SMAX=std::fabs(SV[J1][J2]);
00981                  }
00982                } // 210
00983             }  // 220 
00984             JB1=JB+1-3*(JB/3);
00985             JB2=JB+2-3*((JB+1)/3);
00986             P[N+I][JB1]=-SV[JC][JB2];
00987             P[N+I][JB2]=SV[JC][JB1];
00988             P[N+I][JB]=-(SV[JA][JB1]*P[N+I][JB1]+SV[JA][JB2]*P[N+I][JB2])/
00989                   SV[JA][JB];
00990             PA=TMath::Sqrt(pow(P[N+I][1],2)+pow(P[N+I][2],2)+pow(P[N+I][3],2));
00991 // make a random number
00992             float pa=P[N-1][I];
00993             rlu=std::fabs(pa)-std::fabs(int(pa)*1.);
00994             rlu1=std::fabs(pa*pa)-std::fabs(int(pa*pa)*1.);
00995             SGN=pow((-1.),1.*int(rlu+0.5));
00996             for (J=1;J<4;J++) { // 230
00997                P[N+I][J]=SGN*P[N+I][J]/PA;
00998             } // 230
00999       } // 240
01000  
01001 // C...Middle axis orthogonal to other two. Fill other codes.      
01002       SGN=pow((-1.),1.*int(rlu1+0.5));
01003       P[N+2][1]=SGN*(P[N+1][2]*P[N+3][3]-P[N+1][3]*P[N+3][2]);
01004       P[N+2][2]=SGN*(P[N+1][3]*P[N+3][1]-P[N+1][1]*P[N+3][3]);
01005       P[N+2][3]=SGN*(P[N+1][1]*P[N+3][2]-P[N+1][2]*P[N+3][1]);
01006  
01007 // C...Calculate sphericity and aplanarity. Select storing option.
01008       //SPH=1.5*(P[N+2][4]+P[N+3][4]); //FIXME: commented out since gcc461 complained that this variable is set but unused
01009       //APL=1.5*P[N+3][4];             //FIXME: commented out since gcc461 complained that this variable is set but unused
01010 
01011       } // check 1
01012 
01013       // so assume now we have Sphericity axis, which one give the minimal Pts
01014       double etstot[4];
01015       double eltot[4];
01016       double sum23=0;
01017       double sum22=0;
01018       double sum33=0;
01019       double pina[4];
01020       double ax[4], ay[4], az[4];
01021       for (int ia=1;ia<4;ia++) {
01022         etstot[ia]=0;
01023         eltot[ia]=0;
01024         pina[ia]=0;
01025         ax[ia]=P[N+ia][1];
01026         ay[ia]=P[N+ia][2];
01027         az[ia]=P[N+ia][3];
01028         ax[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01029         ay[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01030         az[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01031       }
01032 
01033 
01034       for (int k =0 ; k<m_np ; k++) {
01035         //       double eta,phi;
01036         //  getetaphi(m_mom(k,1),m_mom(k,2),m_mom(k,3),eta,phi);
01037         double W=1.0;
01038         for (int ia=1;ia<4;ia++) {
01039           double e=sqrt(m_mom(k,1)*m_mom(k,1) +
01040                         m_mom(k,2)*m_mom(k,2) +
01041                         m_mom(k,3)*m_mom(k,3));
01042           double el=ax[ia]*m_mom(k,1) + ay[ia]*m_mom(k,2) + az[ia]*m_mom(k,3);
01043           pina[ia]=el;
01044           double ets=(e*e-el*el);
01045           etstot[ia]+=ets*W;
01046           eltot[ia]+=el*el;
01047         }
01048         double a2=pina[2];
01049         double a3=pina[3];
01050         //      double h=0.4;
01051         //a2=pina[2]*cos(h)+pina[3]*sin(h);
01052         //a3=pina[3]*cos(h)-pina[2]*sin(h);
01053         sum22+=a2*a2*W;
01054         sum23+=a2*a3*W;
01055         sum33+=a3*a3*W;
01056       }
01057 
01058       
01059   
01060         double pi=3.1415927;
01061         double phi=pi/2.0;
01062         double phip=pi/2.0;
01063         double a=sum23; 
01064         double c=-a;
01065         double b=sum22-sum33;
01066         double disc=b*b-4*a*c;
01067         //   cout << " disc " << disc << endl;
01068         if (disc>=0) {
01069           double x1=(sqrt(disc)-b)/2/a;
01070           double x2=(-sqrt(disc)-b)/2/a;
01071           phi=atan(x1);
01072           phip=atan(x2);
01073           if (phi<0) phi=2.*pi+phi;
01074           if (phip<0) phip=2.*pi+phip;
01075         }
01076         double p21=sum22*cos(phi)*cos(phi)+sum33*sin(phi)*sin(phi)+2*sum23*cos(phi)*sin(phi);
01077         double p31=sum22*sin(phi)*sin(phi)+sum33*cos(phi)*cos(phi)-2*sum23*cos(phi)*sin(phi);
01078 
01079         double p22=sum22*cos(phip)*cos(phip)+sum33*sin(phip)*sin(phip)+2*sum23*cos(phip)*sin(phip);
01080         double p32=sum22*sin(phip)*sin(phip)+sum33*cos(phip)*cos(phip)-2*sum23*cos(phip)*sin(phip);
01081 
01082      
01083         double d1=std::fabs(p31*p31 - p21*p21);
01084         double d2=std::fabs(p32*p32 - p22*p22);
01085         //cout << " eltot " << eltot[2] << " " << eltot[3] << endl;
01086         //cout << " phi " << phi << " " << phip << endl;
01087         //cout << " d " << d1 << " " << d2 << endl;
01088         p2=p21;
01089         p3=p31;
01090         if (d2>d1) { 
01091           p2=p22;
01092           p3=p32;
01093         }
01094         pnorm=sqrt(eltot[1]);
01095         if (p2>p3) {
01096           p3=sqrt(p3);
01097           p2=sqrt(p2);
01098         }else {
01099           double p4=p3;
01100           p3=sqrt(p2);
01101           p2=sqrt(p4);
01102         }
01103         //cout << " sum2 sum3 " << sqrt(sum22) << " " << sqrt(sum33) << endl;
01104         //cout << " p2 p3 " << p2 << " " << p3 << endl;
01105         //double els=sqrt(eltot[2]*eltot[2]+eltot[3]*eltot[3]);
01106         //      cout << " ets els " << (ettot[1]) << " " << els << endl;
01107 
01108         //m_sph=SPH; //FIXME: shouldn't the local variables be used to reset the class member variables accordingly?
01109         //m_apl=APL; //FIXME: shouldn't the local variables be used to reset the class member variables accordingly?
01110     return;
01111 } // end planes_sphe
01112 
01113 
01114 void TopologyWorker::planes_sphe_wei(double& pnorm, double& p2, double& p3) {
01115       //float SPH=-1; //FIXME: commented out since gcc461 complained that this variable is set but unused
01116       //float APL=-1; //FIXME: commented out since gcc461 complained that this variable is set but unused
01117 // C...Calculate matrix to be diagonalized.
01118       float P[1000][6];
01119       double SM[4][4],SV[4][4];
01120       double PA,PWT,PS,SQ,SR,SP,SMAX,SGN;
01121       int NP;
01122       int J, J1, J2, I, N, JA, JB, J3, JC, JB1, JB2;
01123       JA=JB=JC=0;
01124       double RL;
01125       float rlu,rlu1;
01126       //
01127       // --- get the input form GTRACK arrays
01128       //
01129       N=m_np;
01130       NP=0;
01131       for (I=1;I<N+1;I++){
01132            NP++; // start at one
01133            P[NP][1]=m_mom(I-1,1) ;
01134            P[NP][2]=m_mom(I-1,2) ;
01135            P[NP][3]=m_mom(I-1,3) ;
01136            P[NP][4]=m_mom(I-1,4) ;
01137            P[NP][5]=0;
01138        }
01139       //
01140       //---
01141       //
01142        N=NP;
01143 
01144       for (J1=1;J1<4;J1++) {
01145         for (J2=J1;J2<4;J2++) {
01146           SM[J1][J2]=0.;
01147         }
01148       }
01149       PS=0.;
01150       for (I=1;I<N+1;I++) { // 140
01151          PA=sqrt(pow(P[I][1],2)+pow(P[I][2],2)+pow(P[I][3],2)); 
01152          // double eta,phi;
01153          // getetaphi(P[I][1],P[I][2],P[I][3],eta,phi);
01154          //  PWT=exp(-std::fabs(eta));
01155          PWT=1.;
01156          for (J1=1;J1<4;J1++) { // 130
01157             for (J2=J1;J2<4;J2++) { // 120
01158                SM[J1][J2]=SM[J1][J2]+PWT*P[I][J1]*P[I][J2];
01159             }
01160          } // 130
01161          PS=PS+PWT*PA*PA;
01162        } //140
01163 // C...Very low multiplicities (0 or 1) not considered.
01164       if(NP<2) {
01165         //SPH=-1.; //FIXME: commented out since gcc461 complained that this variable is set but unused
01166         //APL=-1.; //FIXME: commented out since gcc461 complained that this variable is set but unused
01167         return; 
01168       }
01169       for (J1=1;J1<4;J1++) { // 160
01170          for (J2=J1;J2<4;J2++) { // 150
01171             SM[J1][J2]=SM[J1][J2]/PS;
01172          }
01173       } // 160
01174 // C...Find eigenvalues to matrix (third degree equation).
01175       SQ=(SM[1][1]*SM[2][2]+SM[1][1]*SM[3][3]+SM[2][2]*SM[3][3]
01176           -pow(SM[1][2],2)
01177           -pow(SM[1][3],2)-pow(SM[2][3],2))/3.-1./9.;
01178       SR=-0.5*(SQ+1./9.+SM[1][1]*pow(SM[2][3],2)+SM[2][2]*pow(SM[1][3],2)+SM[3][3]*
01179      pow(SM[1][2],2)-SM[1][1]*SM[2][2]*SM[3][3])+SM[1][2]*SM[1][3]*SM[2][3]+1./27.;
01180 
01181       SP=TMath::Cos(TMath::ACos(TMath::Max(TMath::Min(SR/TMath::Sqrt(-pow(SQ,3)),1.),-1.))/3.);
01182 
01183  P[N+1][4]=1./3.+TMath::Sqrt(-SQ)*TMath::Max(2.*SP,TMath::Sqrt(3.*(1.-SP*SP))-SP);
01184       P[N+3][4]=1./3.+TMath::Sqrt(-SQ)*TMath::Min(2.*SP,-TMath::Sqrt(3.*(1.-SP*SP))-SP);
01185       P[N+2][4]=1.-P[N+1][4]-P[N+3][4];
01186       if (P[N+2][4]> 1E-5) {
01187  
01188 // C...Find first and last eigenvector by solving equation system.
01189       for (I=1;I<4;I=I+2) { // 240
01190          for (J1=1;J1<4;J1++) { // 180
01191             SV[J1][J1]=SM[J1][J1]-P[N+I][4];
01192             for (J2=J1+1;J2<4;J2++) { // 170
01193                SV[J1][J2]=SM[J1][J2];
01194                SV[J2][J1]=SM[J1][J2];
01195             }
01196           } // 180
01197          SMAX=0.;
01198          for (J1=1;J1<4;J1++) { // 200
01199             for (J2=1;J2<4;J2++) { // 190
01200               if(std::fabs(SV[J1][J2])>SMAX) { // 190
01201                  JA=J1;
01202                  JB=J2;
01203                  SMAX=std::fabs(SV[J1][J2]);
01204               }
01205             } // 190
01206           } // 200
01207           SMAX=0.;
01208           for (J3=JA+1;J3<JA+3;J3++) { // 220
01209              J1=J3-3*((J3-1)/3);
01210              RL=SV[J1][JB]/SV[JA][JB];
01211              for (J2=1;J2<4;J2++) { // 210
01212                 SV[J1][J2]=SV[J1][J2]-RL*SV[JA][J2];
01213                 if (std::fabs(SV[J1][J2])>SMAX) { // GOTO 210
01214                    JC=J1;
01215                    SMAX=std::fabs(SV[J1][J2]);
01216                  }
01217                } // 210
01218             }  // 220 
01219             JB1=JB+1-3*(JB/3);
01220             JB2=JB+2-3*((JB+1)/3);
01221             P[N+I][JB1]=-SV[JC][JB2];
01222             P[N+I][JB2]=SV[JC][JB1];
01223             P[N+I][JB]=-(SV[JA][JB1]*P[N+I][JB1]+SV[JA][JB2]*P[N+I][JB2])/
01224                   SV[JA][JB];
01225             PA=TMath::Sqrt(pow(P[N+I][1],2)+pow(P[N+I][2],2)+pow(P[N+I][3],2));
01226 // make a random number
01227             float pa=P[N-1][I];
01228             rlu=std::fabs(pa)-std::fabs(int(pa)*1.);
01229             rlu1=std::fabs(pa*pa)-std::fabs(int(pa*pa)*1.);
01230             SGN=pow((-1.),1.*int(rlu+0.5));
01231             for (J=1;J<4;J++) { // 230
01232                P[N+I][J]=SGN*P[N+I][J]/PA;
01233             } // 230
01234       } // 240
01235  
01236 // C...Middle axis orthogonal to other two. Fill other codes.      
01237       SGN=pow((-1.),1.*int(rlu1+0.5));
01238       P[N+2][1]=SGN*(P[N+1][2]*P[N+3][3]-P[N+1][3]*P[N+3][2]);
01239       P[N+2][2]=SGN*(P[N+1][3]*P[N+3][1]-P[N+1][1]*P[N+3][3]);
01240       P[N+2][3]=SGN*(P[N+1][1]*P[N+3][2]-P[N+1][2]*P[N+3][1]);
01241  
01242 // C...Calculate sphericity and aplanarity. Select storing option.
01243       //SPH=1.5*(P[N+2][4]+P[N+3][4]); //FIXME: commented out since gcc461 complained that this variable is set but unused
01244       //APL=1.5*P[N+3][4];             //FIXME: commented out since gcc461 complained that this variable is set but unused
01245 
01246       } // check 1
01247 
01248       // so assume now we have Sphericity axis, which one give the minimal Pts
01249       double etstot[4];
01250       double eltot[4];
01251       double sum23=0;
01252       double sum22=0;
01253       double sum33=0;
01254       double pina[4];
01255       double ax[4], ay[4], az[4];
01256       for (int ia=1;ia<4;ia++) {
01257         etstot[ia]=0;
01258         eltot[ia]=0;
01259         pina[ia]=0;
01260         ax[ia]=P[N+ia][1];
01261         ay[ia]=P[N+ia][2];
01262         az[ia]=P[N+ia][3];
01263         ax[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01264         ay[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01265         az[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01266       }
01267 
01268       for (int k =0 ; k<m_np ; k++) {
01269          double eta,phi;
01270          getetaphi(m_mom(k,1),m_mom(k,2),m_mom(k,3),eta,phi);
01271          double W=exp(-std::fabs(eta*1.0));
01272         for (int ia=1;ia<4;ia++) {
01273           double e=sqrt(m_mom(k,1)*m_mom(k,1) +
01274                         m_mom(k,2)*m_mom(k,2) +
01275                         m_mom(k,3)*m_mom(k,3));
01276           double el=ax[ia]*m_mom(k,1) + ay[ia]*m_mom(k,2) + az[ia]*m_mom(k,3);
01277           pina[ia]=el;
01278           double ets=(e*e-el*el);
01279           etstot[ia]+=ets*W;
01280           eltot[ia]+=el*el*W;
01281         }
01282         double a2=pina[2];
01283         double a3=pina[3];
01284         //      double h=0.4;
01285         //a2=pina[2]*cos(h)+pina[3]*sin(h);
01286         //a3=pina[3]*cos(h)-pina[2]*sin(h);
01287         sum22+=a2*a2*W;
01288         sum23+=a2*a3*W;
01289         sum33+=a3*a3*W;
01290       }
01291       
01292   
01293         double pi=3.1415927;
01294         double phi=pi/2.0;
01295         double phip=pi/2.0;
01296         double a=sum23; 
01297         double c=-a;
01298         double b=sum22-sum33;
01299         double disc=b*b-4*a*c;
01300         //   cout << " disc " << disc << endl;
01301         if (disc>=0) {
01302           double x1=(sqrt(disc)-b)/2/a;
01303           double x2=(-sqrt(disc)-b)/2/a;
01304           phi=atan(x1);
01305           phip=atan(x2);
01306           if (phi<0) phi=2.*pi+phi;
01307           if (phip<0) phip=2.*pi+phip;
01308         }
01309         double p21=sum22*cos(phi)*cos(phi)+sum33*sin(phi)*sin(phi)+2*sum23*cos(phi)*sin(phi);
01310         double p31=sum22*sin(phi)*sin(phi)+sum33*cos(phi)*cos(phi)-2*sum23*cos(phi)*sin(phi);
01311 
01312         double p22=sum22*cos(phip)*cos(phip)+sum33*sin(phip)*sin(phip)+2*sum23*cos(phip)*sin(phip);
01313         double p32=sum22*sin(phip)*sin(phip)+sum33*cos(phip)*cos(phip)-2*sum23*cos(phip)*sin(phip);
01314 
01315      
01316         double d1=std::fabs(p31*p31 - p21*p21);
01317         double d2=std::fabs(p32*p32 - p22*p22);
01318         //cout << " eltot " << eltot[2] << " " << eltot[3] << endl;
01319         //cout << " phi " << phi << " " << phip << endl;
01320         //cout << " d " << d1 << " " << d2 << endl;
01321         p2=p21;
01322         p3=p31;
01323         if (d2>d1) { 
01324           p2=p22;
01325           p3=p32;
01326         }
01327         pnorm=sqrt(eltot[1]);
01328         if (p2>p3) {
01329           p3=sqrt(p3);
01330           p2=sqrt(p2);
01331         }else {
01332           double p4=p3;
01333           p3=sqrt(p2);
01334           p2=sqrt(p4);
01335         }
01336         //cout << " sum2 sum3 " << sqrt(sum22) << " " << sqrt(sum33) << endl;
01337         //cout << " p2 p3 " << p2 << " " << p3 << endl;
01338         //double els=sqrt(eltot[2]*eltot[2]+eltot[3]*eltot[3]);
01339         //      cout << " ets els " << (ettot[1]) << " " << els << endl;
01340 
01341         //m_sph=SPH; //FIXME: shouldn't the local variables be used to reset the class member variables accordingly?
01342         //m_apl=APL; //FIXME: shouldn't the local variables be used to reset the class member variables accordingly?
01343     return;
01344 } // end planes_sphe
01345 
01346 
01347 
01348 void TopologyWorker::planes_thrust(double& pnorm, double& p2, double& p3) {
01349         TVector3 thrustaxis=thrustAxis();
01350         TVector3 majoraxis=majorAxis();
01351         TVector3 minoraxis=minorAxis();
01352       // so assume now we have Sphericity axis, which one give the minimal Pts
01353       double etstot[4];
01354       double eltot[4];
01355       double sum23=0;
01356       double sum22=0;
01357       double sum33=0;
01358       double pina[4];
01359       double ax[4], ay[4], az[4];
01360       ax[1]=thrustaxis(0); ay[1]=thrustaxis(1); az[1]=thrustaxis(2);
01361       ax[2]=minoraxis(0); ay[2]=minoraxis(1); az[2]=minoraxis(2);
01362       ax[3]=majoraxis(0); ay[3]=majoraxis(1); az[3]=majoraxis(2);
01363       for (int ia=1;ia<4;ia++) {
01364         etstot[ia]=0;
01365         eltot[ia]=0;
01366         pina[ia]=0;
01367         ax[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01368         ay[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01369         az[ia]/=sqrt(ax[ia]*ax[ia]+ay[ia]*ay[ia]+az[ia]*az[ia]);
01370       }
01371 
01372       for (int k =0 ; k<m_np ; k++) {
01373         for (int ia=1;ia<4;ia++) {
01374           double e=sqrt(m_mom(k,1)*m_mom(k,1) +
01375                         m_mom(k,2)*m_mom(k,2) +
01376                         m_mom(k,3)*m_mom(k,3));
01377           double el=ax[ia]*m_mom(k,1) + ay[ia]*m_mom(k,2) + az[ia]*m_mom(k,3);
01378           pina[ia]=el;
01379           double ets=(e*e-el*el);
01380           etstot[ia]+=ets;
01381           eltot[ia]+=std::fabs(el);
01382         }
01383         double a2=pina[2];
01384         double a3=pina[3];
01385         //      double h=0.4;
01386         //a2=pina[2]*cos(h)+pina[3]*sin(h);
01387         //a3=pina[3]*cos(h)-pina[2]*sin(h);
01388         sum22+=a2*a2;
01389         sum23+=a2*a3;
01390         sum33+=a3*a3;
01391       }
01392       
01393   
01394         double pi=3.1415927;
01395         double phi=pi/2.0;
01396         double phip=pi/2.0;
01397         double a=sum23; 
01398         double c=-a;
01399         double b=sum22-sum33;
01400         double disc=b*b-4*a*c;
01401         //   cout << " disc " << disc << endl;
01402         if (disc>=0) {
01403           double x1=(sqrt(disc)-b)/2/a;
01404           double x2=(-sqrt(disc)-b)/2/a;
01405           phi=atan(x1);
01406           phip=atan(x2);
01407           if (phi<0) phi=2.*pi+phi;
01408           if (phip<0) phip=2.*pi+phip;
01409         }
01410         double p21=sum22*cos(phi)*cos(phi)+sum33*sin(phi)*sin(phi)+2*sum23*cos(phi)*sin(phi);
01411         double p31=sum22*sin(phi)*sin(phi)+sum33*cos(phi)*cos(phi)-2*sum23*cos(phi)*sin(phi);
01412 
01413         double p22=sum22*cos(phip)*cos(phip)+sum33*sin(phip)*sin(phip)+2*sum23*cos(phip)*sin(phip);
01414         double p32=sum22*sin(phip)*sin(phip)+sum33*cos(phip)*cos(phip)-2*sum23*cos(phip)*sin(phip);
01415 
01416      
01417         double d1=std::fabs(p31*p31 - p21*p21);
01418         double d2=std::fabs(p32*p32 - p22*p22);
01419         //cout << " eltot " << eltot[2] << " " << eltot[3] << endl;
01420         //cout << " phi " << phi << " " << phip << endl;
01421         //cout << " d " << d1 << " " << d2 << endl;
01422         p2=p21;
01423         p3=p31;
01424         if (d2>d1) { 
01425           p2=p22;
01426           p3=p32;
01427         }
01428         pnorm=sqrt(etstot[1]);
01429         if (p2>p3) {
01430           p3=sqrt(p3);
01431           p2=sqrt(p2);
01432         }else {
01433           double p4=p3;
01434           p3=sqrt(p2);
01435           p2=sqrt(p4);
01436         }
01437         //cout << " sum2 sum3 " << sqrt(sum22) << " " << sqrt(sum33) << endl;
01438         //cout << " p2 p3 " << p2 << " " << p3 << endl;
01439         //double els=sqrt(eltot[2]*eltot[2]+eltot[3]*eltot[3]);
01440         //      cout << " ets els " << (ettot[1]) << " " << els << endl;
01441     return;
01442 } // end planes_thru
01443 
01444 
01445 void TopologyWorker::fowo() {
01446 // 20020830 changed: from p/E to Et/Ettot and include H50 and H60
01447   m_fowo_called=true;
01448     // include fox wolframs
01449     float H10=-1;
01450     float H20=-1;
01451     float H30=-1;
01452     float H40=-1;
01453     float H50=-1;
01454     float H60=-1;
01455     if (1==1) {
01456       float P[1000][6],H0,HD,CTHE;
01457       int N,NP,I,J,I1,I2;      
01458       H0=HD=0.;
01459       N=m_np;
01460       NP=0;
01461       for (I=1;I<N+1;I++){
01462            NP++; // start at one
01463            P[NP][1]=m_mom(I-1,1) ;
01464            P[NP][2]=m_mom(I-1,2) ;
01465            P[NP][3]=m_mom(I-1,3) ;
01466            P[NP][4]=m_mom(I-1,4) ;
01467            P[NP][5]=m_mom(I-1,5) ;
01468        }
01469 
01470        N=NP;
01471        NP=0;
01472 
01473        for (I=1;I<N+1;I++) {
01474          NP=NP+1;
01475          for (J=1;J<5;J++) {
01476            P[N+NP][J]=P[I][J];
01477          }
01478 // p/E
01479          P[N+NP][4]=sqrt(pow(P[I][1],2)+pow(P[I][2],2)+pow(P[I][3],2));
01480 // Et/Ettot
01481          P[N+NP][5]=sqrt(pow(P[I][1],2)+pow(P[I][2],2));
01482          H0=H0+P[N+NP][5];
01483          HD=HD+pow(P[N+NP][5],2);
01484        }
01485        H0=H0*H0;
01486        
01487        
01488        
01489        // Very low multiplicities (0 or 1) not considered.
01490        if (NP<2) {
01491          H10=-1.;
01492          H20=-1.;
01493          H30=-1.;
01494          H40=-1.;
01495          H50=-1.;
01496          H60=-1.;
01497          return;
01498        }
01499  
01500        // Calculate H1 - H4.
01501        H10=0.;
01502        H20=0.;
01503        H30=0.;
01504        H40=0.;
01505        H50=0.;
01506        H60=0.;
01507        for (I1=N+1;I1<N+NP+1;I1++) { //130
01508          for (I2=I1+1;I2<N+NP+1;I2++) { // 120
01509            CTHE=(P[I1][1]*P[I2][1]+P[I1][2]*P[I2][2]+P[I1][3]*P[I2][3])/
01510              (P[I1][4]*P[I2][4]);
01511            H10=H10+P[I1][5]*P[I2][5]*CTHE;
01512            double C2=(1.5*CTHE*CTHE-0.5);
01513            H20=H20+P[I1][5]*P[I2][5]*C2;
01514            double C3=(2.5*CTHE*CTHE*CTHE-1.5*CTHE);
01515            H30=H30+P[I1][5]*P[I2][5]*C3;
01516            // use recurrence
01517            double C4=(7*CTHE*C3 - 3*C2)/4.;
01518            double C5=(9*CTHE*C4 - 4*C3)/5.;
01519            double C6=(11*CTHE*C5 - 5*C4)/6.;
01520 //         H40=H40+P[I1][5]*P[I2][5]*(4.375*pow(CTHE,4)-3.75*CTHE*CTHE+0.375);
01521 //         H50=H50+P[I1][5]*P[I2][5]*
01522 //         (63./8.*pow(CTHE,5)-70./8.*CTHE*CTHE*CTHE+15./8.*CTHE);
01523 //         H60=H60+P[I1][5]*P[I2][5]*
01524 //         (231/16.*pow(CTHE,6)-315./16.*CTHE*CTHE*CTHE*CTHE+105./16.*CTHE*CTHE-5./16.);
01525            H40=H40+P[I1][5]*P[I2][5]*C4;
01526            H50=H50+P[I1][5]*P[I2][5]*C5;
01527            H60=H60+P[I1][5]*P[I2][5]*C6;
01528          } // 120
01529        } // 130
01530  
01531        H10=(HD+2.*H10)/H0;
01532        H20=(HD+2.*H20)/H0;
01533        H30=(HD+2.*H30)/H0;
01534        H40=(HD+2.*H40)/H0;
01535        H50=(HD+2.*H50)/H0;
01536        H60=(HD+2.*H60)/H0;
01537        m_h10=H10;
01538        m_h20=H20;
01539        m_h30=H30;
01540        m_h40=H40;
01541        m_h50=H50;
01542        m_h60=H60;
01543     }
01544 
01545 }
01546 
01547 double TopologyWorker::get_h10() {
01548   if (!m_fowo_called) fowo();
01549   return m_h10;
01550 }
01551 double TopologyWorker::get_h20() {
01552   if (!m_fowo_called) fowo();
01553   return m_h20;
01554 }
01555 double TopologyWorker::get_h30() {
01556   if (!m_fowo_called) fowo();
01557   return m_h30;
01558 }
01559 double TopologyWorker::get_h40() {
01560   if (!m_fowo_called) fowo();
01561   return m_h40;
01562 }
01563 
01564 double TopologyWorker::get_h50() {
01565   if (!m_fowo_called) fowo();
01566   return m_h50;
01567 }
01568 double TopologyWorker::get_h60() {
01569   if (!m_fowo_called) fowo();
01570   return m_h60;
01571 }
01572 
01573 
01574 double TopologyWorker::get_sphericity() {
01575   if (!m_sanda_called) sanda();
01576   return m_sph;
01577 }
01578 double TopologyWorker::get_aplanarity() {
01579   if (!m_sanda_called) sanda();
01580   return m_apl;
01581 }
01582 
01583 void TopologyWorker::getetaphi(double px, double py, double pz, double& eta, double& phi) {
01584 
01585   double pi=3.1415927;
01586 
01587   double p=sqrt(px*px+py*py+pz*pz);
01588   // get eta and phi
01589   double th=pi/2.;
01590   if (p!=0) {
01591     th=acos(pz/p); // Theta
01592   }
01593   float thg=th;
01594   if (th<=0) {
01595     thg = pi + th;
01596   }
01597   eta=-9.;
01598   if (tan( thg/2.0 )>0.000001) {
01599     eta = -log( tan( thg/2.0 ) );    
01600   }
01601   phi = atan2(py,px);
01602   if(phi<=0) phi += 2.0*pi;
01603   return;
01604 }
01605 
01606 
01607 
01608 void TopologyWorker::sumangles(float& sdeta, float& sdr) {
01609   double eta1,eta2,phi1,phi2,deta,dphi,dr;
01610   m_sumangles_called=true;
01611   sdeta=0;
01612   sdr=0;
01613   for (int k=0;k<m_np;k++){
01614     for (int kp=k;kp<m_np;kp++){
01615       getetaphi(m_mom(k,1) , m_mom(k,2), m_mom(k,3), eta1,phi1);
01616       getetaphi(m_mom(kp,1) , m_mom(kp,2), m_mom(kp,3), eta2,phi2);
01617       dphi=std::fabs(phi1-phi2);
01618       if (dphi>3.1415) dphi=2*3.1415-dphi;
01619       deta=std::fabs(eta1-eta2);
01620       dr=sqrt(dphi*dphi+deta*deta);
01621       sdeta+=deta;
01622       sdr+=dr;
01623     }
01624   }
01625   return;
01626 }
01627 
01628 //______________________________________________________________
01629 
01630 Int_t TopologyWorker::iPow(Int_t man, Int_t exp)
01631 {
01632   Int_t ans = 1;
01633   for( Int_t k = 0; k < exp; k++)
01634     {
01635       ans = ans*man;
01636     }
01637   return ans;
01638 }
01639 
01640 // added by Freya:
01641 
01642 void TopologyWorker::CalcWmul(){
01643 
01644   Int_t njets = m_np;
01645   double result=0;
01646   for(Int_t ijet=0; ijet<njets-1; ijet++){
01647     double emin=55;
01648     double emax=55;
01649     if(CalcPt(ijet)<55)
01650       emax=CalcPt(ijet);
01651     if(CalcPt(ijet+1)<55)
01652       emin=CalcPt(ijet+1);
01653     result+=0.5 * (emax*emax-emin*emin)*(ijet+1);
01654   }
01655   double elo=15;
01656   if(CalcPt(njets-1)>elo){
01657     elo=CalcPt(njets-1);
01658   }
01659 
01660   result+=0.5 * (elo*elo-(15*15))*(njets);
01661   result/=((55*55)-100)/2.0;
01662   m_njetsweighed=result;
01663 }
01664 
01665 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01666 
01667 void TopologyWorker::CalcSqrts(){
01668   TLorentzVector event(0,0,0,0);
01669   TLorentzVector worker(0,0,0,0);
01670 
01671   for(int i=0; i< m_np; i++){
01672     double energy=m_mom(i,4);
01673     if(m_mom(i,4)<0.00001)
01674       energy=sqrt(pow(m_mom(i,1),2)+pow(m_mom(i,2),2)+pow(m_mom(i,3),2));
01675     // assume massless particle if only TVector3s are provided...
01676     worker.SetXYZT(m_mom(i,1),m_mom(i,2),m_mom(i,3),energy);
01677     event+=worker;
01678   }
01679   m_sqrts=event.M();
01680 }
01681 
01682 //++++++++++++++++++++++++++++++++++++++
01683 void TopologyWorker::CalcHTstuff(){
01684   m_ht=0;
01685   m_ht3=0;
01686   m_et56=0;
01687   m_et0=0;
01688   double ptlead=0;
01689   double h=0;
01690   for(int i=0; i< m_np; i++){
01691     //cout << i << "/" << m_np << ":" << CalcPt(i) <<  endl;
01692     m_ht+=CalcPt(i);
01693     h+=m_mom(i,4);
01694     if(i>1)
01695       m_ht3+=CalcPt(i);
01696     if(i==5)
01697       m_et56=sqrt(CalcPt(i)*CalcPt(i-1));
01698   }
01699   
01700   for(int j=0; j< m_np2; j++){
01701     //cout << j << "/" << m_np2 << ":" << CalcPt2(j) <<  endl;
01702     if(ptlead<CalcPt2(j))
01703       ptlead=CalcPt2(j);
01704 
01705   }
01706   if(m_ht>0.0001){
01707     m_et0=ptlead/m_ht;
01708     //cout << "calculating ETO" << m_et0 << "=" << ptlead << endl;
01709   }
01710   if(h>0.00001)
01711     m_centrality=m_ht/h;
01712 }
01713 
01714 #endif
01715 
01716 
01717 
01718