// ----------------------------------------------------------------------------
// $Id: LCDTrjPart.cxx,v 1.1 2001/05/10 19:32:08 toshi Exp $
// ----------------------------------------------------------------------------
//
// $Log: LCDTrjPart.cxx,v $
// Revision 1.1  2001/05/10 19:32:08  toshi
// C++ file name convention has been changed from .C to .cxx .
//
//
#include "LCDTrjPart.h"
#include "LCDTrack.h"
#include <iostream.h>

ClassImp(LCDTrjPart)   

//______________________________________________________________________
//                                                                       
// LCDTrjPart
//                                                                
 LCDTrjPart::LCDTrjPart() {
  Init();
}

 LCDTrjPart::LCDTrjPart(LCDGetParameters* gp)  { 
  // Constructor.   Primary job is to assemble various parameters
  // describing detector geometry and resolution.
  Init();
  SetDetectorParameters(gp);
}

 void LCDTrjPart::Init() {
  nVolumes     = 0;
  pInnerVolume = 0;
  pVolumes     = 0;
  f_dblevel    = 0;
}

 void LCDTrjPart::SetDetectorParameters(LCDGetParameters* gp)  { 
  // Constructor.   Primary job is to assemble various parameters
  // describing detector geometry and resolution.
  nVolumes     = gp->GetNVolumes();
  if (nVolumes == 0) {
    Int_t ok = gp->SetDetectorVolumes();
    if (ok) {
      nVolumes     = gp->GetNVolumes();
      pInnerVolume = gp->GetInnerVolume();
      pVolumes     = gp->GetDetectorVolumes();
    } else  { // make it clear we have no detector
      nVolumes     = 0;
      pInnerVolume = 0;
      pVolumes     = 0;
      printf(" Error in TrjPart :: Cannot define detector volumes");
    }
  }else{
    pInnerVolume = gp->GetInnerVolume();
    pVolumes     = gp->GetDetectorVolumes();
  }
  
}

 void LCDTrjPart::Swim(Int_t charge,
		      const TVector3& momentum, 
		      const TVector3& position, 
		      Int_t barend, Double_t tRZ) {  

  LCDSwimTraj* pTraj=&traj;
  traj.SetParticleParams(position, momentum, charge);
    
  LCDSwimTraj::PropagateRet status;
  LCDDetectorVolume*  pCur = (LCDDetectorVolume *) pInnerVolume;

  Double_t decrS;              // measured in cm
  
  //printf("pInnerVolume=%d pVolumes=%dn",pInnerVolume,pVolumes);
  // traj has been initialized with position, momentum, charge
  
  if (f_dblevel > 10)
    cout<<"LCDTrjPart::Swim Start!!!"<<endl;

  while(!(pCur->isInside(position.X(), position.Y(), position.Z()))) {
    if (pCur->pNextZ == 0) {

      if (f_dblevel > 10) {
	cout<<"   "
	    <<"pCur->pNextZ==0!!! @ step 0"<<" "
	    <<"Z="<<pCur->outerZ<<endl;
      }

      return;
    }
    pCur = (LCDDetectorVolume *) pCur->pNextZ;
  }

  // First swim through empty central volume
  if ((pCur->field != 0.0) && (charge != 0)) { // helix
    status = pTraj->HelixToCyl(pCur, &decrS);
  } else {  // straight line
    status = pTraj->LineToCyl(pCur, &decrS);
  }

  if (f_dblevel > 10) {
    cout<<"   "
	<<"First swim status="<<(Int_t)status<<" "
	<<"z="<<pTraj->GetNewPosPtr()->Z()<<" "
	<<endl;
  }

  if ((status == LCDSwimTraj::INTERSECT_NONE) ||
      (status == LCDSwimTraj::INTERSECT_ERROR)   ) return;
  
  // Check that we didn't exit to the air volume next to the beampipe.
  TVector3 pPos(*(pTraj->GetNewPosPtr()));
  if ((status == LCDSwimTraj::INTERSECT_ZPLUS) || 
      (status == LCDSwimTraj::INTERSECT_ZMINUS)) {
    if (pCur->pNextZ == 0) {

      if (f_dblevel > 10) {
	cout<<"   "
	    <<"pCur->pNextZ==0!!! @ step1"<<endl;
      }

      return;
    }
    LCDDetectorVolume* pNext = (LCDDetectorVolume *) pCur->pNextZ;
    if ( pPos.Perp() < pNext->outerR ) {

      if (f_dblevel > 10) {
	cout<<"   "
	    <<"pPos.Perp() < pNextVolume->outerR!!!"<<" "
	    <<"pPos.Perp="<<pPos.Perp()<<" "
	    <<"outerR="<<pNext->outerR<<" "
	    <<endl;
      }

      return;
    }
  }

  pTraj->Update();

  while (kTRUE) {

    if (f_dblevel > 10) {
      cout<<"   "
	  <<"In while loop"<<" "
	  <<"status="<<(Int_t)status<<" "
	  <<endl;
    }

    switch(status) {   // find new volume
    case LCDSwimTraj::INTERSECT_ZMINUS:
    case LCDSwimTraj::INTERSECT_ZPLUS:
      pCur = (LCDDetectorVolume *) pCur->pNextZ;
      if (!pCur) {

	if (f_dblevel > 10) {
	  cout<<"   "
	      <<"pCur==0!!! in while loop"<<" "
	      <<"status="<<(Int_t)status<<" "
	      <<endl;
	}

	break;
      }
      // In the special case in which we're coming from an endcap air
      // volume headed in a z-direction, there will typically be more 
      // than one adjacent volume.  pNextZ pointer gives us innermost.
      // Check this against our current radius.  If necessary, follow
      // pNextR pointers until we find an acceptable volume
      while ( pTraj->GetNewPosPtr()->Perp() > pCur->outerR ) {
	pCur = (LCDDetectorVolume *) pCur->pNextR;
	if (!pCur) {

	  if (f_dblevel > 10) {
	    cout<<"   "
		<<"pCur==0!!! in while loop"<<" "
		<<"status="<<(Int_t)status<<" "
		<<endl;
	  }

	  break;
	}
      }
      break;
    case LCDSwimTraj::INTERSECT_CYLIN:
      // One extra thing to check here as well.  In case we go inwards, 
      // there may be more than one component next to the original. 
      // pPrevR points
      // to the one with smallest z.  If this isn't right (based on
      // new position), follow its pNextZ pointer.
      pCur = (LCDDetectorVolume *) pCur->pPrevR;
      if (!pCur) {

	if (f_dblevel > 10) {
	  cout<<"   "
	      <<"pCur==0!!! in while loop"<<" "
	      <<"status="<<(Int_t)status<<" "
	      <<endl;
	}

	break;
      }
      while (TMath::Abs(pTraj->GetNewPosPtr()->Z()) > pCur->outerZ) {
	pCur = (LCDDetectorVolume *) pCur->pNextZ;
	if (!pCur) {

	  if (f_dblevel > 10) {
	    cout<<"   "
		<<"pCur==0!!! in while loop"<<" "
		<<"status="<<(Int_t)status<<" "
		<<endl;
	  }

	  break;
	}
      }
      break;
    case LCDSwimTraj::INTERSECT_CYLOUT:
      pCur = (LCDDetectorVolume *) pCur->pNextR;
      break;
    default:
      return;
    }
    
    if (!pCur) return;  // Went outside detector
    
    // Propagate to boundary of volume
    Bool_t helix = ((pCur->field != 0.0) && (charge != 0));
    
    Int_t targetvol=1;
    Double_t tmprz=0;
    if (barend == 0) { // barrel
      if (tRZ < pCur->outerR) {
	tmprz = pCur->outerR;
	pCur->outerR = tRZ;
	targetvol=0;
      }
    } else { // endcap
      if (TMath::Abs(tRZ) < pCur->outerZ ) {
	tmprz = pCur->outerZ;
	pCur->outerZ = TMath::Abs(tRZ);
	targetvol=0;
      }
    }
    if (helix) {//helix
      status = pTraj->HelixToCyl(pCur, &decrS);
    } else {  // straight line
      status = pTraj->LineToCyl(pCur, &decrS);
    }
    if (!targetvol) {
      if (barend==0) {
	pCur->outerR=tmprz;
      } else {
	pCur->outerZ=tmprz;
      }
    }
    if ((status == LCDSwimTraj::INTERSECT_NONE) ||
	(status == LCDSwimTraj::INTERSECT_ERROR)  ) return;
    
    if (targetvol) { // keep going
      pTraj->Update();
    } else {  // We'll finish in this volume
      if (helix) {
	status = pTraj->HelixPath(pCur->field, decrS);
      } else {
	status = pTraj->LinePath(decrS); 
      }

      if (f_dblevel > 10) {
	cout<<"   "
	    <<"Swim end"<<" "
	    <<"status"<<(Int_t)status<<" "
	    <<"xposZ="<<traj.GetNewPosPtr()->Z()<<" "
	    <<"helix="<<(Int_t)helix<<" "
	    <<"tRZ="<<tRZ<<" "
	    <<endl;
      }
      
      pTraj->Update();

      if (barend == 0 || 
	  (barend != 0 && status == LCDSwimTraj::INTERSECT_ZPLUS) ||
	  (barend != 0 && status == LCDSwimTraj::INTERSECT_ZMINUS)) {
	return;
      }

    }
  }
  return;
}

 void LCDTrjPart::Swim(LCDEvent* event,Int_t itrk,Int_t barend, Double_t tRZ) {
  LCDTrack*  trk=(LCDTrack*) (event->Tracks()->At(itrk));
  LCDMcPart* mcp=(LCDMcPart*)(event->MCparticles()->At(trk->GetParticle()));
  Swim(trk,mcp,barend,tRZ);
}

 void LCDTrjPart::Swim(LCDTrack* trk,LCDMcPart* pmc,Int_t barend, Double_t tRZ){
  TVector3 ptrk(trk->GetMomentumVector(0.0));
  TVector3 xtrk(trk->GetPositionVector(0.0));

  if (f_dblevel > 10) {
    cout<<"LCDTrjPart::Swim Original Track Swim"<<endl;
  }

  Swim(trk->GetCharge(),ptrk,xtrk,barend,tRZ);
  if (barend != 0) { //endcap cluster...
    Double_t aomega=trk->GetTrackParameter(2);//=1/rho
    Double_t tanl  =trk->GetTrackParameter(4);//=tan lambda
    Double_t cosl  =1.0/TMath::Sqrt(1.0 + tanl*tanl);
    Double_t phi   =traj.GetS()*cosl*aomega;
    if (phi > 2*TMath::Pi()) {
      TVector3 xold(*(traj.GetNewPosPtr()));

      TVector3 p_orig(pmc->Get4MomentumPtr()->Vect());
      TVector3 x_orig(*(pmc->GetPositionPtr()));
      TVector3 p_poca;
      TVector3 x_poca;
      CalcPOCA(pmc->GetCharge(),trk->GetMagneticField(),
	       p_orig,x_orig,p_poca,x_poca);

      if (f_dblevel > 10) {
	cout<<"LCDTrjPart::Swim MC track Swim"<<endl;
      }

      Swim(pmc->GetCharge(),p_poca,x_poca,barend,tRZ);
      TVector3 xtru(*(traj.GetNewPosPtr()));

      Double_t omega0  =-pmc->GetCharge()*trk->GetMagneticField()
	/333.567/p_orig.Pt();
      Double_t z00     = x_poca.Z();
      Double_t tanl0   = p_orig.Pz()/p_orig.Pt();
      Double_t tmpphi  = (tRZ - z00)/tanl0*omega0;
      Int_t    n2pi    = (Int_t)(TMath::Abs(tmpphi)/TMath::Pi()/2.0);
      Double_t l       = TMath::Abs(n2pi*2*TMath::Pi()/omega0);
      Double_t zoffset = tanl0*l;
      xtrk.SetZ(xtrk.Z()+zoffset);

      if (f_dblevel > 10) {
	cout<<"LCDTrjPart::Swim new track Swim"<<endl;
      }

      Swim(trk->GetCharge(),ptrk,xtrk,barend,tRZ);

      TVector3 xnew(*(traj.GetNewPosPtr()));

      if (f_dblevel > 0) {
	cout<<"---"
	    <<"xyz mcp="<<xtru.X()<<","<<xtru.Y()<<","<<xtru.Z()<<" "
	    <<"tRZ="<<tRZ
	    <<endl;
	cout<<"   "
	    <<"xyz old="<<xold.X()<<","<<xold.Y()<<","<<xold.Z()<<" "
	    <<"dist="<<(xold-xtru).Perp()
	    <<endl;
	cout<<"   "
	    <<"xyz new="<<xnew.X()<<","<<xnew.Y()<<","<<xnew.Z()<<" "
	    <<"dist="<<(xnew-xtru).Perp()
	    <<endl;
      }

    }
  }
}

 void LCDTrjPart::CalcPOCA(Double_t  qMC,
			  Double_t  bfld_z,
			  const TVector3&  p_orig, 
			  const TVector3&  x_orig, 
			  TVector3& p_poca, 
			  TVector3& x_poca) {
  Double_t pT   = p_orig.Pt();
  Double_t tanL = p_orig.Z()/pT;
  Double_t arho = 333.567/bfld_z*pT;
  
  TVector3 nzv(0.0,0.0,qMC/TMath::Abs(qMC));
  TVector3 xxc = p_orig.Cross(nzv);
  xxc.SetZ(0.0);
  TVector3 nxxc = xxc.Unit();
  TVector3 xc   = x_orig + arho*nxxc;
  xc.SetZ(0.0);
  TVector3 nxc  = xc.Unit();
  
  TVector3 catMC=nzv.Cross(nxc);
  catMC.SetZ(0.0);
  TVector3 ncatMC=catMC.Unit();

  p_poca    = pT*ncatMC;
  p_poca.SetZ(p_orig.Z());
  
  Double_t dphi     = TMath::ASin(nxxc.Cross(nxc).Z());
  Double_t dl       =-dphi*arho*qMC;
  x_poca            = xc - arho*nxc;
  x_poca.SetZ(x_orig.Z() + dl*tanL);
  
}


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.