// ----------------------------------------------------------------------------
// $Id: LCDEventShape.cxx,v 1.1 2001/05/10 19:32:04 toshi Exp $
// ----------------------------------------------------------------------------
//
// $Log: LCDEventShape.cxx,v $
// Revision 1.1  2001/05/10 19:32:04  toshi
// C++ file name convention has been changed from .C to .cxx .
//
//
// V0.0           :            Thrust finder utility translated from 
//                             Java routines written by G.Bower. 
// V0.2 Jul 07/99 : M.Iwasaki  Change Mod to Mag function in TVector3
//                             so as to use root 2.2.x
// V0.3 Sep 23/99 : M.Iwasaki  Fix setEvent memory leak, 
//                             apply nessesary modifications in Thrust, Major, 
//                             Minor axis, and Thrust, and add ~EventSape().
// V0.4 May 12/00 : M.Iwasaki  Make necessary modifications.
//                                        
// V1.0 Aug   /00 : M.Iwasaki  Change Class name from EventShape to 
//                             LCDEventShape.
//
// V1.1 Aug 29/00 : M.Iwasaki  Remove Thrust(), and add GetThrust(), GetMajor(),
//                             and GetMiner(), so as to provide thrust, Major, 
//                             and Miner values, respectively.
//                             change class names:: thrustAxis -> GetThrustAxis etc..

#include "LCDEventShape.h"

ClassImp(LCDEventShape)

Int_t LCDEventShape::m_maxpart = 1000;

 LCDEventShape::LCDEventShape():
  m_dSphMomPower(2.0),m_dDeltaThPower(0),
  m_iFast(4),m_dConv(0.0001),m_iGood(2)
{
  m_dAxes.ResizeTo(4,4);
}
//______________________________________________________________

 LCDEventShape::~LCDEventShape(){
}
//______________________________________________________________

