er  dev
ERBeamDetPID.cxx
1 #include "ERBeamDetPID.h"
2 
3 #include "G4IonTable.hh"
4 #include "G4ParticleDefinition.hh"
5 #include "G4NistManager.hh"
6 #include "G4EmCalculator.hh"
7 
8 #include "TVector3.h"
9 #include "TMath.h"
10 #include "TDatabasePDG.h"
11 #include "TParticlePDG.h"
12 #include "TGeoManager.h"
13 
14 #include "FairRootManager.h"
15 #include "FairRuntimeDb.h"
16 #include "FairLogger.h"
17 
18 #include "ERRunAna.h"
19 #include "ERDetectorList.h"
20 #include "ERBeamDetSetup.h"
21 #include "ERDigi.h"
22 
23 //--------------------------------------------------------------------------------------------------
25  : ERTask("ER BeamDet particle finding scheme")
26 {
27  fAvailibleRunManagers.push_back("ERRunAna");
28 }
29 //--------------------------------------------------------------------------------------------------
31  : ERTask("ER BeamDet particle finding scheme ", verbose)
32 {
33  fAvailibleRunManagers.push_back("ERRunAna");
34 }
35 //--------------------------------------------------------------------------------------------------
36 void ERBeamDetPID::SetBoxPID(Double_t tof1, Double_t tof2, Double_t dE1, Double_t dE2) {
37  fToF1 = tof1;
38  fToF2 = tof2;
39  fdE1 = dE1;
40  fdE2 = dE2;
41 }
42 //--------------------------------------------------------------------------------------------------
43 InitStatus ERBeamDetPID::Init() {
44  if (ERTask::Init() != kSUCCESS)
45  return kFATAL;
46 
47  if (fPID == -1){
48  LOG(FATAL) << "PID not defined for ERBeamDetPID!" << FairLogger::endl;
49  }
50  // Get input array
51  FairRootManager* ioman = FairRootManager::Instance();
52  if ( ! ioman ) Fatal("Init", "No FairRootManager");
53 
54  fBeamDetToFDigi1 = (TClonesArray*) ioman->GetObject("BeamDetToFDigi1");
55  fBeamDetToFDigi2 = (TClonesArray*) ioman->GetObject("BeamDetToFDigi2");
56  fBeamDetTrack = (TClonesArray*) ioman->GetObject("BeamDetTrack");
57 
58  fProjectile = new TClonesArray("ERBeamDetParticle", consts::approx_beamdet_particle_number);
59 
60  // Register output object fProjectile
61 
62  ioman->Register("BeamDetParticle.", "BeamDet Particle", fProjectile, kTRUE);
63 
64  fBeamDetSetup = ERBeamDetSetup::Instance();
65  fBeamDetSetup->SetParContainers();
66  fBeamDetSetup->GetGeoParamsFromParContainer();
67 }
68 //--------------------------------------------------------------------------------------------------
69 void ERBeamDetPID::Exec(Option_t* opt) {
70  LOG(DEBUG) << "[ERBeamDetPID]---------------------Started-----------------------------------------"
71  << FairLogger::endl;
72  Reset();
73  if (!fBeamDetTrack->At(0) || !fBeamDetToFDigi1->At(0) || !fBeamDetToFDigi2->At(0)) {
74  LOG(DEBUG) << "[ERBeamDetPID] No track" << FairLogger::endl;
75  //fRun->MarkFill(kFALSE);
76  return;
77  }
78  Double_t ToF1, ToF2, ToF;
79  Double_t dE1, dE2, dE;
80  Double_t probability;
81  Double_t beta;
82  Double_t gamma;
83  Double_t p, energy;
84  ERDigi* digi;
85  digi = (ERDigi*)fBeamDetToFDigi1->At(0);
86  ToF1 = digi->Time();
87  dE1 = digi->Edep();
88  LOG(DEBUG) << "[ERBeamDetPID] dE1 = " << dE1 << " ToF1 = " << ToF1 << FairLogger::endl;
89  digi = (ERDigi*)fBeamDetToFDigi2->At(0);
90  ToF2 = digi->Time();
91  dE2 = digi->Edep();
92  LOG(DEBUG) << "[ERBeamDetPID] dE2 = " << dE2 << " ToF2 = " << ToF2 << FairLogger::endl;
93  dE = dE1 + dE2;
94  LOG(DEBUG) << "[ERBeamDetPID] dE = " << dE << " MeV; " << " ToF1 = " << ToF1 << " ns;"
95  << " ToF2 = " << ToF2 << " ns;" << FairLogger::endl;
96  ToF = TMath::Abs(ToF2 - ToF1) + fOffsetToF;
97  LOG(DEBUG) << "[ERBeamDetPID] dE = " << dE << " MeV; " << " ToF = " << ToF << " ns;"
98  << FairLogger::endl;
99  if(ToF <= fToF1 || ToF >= fToF2 || dE <= fdE1 || dE >= fdE2){
100  probability = 0;
101  }
102  else {
103  probability = 1;
104  }
105  if(probability < fProbabilityThreshold) {
106  LOG(DEBUG) << "[ERBeamDetPID] Probability " << probability << " less then threshold "
107  << fProbabilityThreshold << FairLogger::endl;
108  //fRun->MarkFill(kFALSE);
109  return ;
110  }
111  LOG(DEBUG) << "[ERBeamDetPID] Mass " << fIonMass << FairLogger::endl;
112  float distanceBetweenToF = fBeamDetSetup->GetDistanceBetweenToF(0, fBeamDetSetup->GetToFCount() - 1);
113  beta = distanceBetweenToF * 1e-2 / (ToF * 1e-9) / TMath::C();
114  if(beta <= 0 || beta >= 1) {
115  LOG(DEBUG) << "[ERBeamDetPID] Wrong beta " << beta << FairLogger::endl;
116  //fRun->MarkFill(kFALSE);
117  return ;
118  }
119  gamma = 1. / TMath::Sqrt(1.- beta*beta);
120  p = beta * gamma * fIonMass;
121  float px, py, pz;
122  auto* track = dynamic_cast<ERBeamDetTrack*>(fBeamDetTrack->At(0));
123  px = p * TMath::Sin(track->GetVector().Theta()) * TMath::Cos(track->GetVector().Phi());
124  py = p * TMath::Sin(track->GetVector().Theta()) * TMath::Sin(track->GetVector().Phi());
125  pz = p * TMath::Cos(track->GetVector().Theta());
126  energy = fIonMass * gamma;
127  LOG(DEBUG) << "[ERBeamDetPID] TOF State:: PID: " << fPID << "; px: " << px << "; py: " << py
128  << "; pz: " << pz << " energy: " << energy << "; probability " << probability
129  << FairLogger::endl;
130  //eloss calculation, T-kinetic energy on target
131  auto T_and_time_on_target = CalcEkinAndTimeOnTarget(*track, fPID , p, fIonMass, ToF2);
132  float T = T_and_time_on_target.first;
133  float time_on_target = T_and_time_on_target.second;
134  float pt, ptx, pty, ptz, et;
135  pt = TMath::Sqrt(T * T + 2. * T * fIonMass);
136  ptx = pt * TMath::Sin(track->GetVector().Theta()) * TMath::Cos(track->GetVector().Phi());
137  pty = pt * TMath::Sin(track->GetVector().Theta()) * TMath::Sin(track->GetVector().Phi());
138  ptz = pt * TMath::Cos(track->GetVector().Theta());
139  et = fIonMass + T;
140  LOG(DEBUG) << "[ERBeamDetPID] Target State:: px: " << ptx << "; py: " << pty << "; pz: " << ptz
141  << " energy: " << et << FairLogger::endl;
142  AddParticle(fPID, TLorentzVector(px, py, pz, energy), TLorentzVector(ptx,pty,ptz,et),
143  time_on_target, probability);
144  LOG(DEBUG) << "[ERBeamDetPID]---------------------Finished----------------------------------------"
145  << FairLogger::endl;
146 }
147 //--------------------------------------------------------------------------------------------------
148 std::pair<float, float> ERBeamDetPID::CalcEkinAndTimeOnTarget(ERBeamDetTrack& track, int pid, float mom,
149  float mass, float time_on_tof5){
150  FairRun* run = FairRun::Instance();
151  if (!TString(run->ClassName()).Contains("ERRunAna"))
152  LOG(FATAL) << "[ERBeamDet] Use ERRunAna for ERBeamDetPID!!!" << FairLogger::endl;
153  //calculation ion energy loss in BeamDet volumes
154  const TVector3 target_vertex = track.GetTargetVertex();
155  LOG(DEBUG) << "[ERBeamDet][CalcEkinAndTimeOnTarget] Eloss calculation with target vertex = (" << target_vertex.X()
156  << "," << target_vertex.Y() << "," << target_vertex.Z() << "), direction on target = ("
157  << track.GetVector().X() << "," << track.GetVector().Y() << "," << track.GetVector().Z()
158  << ")" << FairLogger::endl;
159  Float_t z_start = -3000.;//@TODO change to BeamDet start position
160  Float_t x_start = target_vertex.X()
161  + z_start*TMath::Sin(track.GetVector().Theta()) * TMath::Cos(track.GetVector().Phi());
162  Float_t y_start = target_vertex.Y()
163  + z_start*TMath::Sin(track.GetVector().Theta()) * TMath::Sin(track.GetVector().Phi());
164  LOG(DEBUG) << "[ERBeamDet][CalcEkinAndTimeOnTarget] Eloss calculation start vertex = (" << x_start << ","
165  << y_start << "," << z_start << ")" << FairLogger::FairLogger::endl;
166  G4IonTable* ion_table = G4IonTable::GetIonTable();
167  G4ParticleDefinition* ion = ion_table->GetIon(pid);
168  G4NistManager* nist = G4NistManager::Instance();
169  const auto track_direction = track.GetDirection();
170  TGeoNode* node = gGeoManager->InitTrack(x_start, y_start, z_start, track_direction.X(),
171  track_direction.Y(), track_direction.Z());
172  Float_t E = TMath::Sqrt(mom * mom + mass * mass);
173  Float_t T = E - mass;
174  float time_on_target = time_on_tof5;
175  Float_t sumLoss = 0.;
176  Bool_t firstTofAlreadySkipped = kFALSE;
177  bool secondTofPassed = false;
178 
179  while(!gGeoManager->IsOutside()) {
180  TString matName = node->GetMedium()->GetMaterial()->GetName();
181  if (TString(node->GetName()).Contains("anode")) {
182  matName = "CF4";
183  }
184  G4Material* mat = nist->FindOrBuildMaterial(matName.Data());
185  node = gGeoManager->FindNextBoundary();
186  Double_t step = gGeoManager->GetStep();
187  const TVector3 current_position(gGeoManager->GetCurrentPoint());
188  LOG(DEBUG) << "[ERBeamDet][CalcEkinAndTimeOnTarget] track position (" << current_position.X() << ", "
189  << current_position.Y() << ", " << current_position.Z() << ")" << FairLogger::endl;
190  LOG(DEBUG) << "[ERBeamDet][CalcEkinAndTimeOnTarget] path = " << gGeoManager->GetPath()
191  << FairLogger::endl;
192  if (!firstTofAlreadySkipped && TString(gGeoManager->GetPath()).Contains("ToF")) {
193  firstTofAlreadySkipped = kTRUE;
194  node = gGeoManager->Step();
195  continue;
196  }
197  if (step == 0.)
198  break;
199  if (!firstTofAlreadySkipped) {
200  node = gGeoManager->Step();
201  continue;
202  }
203  const double step_to_target_vertex = (target_vertex - current_position).Mag();
204  const bool is_last_step = step_to_target_vertex <= step;
205  step = is_last_step ? step_to_target_vertex : step;
206  Double_t edep = ComputeElossIntegralVolStep(T, *ion, *mat, "ionIoni", step);
207  node = gGeoManager->GetCurrentNode();
208  LOG(DEBUG) <<"[ERBeamDet][CalcEkinAndTimeOnTarget] Kinetic Energy = " << T << " medium " << matName
209  << " step = " << step << " edep = " << edep << FairLogger::endl;
210  if (secondTofPassed) {
211  auto velocity = [mass](float Ekin) {
212  float p = TMath::Sqrt(Ekin * Ekin + 2. * Ekin * mass);
213  const float c = TMath::C();
214  p = p / c;
215  float m = mass / c / c;
216  return p * c / TMath::Sqrt(m * m * c * c + p * p) ;
217  };
218  // TODO: welcome to implement relativistic expression
219  float ave_velocity = (velocity(T) + velocity(T - edep)) / 2.;
220  if (ave_velocity > 0.) {
221  time_on_target += step * 0.01 / ave_velocity * 1e9;
222  LOG(DEBUG) <<"[ERBeamDet][CalcEkinAndTimeOnTarget] Current time = "
223  << time_on_target << " ns " << FairLogger::endl;
224  } else {
225  LOG(WARNING) <<"[ERBeamDet][CalcEkinAndTimeOnTarget] Ion has velocity equals zero."
226  << FairLogger::endl;
227  }
228  }
229  T -= edep;
230  sumLoss += edep;
231  if (!secondTofPassed && TString(gGeoManager->GetPath()).Contains("ToF")) {
232  secondTofPassed = true;
233  }
234  if (is_last_step)
235  break;
236  node = gGeoManager->Step();
237  }
238  if (!firstTofAlreadySkipped) {
239  LOG(WARNING) << "[ERBeamDet][CalcEkinAndTimeOnTarget] First ToF not found." << FairLogger::endl;
240  }
241  if (!secondTofPassed) {
242  LOG(WARNING) << "[ERBeamDet][CalcEkinAndTimeOnTarget] Second ToF not found." << FairLogger::endl;
243  }
244  LOG(DEBUG) <<"[ERBeamDet][CalcEkinAndTimeOnTarget] Sum Eloss = " << sumLoss << FairLogger::endl;
245  return std::make_pair(T, time_on_target);
246 }
247 //--------------------------------------------------------------------------------------------------
249  if (fProjectile) {
250  fProjectile->Clear();
251  }
252 }
253 //--------------------------------------------------------------------------------------------------
255  TDatabasePDG* pdgDB = TDatabasePDG::Instance();
256  TParticlePDG* kProton = pdgDB->GetParticle(2212);
257  Double_t kProtonMass=kProton->Mass();
258  fIonMass = kProtonMass * Double_t(a);
259 }
260 //--------------------------------------------------------------------------------------------------
261 ERBeamDetParticle* ERBeamDetPID::AddParticle(Int_t pid, TLorentzVector tofState,
262  TLorentzVector targetState, float time_on_target,
263  float probability){
264  return new((*fProjectile)[fProjectile->GetEntriesFast()])
265  ERBeamDetParticle(pid, tofState, targetState, time_on_target, probability);
266 }
267 //--------------------------------------------------------------------------------------------------
268 ClassImp(ERBeamDetPID)
virtual void Reset()
Resets all output data.
Definition: ERDigi.h:15
Double_t fdE2
ToF summary energy deposit boundaries.
Definition: ERBeamDetPID.h:93
ERBeamDetParticle * AddParticle(Int_t pid, TLorentzVector tofState, TLorentzVector targetState, float time_on_target, float probability)
Adds a ERBeamDetParticle to the output Collection.
TClonesArray * fBeamDetTrack
input collection of tracks
Definition: ERBeamDetPID.h:90
ERBeamDetSetup * fBeamDetSetup
access to ERBeamDetSetup class instance
Definition: ERBeamDetPID.h:86
virtual InitStatus Init()
Definition: ERTask.cxx:31
Double_t fIonMass
ion mass
Definition: ERBeamDetPID.h:95
TClonesArray * fBeamDetToFDigi1
input collection of ToF first plastic points
Definition: ERBeamDetPID.h:88
Double_t fProbabilityThreshold
probability threshold
Definition: ERBeamDetPID.h:96
void SetIonMassNumber(Int_t a)
Sets ion mass number.
Int_t fPID
ion PDG
Definition: ERBeamDetPID.h:91
TClonesArray * fProjectile
output projectile collection
Definition: ERBeamDetPID.h:99
virtual InitStatus Init()
Defines all input and output object colletions participate in particle identification.
Class for particle identification.
Definition: ERBeamDetPID.h:33
std::vector< TString > fAvailibleRunManagers
Run managers that are availible for this task.
Definition: ERTask.h:64
Double_t fOffsetToF
ToF calibration parameter.
Definition: ERBeamDetPID.h:94
Base abstract class for all tasks in er.
Definition: ERTask.h:27
Double_t fToF2
ToF selection boundaries.
Definition: ERBeamDetPID.h:92
ERBeamDetPID()
Default constructor.
TClonesArray * fBeamDetToFDigi2
input collection of ToF second plastic points
Definition: ERBeamDetPID.h:89
void SetBoxPID(Double_t tof1, Double_t tof2, Double_t dE1, Double_t dE2)
Sets selection box area on the ToF/dE scatter plot.
virtual void Exec(Option_t *opt)
Defines selection and calculetion of parameters for each event: Four-vector is determined by equati...