Skip to content

Commit 8d63de6

Browse files
authored
[MCH] modify (pre)clustering workflows to process several ROF per TF (#5463)
1 parent cd087a8 commit 8d63de6

File tree

12 files changed

+471
-196
lines changed

12 files changed

+471
-196
lines changed

Detectors/MUON/MCH/Base/include/MCHBase/ClusterBlock.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#define ALICEO2_MCH_CLUSTERBLOCK_H_
1818

1919
#include <iostream>
20+
#include <stdexcept>
2021

2122
namespace o2
2223
{
@@ -51,7 +52,10 @@ struct ClusterStruct {
5152
/// Build the unique ID of the cluster from the chamber ID, detection element ID and cluster index
5253
static uint32_t buildUniqueId(int chamberId, int deId, int clusterIndex)
5354
{
54-
return (((chamberId & 0xF) << 28) | ((deId & 0x7FF) << 17) | (clusterIndex & 0x1FFFF));
55+
if ((clusterIndex & 0x1FFFF) != clusterIndex) {
56+
throw std::runtime_error("invalid cluster index. Cannot build unique ID");
57+
}
58+
return (((chamberId & 0xF) << 28) | ((deId & 0x7FF) << 17) | clusterIndex);
5559
}
5660
};
5761

Detectors/MUON/MCH/Base/include/MCHBase/PreCluster.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ namespace mch
2929

3030
/// precluster minimal structure
3131
struct PreCluster {
32-
uint16_t firstDigit; ///< index of first associated digit in the ordered vector of digits
33-
uint16_t nDigits; ///< number of digits attached to this precluster
32+
uint32_t firstDigit; ///< index of first associated digit in the ordered vector of digits
33+
uint32_t nDigits; ///< number of digits attached to this precluster
3434

3535
/// return the index of last associated digit in the ordered vector of digits
36-
uint16_t lastDigit() const { return firstDigit + nDigits - 1; }
36+
uint32_t lastDigit() const { return firstDigit + nDigits - 1; }
3737

3838
void print(std::ostream& stream, gsl::span<const Digit> digits) const;
3939
};

Detectors/MUON/MCH/PreClustering/src/PreClusterFinder.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ void PreClusterFinder::getPreClusters(std::vector<o2::mch::PreCluster>& preClust
178178
}
179179

180180
// add this precluster
181-
uint16_t firstDigit = digits.size();
182-
uint16_t nDigits = cluster->lastPad - cluster->firstPad + 1;
181+
uint32_t firstDigit = digits.size();
182+
uint32_t nDigits = cluster->lastPad - cluster->firstPad + 1;
183183
preClusters.push_back({firstDigit, nDigits});
184184

185185
// add the digits of this precluster

Detectors/MUON/MCH/Workflow/CMakeLists.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ o2_add_library(MCHWorkflow
1414
PUBLIC_LINK_LIBRARIES O2::Framework O2::DPLUtils O2::MCHRawDecoder Boost::program_options
1515
O2::MCHRawImplHelpers RapidJSON::RapidJSON O2::MCHMappingInterface
1616
O2::MCHPreClustering O2::MCHMappingImpl4 O2::MCHRawElecMap O2::MCHBase
17-
O2::MCHClustering)
17+
O2::DataFormatsMCH O2::MCHClustering)
1818

1919
o2_add_executable(
2020
cru-page-reader-workflow
@@ -56,13 +56,13 @@ o2_add_executable(
5656
digits-reader-workflow
5757
SOURCES src/DigitSamplerSpec.cxx src/digits-reader-workflow.cxx
5858
COMPONENT_NAME mch
59-
PUBLIC_LINK_LIBRARIES O2::MCHWorkflow)
59+
PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsMCH O2::MCHBase O2::MCHMappingImpl3)
6060

6161
o2_add_executable(
6262
preclusters-sink-workflow
6363
SOURCES src/PreClusterSinkSpec.cxx src/preclusters-sink-workflow.cxx
6464
COMPONENT_NAME mch
65-
PUBLIC_LINK_LIBRARIES O2::MCHWorkflow)
65+
PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsMCH O2::MCHBase O2::MCHMappingImpl3)
6666

6767
o2_add_executable(
6868
preclusters-to-clusters-original-workflow
@@ -74,7 +74,7 @@ o2_add_executable(
7474
clusters-sink-workflow
7575
SOURCES src/ClusterSinkSpec.cxx src/clusters-sink-workflow.cxx
7676
COMPONENT_NAME mch
77-
PUBLIC_LINK_LIBRARIES O2::MCHWorkflow)
77+
PUBLIC_LINK_LIBRARIES O2::Framework O2::DataFormatsMCH O2::MCHBase O2::MCHMappingImpl3)
7878

