83 auto eventTimestamp =
fSNDTree->GetLeaf(
"EventHeader.fEventTime")->GetValue();
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");
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.};
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) {
107 detID =
SetDetID(*hit_chamber, *hit_layer, *hit_wire);
108 (*fDigiDriftTube)[MatchedHits] =
new DriftTubeHit(detID, hit_timestamp - SNDtimestamp);
111 }
else if ((hit_timestamp - SNDtimestamp) > 650e-9) {
145 std::vector<HitPoint> neighbours;
146 neighbours.reserve(10);
148 neighbours.push_back({L, C - 1});
149 neighbours.push_back({L, C + 1});
151 for (
int nextL : {L - 1, L + 1}) {
152 if (nextL < 0 || nextL >= nLayers)
continue;
154 neighbours.push_back({nextL, C});
157 neighbours.push_back({nextL, C + 1});
159 neighbours.push_back({nextL, C - 1});
163 for (
int nextL : {L - 2, L + 2}) {
164 if (nextL < 0 || nextL >= nLayers)
continue;
166 neighbours.push_back({nextL, C});
167 neighbours.push_back({nextL, C - 1});
168 neighbours.push_back({nextL, C + 1});
179 auto gridCells =
static_cast<size_t>(nPlanes * nLayers * nCells);
181 std::vector<int> grid(gridCells, -1);
183 auto gridIdx = [&](
int p,
int l,
int c) ->
int& {
return grid[p * (nLayers * nCells) + l * nCells + c];};
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;
191 for (
int i = 0; i != nHits; ++i) {
193 int p = hit->GetPlane();
194 int l = hit->GetLayer();
195 int c = hit->GetCell();
197 if (p >= 0 && p < nPlanes && l >= 0 && l < nLayers && c >= 0 && c < nCells) {
198 gridIdx(p, l, c) = i;
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)};
208 if (startIdx == -1 || visited[startIdx])
continue;
210 std::vector<int> blob;
211 std::vector<int> stack = {startIdx};
212 visited[startIdx] =
true;
214 while (!stack.empty()) {
215 int currIdx {stack.back()};
217 blob.push_back(currIdx);
219 auto hit =
dynamic_cast<DriftTubeHit*
>(hits->At(currIdx));
220 auto neighbours =
GetNeighbours(hit->GetLayer(), hit->GetCell());
222 for (
const auto& nb : neighbours) {
223 if (nb.C >= 0 && nb.C < nCells) {
224 int nbIdx {gridIdx(p, nb.L, nb.C)};
226 if (nbIdx != -1 && !visited[nbIdx]) {
227 visited[nbIdx] =
true;
228 stack.push_back(nbIdx);
235 if (blob.size() >= 3) {
236 std::vector<std::vector<int>> layerHits(nLayers);
241 for (
int idx : blob) {
243 layerHits[hit->GetLayer()].push_back(idx);
246 for (
auto& layerVec : layerHits) {
247 if (layerVec.empty()) layerVec.push_back(-1);
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;
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);
262 if (candidate.size() < 3)
continue;
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]));
269 int dL {hB->
GetLayer() - hA->GetLayer()};
270 int dC {hB->GetCell() - hA->GetCell()};
273 if (hA->GetLayer() % 2 == 0) {
274 if (dC != 0 && dC != 1) {
279 if (dC != 0 && dC != -1) {
284 }
else if (dL == 2) {
285 if (std::abs(dC) > 1) {
293 allClusters.push_back(candidate);
311 std::vector<int> latCombination {};
313 std::vector<int> indices;
316 std::vector<TrackResult> candidates;
323 for (
const auto& hitsIdx : clusters) {
324 int nHits {hitsIdx.size()};
325 if (nHits < 3)
continue;
327 TrackResult bestInCluster {{}, 1e9, hitsIdx};
334 std::vector<Point> points;
336 int nCombinations {1 << nHits};
338 for (
int i = 0; i < nCombinations; ++i) {
339 std::vector<int> currentLats(nLayers, 0);
340 for (
int j = 0; j < nHits; ++j) {
341 auto hit =
dynamic_cast<DriftTubeHit*
>(hits->At(hitsIdx[j]));
344 int lat = ((i >> j) & 1) ? 1 : -1;
345 currentLats[layer] = lat;
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);
352 if (drift_time < 0) {
354 currentLats[layer] = 0;
356 double dist = std::min(
static_cast<double>(drift_time *
drifttube::vdrift), WCELL * 0.5);
357 x = x_wire + (lat * dist);
359 points.push_back({x, y});
362 std::vector<double> slopes {};
363 double slopesMean {};
364 double slopesStdev {};
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);
379 slopesMean = slopesMean / slopes.size();
381 for (
const auto& slope : slopes) {
382 slopesStdev += std::pow(slope - slopesMean, 2);
385 slopesStdev = std::sqrt(slopesStdev / (slopes.size() - 1));
387 if (slopesStdev < bestInCluster.quality) {
388 bestInCluster.latCombination = currentLats;
389 bestInCluster.quality = slopesStdev;
390 bestInCluster.indices = hitsIdx;
394 candidates.push_back(bestInCluster);
397 if (!candidates.empty()) {
398 std::sort(candidates.begin(), candidates.end(), [](
const TrackResult& a,
const TrackResult& b) {return a.quality < b.quality;});
400 std::vector<bool> hitUsed(
static_cast<int>(hits->GetEntries()),
false);
402 for (
auto& cand : candidates) {
403 bool conflict {
false};
406 for (
int idx : cand.indices) {
414 for (
int idx : cand.indices) {
418 int lat {cand.latCombination[layer]};
420 hit->setLaterality(lat);
421 hit->setClusterID(clusterID);