ARTEMIS-CRIB
 
Loading...
Searching...
No Matches
TDetectParticleProcessor.cc
Go to the documentation of this file.
1/**
2 * @file TDetectParticleProcessor.cc
3 * @brief
4 * @author Kodai Okawa <okawa@cns.s.u-tokyo.ac.jp>
5 * @date 2024-01-18 14:36:43
6 * @note last modified: 2024-09-18 15:57:31
7 * @details
8 */
9
11
15#include "TParticleInfo.h"
16#include <Mass.h> // TSrim library
17#include <TRandom.h>
18
20
22
24 : fInData(nullptr), fInTrackData(nullptr), fOutData(nullptr), fInGeom(nullptr),
25 fDetectorPrm(nullptr), fTargetPrm(nullptr), srim(nullptr) {
26 RegisterInputCollection("InputCollection", "input branch (collection) name", fInputColName, TString("ions"));
27 RegisterInputCollection("InputTrackCollection", "input track branch (collection) name", fInputTrackColName, TString("track"));
28 RegisterOutputCollection("OutputCollection", "output branch (collection) name", fOutputColName,
29 TString("reaction_particles"));
30
31 RegisterProcessorParameter("TargetIsGas", "Bool, target is targer or not", fTargetIsGas, false);
32 RegisterProcessorParameter("TargetName", "gas target name", fTargetName, TString(""));
33 RegisterProcessorParameter("TargetPressure", "Target presure", fTargetPressure, 0.0);
34
35 DoubleVec_t init_d_vec;
36 RegisterProcessorParameter("EnergyResolution", "energy resolution MeV unit", fEResolution, init_d_vec);
37 RegisterProcessorParameter("TimingResolution", "timing resolution ns unit", fTResolution, init_d_vec);
38
39 RegisterOptionalInputInfo("DetectorParameter", "name of telescope parameter", fDetectorParameterName,
40 TString("prm_detectors"), &fDetectorPrm, "TClonesArray", "art::crib::TDetectorParameter");
41 /// currently not use this object
42 RegisterOptionalInputInfo("TargetParameter", "name of target parameter", fTargetParameterName,
43 TString("prm_targets"), &fTargetPrm, "TClonesArray", "art::crib::TTargetParameter");
44}
45
47 delete fOutData;
48 delete srim;
49 fOutData = nullptr;
50 srim = nullptr;
51}
52
53void TDetectParticleProcessor::Init(TEventCollection *col) {
54 fInGeom = reinterpret_cast<TGeoManager **>(col->GetObjectRef("geom"));
55 if (!fInGeom) {
56 SetStateError("gate array not found. Run TUserGeoInitializer before this.");
57 return;
58 }
59
60 Info("Init", "%s => %s", fInputColName.Data(), fOutputColName.Data());
61
62 fInData = reinterpret_cast<TClonesArray **>(col->GetObjectRef(fInputColName.Data()));
63 if (!fInData) {
64 SetStateError(Form("input not found: %s", fInputColName.Data()));
65 return;
66 }
67 const TClass *const cl1 = (*fInData)->GetClass();
68 if (!cl1->InheritsFrom(art::crib::TParticleInfo::Class())) {
69 SetStateError("contents of input array must inherit from art::crib::TParticleInfo");
70 return;
71 }
72 fInTrackData = reinterpret_cast<TClonesArray **>(col->GetObjectRef(fInputTrackColName.Data()));
73 if (!fInTrackData) {
74 SetStateError(Form("input not found: %s", fInputTrackColName.Data()));
75 return;
76 }
77 const TClass *const cl2 = (*fInTrackData)->GetClass();
78 if (!cl2->InheritsFrom(art::TTrack::Class())) {
79 SetStateError("contents of input array must inherit from art::TTrack");
80 return;
81 }
82
83 if (!fDetectorPrm) {
84 SetStateError(Form("not found detector parameter object %s", fDetectorParameterName.Data()));
85 return;
86 }
87 auto det_num = (*fDetectorPrm)->GetEntriesFast();
88 Info("Init", "set %d number of detectors", det_num);
89
90 // currently not used
91 // if (!fTargetPrm) {
92 // SetStateError(Form("not found target parameter object %s", fTargetParameterName.Data()));
93 // }
94
95 if (fEResolution.size() == 1) { /// same energy resolution for all detector
96 for (Int_t iDet = 0; iDet < det_num - 1; iDet++) {
97 fEResolution.emplace_back(fEResolution[0]);
98 }
99 } else if (fEResolution.size() == 0) { /// ignore energy resolution
100 for (Int_t iDet = 0; iDet < det_num; iDet++) {
101 fEResolution.emplace_back(0.0);
102 }
103 } else if ((Int_t)fEResolution.size() != det_num) {
104 SetStateError(Form("Resolution parameter size is wrong, should be %d, but %ld",
105 (*fDetectorPrm)->GetEntriesFast(), fEResolution.size()));
106 return;
107 }
108
109 if (fTResolution.size() == 1) { /// same timing resolution for all detector
110 for (Int_t iDet = 0; iDet < det_num - 1; iDet++) {
111 fTResolution.emplace_back(fTResolution[0]);
112 }
113 } else if (fTResolution.size() == 0) { /// ignore energy resolution
114 for (Int_t iDet = 0; iDet < det_num; iDet++) {
115 fTResolution.emplace_back(0.0);
116 }
117 } else if ((Int_t)fTResolution.size() != det_num) {
118 SetStateError(Form("Resolution parameter size is wrong, should be %d, but %ld",
119 (*fDetectorPrm)->GetEntriesFast(), fTResolution.size()));
120 return;
121 }
122
123 fOutData = new TClonesArray("art::crib::TTelescopeData");
124 fOutData->SetName(fOutputColName);
125 col->Add(fOutputColName, fOutData, fOutputIsTransparent);
126
127 /// initialization for TSrim
128 const char *tsrim_path = std::getenv("TSRIM_DATA_HOME");
129 if (!tsrim_path) {
130 SetStateError("TSRIM_DATA_HOME environment variable is not defined");
131 return;
132 }
133 // get All SRIM table for the target
134 Info("Init", "Initializing SRIM table...");
135 srim = new TSrim("srim", 16,
136 Form("%s/%s/range_fit_pol16_%s.txt", tsrim_path, fTargetName.Data(), fTargetName.Data()));
137 Info("Init", "\t\"%s\" list loaded.", fTargetName.Data());
138
139 StringVec_t material_names;
140 for (auto i = 0; i < det_num; i++) {
141 auto detprm = dynamic_cast<TDetectorParameter *>((*fDetectorPrm)->At(i));
142 for (auto j = 0; j < detprm->GetN(); j++) {
143 material_names.emplace_back(detprm->GetMaterial(j));
144 }
145 }
146 StringVec_t unique_names = GetUniqueElements(material_names);
147 for (const auto &str : unique_names) {
148 srim->AddElement("srim", 16, Form("%s/%s/range_fit_pol16_%s.txt", tsrim_path, str.Data(), str.Data()));
149 }
150
151 gRandom->SetSeed(time(nullptr));
152}
153
155 fOutData->Clear("C");
156 TGeoManager *geom = static_cast<TGeoManager *>(*fInGeom);
157
158 for (Int_t iData = 0; iData < (*fInData)->GetEntriesFast(); ++iData) {
159 const TDataObject *const inData = static_cast<TDataObject *>((*fInData)->At(iData));
160 const TParticleInfo *const Data = dynamic_cast<const TParticleInfo *>(inData);
161
162 TTelescopeData *outData = static_cast<TTelescopeData *>(fOutData->ConstructedAt(iData));
163 outData->SetID(iData);
164
165 Double_t energy = Data->GetEnergy();
166 if (energy < 0.01) {
167 continue; // stop in the target
168 }
169
170 Double_t current_z = Data->GetCurrentZ();
171 TTrack track = Data->GetTrack();
172 TVector3 first_position(track.GetX(current_z), track.GetY(current_z), current_z);
173 TVector3 velocity = (Data->GetLorentzVector()).Vect().Unit();
174
175 // check if beam particle hits the detector
176 geom->SetCurrentPoint(first_position.X(), first_position.Y(), first_position.Z());
177 geom->SetCurrentDirection(velocity.X(), velocity.Y(), velocity.Z());
178
179 // exclude TOP boundary
180 geom->GetCurrentNode();
181 geom->FindNode();
182
183 // geom->FindNextBoundary(10000.0); // need to set some values??
184 geom->FindNextBoundary();
185 Double_t distance = geom->GetStep();
186 geom->Step();
187 Bool_t isHit = geom->IsStepEntering();
188 if (!isHit) {
189 continue;
190 }
191
192 TString hitname = geom->GetPath(); // ex. hitname = /TOP_1/tel1_0, /TOP_1/tel4_3
193 auto index_hitpath = hitname.Last('_');
194 TString det_id = hitname(index_hitpath + 1, hitname.Length()); // get last number /TOP_1/tel1_0 -> 0
195 if (hitname.Length() < 8 || det_id.Atoi() >= (*fDetectorPrm)->GetEntriesFast()) {
196 // /TOP_1/ -> length = 7
197 continue;
198 }
199
200 if (fTargetIsGas) {
201 energy = srim->EnergyNew(Data->GetAtomicNumber(), Data->GetMassNumber(), energy,
202 std::string(fTargetName.Data()), distance, fTargetPressure, 300.0);
203 if (energy < 0.01) {
204 continue; // stop in the target
205 }
206 }
207
208 outData->SetTelID(det_id.Atoi() + 1); /// 1 start (not 0)
209 TVector3 det_position(distance * velocity.X(), distance * velocity.Y(), distance * velocity.Z());
210 det_position += first_position;
211 outData->SetPosition(det_position);
212
213 TParameterObject *inPrm = static_cast<TParameterObject *>((*fDetectorPrm)->At(det_id.Atoi()));
214 TDetectorParameter *Prm = dynamic_cast<TDetectorParameter *>(inPrm);
215 outData->SetN(Prm->GetN());
216
217 det_position -= TVector3(Prm->GetCenterRotPos(0), Prm->GetCenterRotPos(1), Prm->GetCenterRotPos(2));
218 det_position.RotateY(-Prm->GetAngle());
219
220 outData->SetXID(GetStripID(det_position.X(), Prm->GetStripNum(0), Prm->GetSize(0)));
221 outData->SetYID(GetStripID(det_position.Y(), Prm->GetStripNum(1), Prm->GetSize(1)));
222 if (outData->GetXID() == -1 || outData->GetYID() == -1) {
223 continue; /// hit from side, so not caliculate energy
224 }
225
226 // calculate TOF
227 Double_t ion_mass = amdc::Mass(Data->GetAtomicNumber(), Data->GetMassNumber()) * amdc::amu; // MeV
228 Double_t duration = distance / (TMath::Sqrt(1.0 - TMath::Power(ion_mass / (ion_mass + energy), 2.0)) * c); // ns
229 duration += Data->GetDurationTime();
230 outData->PushTimingArray(gRandom->Gaus(duration, fTResolution[det_id.Atoi()]));
231
232 // caliculate energy
233 Double_t energy_total = 0.0;
234 for (auto iMat = 0; iMat < Prm->GetN(); iMat++) {
235 if (energy > 0.01) {
236 Double_t new_energy = srim->EnergyNew(Data->GetAtomicNumber(), Data->GetMassNumber(), energy,
237 std::string((Prm->GetMaterial(iMat)).Data()), Prm->GetThickness(iMat));
238 energy_total += energy - new_energy;
239 outData->PushEnergyArray(energy - new_energy);
240 energy = new_energy;
241 } else {
242 outData->PushEnergyArray(0.0);
243 }
244 }
245 outData->SetEtotal(gRandom->Gaus(energy_total, fEResolution[det_id.Atoi()]));
246
247 // caliculate LAB angle
248 const TDataObject *const inTrackData = static_cast<TDataObject *>((*fInTrackData)->At(0));
249 const TTrack *const TrackData = dynamic_cast<const TTrack *>(inTrackData);
250 TVector3 beam(TrackData->GetX(1.0) - TrackData->GetX(0.0), TrackData->GetY(1.0) - TrackData->GetY(0.0), 1.0);
251 Double_t theta = beam.Angle(velocity);
252 outData->SetTheta_L(theta * TMath::RadToDeg());
253 }
254}
255
256std::vector<TString> TDetectParticleProcessor::GetUniqueElements(const std::vector<TString> &input) {
257 std::unordered_set<std::string> uniqueSet;
258 std::vector<TString> result;
259
260 for (const auto &tstr : input) {
261 std::string str(tstr.Data());
262 if (uniqueSet.find(str) == uniqueSet.end()) {
263 uniqueSet.insert(str);
264 result.emplace_back(tstr);
265 }
266 }
267 return result;
268}
269
270Int_t TDetectParticleProcessor::GetStripID(Double_t pos, Int_t max_strip, Double_t size) {
271 Int_t result = -1;
272 for (Int_t i = 0; i < max_strip; i++) {
273 if (size * ((Double_t)i / max_strip - 0.5) < pos && pos < size * ((Double_t)(i + 1) / max_strip - 0.5)) {
274 result = i;
275 break;
276 }
277 }
278 // if(result == -1) std::cout << "warning, stripID is incorrect" << std::endl;
279 return result;
280}
281
282// ===========================================
283// kinematics
284// tof
285// beta = v/c
286// E = m/sqrt(1-beta^2)
287// v = sqrt(1-(M/E)^2) c
ClassImp(TDetectParticleProcessor)
particle information class
DoubleVec_t fTResolution
x 100 = %, index=telescope id
void Init(TEventCollection *col) override
Int_t GetStripID(Double_t pos, Int_t max_strip, Double_t size)
std::vector< TString > GetUniqueElements(const std::vector< TString > &input)
TSrim * srim
x 100 = %, index=telescope id
Double_t GetCenterRotPos(Int_t id) const
Int_t GetStripNum(Int_t id) const
Double_t GetThickness(Int_t id) const
TString GetMaterial(Int_t id) const
Double_t GetSize(Int_t id) const
Double_t GetCurrentZ() const
TLorentzVector GetLorentzVector() const
Int_t GetAtomicNumber() const
Double_t GetEnergy() const
Int_t GetMassNumber() const
Double_t GetDurationTime() const
void SetPosition(TVector3 vec)
void SetTheta_L(Double_t arg)
void PushEnergyArray(Double_t arg)
void PushTimingArray(Double_t arg)
void SetEtotal(Double_t arg)
return to the guide