7979
o2_add_executable(
8080
clusters-sampler-workflow

Detectors/MUON/MCH/Workflow/README.md

Lines changed: 111 additions & 25 deletions
Large diffs are not rendered by default.

Detectors/MUON/MCH/Workflow/src/ClusterFinderOriginalSpec.cxx

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@
1919
#include <fstream>
2020
#include <chrono>
2121
#include <vector>
22-
2322
#include <stdexcept>
2423

24+
#include <gsl/span>
25+
2526
#include "Framework/CallbackService.h"
2627
#include "Framework/ConfigParamRegistry.h"
2728
#include "Framework/ControlService.h"
@@ -31,6 +32,7 @@
3132
#include "Framework/Task.h"
3233
#include "Framework/Logger.h"
3334

35+
#include "DataFormatsMCH/ROFRecord.h"
3436
#include "MCHBase/Digit.h"
3537
#include "MCHBase/PreCluster.h"
3638
#include "MCHBase/ClusterBlock.h"
@@ -65,27 +67,59 @@ class ClusterFinderOriginalTask
6567
//_________________________________________________________________________________________________
6668
void run(framework::ProcessingContext& pc)
6769
{
68-
/// read the preclusters and associated digits, clusterize and send the clusters
70+
/// read the preclusters and associated digits, clusterize and send the clusters for all events in the TF
6971

7072
// get the input preclusters and associated digits
73+
auto preClusterROFs = pc.inputs().get<gsl::span<ROFRecord>>("preclusterrofs");
7174
auto preClusters = pc.inputs().get<gsl::span<PreCluster>>("preclusters");
7275
auto digits = pc.inputs().get<gsl::span<Digit>>("digits");
7376

74-
// clusterize every preclusters
75-
auto tStart = std::chrono::high_resolution_clock::now();
76-
mClusterFinder.reset();
77-
for (const auto& preCluster : preClusters) {
78-
mClusterFinder.findClusters(digits.subspan(preCluster.firstDigit, preCluster.nDigits));
79-
}
80-
auto tEnd = std::chrono::high_resolution_clock::now();
81-
mTimeClusterFinder += tEnd - tStart;
77+
//LOG(INFO) << "received time frame with " << preClusterROFs.size() << " interactions";
78+
79+
// create the output messages for clusters and attached digits
80+
auto& clusterROFs = pc.outputs().make<std::vector<ROFRecord>>(OutputRef{"clusterrofs"});
81+
auto& clusters = pc.outputs().make<std::vector<ClusterStruct>>(OutputRef{"clusters"});
82+
auto& usedDigits = pc.outputs().make<std::vector<Digit>>(OutputRef{"clusterdigits"});
8283

83-
// send the output messages
84-
pc.outputs().snapshot(Output{"MCH", "CLUSTERS", 0, Lifetime::Timeframe}, mClusterFinder.getClusters());
85-
pc.outputs().snapshot(Output{"MCH", "CLUSTERDIGITS", 0, Lifetime::Timeframe}, mClusterFinder.getUsedDigits());
84+
clusterROFs.reserve(preClusterROFs.size());
85+
for (const auto& preClusterROF : preClusterROFs) {
86+
87+
//LOG(INFO) << "processing interaction: " << preClusterROF.getBCData() << "...";
88+
89+
// clusterize every preclusters
90+
auto tStart = std::chrono::high_resolution_clock::now();
91+
mClusterFinder.reset();
92+
for (const auto& preCluster : preClusters.subspan(preClusterROF.getFirstIdx(), preClusterROF.getNEntries())) {
93+
mClusterFinder.findClusters(digits.subspan(preCluster.firstDigit, preCluster.nDigits));
94+
}
95+
auto tEnd = std::chrono::high_resolution_clock::now();
96+
mTimeClusterFinder += tEnd - tStart;
97+
98+
// fill the ouput messages
99+
clusterROFs.emplace_back(preClusterROF.getBCData(), clusters.size(), mClusterFinder.getClusters().size());
100+
writeClusters(clusters, usedDigits);
101+
}
86102
}
87103

88104
private:
105+
//_________________________________________________________________________________________________
106+
void writeClusters(std::vector<ClusterStruct, o2::pmr::polymorphic_allocator<ClusterStruct>>& clusters,
107+
std::vector<Digit, o2::pmr::polymorphic_allocator<Digit>>& usedDigits) const
108+
{
109+
/// fill the output messages with clusters and attached digits of the current event
110+
/// modify the references to the attached digits according to their position in the global vector
111+
112+
auto clusterOffset = clusters.size();
113+
clusters.insert(clusters.end(), mClusterFinder.getClusters().begin(), mClusterFinder.getClusters().end());
114+
115+
auto digitOffset = usedDigits.size();
116+
usedDigits.insert(usedDigits.end(), mClusterFinder.getUsedDigits().begin(), mClusterFinder.getUsedDigits().end());
117+
118+
for (auto itCluster = clusters.begin() + clusterOffset; itCluster < clusters.end(); ++itCluster) {
119+
itCluster->firstDigit += digitOffset;
120+
}
121+
}
122+
89123
ClusterFinderOriginal mClusterFinder{}; ///< clusterizer
90124
std::chrono::duration<double> mTimeClusterFinder{}; ///< timer
91125
};
@@ -95,10 +129,12 @@ o2::framework::DataProcessorSpec getClusterFinderOriginalSpec()
95129
{
96130
return DataProcessorSpec{
97131
"ClusterFinderOriginal",
98-
Inputs{InputSpec{"preclusters", "MCH", "PRECLUSTERS", 0, Lifetime::Timeframe},
132+
Inputs{InputSpec{"preclusterrofs", "MCH", "PRECLUSTERROFS", 0, Lifetime::Timeframe},
133+
InputSpec{"preclusters", "MCH", "PRECLUSTERS", 0, Lifetime::Timeframe},
99134
InputSpec{"digits", "MCH", "PRECLUSTERDIGITS", 0, Lifetime::Timeframe}},
100-
Outputs{OutputSpec{"MCH", "CLUSTERS", 0, Lifetime::Timeframe},
101-
OutputSpec{"MCH", "CLUSTERDIGITS", 0, Lifetime::Timeframe}},
135+
Outputs{OutputSpec{{"clusterrofs"}, "MCH", "CLUSTERROFS", 0, Lifetime::Timeframe},
136+
OutputSpec{{"clusters"}, "MCH", "CLUSTERS", 0, Lifetime::Timeframe},
137+
OutputSpec{{"clusterdigits"}, "MCH", "CLUSTERDIGITS", 0, Lifetime::Timeframe}},
102138
AlgorithmSpec{adaptFromTask<ClusterFinderOriginalTask>()},
103139
Options{}};
104140
}

Detectors/MUON/MCH/Workflow/src/ClusterSinkSpec.cxx

Lines changed: 77 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717

1818
#include <iostream>
1919
#include <fstream>
20-
2120
#include <array>
2221
#include <stdexcept>
2322
#include <vector>
2423

24+
#include <gsl/span>
25+
2526
#include "Framework/CallbackService.h"
2627
#include "Framework/ConfigParamRegistry.h"
2728
#include "Framework/ControlService.h"
@@ -30,6 +31,7 @@
3031
#include "Framework/Task.h"
3132
#include "Framework/Logger.h"
3233

34+
#include "DataFormatsMCH/ROFRecord.h"
3335
#include "MCHBase/Digit.h"
3436
#include "MCHBase/ClusterBlock.h"
3537
#include "MCHMappingInterface/Segmentation.h"
@@ -72,42 +74,89 @@ class ClusterSinkTask
7274
//_________________________________________________________________________________________________
7375
void run(framework::ProcessingContext& pc)
7476
{
75-
/// dump the clusters with associated digits of the current event
77+
/// dump the clusters with associated digits of all events in the current TF
7678

7779
// get the input clusters and associated digits
80+
auto rofs = pc.inputs().get<gsl::span<ROFRecord>>("rofs");
7881
auto clusters = pc.inputs().get<gsl::span<ClusterStruct>>("clusters");
7982
auto digits = pc.inputs().get<gsl::span<Digit>>("digits");
8083

81-
if (mText) {
82-
// write the clusters in ascii format
83-
mOutputFile << clusters.size() << " clusters:" << endl;
84-
for (const auto& cluster : clusters) {
85-
mOutputFile << cluster << endl;
86-
}
87-
} else {
88-
// write the number of clusters
89-
int nClusters = clusters.size();
90-
mOutputFile.write(reinterpret_cast<char*>(&nClusters), sizeof(int));
91-
92-
// write the total number of digits in these clusters
93-
int nDigits = digits.size();
94-
mOutputFile.write(reinterpret_cast<char*>(&nDigits), sizeof(int));
95-
96-
// write the clusters
97-
mOutputFile.write(reinterpret_cast<const char*>(clusters.data()), clusters.size_bytes());
98-
99-
// write the digits (after converting the pad ID into a digit UID if requested)
100-
if (mUseRun2DigitUID) {
101-
std::vector<Digit> digitsCopy(digits.begin(), digits.end());
102-
convertPadID2DigitUID(digitsCopy);
103-
mOutputFile.write(reinterpret_cast<char*>(digitsCopy.data()), digitsCopy.size() * sizeof(Digit));
84+
std::vector<ClusterStruct> eventClusters{};
85+
for (const auto& rof : rofs) {
86+
87+
if (mText) {
88+
89+
// write the clusters in ascii format
90+
mOutputFile << rof.getNEntries() << " clusters:" << endl;
91+
for (const auto& cluster : clusters.subspan(rof.getFirstIdx(), rof.getNEntries())) {
92+
mOutputFile << cluster << endl;
93+
}
94+
10495
} else {
105-
mOutputFile.write(reinterpret_cast<const char*>(digits.data()), digits.size_bytes());
96+
97+
// get the clusters and associated digits of the current event
98+
auto eventDigits = getEventClustersAndDigits(rof, clusters, digits, eventClusters);
99+
100+
// write the number of clusters
101+
int nClusters = eventClusters.size();
102+
mOutputFile.write(reinterpret_cast<char*>(&nClusters), sizeof(int));
103+
104+
// write the total number of digits in these clusters
105+
int nDigits = eventDigits.size();
106+
mOutputFile.write(reinterpret_cast<char*>(&nDigits), sizeof(int));
107+
108+
// write the clusters
109+
mOutputFile.write(reinterpret_cast<const char*>(eventClusters.data()),
110+
eventClusters.size() * sizeof(ClusterStruct));
111+
112+
// write the digits (after converting the pad ID into a digit UID if requested)
113+
if (mUseRun2DigitUID) {
114+
std::vector<Digit> digitsCopy(eventDigits.begin(), eventDigits.end());
115+
convertPadID2DigitUID(digitsCopy);
116+
mOutputFile.write(reinterpret_cast<char*>(digitsCopy.data()), digitsCopy.size() * sizeof(Digit));
117+
} else {
118+
mOutputFile.write(reinterpret_cast<const char*>(eventDigits.data()), eventDigits.size_bytes());
119+
}
106120
}
107121
}
108122
}
109123

110124
private:
125+
//_________________________________________________________________________________________________
126+
gsl::span<const Digit> getEventClustersAndDigits(const ROFRecord& rof, gsl::span<const ClusterStruct> clusters,
127+
gsl::span<const Digit> digits,
128+
std::vector<ClusterStruct>& eventClusters) const
129+
{
130+
/// copy the clusters of the current event (needed to edit the clusters)
131+
/// modify the references to the associated digits to start the indexing from 0
132+
/// return a sub-span with the associated digits
133+
134+
eventClusters.clear();
135+
136+
if (rof.getNEntries() < 1) {
137+
return {};
138+
}
139+
140+
if (rof.getLastIdx() >= clusters.size()) {
141+
throw length_error("missing clusters");
142+
}
143+
144+
eventClusters.insert(eventClusters.end(), clusters.begin() + rof.getFirstIdx(),
145+
clusters.begin() + rof.getLastIdx() + 1);
146+
147+
auto digitOffset = eventClusters.front().firstDigit;
148+
for (auto& cluster : eventClusters) {
149+
cluster.firstDigit -= digitOffset;
150+
}
151+
152+
auto nDigits = eventClusters.back().firstDigit + eventClusters.back().nDigits;
153+
if (digitOffset + nDigits > digits.size()) {
154+
throw length_error("missing digits");
155+
}
156+
157+
return digits.subspan(digitOffset, nDigits);
158+
}
159+
111160
//_________________________________________________________________________________________________
112161
void convertPadID2DigitUID(std::vector<Digit>& digits)
113162
{
@@ -153,7 +202,8 @@ o2::framework::DataProcessorSpec getClusterSinkSpec()
153202
{
154203
return DataProcessorSpec{
155204
"ClusterSink",
156-
Inputs{InputSpec{"clusters", "MCH", "CLUSTERS", 0, Lifetime::Timeframe},
205+
Inputs{InputSpec{"rofs", "MCH", "CLUSTERROFS", 0, Lifetime::Timeframe},
206+
InputSpec{"clusters", "MCH", "CLUSTERS", 0, Lifetime::Timeframe},
157207
InputSpec{"digits", "MCH", "CLUSTERDIGITS", 0, Lifetime::Timeframe}},
158208
Outputs{},
159209
AlgorithmSpec{adaptFromTask<ClusterSinkTask>()},

0 commit comments

Comments
 (0)