GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
TS3.cxx
Go to the documentation of this file.
1#include "TS3.h"
2#include "TMnemonic.h"
3
4#include <cmath>
5#include "TMath.h"
6
7#include "TGRSIOptions.h"
8
9int TS3::fRingNumber = 24;
10int TS3::fSectorNumber = 32;
11
12double TS3::fOffsetPhiCon = 0.5 * TMath::Pi(); // Offset between connector and sector 0 (viewed from sector side)
13double TS3::fOffsetPhiSet =
14 -22.5 * TMath::Pi() / 180.; // Phi rotation of connector in setup // -112.5 for bambino -22.5 for SPICE
15double TS3::fOuterDiameter = 70.;
16double TS3::fInnerDiameter = 22.;
17double TS3::fTargetDistance = 31.;
18
19// Default tigress unpacking settings
20TTransientBits<UShort_t> TS3::fGlobalS3Bits = TTransientBits<UShort_t>(static_cast<std::underlying_type<TS3::ES3GlobalBits>::type>(TS3::ES3GlobalBits::kMultHit));
21
22Int_t TS3::fFrontBackTime = 75;
23double TS3::fFrontBackEnergy = 0.9;
24double TS3::fFrontBackOffset = 0;
25
27{
28 Clear();
29}
30
32{
33 rhs.Copy(*this);
34 return *this;
35}
36
37TS3::TS3(const TS3& rhs) : TDetector(rhs)
38{
39 rhs.Copy(*this);
40}
41
42void TS3::Copy(TObject& rhs) const
43{
44 TDetector::Copy(rhs);
45 static_cast<TS3&>(rhs).fS3RingHits = fS3RingHits;
46 static_cast<TS3&>(rhs).fS3SectorHits = fS3SectorHits;
47 static_cast<TS3&>(rhs).fS3PixelHits = fS3PixelHits;
48}
49
50void TS3::AddFragment(const std::shared_ptr<const TFragment>& frag, TChannel* chan)
51{
52 /// This function creates TS3Hits for each fragment and stores them in separate front and back vectors
53 if(frag == nullptr || chan == nullptr) {
54 return;
55 }
56
57 TS3Hit dethit(*frag); // Moved upstream/downstream switch into hit ctor
58
60 dethit.SetRingNumber(frag->GetSegment());
61 dethit.SetSectorNumber(0);
62
63 if(TGRSIOptions::AnalysisOptions()->IsWaveformFitting()) {
64 dethit.SetWavefit(*frag);
65 }
66
67 fS3RingHits.push_back(std::move(dethit));
68 } else {
69 dethit.SetRingNumber(0);
70 dethit.SetSectorNumber(frag->GetSegment());
71
72 if(TGRSIOptions::AnalysisOptions()->IsWaveformFitting()) {
73 dethit.SetWavefit(*frag);
74 }
75
76 fS3SectorHits.push_back(std::move(dethit));
77 }
78}
79
80void TS3::SetBitNumber(enum ES3Bits bit, Bool_t set)
81{
82 // Used to set the flags that are stored in TS3.
83 fS3Bits.SetBit(bit, set);
84}
85
87{
88 // Creates a vector of TS3Hits based on front/back coincidences
89 // Returns the size of the resultant vector
90
92
93 return fS3PixelHits.size();
94}
95
97{
98 // Constructs the front/back coincidences to create pixels based on energy and time differences
99 // Energy and time differences can be changed using the SetFrontBackEnergy and SetFrontBackTime functions
100 // Shared rings and sectors can be constructed, by default they are not.
101 // To enable shared hits, use SetMultiHit function
102
103 // if the pixels have been reset (or never set), clear the pixel hits //MUST BE FIRST
105 fS3PixelHits.clear();
106 }
107
108 if(fS3RingHits.empty() || fS3SectorHits.empty()) {
109 return;
110 }
111
112 if(fS3PixelHits.empty()) {
113
114 // We are going to want energies several times
115 // So build a quick vector
116 std::vector<double> EneR;
117 std::vector<double> EneS;
118 std::vector<bool> UsedRing;
119 std::vector<bool> UsedSector;
120 for(auto& fS3RingHit : fS3RingHits) {
121 EneR.push_back(fS3RingHit.GetEnergy());
122 UsedRing.push_back(false);
123 }
124 for(auto& fS3SectorHit : fS3SectorHits) {
125 EneS.push_back(fS3SectorHit.GetEnergy());
126 UsedSector.push_back(false);
127 }
128
129 // new
130 /// Loop over two vectors and build energy+time matching hits
131 for(size_t i = 0; i < fS3RingHits.size(); ++i) {
132 for(size_t j = 0; j < fS3SectorHits.size(); ++j) {
133 if(fS3RingHits[i].GetArrayPosition() != fS3SectorHits[j].GetArrayPosition()) { continue; }
134
135 if(abs(fS3RingHits[i].GetTime() - fS3SectorHits[j].GetTime()) * 1.6 < fFrontBackTime) { // check time
136 if((EneR[i] - fFrontBackOffset) * fFrontBackEnergy < EneS[j] &&
137 (EneS[j] - fFrontBackOffset) * fFrontBackEnergy < EneR[i]) { // if time is good check energy
138
139 // Now we have accepted a good event, build it
140 if(SectorPreference()) {
141 TS3Hit dethit = fS3SectorHits[j]; // Sector defines all data ring just gives position
142 dethit.SetRingNumber(fS3RingHits[i].GetRing());
143 fS3PixelHits.push_back(dethit);
144 } else {
145 TS3Hit dethit = fS3RingHits[i]; // Ring defines all data sector just gives position (default)
146 dethit.SetSectorNumber(fS3SectorHits[j].GetSector());
147 fS3PixelHits.push_back(dethit);
148 }
149
150 // Although set to used for MultiHit, continue to check all combinations in this loop.
151 UsedRing[i] = true;
152 UsedSector[j] = true;
153 // This is desired behaviour for telescope, debugging, etc, when one would set fFrontBackEnergy=0 and
154 // build all combinations
155 }
156 }
157 }
158 }
159
160 if(MultiHit()) {
161
162 int ringcount = 0;
163 int sectorcount = 0;
164 for(auto&& i : UsedRing) {
165 if(!i) {
166 ringcount++;
167 }
168 }
169
170 for(auto&& i : UsedSector) {
171 if(!i) {
172 sectorcount++;
173 }
174 }
175
176 /// If we have parts of hit left here they are possibly a shared strip hit not easy singles
177 if(ringcount > 1 || sectorcount > 1) {
178
179 // Shared Ring loop
180 for(size_t i = 0; i < fS3RingHits.size(); ++i) {
181 if(UsedRing.at(i)) {
182 continue;
183 }
184 for(size_t j = 0; j < fS3SectorHits.size(); ++j) {
185 if(UsedSector.at(j)) {
186 continue;
187 }
188 if(fS3RingHits[i].GetArrayPosition() != fS3SectorHits[j].GetArrayPosition()) { continue; }
189
190 for(size_t k = j + 1; k < fS3SectorHits.size(); ++k) {
191 if(UsedSector.at(k)) {
192 continue;
193 }
194 if(fS3SectorHits[j].GetArrayPosition() != fS3SectorHits[k].GetArrayPosition()) { continue; }
195
196 if(abs(fS3RingHits[i].GetTime() - fS3SectorHits[j].GetTime()) * 1.6 < fFrontBackTime &&
197 abs(fS3RingHits[i].GetTime() - fS3SectorHits[k].GetTime()) * 1.6 < fFrontBackTime) { // check time
198 if((EneR[i] - fFrontBackOffset) * fFrontBackEnergy < (EneS[j] + EneS[k]) &&
199 (EneS[j] + EneS[k] - fFrontBackOffset) * fFrontBackEnergy < EneR[i]) { // if time is good check energy
200
201 int SectorSep = fS3SectorHits[j].GetSector() - fS3SectorHits[k].GetSector();
202 if(abs(SectorSep) == 1 || abs(SectorSep) == fSectorNumber) {
203 // Same ring and neighbour sectors, almost certainly charge sharing
204 // Experiments with breakup might get real mult2 events like this but most will be
205 // charge
206 // sharing
207
208 if(KeepShared()) {
209 TS3Hit dethit = fS3RingHits[i]; // Ring defines all data sector just gives position
210 // Selecting one of the sectors is currently the best class allows, some loss of
211 // position information
212 if(fS3SectorHits[k].GetEnergy() < fS3SectorHits[j].GetEnergy()) {
213 dethit.SetSectorNumber(fS3SectorHits[j].GetSector());
214 } else {
215 dethit.SetSectorNumber(fS3SectorHits[k].GetSector());
216 }
217 fS3PixelHits.push_back(dethit);
218 }
219 } else {
220 // 2 separate hits with shared ring
221
222 // Now we have accepted a good event, build it
223 TS3Hit dethit = fS3SectorHits[j]; // Sector now defines all data ring just gives position
224 dethit.SetRingNumber(fS3RingHits[i].GetRing());
225 fS3PixelHits.push_back(dethit);
226
227 // Now we have accepted a good event, build it
228 TS3Hit dethitB = fS3SectorHits[k]; // Sector now defines all data ring just gives position
229 dethitB.SetRingNumber(fS3RingHits[i].GetRing());
230 fS3PixelHits.push_back(dethitB);
231 }
232
233 UsedRing[i] = true;
234 UsedSector[j] = true;
235 UsedSector[k] = true;
236 }
237 }
238 }
239 }
240 } // End Shared Ring loop
241 }
242
243 ringcount = 0;
244 sectorcount = 0;
245 for(auto&& i : UsedRing) {
246 if(!i) {
247 ringcount++;
248 }
249 }
250
251 for(auto&& i : UsedSector) {
252 if(!i) {
253 sectorcount++;
254 }
255 }
256
257 if(ringcount > 1 || sectorcount > 1) {
258 // Shared Sector loop
259 for(size_t i = 0; i < fS3SectorHits.size(); ++i) {
260 if(UsedSector.at(i)) {
261 continue;
262 }
263 for(size_t j = 0; j < fS3RingHits.size(); ++j) {
264 if(UsedRing.at(j)) {
265 continue;
266 }
267 if(fS3SectorHits[i].GetArrayPosition() != fS3RingHits[j].GetArrayPosition()) { continue; }
268
269 for(size_t k = j + 1; k < fS3RingHits.size(); ++k) {
270 if(UsedRing.at(k)) {
271 continue;
272 }
273 if(fS3RingHits[j].GetArrayPosition() != fS3RingHits[k].GetArrayPosition()) { continue; }
274
275 if(abs(fS3SectorHits[i].GetTime() - fS3RingHits[j].GetTime()) * 1.6 < fFrontBackTime &&
276 abs(fS3SectorHits[i].GetTime() - fS3RingHits[k].GetTime()) * 1.6 < fFrontBackTime) { // first check time
277 if((EneS[i] - fFrontBackOffset) * fFrontBackEnergy < (EneR[j] + EneR[k]) &&
278 (EneR[j] + EneR[k] - fFrontBackOffset) * fFrontBackEnergy < EneS[i]) { // if time is good check energy
279
280 if(abs(fS3RingHits[j].GetRing() - fS3RingHits[k].GetRing()) == 1) {
281 // Same sector and neighbour rings, almost certainly charge sharing
282 // Experiments with breakup might get real mult2 events like this but most
283 // will be charge
284 // sharing
285
286 if(KeepShared()) {
287 TS3Hit dethit = fS3SectorHits[i]; // Sector defines all data ring just gives position
288 // Selecting one of the sectors is currently the best class allows, some
289 // loss of
290 // position information
291 if(fS3RingHits[k].GetEnergy() < fS3RingHits[j].GetEnergy()) {
292 dethit.SetRingNumber(fS3RingHits[j].GetRing());
293 } else {
294 dethit.SetRingNumber(fS3RingHits[k].GetRing());
295 }
296 fS3PixelHits.push_back(dethit);
297 }
298 } else {
299 // 2 separate hits with shared sector
300
301 // Now we have accepted a good event, build it
302 TS3Hit dethit = fS3RingHits[j]; // Ring defines all data sector just gives position
303 dethit.SetSectorNumber(fS3SectorHits[i].GetSector());
304 fS3PixelHits.push_back(dethit);
305
306 // Now we have accepted a good event, build it
307 TS3Hit dethitB = fS3RingHits[k]; // Ring defines all data sector just gives position
308 dethitB.SetSectorNumber(fS3SectorHits[i].GetSector());
309 fS3PixelHits.push_back(dethitB);
310 }
311
312 UsedSector[i] = true;
313 UsedRing[j] = true;
314 UsedRing[k] = true;
315 }
316 }
317 }
318 }
319 } // End Shared Sector loop
320 }
321 }
322
324 }
325}
326
327TVector3 TS3::GetPosition(int ring, int sector, bool smear)
328{
329 return GetPosition(ring, sector, fOffsetPhiSet, fTargetDistance, true, smear);
330}
331
332TVector3 TS3::GetPosition(int ring, int sector, double offsetphi, double offsetZ, bool sectorsdownstream, bool smear)
333{
334
335 double ring_width = (fOuterDiameter - fInnerDiameter) * 0.5 / fRingNumber; // 24 rings radial width!
336 double inner_radius = fInnerDiameter / 2.0;
337 double phi_width = 2. * TMath::Pi() / fSectorNumber;
338 double radius = inner_radius + ring_width * (ring + 0.5);
339 double phi = phi_width * sector; // the phi angle....
340 phi += fOffsetPhiCon;
341 // The above calculates the position on the S3
342
343 // This sets orientation of the detector face relative to the beam
344 if(sectorsdownstream) {
345 phi = -phi;
346 }
347
348 //This rotates the detector around the beam-axis into the correct lab position
349 phi += offsetphi;
350
351 //This produces a uniform distribution over the area of a pixel
352 if(smear) {
353 double sep = ring_width * 0.025;
354 double r1 = radius - ring_width * 0.5 + sep;
355 double r2 = radius + ring_width * 0.5 - sep;
356 radius = sqrt(gRandom->Uniform(r1 * r1, r2 * r2));
357 double sepphi = sep / radius;
358 phi = gRandom->Uniform(phi - phi_width * 0.5 + sepphi, phi + phi_width * 0.5 - sepphi);
359 }
360
361 return {cos(phi) * radius, sin(phi) * radius, offsetZ};
362}
363
365{
366 // This is necessary if you want mnemonics in a cal file to override those used during frag sort.
367 for(auto& hit : fS3SectorHits) {
368 hit.SetSectorNumber();
369 }
370 for(auto& hit : fS3RingHits) {
371 hit.SetRingNumber();
372 }
373}
374
376{
377 if(i < GetRingMultiplicity()) {
378 return &fS3RingHits.at(i);
379 }
380 std::cerr << "S3 ring hits are out of range" << std::endl;
381 throw grsi::exit_exception(1);
382 return nullptr;
383}
384
386{
387 if(i < GetSectorMultiplicity()) {
388 return &fS3SectorHits.at(i);
389 }
390 std::cerr << "S3 sector hits are out of range" << std::endl;
391 throw grsi::exit_exception(1);
392 return nullptr;
393}
394
396{
397 if(i < GetPixelMultiplicity()) {
398 return &fS3PixelHits.at(i);
399 }
400 std::cerr << "S3 Pixel hits are out of range" << std::endl;
401 throw grsi::exit_exception(1);
402 return nullptr;
403}
404
405void TS3::Print(Option_t*) const
406{
407 Print(std::cout);
408}
409
410void TS3::Print(std::ostream& out) const
411{
412 std::ostringstream str;
413 str << __PRETTY_FUNCTION__ << "\tnot yet written." << std::endl; // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
414 out << str.str();
415}
416
417void TS3::Clear(Option_t* opt)
418{
419 TDetector::Clear(opt);
420 fS3PixelHits.clear();
421 fS3RingHits.clear();
422 fS3SectorHits.clear();
423
424 SetPixels(false);
425 SetMultiHit(false);
426}
const TMnemonic * GetMnemonic() const
void Copy(TObject &) const override
!
Definition TDetector.cxx:24
void Clear(Option_t *="") override
!
Definition TDetector.h:68
static TAnalysisOptions * AnalysisOptions()
virtual EMnemonic CollectedCharge() const
Definition TMnemonic.h:64
void SetSectorNumber(Short_t sn)
Definition TS3Hit.h:50
void SetRingNumber(Short_t rn)
Definition TS3Hit.h:49
void SetWavefit(const TFragment &)
Definition TS3Hit.cxx:59
Definition TS3.h:15
static bool SectorPreference()
!
Definition TS3.h:77
static TTransientBits< UShort_t > fGlobalS3Bits
Global Bit.
Definition TS3.h:132
static int fRingNumber
for geometery
Definition TS3.h:137
Int_t GetPixelMultiplicity()
Definition TS3.cxx:86
std::vector< TS3Hit > fS3PixelHits
! transient vector to hold the on-the-fly calculated pixel hits
Definition TS3.h:125
std::vector< TS3Hit > fS3RingHits
vector to store hits of the ring side
Definition TS3.h:123
static double fOffsetPhiSet
!
Definition TS3.h:141
void Clear(Option_t *opt="all") override
!
Definition TS3.cxx:417
Short_t GetRingMultiplicity() const
Definition TS3.h:47
TS3Hit * GetRingHit(const int &i)
Definition TS3.cxx:375
static bool KeepShared()
!
Definition TS3.h:89
void BuildPixels()
Definition TS3.cxx:96
@ kMultHit
Attempt to reconstruct multi strip-hit events.
std::vector< TS3Hit > fS3SectorHits
vector to store hits of the sector side
Definition TS3.h:124
static int fSectorNumber
!
Definition TS3.h:138
static TVector3 GetPosition(int ring, int sector, bool smear=false)
Definition TS3.cxx:327
TS3Hit * GetPixelHit(const int &i)
Definition TS3.cxx:395
static bool SetMultiHit(bool set=true)
!
Definition TS3.h:78
static bool MultiHit()
!
Definition TS3.h:83
static double fInnerDiameter
!
Definition TS3.h:144
void ResetRingsSectors()
Definition TS3.cxx:364
static double fOffsetPhiCon
!
Definition TS3.h:140
TS3()
Definition TS3.cxx:26
void AddFragment(const std::shared_ptr< const TFragment > &, TChannel *) override
!
Definition TS3.cxx:50
void SetPixels(bool flag=true)
Definition TS3.h:92
TTransientBits< UChar_t > fS3Bits
flags for transient members
Definition TS3.h:127
static double fOuterDiameter
!
Definition TS3.h:143
static double fFrontBackEnergy
!
Definition TS3.h:149
static double fTargetDistance
!
Definition TS3.h:145
TS3 & operator=(const TS3 &)
Definition TS3.cxx:31
TS3Hit * GetSectorHit(const int &i)
Definition TS3.cxx:385
static double fFrontBackOffset
!
Definition TS3.h:150
Short_t GetSectorMultiplicity() const
Definition TS3.h:48
void SetBitNumber(ES3Bits bit, Bool_t set=true)
Definition TS3.cxx:80
ES3Bits
Definition TS3.h:17
void Copy(TObject &) const override
Definition TS3.cxx:42
static Int_t fFrontBackTime
!
Definition TS3.h:148
void Print(Option_t *opt="") const override
!
Definition TS3.cxx:405
void SetBit(T bit, Bool_t flag)
Bool_t TestBit(T bit) const