///§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§//*
//             LOW ENERGY MUON SPIN RELAXATION, ROTATION, RADIATION 
// 
//  ID    :FieldCheck.cc , v 1.2
//  AUTHOR: Taofiq PARAISO
//  DATE  : 2004-09-17 10:20
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§//
//
//  &           &&&&&&&&&&                            &&&&&&&         &&&&&&&&
//  &           &                                   &&      &&       &       &&
//  &           &                   &      &       &                &       &&
//  &           &&&&&&&            &      &         &&&&&&         &&&&&&&&  
//  &           &                 &      &&                &      &      &&
//  &           &                &&     &  &     &&      &&      &        &
//  &&&&&&&&&&  &&&&&&&&&&      &  &&&&&    &&    &&&&&&&       &        &&   
//                             &
//                            &
//                           &
//                         &  
//                               FIELDCHECK   
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§//
#include "FieldCheck.hh"

#include "G4SteppingManager.hh"
#include "G4Transform3D.hh"
#include "G4DynamicParticle.hh"
#include "G4UnitsTable.hh"
#include "LEMuSRDetectorConstruction.hh"
#include "G4VVisManager.hh"
#include "G4Polyline.hh"
#include "G4VisAttributes.hh"
#include "G4Colour.hh"



FieldCheck::FieldCheck()
{

  BookRoot();
  muon.index= 0;


  loop=0;
  pointer=this  ;
}


FieldCheck::~FieldCheck()
{
  WriteRoot();
}

FieldCheck*  FieldCheck::pointer=0;
FieldCheck*  FieldCheck::GetInstance()
{
  return pointer;
}


void FieldCheck::UserSteppingAction(const G4Step* aStep)
  
{  
  if( aStep->GetPreStepPoint()&& aStep->GetPostStepPoint()->GetPhysicalVolume() )
    {
      SetParticleVolumeNames(aStep);
      kenergy= aStep->GetTrack()->GetDynamicParticle()->GetKineticEnergy(); // position

      if(CheckCondition(aStep))
	{	  

	  SetPositionMomentum(aStep);
	  SetTimeEnergy(aStep);
	  //	  SetSpinDirection(aStep);      
	  
	  // Print datas to screen
	  //	  PrintDatas(aStep);
	  	  PrintField(aStep);
	  
	  Update();
	  FillRoot();
#if defined G4UI_USE_ROOT 
	  myFile->Write();
#endif

	}


      // kill useless particles
      // kill useless particles
      /*  if(aStep->GetTrack()->GetDefinition()->GetParticleName()=="e-"
     ||aStep->GetTrack()->GetDefinition()->GetParticleName()=="gamma")
      {
	aStep->GetTrack()->SetTrackStatus(fStopAndKill);
	}*/

      if(p_name!="mu+"   &&p_name!="Mu"   &&p_name!="e+" &&p_name!="geantino")
      {
	aStep->GetTrack()->SetTrackStatus(fStopAndKill);
      }
      
 
      // loop killa
      if(aStep->GetStepLength()<0.01*mm)
	{
	  loop++;
	  if(loop>20)
	    {
	      aStep->GetTrack()->SetTrackStatus(fStopAndKill);
	      loop=0;
	    }
	}     
      
      
      
    }
  
  
  G4VVisManager* pVVisManager = G4VVisManager::GetConcreteInstance();
  
  if (pVVisManager) {
    //----- Define a line segment 
    G4Polyline polyline;
    G4Colour colour;
    if      (p_name == "mu+") colour = G4Colour(1., 0., 0.);
    else if (p_name == "Mu" ) colour = G4Colour(0., 0., 1.);
    else if (p_name == "e+" ) colour = G4Colour(1., 1., 0.);
    else  colour = G4Colour(1., 0., 1.);
    G4VisAttributes attribs(colour);
    polyline.SetVisAttributes(attribs);
    polyline.push_back(aStep->GetPreStepPoint()->GetPosition());
    polyline.push_back(aStep->GetPostStepPoint()->GetPosition());
    
    //----- Call a drawing method for G4Polyline 
    pVVisManager -> Draw(polyline); 
    
  } 
}





