//*************************************************************************
//* =======================
//*  ANLEventShape Classes 
//* =======================
//*
//* (Description)
//*    Jet finder classes for JLC analyses.
//* (Requires)
//* 	class TLorentzVector
//* 	class Lockable
//* 	class ANL4DVector
//* (Provides)
//* 	class ANLEventShape
//* (Usage)
//* (Update Recored)
//*    1999/08/11  K.Fujii	Original version derived from the LCD 
//*				version converted from java routines 
//*				written by Gary Bower.
//*				No essential changes except for the
//*				input event format.
//*    1999/09/05  K.Ikematsu	Replaced LockableLVector with ANL4DVector.
//*    1999/09/28  K.Fujii	Plugged memory leaks as recommended by
//*				M.Iwasaki.
//*
//*************************************************************************
//
#include "ANLEventShape.h"

//_____________________________________________________________________
//  -------------------
//  ANLEventShape Class
//  -------------------
//

ClassImp(ANLEventShape)

Int_t ANLEventShape::m_maxpart = 1000;

//______________________________________________________________

 ANLEventShape::ANLEventShape() 
	: m_dSphMomPower(2.0), m_dDeltaThPower(0), m_iFast(4),
	  m_dConv(0.0001), m_iGood(2),
	  m_ThrustAxis(0), m_MajorAxis(0),
	  m_MinorAxis(0), m_Thrust(0)
{
  m_dAxes.ResizeTo(4,4);
}
//______________________________________________________________

 ANLEventShape::~ANLEventShape() 
{
  if (m_ThrustAxis) 	delete m_ThrustAxis;
  if (m_MajorAxis) 	delete m_MajorAxis;
  if (m_MinorAxis) 	delete m_MinorAxis;
  if (m_Thrust) 	delete m_Thrust;
}
//______________________________________________________________


 void ANLEventShape::Initialize(const TObjArray& parts) 
{
  setEvent((TObjArray *)&parts);
}
//______________________________________________________________

/** 
* Call this to input a new event to the event shape routines.
* @param e An Enumeration of ANL4DVectors or their variants.
*/
// The zero element in each array in m_dAxes is ignored. Elements
// 1,2 and 3 are the x, y, and z direction cosines of the axis.
// Also the zeroth axis and thrust are ignored.
 
 void ANLEventShape::setEvent(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...
  TMatrix mom(m_maxpart,6);
  Double_t tmax = 0;
  Double_t phi = 0.;
  Double_t the = 0.;
  Double_t sgn;
  TMatrix fast(m_iFast + 1,6);
  TMatrix work(11,6);
  Double_t tdi[4] = {0.,0.,0.,0.};
  Double_t tds;
  Double_t tpr[4] = {0.,0.,0.,0.};
  Double_t thp;
  Double_t thps;
  TMatrix temp(3,5);

  // -----------------------------------
  // Store particles' 3-momenta in "mom"
  // -----------------------------------

  Int_t np = 0;
  TIter nextinev(e);
  TObject* o;
  while ((o = (TObject *)nextinev())) {
      if (np >= m_maxpart) { 
	  cerr << "Too many particles input to ANLEventShape" << endl;
	  return;
      }
      ANL4DVector *qp;
      if (o->IsA()->InheritsFrom("ANL4DVector")) {
	  qp = (ANL4DVector *)o;
      } else {
         cerr << "ANLEventShape::setEvent input is not a ANL4DVector" << endl;
	 continue;
      }
      ANL4DVector &q = *qp;
      if (q.IsLocked()) continue; 	// Skip if locked.
      mom(np,1) = q(1);
      mom(np,2) = q(2);
      mom(np,3) = q(3);
      mom(np,4) = q.GetMag();
      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 ) {			// Skip if only a single track there
      m_dThrust[1] = -1.0;
      m_dOblateness = -1.0;
      return;
  }
  
  // -----------------------------------
  // Find thrust/major axes
  // -----------------------------------
  // 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 ANLEventShape::setThMomPower(Double_t tp)
{
  // Error if sp not positive.
  if ( tp > 0. ) m_dDeltaThPower = tp - 1.0;
  return;
}
//______________________________________________________________

 Double_t ANLEventShape::getThMomPower()
{
  return 1.0 + m_dDeltaThPower;
}
//______________________________________________________________

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

 Int_t ANLEventShape::getFast()
{
  return m_iFast;
}
//______________________________________________________________

// Returning results

 TVector3* ANLEventShape::thrustAxis()
{
  if (m_ThrustAxis) {
    m_ThrustAxis->SetXYZ(m_dAxes(1,1),m_dAxes(1,2),m_dAxes(1,3));
  } else {
    m_ThrustAxis = new TVector3(m_dAxes(1,1),m_dAxes(1,2),m_dAxes(1,3));
  }
  return m_ThrustAxis;
}
//______________________________________________________________

 TVector3* ANLEventShape::majorAxis()
{
  if (m_MajorAxis) {
    m_MajorAxis->SetXYZ(m_dAxes(2,1),m_dAxes(2,2),m_dAxes(2,3));
  } else {
    m_MajorAxis = new TVector3(m_dAxes(2,1),m_dAxes(2,2),m_dAxes(2,3));
  }
  return m_MajorAxis;
}
//______________________________________________________________

 TVector3* ANLEventShape::minorAxis()
{
  if (m_MinorAxis) {
    m_MinorAxis->SetXYZ(m_dAxes(3,1),m_dAxes(3,2),m_dAxes(3,3));
  } else {
    m_MinorAxis = new TVector3(m_dAxes(3,1),m_dAxes(3,2),m_dAxes(3,3));
  }
  return m_MinorAxis;
}
//______________________________________________________________

 Double_t ANLEventShape::GetThrust() const
{
  return m_dThrust[1];
}
//______________________________________________________________

 TVector3* ANLEventShape::thrust()
{
  if (m_Thrust) {
    m_Thrust->SetXYZ(m_dThrust[1],m_dThrust[2],m_dThrust[3]);
  } else {
    m_Thrust = new TVector3(m_dThrust[1],m_dThrust[2],m_dThrust[3]);
  }
  return m_Thrust;
}
//______________________________________________________________

 Double_t ANLEventShape::oblateness()
{
  return m_dOblateness;
}
//______________________________________________________________
//
// utilities(from Jetset):

 Double_t ANLEventShape::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 ANLEventShape::sign(Double_t a, Double_t b)
{
  if ( b < 0 ) 	return -TMath::Abs(a);
  else 		return TMath::Abs(a);
}
//______________________________________________________________

 void ANLEventShape::ludbrb(TMatrix* 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.

  TMatrix 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 ANLEventShape::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 - Home 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.