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

#include "G4SteppingManager.hh"
#include "G4Transform3D.hh"
#include "G4DynamicParticle.hh"
#include "G4UnitsTable.hh"
#include "LEMuSRMuonDecayChannel.hh"
#include "G4MuonDecayChannelWithSpin.hh"
  
AsymCheck::AsymCheck()
{

  A=0;L=0;R=0;
  BR1=BR2=dm1=dm2=0;
  BookRoot();

  pointer=this  ;
}


AsymCheck::~AsymCheck()
{
  PrintAsym();
G4cout <<"\n Left/Right Asymmetry: L vs R =  " << L <<" vs " << R <<" => A = " <<  A <<" for "<< L+R <<" particles.\n"<<G4endl;
  WriteRoot();
}

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


void AsymCheck::UserSteppingAction(const G4Step* aStep)
  
{  
 
  SetParticleVolumeNames(aStep);

  if(CheckCondition(aStep))
    {	  

      // Get datas
      SetPositionMomentum(aStep);
      SetTimeEnergy(aStep);
      SetAngles(aStep);

	SetSpinDirection(aStep);      
      // Print datas to screen
	//	PrintDatas(aStep);
      Update();
      FillRoot();
    
    }
  
  
  
}


G4bool AsymCheck::CheckCondition(const G4Step* aStep)
{
  G4bool condition=false;

  if (v_name == "lv_AsymL" ||v_name == "lv_AsymR")
     {   
       if(p_name == "e+")
	 {	  
	   if( aStep->GetTrack()->GetCreatorProcess())      
 	     {
	       if( aStep->GetTrack()->GetCreatorProcess()->GetProcessName()=="Decay"|| aStep->GetTrack()->GetCreatorProcess()->GetProcessName()=="DecayWithSpin")

		 {
		   condition=true;
		 }
	     }
	 }
     }
  
  return condition;

}  


void AsymCheck::SetAngles(const G4Step* aStep)
{
  //lemu
  //  theta =  LEMuSRMuonDecayChannel::GetInstance()->theta;
  //  phi   = LEMuSRMuonDecayChannel::GetInstance()->phi;
  
  // triumf
  m=aStep->GetPreStepPoint()->GetMomentumDirection(); 
  p=  aStep->GetTrack()->GetDynamicParticle()->GetPolarization();

  m.rotateUz(G4ThreeVector(-1.,0.,0.));
  p.rotateUz(G4ThreeVector(-1.,0.,0.));
  
  theta =  m.theta(p);
  if (m.x()<0)phi = acos(m.x()/sin(theta))*(-1.);
  else if (m.x()>=0)phi = acos(m.x()/sin(theta))*(+1.);
  

}


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

}


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

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

  if(position.x()>0) L++;
  else if(position.x()<0) R++;

}


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

  positron.kenergy =kenergy ;
}


void AsymCheck::SetSpinDirection(const G4Step* aStep)
{
  polarization = aStep->GetTrack()->GetDynamicParticle()->GetPolarization();
  //  G4cout <<"Polarization " << polarization <<G4endl;
  spin.omegat = acos(polarization.x());
  spin.time = aStep->GetPreStepPoint()->GetGlobalTime();
}


void AsymCheck::Update()
{
  positron.kenergy =kenergy/MeV ;
  positron.tenergy =tenergy;
  positron.localtime =localtime ;
  positron.globaltime =globaltime/ns ;
  positron.proptime = proptime ;
  
  positron.theta = theta/rad ;
  positron.phi = phi/rad;

  positron.positionx = position.x()/mm;
  positron.positiony = position.y()/mm;
  positron.positionz = position.z()/mm;

  positron.momdirx= momentum_direction.x()/mm;
  positron.momdiry= momentum_direction.y()/mm;
  positron.momdirz= momentum_direction.z()/mm;

  positron.ID=G4RunManager::GetRunManager()->GetCurrentRun()->GetRunID();

 
}


//                          PRINT VALUES

void AsymCheck::PrintAsym()
{
  A = (L-R)/(L+R);
  //  G4cout <<"\n Left/Right Asymmetry: L vs R =  " << L <<" vs " << R <<" => A = " <<  A <<" for "<< L+R <<" particles.\n"<<G4endl;
  asym.asym=A;
  asym.L=L;
  asym.R=R;
  asym.S=L+R;
}


void AsymCheck::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 " 
	 << "total energy      : " <<  G4BestUnit(tenergy,"Energy") <<" ;\n " 
	 << "current energy    : " <<  G4BestUnit(aStep->GetPreStepPoint()->GetTotalEnergy(),"Energy") <<" ;\n " 
	 << "Time (l,g,p)      : " <<  G4BestUnit(localtime,"Time") <<" ; " 
	 <<  G4BestUnit(globaltime,"Time")<<" ; " 
	 <<  G4BestUnit(proptime,"Time")   <<" ;\n " 
	 << "position          : " <<  position          <<" ;\n " 
	 << "momentum          : " <<  momentum          <<" ;\n " 
	 << "momentum direction: " <<  momentum_direction<<" ;\n " 
	 << "theta angle       : " <<  theta             <<" ;\n " 
	 << "phi angle         : " <<  phi               <<" ;\n " 

	 <<G4endl;
  
  
}    




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

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

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

  tree->Branch("positron",&positron.kenergy,"kenergy/F:tenergy/F:localtime/F:globaltime:propertime/F:theta:phi:positionx/F:positiony:positionz:momdirx:momdiry:momdirz/F:runID/I");

  tree->Branch("Asymetry",&asym.asym,"Asym/F:L:R:S");

  tree->Branch("spin",&spin.omegat,"omegat/F:time");

}


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

}

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

}