G4bool FieldCheck::CheckCondition(const G4Step* aStep)
{
  G4bool condition=false;
  
  if((p_name == "mu+"||p_name=="Mu"||p_name=="geantino")/*&&v_name=="lv_MCPV"*/&&aStep->GetPreStepPoint()->GetPosition().z()<16*cm)
    
    //     if(aStep->GetPostStepPoint()->GetProcessDefinedStep() != NULL)
    //	{
    //	  if( aStep->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName()=="Decay")
    //	    {
    {
      condition=true;
    }
  return condition;
  
  
}


void FieldCheck::SetParticleVolumeNames(const G4Step* aStep)
{
  // NAMES
  p_name = aStep->GetTrack()->GetDefinition()->GetParticleName(); // particle name 
  v_name = aStep->GetPostStepPoint()->GetPhysicalVolume()->GetLogicalVolume()->GetName(); //lv_name
  pv_name = aStep->GetTrack()->GetVolume()->GetName(); //lv_name

}


void FieldCheck::SetPositionMomentum(const G4Step* aStep)
{

  // POSITION, MOMENTUM
  position = aStep->GetTrack()->GetPosition(); // position
  momentum = aStep->GetTrack()->GetMomentum(); // momentum
  momentum_direction = aStep->GetTrack()->GetMomentumDirection(); // momentum

}


void FieldCheck::SetTimeEnergy(const G4Step* aStep)
{
 
  // ENERGY
  kenergy= aStep->GetTrack()->GetDynamicParticle()->GetKineticEnergy(); // position
 
  tenergy= aStep->GetTrack()->GetDynamicParticle()->GetTotalEnergy(); // position
 
  // TIME
  localtime =  aStep->GetPostStepPoint()->GetLocalTime(); // time since track creation
  globaltime =  aStep->GetPostStepPoint()->GetGlobalTime();// time since event creation
  proptime =  aStep->GetPostStepPoint()->GetProperTime(); // proper time of the particle
  time = proptime;

  charge=aStep->GetTrack()->GetDynamicParticle()->GetCharge();

}


void FieldCheck::SetSpinDirection(const G4Step* aStep)
{
  polarization = aStep->GetTrack()->GetDynamicParticle()->GetPolarization();
  //  G4cout<<polarization.y()<<G4endl;
}


void FieldCheck::Update()
{
  muon.tenergy   = kenergy/keV;
  muon.localtime = localtime ;
  muon.globaltime= globaltime/ns ;
  muon.proptime   = proptime ;
  
  muon.positionx = position.x()/mm;
  muon.positiony = position.y()/mm;
  muon.positionz = position.z()/mm;
  
  muon.momdirx= momentum_direction.x();
  muon.momdiry= momentum_direction.y();
  muon.momdirz= momentum_direction.z();

  muon.Ex=fx;
  muon.Ey=fy;
  muon.Ez=fz;

  muon.Bx=bx;
  muon.By=by;
  muon.Bz=bz;
  
  muon.id = G4RunManager::GetRunManager()->GetCurrentRun()->GetRunID();
  evt=G4RunManager::GetRunManager()->GetCurrentEvent()->GetEventID();
  muon.event = evt;

  muon.charge= charge;

}


//                          PRINT VALUES

