|
15 | 15 | #include <chrono> |
16 | 16 | #include <format> |
17 | 17 | #include <fstream> |
| 18 | +#include <numeric> |
18 | 19 |
|
| 20 | +#include "CommonDataFormat/IRFrame.h" |
19 | 21 | #include "DataFormatsTRK/Cluster.h" |
20 | 22 | #include "DataFormatsTRK/ROFRecord.h" |
21 | 23 | #include "DetectorsBase/GeometryManager.h" |
@@ -464,12 +466,69 @@ void TrackerDPL::run(ProcessingContext& pc) |
464 | 466 | LOGP(info, "Good tracks: {} ({:.1f}%)", goodTracks, totalTracks > 0 ? 100.0 * goodTracks / totalTracks : 0); |
465 | 467 | LOGP(info, "Fake tracks: {} ({:.1f}%)", fakeTracks, totalTracks > 0 ? 100.0 * fakeTracks / totalTracks : 0); |
466 | 468 |
|
| 469 | + // Build per-ROF track records and IR frames in the clock-layer's frame. |
| 470 | + // The clock layer is the fastest TRK layer (max mNROFsTF) — see |
| 471 | + // ROFOverlapTableView::getClock(). Each track's TimeStamp deterministically |
| 472 | + // maps to a clock-layer ROF; track ordering from the tracker is by |
| 473 | + // increasing time, so the per-ROF firstEntry/nEntries pair indexes a |
| 474 | + // contiguous range of allTracks. Mirrors ITS TrackingInterface.cxx. |
| 475 | + const auto& rofView = timeFrame.getROFOverlapTableView(); |
| 476 | + const auto& clockLayer = rofView.getClockLayer(); |
| 477 | + const int clockLayerId = rofView.getClock(); |
| 478 | + const int64_t anchorBC = timeFrame.getTFAnchorIR().toLong(); |
| 479 | + |
| 480 | + int highestROF = static_cast<int>(clockLayer.mNROFsTF); |
| 481 | + for (const auto& trc : allTracks) { |
| 482 | + highestROF = std::max(highestROF, static_cast<int>(clockLayer.getROF(trc.getTimeStamp()))); |
| 483 | + } |
| 484 | + for (const auto& vtx : timeFrame.getPrimaryVertices()) { |
| 485 | + highestROF = std::max(highestROF, static_cast<int>(clockLayer.getROF(vtx.getTimeStamp().lower()))); |
| 486 | + } |
| 487 | + |
| 488 | + std::vector<o2::trk::ROFRecord> allTrackROFs(highestROF); |
| 489 | + for (size_t iROF = 0; iROF < allTrackROFs.size(); ++iROF) { |
| 490 | + auto& rof = allTrackROFs[iROF]; |
| 491 | + o2::InteractionRecord ir; |
| 492 | + ir.setFromLong(anchorBC + static_cast<int64_t>(clockLayer.getROFStartInBC(iROF))); |
| 493 | + rof.setBCData(ir); |
| 494 | + rof.setROFrame(iROF); |
| 495 | + rof.setFirstEntry(0); |
| 496 | + rof.setNEntries(0); |
| 497 | + } |
| 498 | + |
| 499 | + std::vector<int> rofEntries(highestROF + 1, 0); |
| 500 | + for (const auto& trc : allTracks) { |
| 501 | + const int rof = static_cast<int>(clockLayer.getROF(trc.getTimeStamp())); |
| 502 | + if (rof >= 0 && rof < highestROF) { |
| 503 | + ++rofEntries[rof]; |
| 504 | + } |
| 505 | + } |
| 506 | + std::exclusive_scan(rofEntries.begin(), rofEntries.end(), rofEntries.begin(), 0); |
| 507 | + |
| 508 | + std::vector<o2::dataformats::IRFrame> irFrames; |
| 509 | + irFrames.reserve(allTrackROFs.size()); |
| 510 | + const auto& maskView = timeFrame.getROFMaskView(); |
| 511 | + const auto rofLenMinus1 = clockLayer.mROFLength > 0 ? clockLayer.mROFLength - 1 : 0; |
| 512 | + for (size_t iROF = 0; iROF < allTrackROFs.size(); ++iROF) { |
| 513 | + allTrackROFs[iROF].setFirstEntry(rofEntries[iROF]); |
| 514 | + allTrackROFs[iROF].setNEntries(rofEntries[iROF + 1] - rofEntries[iROF]); |
| 515 | + if (maskView.isROFEnabled(clockLayerId, static_cast<int>(iROF))) { |
| 516 | + const auto& bcStart = allTrackROFs[iROF].getBCData(); |
| 517 | + auto& irFrame = irFrames.emplace_back(bcStart, bcStart + rofLenMinus1); |
| 518 | + irFrame.info = allTrackROFs[iROF].getNEntries(); |
| 519 | + } |
| 520 | + } |
| 521 | + |
467 | 522 | pc.outputs().snapshot(o2::framework::Output{"TRK", "TRACKS", 0}, allTracks); |
| 523 | + pc.outputs().snapshot(o2::framework::Output{"TRK", "TRACKSROF", 0}, allTrackROFs); |
| 524 | + pc.outputs().snapshot(o2::framework::Output{"TRK", "IRFRAMES", 0}, irFrames); |
468 | 525 | if (mIsMC) { |
469 | 526 | pc.outputs().snapshot(o2::framework::Output{"TRK", "TRACKSMCTR", 0}, allLabels); |
470 | 527 | } |
471 | 528 |
|
472 | | - LOGP(info, "Tracks{} streamed to output", mIsMC ? " and MC labels" : ""); |
| 529 | + LOGP(info, "TRK pushed {} tracks in {} ROFs and {} IR frames{}", |
| 530 | + allTracks.size(), allTrackROFs.size(), irFrames.size(), |
| 531 | + mIsMC ? " (with MC labels)" : ""); |
473 | 532 | }; |
474 | 533 |
|
475 | 534 | #ifdef TRK_HAS_GPU_TRACKING |
@@ -511,6 +570,8 @@ DataProcessorSpec getTrackerSpec(bool useMC, const std::string& hitRecoConfig, c |
511 | 570 | std::vector<InputSpec> inputs; |
512 | 571 | std::vector<OutputSpec> outputs; |
513 | 572 | outputs.emplace_back("TRK", "TRACKS", 0, Lifetime::Timeframe); |
| 573 | + outputs.emplace_back("TRK", "TRACKSROF", 0, Lifetime::Timeframe); |
| 574 | + outputs.emplace_back("TRK", "IRFRAMES", 0, Lifetime::Timeframe); |
514 | 575 | auto ggRequest = std::make_shared<o2::base::GRPGeomRequest>(false, // orbitResetTime |
515 | 576 | false, // GRPECS=true |
516 | 577 | false, // GRPLHCIF |
|
0 commit comments