// Input the particle 3(4)-vector list
// e: 3-vector  TVector3       ..(px,py,pz) or
//    4-vector  TLorentzVector ..(px,py,pz,E) 
// Even input the TLorentzVector, we don't use Energy 
// 
 void LCDEventShape::SetPartList(TObjArray* e)
{	
  //To make this look like normal physics notation the
  //zeroth element of each array, mom[i][0], will be ignored
  //and operations will be on elements 1,2,3...
  TMatrixD mom(m_maxpart,6);
  Double_t tmax = 0;
  Double_t phi = 0.;
  Double_t the = 0.;
  Double_t sgn;
  TMatrixD fast(m_iFast + 1,6);
  TMatrixD work(11,6);
  Double_t tdi[] = {0.,0.,0.,0.};
  Double_t tds;
  Double_t tpr[] = {0.,0.,0.,0.};
  Double_t thp;
  Double_t thps;
  TMatrixD temp(3,5);
  Int_t np = 0;
  Int_t numElements = e->GetEntries();
  TObject* o;
  for(Int_t elem=0;elem<numElements;elem++) {
    o = e->At(elem);
    
    if (np >= m_maxpart) { 
      printf("Too many particles input to LCDEventShape");
      return;
    }

    TString nam(o->IsA()->GetName());
    if (nam.Contains("TVector3")) {
      mom(np,1) = ((TVector3 *) o)->X();
      mom(np,2) = ((TVector3 *) o)->Y();
      mom(np,3) = ((TVector3 *) o)->Z();
      mom(np,4) = TMath::Sqrt(mom(np,1)*mom(np,1) + mom(np,2)*mom(np,2)
			      + mom(np,3)*mom(np,3));
    } else if (nam.Contains("TLorentzVector")) {
      mom(np,1) = ((TLorentzVector *) o)->X();
      mom(np,2) = ((TLorentzVector *) o)->Y();
      mom(np,3) = ((TLorentzVector *) o)->Z();
      mom(np,4) = TMath::Sqrt(mom(np,1)*mom(np,1) + mom(np,2)*mom(np,2)
			      + mom(np,3)*mom(np,3));
    } else {
      printf("LCDEventShape::SetEvent input is not a TVector3 or a TLorentzVectorn");
      continue;
    }

    if ( TMath::Abs( m_dDeltaThPower ) <= 0.001 ) {
      mom(np,5) = 1.0;
    } else {
      mom(np,5) = TMath::Power(mom(np,4),m_dDeltaThPower);
    }
    tmax = tmax + mom(np,4)*mom(np,5);
    np++;
  }
  if ( np < 2 ) {
    m_dThrust[1] = -1.0;
    m_dOblateness = -1.0;
    return;
  }
  // for pass = 1: find thrust axis.
  // for pass = 2: find major axis.
  for ( Int_t pass=1; pass < 3; pass++) {
    if ( pass == 2 ) {
      phi = ulAngle(m_dAxes(1,1), m_dAxes(1,2));
      ludbrb( &mom, 0, -phi, 0., 0., 0. );
      for ( Int_t i = 0; i < 3; i++ ) {
	for ( Int_t j = 1; j < 4; j++ ) {
	  temp(i,j) = m_dAxes(i+1,j);
	}
	temp(i,4) = 0;
      }
      ludbrb(&temp,0.,-phi,0.,0.,0.);
      for ( Int_t ib = 0; ib < 3; ib++ ) {
	for ( Int_t j = 1; j < 4; j++ ) {
	  m_dAxes(ib+1,j) = temp(ib,j);
	}
      }
      the = ulAngle( m_dAxes(1,3), m_dAxes(1,1) );
      ludbrb( &mom, -the, 0., 0., 0., 0. );
      for ( Int_t ic = 0; ic < 3; ic++ ) {
	for ( Int_t j = 1; j < 4; j++ ) {
	  temp(ic,j) = m_dAxes(ic+1,j);
	}
	temp(ic,4) = 0;
      }
      ludbrb(&temp,-the,0.,0.,0.,0.);
      for ( Int_t id = 0; id < 3; id++ ) {	
	for ( Int_t j = 1; j < 4; j++ ) {
	  m_dAxes(id+1,j) = temp(id,j);
	}
      }
    }
    for ( Int_t ifas = 0; ifas < m_iFast + 1 ; ifas++ ) {
      fast(ifas,4) = 0.;
    }
    // Find the m_iFast highest momentum particles and
    // put the highest in fast[0], next in fast[1],....fast[m_iFast-1].
    // fast[m_iFast] is just a workspace.
    for ( Int_t i = 0; i < np; i++ ) {
      if ( pass == 2 ) {
	mom(i,4) = TMath::Sqrt( mom(i,1)*mom(i,1) 
				+ mom(i,2)*mom(i,2) ); 
      }
      for ( Int_t ifas = m_iFast - 1; ifas > -1; ifas-- ) {
	if ( mom(i,4) > fast(ifas,4) ) {
	  for ( Int_t j = 1; j < 6; j++ ) {
	    fast(ifas+1,j) = fast(ifas,j);
	    if ( ifas == 0 ) fast(ifas,j) = mom(i,j);	    
	  }
	} else {
	  for ( Int_t j = 1; j < 6; j++ ) {
	    fast(ifas+1,j) = mom(i,j);
	  }
	  break;
	}
      }
    }
    // Find axis with highest thrust (case 1)/ highest major (case 2).
    for ( Int_t ie = 0; ie < work.GetNrows(); ie++ ) {
      work(ie,4) = 0.;
    }
    Int_t p = TMath::Min( m_iFast, np ) - 1;
    // Don't trust Math.pow to give right answer always.
    // Want nc = 2**p.
    Int_t nc = iPow(2,p); 
    for ( Int_t n = 0; n < nc; n++ ) {
      for ( Int_t j = 1; j < 4; j++ ) {
	tdi[j] = 0.;
      }
      for ( Int_t i = 0; i < TMath::Min(m_iFast,n); i++ ) {
	sgn = fast(i,5);
	if (iPow(2,(i+1))*((n+iPow(2,i))/iPow(2,(i+1))) >= i+1){
	  sgn = -sgn;
	}
	for ( Int_t j = 1; j < 5-pass; j++ ) {
	  tdi[j] = tdi[j] + sgn*fast(i,j);
	}
      }
      tds = tdi[1]*tdi[1] + tdi[2]*tdi[2] + tdi[3]*tdi[3];
      for ( Int_t iw = TMath::Min(n,9); iw > -1; iw--) {
	if( tds > work(iw,4) ) {
	  for ( Int_t j = 1; j < 5; j++ ) {
	    work(iw+1,j) = work(iw,j);
	    if ( iw == 0 ) {
	      if ( j < 4 ) {
		work(iw,j) = tdi[j];
	      } else {
		work(iw,j) = tds;
	      }
	    }
	  }
	} else {
	  for ( Int_t j = 1; j < 4; j++ ) {
	    work(iw+1,j) = tdi[j];
	  }
	  work(iw+1,4) = tds;
	}
      }
    }
    // Iterate direction of axis until stable maximum.
    m_dThrust[pass] = 0;
    thp = -99999.;
    Int_t nagree = 0;
    for ( Int_t iw = 0; 
	  iw < TMath::Min(nc,10) && nagree < m_iGood; iw++ ){
      thp = 0.;
      thps = -99999.;
      while ( thp > thps + m_dConv ) {
	thps = thp;
	for ( Int_t j = 1; j < 4; j++ ) {
	  if ( thp <= 1E-10 ) {
	    tdi[j] = work(iw,j);
	  } else {
	    tdi[j] = tpr[j];
	    tpr[j] = 0;
	  }
	}
	for ( Int_t i = 0; i < np; i++ ) {
	  sgn = sign(mom(i,5), 
		     tdi[1]*mom(i,1) + 
		     tdi[2]*mom(i,2) + 
		     tdi[3]*mom(i,3));
	  for ( Int_t j = 1; j < 5 - pass; j++ ){
	    tpr[j] = tpr[j] + sgn*mom(i,j);
	  }
	}
	thp = TMath::Sqrt(tpr[1]*tpr[1] 
			  + tpr[2]*tpr[2] 
			  + tpr[3]*tpr[3])/tmax;
      }
      // Save good axis. Try new initial axis until enough
      // tries agree.
      if ( thp < m_dThrust[pass] - m_dConv ) {
	break;
      }
      if ( thp > m_dThrust[pass] + m_dConv ) {
	nagree = 0;
	sgn = iPow( -1, (Int_t)TMath::Nint(m_random.Rndm()) );
	for ( Int_t j = 1; j < 4; j++ ) {
	  m_dAxes(pass,j) = sgn*tpr[j]/(tmax*thp);
	}
	m_dThrust[pass] = thp;
      }
      nagree = nagree + 1;
    }
  }
  // Find minor axis and value by orthogonality.
  sgn = iPow( -1, (Int_t)TMath::Nint(m_random.Rndm()));
  m_dAxes(3,1) = -sgn*m_dAxes(2,2);
  m_dAxes(3,2) = sgn*m_dAxes(2,1);
  m_dAxes(3,3) = 0.;
  thp = 0.;
  for ( Int_t i = 0; i < np; i++ ) {
    thp += mom(i,5)*TMath::Abs(m_dAxes(3,1)*mom(i,1) + 
			       m_dAxes(3,2)*mom(i,2));
  }
  m_dThrust[3] = thp/tmax;
  // Rotate back to original coordinate system.
  for ( Int_t i6 = 0; i6 < 3; i6++ ) {
    for ( Int_t j = 1; j < 4; j++ ) {
      temp(i6,j) = m_dAxes(i6+1,j);
    }
    temp(i6,4) = 0;
  }
  ludbrb(&temp,the,phi,0.,0.,0.);
  for ( Int_t i7 = 0; i7 < 3; i7++ ) {
    for ( Int_t j = 1; j < 4; j++ ) {
      m_dAxes(i7+1,j) = temp(i7,j);
    }
  }
  m_dOblateness = m_dThrust[2] - m_dThrust[3];
  
}
//______________________________________________________________