void FieldCheck::PrintField(const G4Step* aStep)
{
  //      G4cout<< position.z()<<G4endl;
   if(aStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetFieldManager())
    {
      G4double point[4];
      G4double Bfield[6];
      
      point[0]=position.x();
      point[1]=position.y();
      point[2]=position.z();
      
      aStep->GetTrack()->GetVolume()->GetLogicalVolume()->GetFieldManager()->GetDetectorField()->GetFieldValue(point, Bfield);
      //        G4cout<< position.z()<<G4endl;
 
      if(position.z()<-34.7*cm)
	{
	  //	  G4cout<< position.z() <<" Case TL "<<G4endl;
	  fx=Bfield[0]/kilovolt*meter;
	  fy=Bfield[1]/kilovolt*meter;
	  fz=Bfield[2]/kilovolt*meter;
	}	  

      if(position.z()>-34.7*cm
	 &&LEMuSRDetectorConstruction::GetInstance()->magfield==1
	 &&LEMuSRDetectorConstruction::GetInstance()->anode_elfield==1)    
	{
	  //	  	  G4cout<<"Case EM "<<G4endl;
	  bx=Bfield[0]/gauss;
	  by=Bfield[1]/gauss; //kilovolt*meter;
	  bz=Bfield[2]/gauss;
	  fx=Bfield[3]/kilovolt*meter;
	  fy=Bfield[4]/kilovolt*meter;
	  fz=Bfield[5]/kilovolt*meter;
	}	  

      if(position.z()>-34.7*cm
	 &&LEMuSRDetectorConstruction::GetInstance()->magfield==1
	 &&LEMuSRDetectorConstruction::GetInstance()->anode_elfield==0)    
	{
	  //	  	  G4cout<<"Case Mag "<<G4endl;
	  bx=Bfield[0]/gauss;
	  by=Bfield[1]/gauss; //kilovolt*meter;
	  bz=Bfield[2]/gauss;
	  fx=0*Bfield[3]/kilovolt*meter;
	  fy=0*Bfield[4]/kilovolt*meter;
	  fz=0*Bfield[5]/kilovolt*meter;
	}	  

      if(position.z()>-34.7*cm
	 &&LEMuSRDetectorConstruction::GetInstance()->magfield==0
	 &&LEMuSRDetectorConstruction::GetInstance()->anode_elfield==1)    
	{
	  //	  G4cout<<"Case Elec "<<G4endl;
	  fx=Bfield[0]/kilovolt*meter;
	  fy=Bfield[1]/kilovolt*meter;
	  fz=Bfield[2]/kilovolt*meter;
	  bx=0.;
	  by=0.; //kilovolt*meter;
	  bz=0.;
	}	  



      
#ifdef  DEBUG_FIELD
      G4cout<<"Field Value " << G4BestUnit(Bfield[0]*meter,"Electric potential") <<" /m " <<Bfield[1] /volt*meter <<" V/m "<< Bfield[2]/volt*meter <<" V/m " <<G4endl;
#endif
    }

  else
    {
      fx=0;
      fy=0;
      fz=0; 
      bx=0;
      by=0;
      bz=0; 
     
    }
}


void FieldCheck::PrintDatas(const G4Step* aStep)
{
  
  if( aStep->GetTrack()->GetCreatorProcess())
    {
      G4cout << "NOT PRIMARY PARTICLE     :  created by : " << aStep->GetTrack()->GetCreatorProcess()->GetProcessName()   <<" ;\n ";
    }
  
  G4cout << "particle name     : " <<  p_name  <<" ;\n " 
	 << "volume name       : " <<  v_name   <<" ;\n " 
	 << "kinetic energy    : " << G4BestUnit(kenergy,"Energy") <<" ;\n " 
	 << "Time (l,g,p)      : " <<  G4BestUnit(localtime,"Time") <<" ; " 
	 <<  G4BestUnit(globaltime,"Time")<<" ; " 
	 <<  G4BestUnit(proptime,"Time")   <<" ;\n " 
	 << "position          : " <<  G4BestUnit(position,"Length")<<" ;\n " 
	 << "momentum          : " <<  momentum         <<" ;\n " 
	 << "momentum direction: " <<  momentum_direction<<" ;\n " 
	 <<G4endl;
  
}    




//----------------------------------------------------------------------------------------//
//                                            ROOT

void FieldCheck::BookRoot()
{
  myFile = new TFile("field2.root", "RECREATE");

  tree = new TTree ("tree","Muons parameters");

  tree->Branch("muon",&muon.tenergy,"kenergy/F:localtime/F:globaltime:propertime/F:positionx/F:positiony:positionz:momdirx:momdiry:momdirz:Bx:By:Bz:Ex:Ey:Ez:charge/F:index/I:event/I:runID/I");

}


void FieldCheck::FillRoot()
{
  tree->Fill();
  //  tree->Scan();

}

void FieldCheck::WriteRoot()
{
  myFile->Write();
  myFile->Close();

}
