SND@LHC Software
Loading...
Searching...
No Matches
ConvDriftTubeRawData.cxx
Go to the documentation of this file.
1#include <TClonesArray.h> // for TClonesArray
2#include <TGenericClassInfo.h> // for TGenericClassInfo
3#include <TMath.h> // for Sqrt
4#include <TFile.h>
5#include <TTree.h>
6#include <TBranch.h>
7#include <TLeaf.h>
8#include <TROOT.h>
9#include <TChain.h>
10#include <TTreeReader.h>
11#include <TTreeReaderValue.h>
12#include <TTreeReaderArray.h>
13#include <iostream> // for operator<<, basic_ostream, endl
14#include <algorithm> // std::sort
15#include <vector> // std::vector
16#include <array> // std::array
17#include <cmath>
18#include "FairMCEventHeader.h" // for FairMCEventHeader
19#include "FairLink.h" // for FairLink
20#include "FairRunAna.h" // for FairRunAna
21#include "FairRootManager.h" // for FairRootManager
22#include "ConvDriftTubeRawData.h" // for Conversion
23#include "DriftTube.h" // for Drift Tube detector
24#include "DriftTubeConstants.h"
25#include "ShipUnit.h"
26
27
29 : FairTask("ConvDriftTubeRawData"), fSNDTree(nullptr), fMiniDTChain(nullptr), fDigiDriftTube(nullptr),
30 MiniDTeventNumber(0)
31{
32}
33
35
37{
38 FairRootManager *ioman = FairRootManager::Instance();
39 if (!ioman) {
40 LOG(FATAL) << "ConvDriftTubeRawData::Init: RootManager not instantiated!";
41 }
42
43 // Get the DriftTube detector from the list of globals
44 DriftTubeDet = dynamic_cast<DriftTube *>(gROOT->GetListOfGlobals()->FindObject("DriftTube"));
45
46 // Input raw data file is read from the FairRootManager
47 // This allows to have it in custom format, e.g. have arbitary names of TTrees
48
49 // converted SND
50 TFile *f0 = dynamic_cast<TFile *>(ioman->GetObject("rawConv"));
51 fSNDTree = (TTree *)f0->Get("rawConv");
52
53 // load MiniDT data for the current run
54 fMiniDTChain = (TChain *)ioman->GetObject("MiniDTChain");
55
56 // Register the output
57 fDigiDriftTube = new TClonesArray("DriftTubeHit");
58 ioman->Register("Digi_DriftTubeHits", "DigiDriftTubeHit_det", fDigiDriftTube, kTRUE);
59
60 // Get the FairLogger
61 FairLogger *logger = FairLogger::GetLogger();
62
64
65 return kSUCCESS;
66}
67
68void ConvDriftTubeRawData::Exec(Option_t * /*opt*/)
69{
70
71 fDigiDriftTube->Clear("C");
72
73 // run the conversion
74 Process();
76}
77
79{
80 int indexDriftTube{}; // index of DT hits
81 int detID;
82 fSNDTree->GetEvent(eventNumber);
83 auto eventTimestamp = fSNDTree->GetLeaf("EventHeader.fEventTime")->GetValue();
84
85 TTreeReader MiniDTReader(fMiniDTChain);
86
87 TTreeReaderValue<Long64_t> hit_oc(MiniDTReader, "hit_orbit");
88 TTreeReaderValue<int> hit_bx(MiniDTReader, "hit_bx");
89 TTreeReaderValue<int> hit_tdc(MiniDTReader, "hit_tdc");
90 TTreeReaderValue<int> hit_chamber(MiniDTReader, "hit_chamber");
91 TTreeReaderValue<int> hit_layer(MiniDTReader, "hit_layer");
92 TTreeReaderValue<int> hit_wire(MiniDTReader, "hit_wire");
93
94 const double T_o {3564. * 4. / (ShipUnit::snd_freq * 1e9)};
95 const double T_bx {1. * 4. / (ShipUnit::snd_freq * 1e9)};
96 const double tdc_conv {T_bx / 32.};
97
98 MiniDTReader.SetEntry(MiniDTeventNumber);
99 int MatchedHits {};
100 while (MiniDTReader.Next()) {
101 auto SNDtimestamp = static_cast<double>(eventTimestamp / (ShipUnit::snd_freq * 1e9));
102 auto hit_timestamp = static_cast<double>(*hit_oc * T_o + *hit_bx * T_bx + *hit_tdc * tdc_conv);
103 if (((hit_timestamp - SNDtimestamp) > -50e-9) && ((hit_timestamp - SNDtimestamp) < 650e-9)) {
104 if (MatchedHits == 0) {
105 MiniDTeventNumber = MiniDTReader.GetCurrentEntry();
106 }
107 detID = SetDetID(*hit_chamber, *hit_layer, *hit_wire);
108 (*fDigiDriftTube)[MatchedHits] = new DriftTubeHit(detID, hit_timestamp - SNDtimestamp);
109 auto hit = dynamic_cast<DriftTubeHit*>(fDigiDriftTube->At(MatchedHits));
110 ++MatchedHits;
111 } else if ((hit_timestamp - SNDtimestamp) > 650e-9) {
112 // run laterality computation and hit redefinition
113 std::vector<std::vector<int>> hitsClusters = FindClusters(fDigiDriftTube);
114 FindLateralitySlope(fDigiDriftTube, hitsClusters);
115 MatchedHits = 0;
116 break;
117 } else {
118 continue;
119 }
120 }
121
122 // LOG(INFO) << eventNumber << " events processed out of " << fSNDTree->GetEntries() << " number of events in file.";
124}
125
127{
128 eventNumber = NewStart;
129}
130
131int ConvDriftTubeRawData::SetDetID(const int& chamber, const int& layer, const int& wire)
132{
133 int detID = 40000 + 1000 * (1 - chamber) + 100 * (3 - layer) + (15 - wire);
134 return detID;
135}
136
141
142std::vector<ConvDriftTubeRawData::HitPoint> ConvDriftTubeRawData::GetNeighbours(const int& L, const int& C) {
143 auto nLayers = static_cast<int>(DriftTubeDet->GetConfParI("DriftTube/nLayers"));
144
145 std::vector<HitPoint> neighbours;
146 neighbours.reserve(10);
147
148 neighbours.push_back({L, C - 1});
149 neighbours.push_back({L, C + 1});
150
151 for (int nextL : {L - 1, L + 1}) {
152 if (nextL < 0 || nextL >= nLayers) continue;
153
154 neighbours.push_back({nextL, C});
155
156 if (L % 2 == 0) {
157 neighbours.push_back({nextL, C + 1});
158 } else {
159 neighbours.push_back({nextL, C - 1});
160 }
161 }
162
163 for (int nextL : {L - 2, L + 2}) {
164 if (nextL < 0 || nextL >= nLayers) continue;
165
166 neighbours.push_back({nextL, C});
167 neighbours.push_back({nextL, C - 1});
168 neighbours.push_back({nextL, C + 1});
169 }
170
171 return neighbours;
172}
173
174std::vector<std::vector<int>> ConvDriftTubeRawData::FindClusters(const TClonesArray * hits) {
175 auto nPlanes = static_cast<int>(DriftTubeDet->GetConfParI("DriftTube/nPlanes"));
176 auto nLayers = static_cast<int>(DriftTubeDet->GetConfParI("DriftTube/nLayers"));
177 auto nCells = static_cast<int>(DriftTubeDet->GetConfParI("DriftTube/nCells"));
178
179 auto gridCells = static_cast<size_t>(nPlanes * nLayers * nCells);
180
181 std::vector<int> grid(gridCells, -1);
182
183 auto gridIdx = [&](int p, int l, int c) -> int& {return grid[p * (nLayers * nCells) + l * nCells + c];};
184
185 int nHits {static_cast<int>(hits->GetEntries())};
186 if (nHits == 0) return {};
187 std::vector<bool> visited(nHits, false);
188 std::vector<std::vector<int>> allClusters;
189
190 // Fill grid
191 for (int i = 0; i != nHits; ++i) {
192 auto hit = dynamic_cast<DriftTubeHit*>(hits->At(i));
193 int p = hit->GetPlane();
194 int l = hit->GetLayer();
195 int c = hit->GetCell();
196
197 if (p >= 0 && p < nPlanes && l >= 0 && l < nLayers && c >= 0 && c < nCells) {
198 gridIdx(p, l, c) = i;
199 }
200 }
201
202 // Find cluster
203 for (int p = 0; p != nPlanes; ++p) {
204 for (int l = 0; l != nLayers; ++l) {
205 for (int c = 0; c != nCells; ++c) {
206 int startIdx {gridIdx(p, l, c)};
207
208 if (startIdx == -1 || visited[startIdx]) continue;
209
210 std::vector<int> blob;
211 std::vector<int> stack = {startIdx};
212 visited[startIdx] = true;
213
214 while (!stack.empty()) {
215 int currIdx {stack.back()};
216 stack.pop_back();
217 blob.push_back(currIdx);
218
219 auto hit = dynamic_cast<DriftTubeHit*>(hits->At(currIdx));
220 auto neighbours = GetNeighbours(hit->GetLayer(), hit->GetCell());
221
222 for (const auto& nb : neighbours) {
223 if (nb.C >= 0 && nb.C < nCells) {
224 int nbIdx {gridIdx(p, nb.L, nb.C)};
225
226 if (nbIdx != -1 && !visited[nbIdx]) {
227 visited[nbIdx] = true;
228 stack.push_back(nbIdx);
229 }
230 }
231 }
232 }
233
234 // Split clusters
235 if (blob.size() >= 3) {
236 std::vector<std::vector<int>> layerHits(nLayers);
237 // for (int l = 0; l < nLayers; ++l) {
238 // layerHits[l].clear();
239 // }
240
241 for (int idx : blob) {
242 auto hit = dynamic_cast<DriftTubeHit*>(hits->At(idx));
243 layerHits[hit->GetLayer()].push_back(idx);
244 }
245
246 for (auto& layerVec : layerHits) {
247 if (layerVec.empty()) layerVec.push_back(-1);
248 }
249
250 for (int i0 : layerHits[0]) {
251 for (int i1 : layerHits[1]) {
252 for (int i2 : layerHits[2]) {
253 for (int i3 : layerHits[3]) {
254 std::vector<int> candidate;
255
256 candidate.reserve(nLayers);
257 if (i0 != -1) candidate.push_back(i0);
258 if (i1 != -1) candidate.push_back(i1);
259 if (i2 != -1) candidate.push_back(i2);
260 if (i3 != -1) candidate.push_back(i3);
261
262 if (candidate.size() < 3) continue;
263
264 bool validChain {true};
265 for (size_t k = 0; k < candidate.size() - 1; ++k) {
266 auto hA = dynamic_cast<DriftTubeHit*>(hits->At(candidate[k]));
267 auto hB = dynamic_cast<DriftTubeHit*>(hits->At(candidate[k + 1]));
268
269 int dL {hB->GetLayer() - hA->GetLayer()};
270 int dC {hB->GetCell() - hA->GetCell()};
271
272 if (dL == 1) {
273 if (hA->GetLayer() % 2 == 0) {
274 if (dC != 0 && dC != 1) {
275 validChain = false;
276 break;
277 }
278 } else {
279 if (dC != 0 && dC != -1) {
280 validChain = false;
281 break;
282 }
283 }
284 } else if (dL == 2) {
285 if (std::abs(dC) > 1) {
286 validChain = false;
287 break;
288 }
289 }
290 }
291
292 if (validChain) {
293 allClusters.push_back(candidate);
294 }
295 }
296 }
297 }
298 }
299
300 }
301 }
302 }
303 }
304 return allClusters;
305}
306
307void ConvDriftTubeRawData::FindLateralitySlope(const TClonesArray * hits, const std::vector<std::vector<int>>& clusters) {
308 auto nLayers = static_cast<int>(DriftTubeDet->GetConfParI("DriftTube/nLayers"));
309
310 struct TrackResult {
311 std::vector<int> latCombination {};
312 double quality;
313 std::vector<int> indices;
314 };
315
316 std::vector<TrackResult> candidates;
317
318 const auto HCELL = static_cast<double>(DriftTubeDet->GetConfParF("DriftTube/cellHeight") + DriftTubeDet->GetConfParF("DriftTube/plateThickness")); // Al plate thickness
319 const auto WCELL = static_cast<double>(DriftTubeDet->GetConfParF("DriftTube/cellWidth"));
320
321 int clusterID {-1};
322
323 for (const auto& hitsIdx : clusters) {
324 int nHits {hitsIdx.size()};
325 if (nHits < 3) continue;
326
327 TrackResult bestInCluster {{}, 1e9, hitsIdx};
328
329 struct Point {
330 double x;
331 double y;
332 };
333
334 std::vector<Point> points;
335
336 int nCombinations {1 << nHits};
337
338 for (int i = 0; i < nCombinations; ++i) {
339 std::vector<int> currentLats(nLayers, 0); // if no hit in that layer, lat stays 0
340 for (int j = 0; j < nHits; ++j) {
341 auto hit = dynamic_cast<DriftTubeHit*>(hits->At(hitsIdx[j]));
342 int layer {hit->GetLayer()};
343
344 int lat = ((i >> j) & 1) ? 1 : -1;
345 currentLats[layer] = lat;
346
347 double y {(layer + 0.5) * HCELL};
348 double x_wire {(hit->GetCell() + (layer % 2 == 1 ? 0.5 : 1.0)) * WCELL};
349 double drift_time = static_cast<double>(hit->GetTimestamp()- drifttube::tped);
350
351 double x {};
352 if (drift_time < 0) {
353 x = x_wire;
354 currentLats[layer] = 0;
355 } else {
356 double dist = std::min(static_cast<double>(drift_time * drifttube::vdrift), WCELL * 0.5);
357 x = x_wire + (lat * dist);
358 }
359 points.push_back({x, y});
360 }
361
362 std::vector<double> slopes {};
363 double slopesMean {};
364 double slopesStdev {};
365
366 for (size_t j = 0; j != points.size(); ++j) {
367 for (size_t k = j + 1; k != points.size(); ++k) {
368 double dx {points[j].x - points[k].x};
369 double dy {points[j].y - points[k].y};
370 if (std::abs(dy) > std::numeric_limits<double>::epsilon()) {
371 slopes.push_back(dx / dy);
372 slopesMean += (dx / dy);
373 }
374 }
375 }
376
377 points.clear();
378
379 slopesMean = slopesMean / slopes.size();
380
381 for (const auto& slope : slopes) {
382 slopesStdev += std::pow(slope - slopesMean, 2);
383 }
384
385 slopesStdev = std::sqrt(slopesStdev / (slopes.size() - 1));
386
387 if (slopesStdev < bestInCluster.quality) {
388 bestInCluster.latCombination = currentLats;
389 bestInCluster.quality = slopesStdev;
390 bestInCluster.indices = hitsIdx;
391 }
392 slopes.clear();
393 }
394 candidates.push_back(bestInCluster);
395 }
396
397 if (!candidates.empty()) {
398 std::sort(candidates.begin(), candidates.end(), [](const TrackResult& a, const TrackResult& b) {return a.quality < b.quality;});
399
400 std::vector<bool> hitUsed(static_cast<int>(hits->GetEntries()), false);
401
402 for (auto& cand : candidates) {
403 bool conflict {false};
404 ++clusterID;
405
406 for (int idx : cand.indices) {
407 if (hitUsed[idx]) {
408 conflict = true;
409 break;
410 }
411 }
412
413 if (!conflict) {
414 for (int idx : cand.indices) {
415 auto hit = dynamic_cast<DriftTubeHit*>(hits->At(idx));
416 int layer {hit->GetLayer()};
417
418 int lat {cand.latCombination[layer]};
419
420 hit->setLaterality(lat);
421 hit->setClusterID(clusterID);
422
423 hitUsed[idx] = true;
424 }
425 }
426 }
427 }
428 candidates.clear();
429}
std::vector< std::vector< int > > FindClusters(const TClonesArray *hits)
virtual InitStatus Init()
int SetDetID(const int &chamber, const int &layer, const int &wire)
void FindLateralitySlope(const TClonesArray *hits, const std::vector< std::vector< int > > &clusters)
std::vector< HitPoint > GetNeighbours(const int &L, const int &C)
virtual void Exec(Option_t *opt)
Int_t GetLayer()
Int_t GetConfParI(TString name)
Definition DriftTube.h:34
Float_t GetConfParF(TString name)
Definition DriftTube.h:33
constexpr double vdrift
constexpr double tped