// Setting and getting parameters.

 void LCDEventShape::SetThMomPower(Double_t tp)
{
  // Error if sp not positive.
  if ( tp > 0. ) m_dDeltaThPower = tp - 1.0;
  return;
}
//______________________________________________________________

 Double_t LCDEventShape::GetThMomPower()
{
  return 1.0 + m_dDeltaThPower;
}
//______________________________________________________________

 void LCDEventShape::SetFast(Int_t nf)
{
  // Error if sp not positive.
  if ( nf > 3 ) m_iFast = nf;
  return;
}
//______________________________________________________________

 Int_t LCDEventShape::GetFast()
{
  return m_iFast;
}
//______________________________________________________________

// Returning results

 TVector3 LCDEventShape::GetThrustAxis() {
  return TVector3(m_dAxes(1,1),m_dAxes(1,2),m_dAxes(1,3));
}
//______________________________________________________________

 TVector3 LCDEventShape::GetMajorAxis() {
  return TVector3(m_dAxes(2,1),m_dAxes(2,2),m_dAxes(2,3));
}
//______________________________________________________________

 TVector3 LCDEventShape::GetMinorAxis() {
  return TVector3(m_dAxes(3,1),m_dAxes(3,2),m_dAxes(3,3));
}
//______________________________________________________________

 Double_t LCDEventShape::oblateness() {
  return m_dOblateness;
}
//______________________________________________________________

