177 constexpr std::array<int, 2> startLayer{0, 3};
178 const Long64_t
nEvents = hitsTree->GetEntries();
179 this->setIsStaggered(
true);
183 std::vector<o2::trk::Hit>* trkHit =
nullptr;
184 hitsTree->SetBranchAddress(
"TRKHit", &trkHit);
186 const int inROFpileup{config.contains(
"inROFpileup") ? config[
"inROFpileup"].get<
int>() : 1};
188 const int nRofs = (
nEvents + inROFpileup - 1) / inROFpileup;
189 std::array<o2::its::LayerTiming, nLayers> timings{};
190 for (
int iLayer{0}; iLayer < nLayers; ++iLayer) {
192 timings[iLayer].mROFLength = 1;
194 this->initTimingTables(timings);
195 const auto& timing = this->getROFOverlapTableView().getLayer(0);
197 LOGP(fatal,
"TRK: inconsistent number of ROFs across TFs: timing has {}, hit-tree path produced {}", timing.mNROFsTF, nRofs);
200 for (
int iLayer{0}; iLayer < nLayers; ++iLayer) {
201 this->mMinR[iLayer] = std::numeric_limits<float>::max();
202 this->mMaxR[iLayer] = std::numeric_limits<float>::lowest();
203 this->mROFramesClusters[iLayer].clear();
204 this->mROFramesClusters[iLayer].resize(nRofs + 1, 0);
205 this->mUnsortedClusters[iLayer].clear();
206 this->mTrackingFrameInfo[iLayer].clear();
207 this->mClusterExternalIndices[iLayer].clear();
208 this->mClusterSize[iLayer].clear();
211 std::array<int, nLayers> clusterCountPerLayer{};
212 for (Long64_t iEvent = 0; iEvent <
nEvents; ++iEvent) {
213 hitsTree->GetEntry(iEvent);
214 for (
const auto& hit : *trkHit) {
215 if (gman->
getDisk(hit.GetDetectorID()) != -1) {
218 int subDetID = gman->
getSubDetID(hit.GetDetectorID());
219 const int layer = startLayer[subDetID] + gman->
getLayer(hit.GetDetectorID());
220 if (
layer >= nLayers) {
223 ++clusterCountPerLayer[
layer];
227 for (
int iLayer{0}; iLayer < nLayers; ++iLayer) {
228 this->mUnsortedClusters[iLayer].reserve(clusterCountPerLayer[iLayer]);
229 this->mTrackingFrameInfo[iLayer].reserve(clusterCountPerLayer[iLayer]);
230 this->mClusterExternalIndices[iLayer].reserve(clusterCountPerLayer[iLayer]);
231 this->mClusterSize[iLayer].reserve(clusterCountPerLayer[iLayer]);
234 std::array<float, 11> resolution{0.001, 0.001, 0.001, 0.001, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004, 0.004};
235 if (config[
"geometry"][
"pitch"].
size() == nLayers) {
236 for (
int iLayer{0}; iLayer < config[
"geometry"][
"pitch"].size(); ++iLayer) {
237 LOGP(info,
"Setting resolution for layer {} from config", iLayer);
238 LOGP(info,
"Layer {} pitch {} cm", iLayer, config[
"geometry"][
"pitch"][iLayer].get<float>());
239 resolution[iLayer] = config[
"geometry"][
"pitch"][iLayer].get<
float>() / std::sqrt(12.f);
244 std::array<int, nLayers> hitCounterPerLayer{};
245 std::array<dataformats::MCTruthContainer<MCCompLabel>*, nLayers>
labels{};
246 for (
int iLayer{0}; iLayer < nLayers; ++iLayer) {
248 this->mClusterLabels[iLayer] =
labels[iLayer];
252 for (Long64_t iEvent = 0; iEvent <
nEvents; ++iEvent) {
253 hitsTree->GetEntry(iEvent);
255 for (
auto& hit : *trkHit) {
256 if (gman->
getDisk(hit.GetDetectorID()) != -1) {
259 int subDetID = gman->
getSubDetID(hit.GetDetectorID());
260 const int layer = startLayer[subDetID] + gman->
getLayer(hit.GetDetectorID());
266 if (
layer >= nLayers) {
270 int chipID = hit.GetDetectorID();
273 auto locXYZ = l2g ^ (hit.GetPos());
274 locXYZ.SetX(locXYZ.X() + gRandom->Gaus(0.0, resolution[
layer]));
275 locXYZ.SetZ(locXYZ.Z() + gRandom->Gaus(0.0, resolution[
layer]));
278 r = std::hypot(gloXYZ.X(), gloXYZ.Y());
280 const auto& hitPos = hit.GetPos();
281 r = std::hypot(hitPos.X(), hitPos.Y());
282 alpha = std::atan2(hitPos.Y(), hitPos.X()) + gRandom->Gaus(0.0, resolution[
layer] /
r);
283 o2::math_utils::bringTo02Pi(
alpha);
284 gloXYZ.SetX(
r * std::cos(
alpha));
285 gloXYZ.SetY(
r * std::sin(
alpha));
286 gloXYZ.SetZ(hitPos.Z() + gRandom->Gaus(0.0, resolution[
layer]));
289 trkXYZ.SetZ(gloXYZ.Z());
291 this->mMinR[
layer] = std::min(this->mMinR[
layer],
r);
292 this->mMaxR[
layer] = std::max(this->mMaxR[
layer],
r);
293 this->addTrackingFrameInfoToLayer(
layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), trkXYZ.x(),
alpha,
294 std::array<float, 2>{trkXYZ.y(), trkXYZ.z()},
295 std::array<float, 3>{resolution[layer] * resolution[layer], 0., resolution[layer] * resolution[layer]});
296 this->addClusterToLayer(
layer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), this->mUnsortedClusters[
layer].size());
297 const int layerHitCounter = hitCounterPerLayer[
layer]++;
298 this->addClusterExternalIndexToLayer(
layer, layerHitCounter);
299 this->mClusterSize[
layer].push_back(1);
305 if ((iEvent + 1) % inROFpileup == 0 || iEvent ==
nEvents - 1) {
307 for (
unsigned int iLayer{0}; iLayer < this->mUnsortedClusters.size(); ++iLayer) {
308 this->mROFramesClusters[iLayer][iRof] = this->mUnsortedClusters[iLayer].size();
317 const std::array<gsl::span<const o2::trk::Cluster>, nLayers>& layerClusters,
318 const std::array<gsl::span<const unsigned char>, nLayers>& layerPatterns,
322 constexpr std::array<int, 2> startLayer{0, 3};
323 this->setIsStaggered(
true);
327 if (!mTimingTablesInitialised) {
328 LOGP(fatal,
"TRK::loadROFrameData: timing tables not initialised — call deriveAndInitTiming() first");
331 for (
const auto& rofs : layerROFs) {
332 nRofs = std::max(nRofs,
static_cast<int>(rofs.size()));
335 for (
int iLayer{0}; iLayer < nLayers; ++iLayer) {
336 const auto& timing = this->getROFOverlapTableView().getLayer(iLayer);
338 LOGP(fatal,
"TRK: inconsistent number of ROFs on layer {}: timing has {}, cluster path received {}", iLayer, timing.mNROFsTF, layerROFs[iLayer].size());
340 this->mMinR[iLayer] = std::numeric_limits<float>::max();
341 this->mMaxR[iLayer] = std::numeric_limits<float>::lowest();
342 this->mROFramesClusters[iLayer].clear();
343 this->mROFramesClusters[iLayer].resize(layerROFs[iLayer].
size() + 1, 0);
344 this->mUnsortedClusters[iLayer].clear();
345 this->mTrackingFrameInfo[iLayer].clear();
346 this->mClusterExternalIndices[iLayer].clear();
347 this->mClusterSize[iLayer].clear();
348 this->mUnsortedClusters[iLayer].reserve(layerClusters[iLayer].
size());
349 this->mTrackingFrameInfo[iLayer].reserve(layerClusters[iLayer].
size());
350 this->mClusterExternalIndices[iLayer].reserve(layerClusters[iLayer].
size());
351 this->mClusterSize[iLayer].reserve(layerClusters[iLayer].
size());
354 std::array<std::vector<size_t>, nLayers> patternOffsetsPerLayer;
355 for (
int iLayer{0}; iLayer < nLayers; ++iLayer) {
356 auto&
offsets = patternOffsetsPerLayer[iLayer];
357 offsets.resize(layerClusters[iLayer].
size(), std::numeric_limits<size_t>::max());
359 bool validPatterns =
true;
360 for (
size_t clusterId{0}; clusterId < layerClusters[iLayer].size(); ++clusterId) {
361 if (pattPos + 2 > layerPatterns[iLayer].
size()) {
362 validPatterns =
false;
366 const uint8_t rowSpan = layerPatterns[iLayer][pattPos];
367 const uint8_t colSpan = layerPatterns[iLayer][pattPos + 1];
368 const size_t nBytes = (size_t(rowSpan) * colSpan + 7) / 8;
369 if (pattPos + 2 + nBytes > layerPatterns[iLayer].
size()) {
370 validPatterns =
false;
373 pattPos += 2 + nBytes;
375 if (!validPatterns || pattPos != layerPatterns[iLayer].
size()) {
376 LOGP(fatal,
"Malformed TRK pattern stream for layer {}: {} bytes for {} clusters",
377 iLayer, layerPatterns[iLayer].
size(), layerClusters[iLayer].
size());
381 for (
int iLayer{0}; iLayer < nLayers; ++iLayer) {
382 for (
size_t iRof{0}; iRof < layerROFs[iLayer].size(); ++iRof) {
383 const auto& rof = layerROFs[iLayer][iRof];
384 const int first = rof.getFirstEntry();
385 const int last =
first + rof.getNEntries();
387 for (
int clusterId{
first}; clusterId < last; ++clusterId) {
388 if (clusterId < 0 || clusterId >=
static_cast<int>(layerClusters[iLayer].
size())) {
389 LOGP(warning,
"Skipping out-of-range TRK cluster {} on layer {}", clusterId, iLayer);
393 const auto&
c = layerClusters[iLayer][clusterId];
394 if (
c.subDetID < 0 ||
c.subDetID > 1 ||
c.disk != -1) {
398 const int clusterLayer = startLayer[
c.subDetID] +
c.layer;
399 if (clusterLayer != iLayer) {
400 LOGP(error,
"Skipping cluster from layer {} found in TRK layer stream {}", clusterLayer, iLayer);
404 const auto pattOffset = patternOffsetsPerLayer[iLayer][clusterId];
405 const uint8_t* pattForCluster = layerPatterns[iLayer].data() + pattOffset;
412 if (
c.subDetID == 1) {
416 const float r = std::hypot(gloXYZ.X(), gloXYZ.Y());
417 alpha = std::atan2(gloXYZ.Y(), gloXYZ.X());
418 o2::math_utils::bringTo02Pi(
alpha);
421 trkXYZ.SetZ(gloXYZ.Z());
424 const float r = std::hypot(gloXYZ.X(), gloXYZ.Y());
425 this->mMinR[iLayer] = std::min(this->mMinR[iLayer],
r);
426 this->mMaxR[iLayer] = std::max(this->mMaxR[iLayer],
r);
428 const float sigmaY2 = (
c.subDetID == 0)
431 const float sigmaZ2 = (
c.subDetID == 0)
435 this->addTrackingFrameInfoToLayer(iLayer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), trkXYZ.x(),
alpha,
436 std::array<float, 2>{trkXYZ.y(), trkXYZ.z()},
437 std::array<float, 3>{sigmaY2, 0.f, sigmaZ2});
438 this->addClusterToLayer(iLayer, gloXYZ.x(), gloXYZ.y(), gloXYZ.z(), this->mUnsortedClusters[iLayer].size());
439 this->addClusterExternalIndexToLayer(iLayer, clusterId);
440 this->mClusterSize[iLayer].push_back(std::clamp(
static_cast<unsigned int>(
c.size), 0u, 255u));
443 this->mROFramesClusters[iLayer][iRof + 1] = this->mUnsortedClusters[iLayer].size();
447 for (
auto i = 0;
i < this->mNTrackletsPerCluster.size(); ++
i) {
448 this->mNTrackletsPerCluster[
i].resize(this->mUnsortedClusters[1].
size());
449 this->mNTrackletsPerClusterSum[
i].resize(this->mUnsortedClusters[1].
size() + 1);
452 if (mcLabels !=
nullptr) {
453 for (
int iLayer{0}; iLayer < nLayers; ++iLayer) {
454 this->mClusterLabels[iLayer] = (*mcLabels)[iLayer];
465 mcHeaderTree->SetBranchAddress(
"MCEventHeader.", &mcheader);
467 this->mPrimaryVertices.clear();
468 this->mPrimaryVerticesLabels.clear();
470 const auto& clockLayer = this->getROFOverlapTableView().getClockLayer();
471 const auto rofLength = clockLayer.mROFLength;
474 for (Long64_t iEvent = 0; iEvent <
nEvents; ++iEvent) {
475 mcHeaderTree->GetEntry(iEvent);
478 clockLayer.getROFStartInBC(iRof),
480 vertex.setXYZ(mcheader->GetX(), mcheader->GetY(), mcheader->GetZ());
481 vertex.setNContributors(30);
483 LOGP(
debug,
"ROF {}: Added primary vertex at ({}, {}, {})", iRof, mcheader->GetX(), mcheader->GetY(), mcheader->GetZ());
484 this->addPrimaryVertex(
vertex);
486 if ((iEvent + 1) % inROFpileup == 0 || iEvent ==
nEvents - 1) {
490 updateHostROFVertexLookupTable();
496 LOGP(info,
"TRK: using truth seeds as vertices from DigitizationContext");
497 this->mPrimaryVertices.clear();
498 this->mPrimaryVerticesLabels.clear();
501 const auto irs = dc->getEventRecords();
504 const int64_t anchorBC = mTFAnchorIR.toLong();
505 const auto& clockLayer = this->getROFOverlapTableView().getClockLayer();
506 const auto rofLength = clockLayer.mROFLength;
514 std::vector<VertEntry> entries;
517 auto eveId2colId = dc->getCollisionIndicesForSource(iSrc);
518 for (
int iEve{0}; iEve < mcReader.
getNEvents(iSrc); ++iEve) {
519 const auto&
ir = irs[eveId2colId[iEve]];
528 vert.setNContributors(std::max(1L, std::ranges::count_if(
530 [](
const auto& trk) {
531 return trk.isPrimary() && trk.GetPt() > 0.05 && std::abs(trk.GetEta()) < 1.1;
533 vert.setXYZ((
float)eve.GetX(), (float)eve.GetY(), (float)eve.GetZ());
535 constexpr float cov = 50e-9f;
536 vert.setCov(cov, cov, cov, cov, cov, cov);
537 entries.push_back({evBC, vert, iEve});
544 std::ranges::sort(entries, {}, &VertEntry::bc);
546 for (
const auto& e : entries) {
547 this->addPrimaryVertex(e.vertex);
549 this->addPrimaryVertexLabel({lbl, 1.f});
551 updateHostROFVertexLookupTable();
552 LOGP(info,
"TRK truth seeding: added {} vertices", entries.size());