ARTEMIS-CRIB
 
Loading...
Searching...
No Matches
TTelescopeProcessor.cc
Go to the documentation of this file.
1/**
2 * @file TTelescopeProcessor.cc
3 * @brief gather the telescope information to the one object
4 * @author Kodai Okawa<okawa@cns.s.u-tokyo.ac.jp>
5 * @date 2024-01-17 17:52:58
6 * @note last modified: 2024-08-23 21:05:12
7 * @details treat the largest value of each layor
8 * the data of X side is used for DSSSD
9 * assume beam position (0, 0) and direction (0, 0, 1)
10 * NEED OutputColName == prm/geo detector name
11 */
12
13#include "TTelescopeProcessor.h"
14
17#include "TTelescopeData.h"
18#include "TTimingChargeData.h"
19#include <TRandom.h>
20
22
24
25// Default constructor
27 : fInData1(nullptr), fInData2(nullptr), fInData3(nullptr), fOutData(nullptr), fTelID(0) {
28 RegisterInputCollection("InputCollection1",
29 "array of objects inheriting from art::TTimingChargeData",
30 fInputColName1, TString("dEX"));
31 RegisterInputCollection("InputCollection2",
32 "array of objects inheriting from art::TTimingChargeData",
33 fInputColName2, TString("dEY"));
34 RegisterInputCollection("InputCollection3",
35 "array of objects inheriting from art::TTimingChargeData",
36 fInputColName3, TString("E"));
37 RegisterOutputCollection("OutputCollection", "output class will be art::crib::TTelescopeData",
38 fOutputColName, TString("telescope"));
39
40 RegisterProcessorParameter("IsDSSSD", "Bool, true: first layer is DSSSD, false: first and second layer is SSSSD", fIsDSSSD, true);
41 RegisterProcessorParameter("UseRandom", "Bool, true: Uniform distribution in one pixel, false: center of the pixel", fUseRandom, false);
42
43 RegisterOptionalInputInfo("DetectorParameter", "name of detector parameter defined in TUserGeoInitializer", fDetPrmName,
44 TString("prm_detectors"), &fDetParameters, "TClonesArray", "art::crib::TDetectorParameter");
45 RegisterOptionalInputInfo("TargetParameter", "name of target parameter defined in TUserGeoInitializer", fTargetPrmName,
46 TString("prm_targets"), &fTargetParameters, "TClonesArray", "art::crib::TTargetParameter");
47}
48
53
54void TTelescopeProcessor::Init(TEventCollection *col) {
55 Info("Init", "%s %s %s => %s", fInputColName1.Data(), fInputColName2.Data(), fInputColName3.Data(), fOutputColName.Data());
56
57 // check if X strip SSD object exist or not
58 fInData1 = reinterpret_cast<TClonesArray **>(col->GetObjectRef(fInputColName1.Data()));
59 if (!fInData1) {
60 SetStateError(TString::Format("input not found: %s", fInputColName1.Data()));
61 return;
62 }
63
64 // check if Y strip SSD object exist or not
65 fInData2 = reinterpret_cast<TClonesArray **>(col->GetObjectRef(fInputColName2.Data()));
66 if (!fInData2) {
67 SetStateError(TString::Format("input not found: %s", fInputColName2.Data()));
68 return;
69 }
70
71 // check if thick SSDs object exist or not
72 fInData3 = reinterpret_cast<TClonesArray **>(col->GetObjectRef(fInputColName3.Data()));
73 if (!fInData3) {
74 SetStateError(TString::Format("input not found: %s", fInputColName3.Data()));
75 return;
76 }
77
78 // detector parameter
79 if (!fDetParameters) {
80 fHasDetPrm = false;
81 } else {
82 fHasDetPrm = true;
83 for (Int_t iDet = 0; iDet < (*fDetParameters)->GetEntriesFast(); iDet++) {
84 TParameterObject *inPrm = static_cast<TParameterObject *>((*fDetParameters)->At(iDet));
85 TDetectorParameter *prm = dynamic_cast<TDetectorParameter *>(inPrm);
86 if (prm->GetDetName() == fOutputColName) {
87 fTelID = iDet + 1;
88 fDetParameter = prm;
89 }
90 }
91 if (fTelID == 0) {
92 Warning("Init", "cannot find %s node, please check TUserGeoInitializer", fOutputColName.Data());
93 fHasDetPrm = false;
94 }
95 }
96
97 // target parameter
98 if (!fTargetParameters) {
99 fHasTargetPrm = false;
100 } else {
101 fHasTargetPrm = true;
102 if ((*fTargetParameters)->GetEntriesFast() == 0) {
103 Warning("Init", "cannot find target node. please check TUserGeoInitializer");
104 fHasTargetPrm = false;
105 } else {
106 // use the first target node
107 TParameterObject *inPrm = static_cast<TParameterObject *>((*fTargetParameters)->At(0));
108 TTargetParameter *prm = dynamic_cast<TTargetParameter *>(inPrm);
109 fTargetParameter = prm;
110 Info("Init", "use first target %s information (only use the position)", prm->GetTargetName().Data());
111 }
112 }
113
114 if (!fHasDetPrm || !fHasTargetPrm) {
115 Warning("Init", "not initialized by TUserGeoInitializer, not calculate geometry info");
116 }
117
118 // check if input collection is valid or not
119 const TClass *const cl1 = (*fInData1)->GetClass();
120 const TClass *const cl2 = (*fInData2)->GetClass();
121 const TClass *const cl3 = (*fInData3)->GetClass();
122 fInputHasData = (cl1->InheritsFrom(art::TTimingChargeData::Class())) && (cl2->InheritsFrom(art::TTimingChargeData::Class())) && (cl3->InheritsFrom(art::TTimingChargeData::Class()));
123
124 if (!fInputHasData) {
125 SetStateError("contents of input array must inherit from art::TTimingChargeData");
126 return;
127 }
128
129 fOutData = new TClonesArray("art::crib::TTelescopeData");
130 fOutData->SetName(fOutputColName);
131 col->Add(fOutputColName, fOutData, fOutputIsTransparent);
132
133 gRandom->SetSeed(time(nullptr));
134}
135
137 fOutData->Clear("C");
138
139 Int_t nData1 = (*fInData1)->GetEntriesFast();
140 Int_t nData2 = (*fInData2)->GetEntriesFast();
141 Int_t nData3 = (*fInData3)->GetEntriesFast();
142
143 // if no hit, do nothing
144 if (nData1 == 0 && nData2 == 0 && nData3 == 0) {
145 return;
146 }
147
148 TTelescopeData *outData = static_cast<TTelescopeData *>(fOutData->ConstructedAt(0));
149 outData->Clear();
150 outData->SetID(0); // always 0
151 outData->SetTelID(fTelID);
152 if (fHasDetPrm && fHasTargetPrm) {
153 outData->SetN(fDetParameter->GetN());
154 } else {
156 }
157
158 Double_t Etotal = 0.0;
159 Double_t dE = 0.0;
160
161 // dEX process
162 // search the highest channel
163 Int_t dEXID = -1;
164 Double_t dEX_tmp = 0.0;
165 for (Int_t iData1 = 0; iData1 < nData1; ++iData1) {
166 const TDataObject *const inData1 = static_cast<TDataObject *>((*fInData1)->At(iData1));
167 const TTimingChargeData *const Data1 = dynamic_cast<const TTimingChargeData *>(inData1);
168 /// need to update: care about overflow event more clevar
169 if (dEX_tmp < Data1->GetCharge() && Data1->GetCharge() < 50.0) { // overflow signal should have very large value
170 dEXID = iData1;
171 dEX_tmp = Data1->GetCharge();
172 }
173 }
174
175 // fill the highest channel
176 if (nData1 != 0 && dEXID != -1) {
177 const TDataObject *const inData1 = static_cast<TDataObject *>((*fInData1)->At(dEXID));
178 const TTimingChargeData *const Data1 = dynamic_cast<const TTimingChargeData *>(inData1);
179 Double_t energy = Data1->GetCharge();
180 Double_t timing = Data1->GetTiming();
181
182 // judge if the event is pedestal or not
183 if (fHasDetPrm) {
184 if (energy < fDetParameter->GetPedestal(0)) { // first layer
185 energy = 0.0;
186 }
187 }
188
189 outData->SetXID(Data1->GetDetID());
190 if (fIsDSSSD) {
191 outData->SetdE(energy); // now fdE is used the value of dEX
192 } else {
193 dE += energy;
194 }
195 outData->SetdEX(energy);
196 outData->SetTelXTiming(timing);
197 outData->PushEnergyArray(energy);
198 outData->PushTimingArray(timing);
199 Etotal += energy;
200 } else {
201 outData->PushEnergyArray(0.0);
202 outData->PushTimingArray(kInvalidD);
203 }
204
205 // dEY process
206 // search the highest channel
207 Int_t dEYID = -1;
208 Double_t dEY_tmp = 0.0;
209 for (Int_t iData2 = 0; iData2 < nData2; ++iData2) {
210 const TDataObject *const inData2 = static_cast<TDataObject *>((*fInData2)->At(iData2));
211 const TTimingChargeData *const Data2 = dynamic_cast<const TTimingChargeData *>(inData2);
212 /// need to update: care about overflow event more clevar
213 if (dEY_tmp < Data2->GetCharge() && Data2->GetCharge() < 50.0) { // overflow signal should have very large value
214 dEYID = iData2;
215 dEY_tmp = Data2->GetCharge();
216 }
217 }
218
219 // fill the highest channel
220 if (nData2 != 0 && dEYID != -1) {
221 const TDataObject *const inData2 = static_cast<TDataObject *>((*fInData2)->At(dEYID));
222 const TTimingChargeData *const Data2 = dynamic_cast<const TTimingChargeData *>(inData2);
223 Double_t energy = Data2->GetCharge();
224 Double_t timing = Data2->GetTiming();
225
226 // judge if this event is pedestal or not
227 if (fHasDetPrm) {
228 if (fIsDSSSD) {
229 if (energy < fDetParameter->GetPedestal(0)) { // first layer
230 energy = 0.0;
231 }
232 } else {
233 if (energy < fDetParameter->GetPedestal(1)) { // second layer
234 energy = 0.0;
235 }
236 }
237 }
238
239 outData->SetYID(Data2->GetDetID());
240 if (!fIsDSSSD) {
241 dE += energy;
242 outData->SetdE(dE);
243 outData->PushEnergyArray(energy);
244 outData->PushTimingArray(timing);
245 Etotal += energy;
246 }
247 outData->SetdEY(energy);
248 outData->SetTelYTiming(timing);
249 } else if (!fIsDSSSD) {
250 outData->PushEnergyArray(0.0);
251 outData->PushTimingArray(kInvalidD);
252 }
253
254 // geometry process
255 /// for the definition, please check https://okawak.github.io/artemis_crib/example/simulation/geometry/index.html
256 if (IsValid(outData->GetXID()) && IsValid(outData->GetYID()) && fHasDetPrm && fHasTargetPrm) {
257 Double_t target_z = fTargetParameter->GetZ();
260 DoubleVec_t size = fDetParameter->GetSize();
261 IntVec_t stripN = fDetParameter->GetStripNum();
262 Int_t xid = outData->GetXID();
263 Int_t yid = outData->GetYID();
264
265 // (x, y) position before rotation
266 Double_t x = size[0] * (2.0 * (Double_t)xid + 1.0 - (Double_t)stripN[0]) / (2.0 * (Double_t)stripN[0]);
267 if (fUseRandom) {
268 x += gRandom->Uniform(-size[0] / (2.0 * (Double_t)stripN[0]), size[0] / (2.0 * (Double_t)stripN[0]));
269 }
270 Double_t y = size[1] * (2.0 * (Double_t)yid + 1.0 - (Double_t)stripN[1]) / (2.0 * (Double_t)stripN[1]);
271 if (fUseRandom) {
272 y += gRandom->Uniform(-size[1] / (2.0 * (Double_t)stripN[1]), size[1] / (2.0 * (Double_t)stripN[1]));
273 }
274
275 // rotate the detector
276 TVector3 det_pos(x, y, fDetParameter->GetDistance());
277 det_pos += offset;
278 det_pos.RotateY(fDetParameter->GetAngle()); // radian
279 det_pos += center_rot;
280 outData->SetPosition(det_pos);
281
282 TVector3 target(0., 0., target_z);
283 TVector3 beam(0., 0., 1.); // assume beam center!
284 Double_t theta = beam.Angle(det_pos - target);
285 outData->SetTheta_L(theta * TMath::RadToDeg());
286 }
287
288 // Thick SSDs process
289 Double_t E = 0.0;
290 Int_t NE;
291 if (fHasDetPrm && fHasTargetPrm) {
292 NE = fIsDSSSD ? fDetParameter->GetN() - 1 : fDetParameter->GetN() - 2;
293 } else {
295 }
296 Int_t index = fIsDSSSD ? 1 : 2;
297
298 if (NE < nData3) {
299 Warning("process", "Thick SSD number is wrong between actual data and define in get/expname.yaml");
300 }
301
302 for (Int_t iE = 0; iE < NE; iE++) {
303 Int_t itr = -1;
304 // get "iE" index object
305 /// in case single-pad SSD don't have data
306 for (Int_t iData3 = 0; iData3 < nData3; ++iData3) {
307 const TDataObject *const inData3 = static_cast<TDataObject *>((*fInData3)->At(iData3));
308 const TTimingChargeData *const Data3 = dynamic_cast<const TTimingChargeData *>(inData3);
309 if (Data3->GetDetID() == iE) {
310 itr = iData3;
311 break;
312 }
313 }
314
315 if (itr < 0) {
316 outData->PushEnergyArray(0.0);
317 outData->PushTimingArray(kInvalidD);
318 } else {
319 const TDataObject *const inData3 = static_cast<TDataObject *>((*fInData3)->At(itr));
320 const TTimingChargeData *const Data3 = dynamic_cast<const TTimingChargeData *>(inData3);
321 Double_t energy = Data3->GetCharge();
322 Double_t timing = Data3->GetTiming();
323
324 // judge if the event is pedestal or not
325 if (fHasDetPrm) {
326 if (energy < fDetParameter->GetPedestal(index + iE)) {
327 energy = 0.0;
328 }
329 }
330
331 outData->PushEnergyArray(energy);
332 outData->PushTimingArray(timing);
333 E += energy;
334 Etotal += energy;
335 }
336 }
337
338 outData->SetE(E);
339 outData->SetEtotal(Etotal);
340}
ClassImp(TTelescopeProcessor)
Double_t GetCenterRotPos(Int_t id) const
Int_t GetStripNum(Int_t id) const
Double_t GetOffset(Int_t id) const
Double_t GetSize(Int_t id) const
void SetPosition(TVector3 vec)
void SetdEX(Double_t arg)
void SetTelXTiming(Double_t arg)
void Clear(Option_t *opt="") override
void SetE(Double_t arg)
void SetTheta_L(Double_t arg)
void PushEnergyArray(Double_t arg)
void SetdEY(Double_t arg)
void PushTimingArray(Double_t arg)
void SetTelYTiming(Double_t arg)
void SetEtotal(Double_t arg)
void SetdE(Double_t arg)
TDetectorParameter * fDetParameter
all parameter info of TTargetParameter
TTargetParameter * fTargetParameter
one (this telescope) detector parameter
void Init(TEventCollection *col) override
TString fInputColName2
from X strip SSD
TClonesArray * fOutData
TTimingChargeData array from thick SSDs.
static const Int_t DEFAULT_SSD_MAX_NUMBER
TString fOutputColName
from thick SSD array
TClonesArray ** fInData2
TTimingChargeData array from X strip SSD.
TClonesArray ** fInData3
TTimingChargeData array from Y strip SSD.
TClonesArray ** fInData1
output object
TClonesArray ** fTargetParameters
all parameter info of TDetectorParameter
TString fInputColName3
from Y strip SSD
Bool_t fIsDSSSD
TTelescopeData array.
Bool_t fHasDetPrm
one (default index 0) target parameter
return to the guide