// utilities(from Jetset):
 Double_t LCDEventShape::ulAngle(Double_t x, Double_t y)
{
  Double_t ulangl = 0;
  Double_t r = TMath::Sqrt(x*x + y*y);
  if ( r < 1.0E-20 ) {
    return ulangl; 
  }
  if ( TMath::Abs(x)/r < 0.8 ) {
    ulangl = sign(TMath::ACos(x/r),y);
  } else {
    ulangl = TMath::ASin(y/r);
    if ( x < 0. && ulangl >= 0. ) {
      ulangl = TMath::Pi() - ulangl;
    } else if ( x < 0. ) {
      ulangl = -TMath::Pi() - ulangl;
    }
  }
  return ulangl;
}
//______________________________________________________________

 Double_t LCDEventShape::sign(Double_t a, Double_t b) {
  if ( b < 0 ) {
    return -TMath::Abs(a);
  } else {
    return TMath::Abs(a);
  }
}
//______________________________________________________________

 void LCDEventShape::ludbrb(TMatrixD* mom, 
			Double_t the, 
			Double_t phi, 
			Double_t bx, 
			Double_t by,
			Double_t bz)
{
  // Ignore "zeroth" elements in rot,pr,dp.
  // Trying to use physics-like notation.
  TMatrixD rot(4,4);
  Double_t pr[4];
  Double_t dp[5];
  Int_t np = mom->GetNrows();
  if ( the*the + phi*phi > 1.0E-20 )
    {
      rot(1,1) = TMath::Cos(the)*TMath::Cos(phi);
      rot(1,2) = -TMath::Sin(phi);
      rot(1,3) = TMath::Sin(the)*TMath::Cos(phi);
      rot(2,1) = TMath::Cos(the)*TMath::Sin(phi);
      rot(2,2) = TMath::Cos(phi);
      rot(2,3) = TMath::Sin(the)*TMath::Sin(phi);
      rot(3,1) = -TMath::Sin(the);
      rot(3,2) = 0.0;
      rot(3,3) = TMath::Cos(the);
      for ( Int_t i = 0; i < np; i++ ) {
	for ( Int_t j = 1; j < 4; j++ ) {
	  pr[j] = (*mom)(i,j);
	  (*mom)(i,j) = 0;
	}
	for ( Int_t jb = 1; jb < 4; jb++) {
	  for ( Int_t k = 1; k < 4; k++) {
	    (*mom)(i,jb) = (*mom)(i,jb) + rot(jb,k)*pr[k];
	  }
	}
      }
      Double_t beta = TMath::Sqrt( bx*bx + by*by + bz*bz );
      if ( beta*beta > 1.0E-20 ) {
	if ( beta >  0.99999999 ) {
	  //send message: boost too large, resetting to <~1.0.
	  bx = bx*(0.99999999/beta);
	  by = by*(0.99999999/beta);
	  bz = bz*(0.99999999/beta);
	  beta =   0.99999999;
	}
	Double_t gamma = 1.0/TMath::Sqrt(1.0 - beta*beta);
	for ( Int_t i = 0; i < np; i++ ) {
	  for ( Int_t j = 1; j < 5; j++ ) {
	    dp[j] = (*mom)(i,j);
	  }
	  Double_t bp = bx*dp[1] + by*dp[2] + bz*dp[3];
	  Double_t gbp = gamma*(gamma*bp/(1.0 + gamma) + dp[4]);
	  (*mom)(i,1) = dp[1] + gbp*bx;
	  (*mom)(i,2) = dp[2] + gbp*by;
	  (*mom)(i,3) = dp[3] + gbp*bz;
	  (*mom)(i,4) = gamma*(dp[4] + bp);
	}
      }
    }
  return;
}
//______________________________________________________________

 Int_t LCDEventShape::iPow(Int_t man, Int_t exp)
{
  Int_t ans = 1;
  for( Int_t k = 0; k < exp; k++) {
    ans = ans*man;
  }
  return ans;
}




ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.