Skip to content

Commit a072ce3

Browse files
wiechulashahor02
authored andcommitted
TPC: Update Kr cluster finder workflow
* smaller algorithm improvements in Kr cluster finder * adapt workflow to new moving window in Kr cluster finder to be able to process full TFs * some code cleanup
1 parent c8fc52f commit a072ce3

6 files changed

Lines changed: 162 additions & 232 deletions

File tree

Detectors/TPC/reconstruction/include/TPCReconstruction/KrBoxClusterFinder.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
#include <vector>
8888
#include <array>
8989
#include <deque>
90+
#include <gsl/span>
9091

9192
namespace o2
9293
{
@@ -171,10 +172,12 @@ class KrBoxClusterFinder
171172
mMaxClusterSizeTime = maxClusterSizeTime;
172173
}
173174

174-
void fillADCValue(int cru, int rowInSector, int padInRow, int timeBin, float adcValue);
175-
void resetADCMap();
175+
void loopOverSector(const gsl::span<const Digit> eventSector, const int sector);
176176

177-
void loopOverSector(std::vector<o2::tpc::Digit>& eventSector, const int sector);
177+
void loopOverSector(const std::vector<Digit>& eventSector, const int sector)
178+
{
179+
loopOverSector(gsl::span(eventSector.data(), eventSector.size()), sector);
180+
}
178181

179182
private:
180183
// These variables can be varied
@@ -243,10 +246,17 @@ class KrBoxClusterFinder
243246
/// Time slice four is the interesting one. In there, local maxima are found and clusters are built from it. After it is processed, timeslice number 1 will be dropped and another timeslice will be put at the end of the set.
244247
std::deque<TimeSliceSector> mSetOfTimeSlices{};
245248

246-
void createInitialMap(std::vector<o2::tpc::Digit>& eventSector);
247-
void popFirstTimeSliceFromMap();
249+
/// count the number of ADC values in each slice which satisfy the condition for the minumum Qmax
250+
std::deque<int> mNumADCwithMinQmax{};
251+
252+
void createInitialMap(const gsl::span<const Digit> eventSector);
253+
void popFirstTimeSliceFromMap()
254+
{
255+
mSetOfTimeSlices.pop_front();
256+
mNumADCwithMinQmax.pop_front();
257+
}
248258
void fillADCValueInLastSlice(int cru, int rowInSector, int padInRow, float adcValue);
249-
void addTimeSlice(std::vector<o2::tpc::Digit>& eventSector, const int timeSlice);
259+
void addTimeSlice(const gsl::span<const Digit> eventSector, const int timeSlice);
250260

251261
/// For each ROC, the maximum cluster size has to be chosen
252262
void setMaxClusterSize(int row);

Detectors/TPC/reconstruction/src/KrBoxClusterFinder.cxx

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,16 @@ void KrBoxClusterFinder::loadGainMapFromFile(const std::string_view calDetFileNa
3838
LOGP(info, "Loaded gain map object '{}' from file '{}'", calDetFileName, gainMapName);
3939
}
4040

41-
void KrBoxClusterFinder::createInitialMap(std::vector<o2::tpc::Digit>& eventSector)
41+
void KrBoxClusterFinder::createInitialMap(const gsl::span<const Digit> eventSector)
4242
{
4343
mSetOfTimeSlices.clear();
44+
mNumADCwithMinQmax.clear();
4445

4546
for (int iTimeSlice = 0; iTimeSlice <= 2 * mMaxClusterSizeTime; ++iTimeSlice) {
4647
addTimeSlice(eventSector, iTimeSlice);
4748
}
4849
}
4950

50-
void KrBoxClusterFinder::popFirstTimeSliceFromMap()
51-
{
52-
mSetOfTimeSlices.pop_front();
53-
}
54-
5551
void KrBoxClusterFinder::fillADCValueInLastSlice(int cru, int rowInSector, int padInRow, float adcValue)
5652
{
5753
auto& timeSlice = mSetOfTimeSlices.back();
@@ -81,9 +77,10 @@ void KrBoxClusterFinder::fillADCValueInLastSlice(int cru, int rowInSector, int p
8177
timeSlice[rowInSector][corPad] = adcValue;
8278
}
8379

84-
void KrBoxClusterFinder::addTimeSlice(std::vector<o2::tpc::Digit>& eventSector, const int timeSlice)
80+
void KrBoxClusterFinder::addTimeSlice(const gsl::span<const Digit> eventSector, const int timeSlice)
8581
{
8682
mSetOfTimeSlices.emplace_back();
83+
auto& nADCminQmax = mNumADCwithMinQmax.emplace_back();
8784

8885
for (; mFirstDigit < eventSector.size(); ++mFirstDigit) {
8986
const auto& digit = eventSector[mFirstDigit];
@@ -97,35 +94,34 @@ void KrBoxClusterFinder::addTimeSlice(std::vector<o2::tpc::Digit>& eventSector,
9794

9895
const int rowInSector = digit.getRow();
9996
const int padInRow = digit.getPad();
100-
float adcValue = digit.getChargeFloat();
97+
const float adcValue = digit.getChargeFloat();
98+
if (adcValue > mQThresholdMax) {
99+
++nADCminQmax;
100+
}
101101

102102
fillADCValueInLastSlice(cru, rowInSector, padInRow, adcValue);
103103
}
104104
}
105105

106-
void KrBoxClusterFinder::loopOverSector(std::vector<o2::tpc::Digit>& eventSector, const int sector)
106+
void KrBoxClusterFinder::loopOverSector(const gsl::span<const Digit> eventSector, const int sector)
107107
{
108108
mFirstDigit = 0;
109109
mSector = sector;
110110

111111
createInitialMap(eventSector);
112112
for (int iTimeSlice = mMaxClusterSizeTime; iTimeSlice < mMaxTimes - mMaxClusterSizeTime; ++iTimeSlice) {
113-
findLocalMaxima(true, iTimeSlice);
113+
// only search for a local maximum if the central time slice has at least one ADC above the charge threshold
114+
if (mNumADCwithMinQmax[mMaxClusterSizeTime]) {
115+
findLocalMaxima(true, iTimeSlice);
116+
}
114117
popFirstTimeSliceFromMap();
115118
addTimeSlice(eventSector, iTimeSlice + mMaxClusterSizeTime + 1);
116-
}
117-
}
118119

119-
void KrBoxClusterFinder::resetADCMap()
120-
{
121-
// Has to be reimplemented!
122-
return;
123-
}
124-
125-
void KrBoxClusterFinder::fillADCValue(int cru, int rowInSector, int padInRow, int timeBin, float adcValue)
126-
{
127-
// Has to be reimplemented!
128-
return;
120+
// don't spend unnecessary time looping till mMaxTimes if there is no more data
121+
if (mFirstDigit >= eventSector.size()) {
122+
break;
123+
}
124+
}
129125
}
130126

131127
void KrBoxClusterFinder::init()
@@ -323,6 +319,7 @@ std::vector<std::tuple<int, int, int>> KrBoxClusterFinder::findLocalMaxima(bool
323319
}
324320
}
325321
}
322+
326323
if (!thisIsMax) {
327324
continue;
328325
} else {
@@ -338,7 +335,7 @@ std::vector<std::tuple<int, int, int>> KrBoxClusterFinder::findLocalMaxima(bool
338335
}
339336
}
340337
}
341-
// }
338+
342339
return localMaximaCoords;
343340
}
344341

Detectors/TPC/workflow/include/TPCWorkflow/KryptonClustererSpec.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#define TPC_KryptonClustererSpec_H_
1919

2020
#include "Framework/DataProcessorSpec.h"
21-
#include <string_view>
2221

2322
namespace o2
2423
{
@@ -27,7 +26,7 @@ namespace tpc
2726

2827
/// create a processor spec
2928
/// read simulated TPC clusters from file and publish
30-
o2::framework::DataProcessorSpec getKryptonClustererSpec(const std::string inputSpec, int ilane, std::vector<int> const& sectors);
29+
o2::framework::DataProcessorSpec getKryptonClustererSpec();
3130

3231
} // end namespace tpc
3332
} // end namespace o2

Detectors/TPC/workflow/src/KryptonClustererSpec.cxx

Lines changed: 35 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,20 @@
1010
// or submit itself to any jurisdiction.
1111

1212
#include <memory>
13-
#include <vector>
14-
#include <string>
15-
#include <algorithm>
16-
#include "fmt/format.h"
1713

1814
#include "Framework/Task.h"
19-
#include "Framework/ControlService.h"
20-
#include "Framework/ConfigParamRegistry.h"
15+
#include "Framework/InputRecordWalker.h"
2116
#include "Framework/Logger.h"
2217
#include "Framework/DataProcessorSpec.h"
23-
#include "Framework/WorkflowSpec.h"
24-
25-
#include "DataFormatsTPC/TPCSectorHeader.h"
2618
#include "Headers/DataHeader.h"
27-
#include "CCDB/CcdbApi.h"
28-
#include "DetectorsCalibration/Utils.h"
19+
#include "DataFormatsTPC/TPCSectorHeader.h"
2920

30-
#include "TPCBase/RDHUtils.h"
31-
#include "TPCBase/Mapper.h"
3221
#include "TPCReconstruction/KrBoxClusterFinder.h"
3322
#include "TPCReconstruction/KrCluster.h"
34-
#include "TPCReconstruction/RawReaderCRU.h"
35-
#include "TPCWorkflow/CalibProcessingHelper.h"
3623
#include "TPCWorkflow/KryptonClustererSpec.h"
3724

3825
using namespace o2::framework;
26+
using namespace o2::header;
3927
using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType;
4028

4129
namespace o2
@@ -46,132 +34,69 @@ namespace tpc
4634
class KrBoxClusterFinderDevice : public o2::framework::Task
4735
{
4836
public:
49-
KrBoxClusterFinderDevice(int lane, const std::vector<int>& sectors) : mClusters(36), mLane{lane}, mSectors(sectors), mClusterFinder{std::make_unique<KrBoxClusterFinder>()} {}
37+
KrBoxClusterFinderDevice() : mClusterFinder{std::make_unique<KrBoxClusterFinder>()} {}
5038

5139
void init(o2::framework::InitContext& ic) final
5240
{
53-
// set up ADC value filling
54-
mRawReader.createReader("");
55-
56-
mRawReader.setLinkZSCallback([this](int cru, int rowInSector, int padInRow, int timeBin, float adcValue) -> bool {
57-
const int sector = cru / 10;
58-
if ((mLastSector > -1) && (sector != mLastSector)) {
59-
LOGP(debug, "analysing sector {} ({})", mLastSector, sector);
60-
mClusterFinder->findLocalMaxima(true);
61-
LOGP(info, "found {} clusters in sector {}", mClusterFinder->getClusters().size(), mLastSector);
62-
std::swap(mClusters[mLastSector], mClusterFinder->getClusters());
63-
mClusterFinder->resetADCMap();
64-
mClusterFinder->resetClusters();
65-
}
66-
67-
mClusterFinder->fillADCValue(cru, rowInSector, padInRow, timeBin, adcValue);
68-
69-
mLastSector = sector;
70-
return true;
71-
});
72-
73-
mMaxEvents = static_cast<uint32_t>(ic.options().get<int>("max-events"));
74-
mForceQuit = ic.options().get<bool>("force-quit");
41+
mClusterFinder->init();
7542
}
7643

7744
void run(o2::framework::ProcessingContext& pc) final
7845
{
79-
// in case the maximum number of events was reached don't do further processing
80-
if (mReadyToQuit) {
81-
return;
82-
}
46+
for (auto const& inputRef : InputRecordWalker(pc.inputs())) {
47+
auto const* sectorHeader = DataRefUtils::getHeader<TPCSectorHeader*>(inputRef);
48+
if (sectorHeader == nullptr) {
49+
LOGP(error, "sector header missing on header stack for input on ", inputRef.spec->binding);
50+
continue;
51+
}
8352

84-
std::for_each(mClusters.begin(), mClusters.end(), [](auto& cl) { cl.clear(); });
53+
const int sector = sectorHeader->sector();
54+
auto inDigits = pc.inputs().get<gsl::span<o2::tpc::Digit>>(inputRef);
8555

86-
auto& reader = mRawReader.getReaders()[0];
87-
mActiveSectors = calib_processing_helper::processRawData(pc.inputs(), reader, false, mSectors);
56+
mClusterFinder->loopOverSector(inDigits, sector);
8857

89-
// analyse the final sector
90-
if (mLastSector > -1) {
91-
LOGP(debug, "analysing sector {}", mLastSector);
92-
mClusterFinder->findLocalMaxima(true);
93-
if (mClusterFinder->getClusters().size()) {
94-
LOGP(info, "found {} clusters in sector {}", mClusterFinder->getClusters().size(), mLastSector);
95-
std::swap(mClusters[mLastSector], mClusterFinder->getClusters());
96-
}
97-
}
98-
mClusterFinder->resetADCMap();
99-
mClusterFinder->resetClusters();
58+
snapshotClusters(pc.outputs(), mClusterFinder->getClusters(), sector);
10059

101-
++mProcessedTFs;
102-
LOGP(info, "Number of processed time frames: {} ({})", mProcessedTFs, mMaxEvents);
103-
104-
snapshotClusters(pc.outputs());
105-
106-
// TODO: is this still needed?
107-
if (mMaxEvents && (mProcessedTFs >= mMaxEvents)) {
108-
LOGP(info, "Maximm number of time frames reached ({}), no more processing will be done", mMaxEvents);
109-
mReadyToQuit = true;
110-
if (mForceQuit) {
111-
pc.services().get<ControlService>().endOfStream();
112-
pc.services().get<ControlService>().readyToQuit(QuitRequest::All);
113-
} else {
114-
pc.services().get<ControlService>().readyToQuit(QuitRequest::Me);
115-
}
116-
}
117-
}
60+
LOGP(info, "processed sector {} with {} digits and {} reconstructed clusters", sector, inDigits.size(), mClusterFinder->getClusters().size());
11861

119-
void endOfStream(o2::framework::EndOfStreamContext& ec) final
120-
{
121-
LOGP(info, "endOfStream");
122-
if (mActiveSectors) {
123-
snapshotClusters(ec.outputs());
62+
mClusterFinder->resetClusters();
12463
}
125-
ec.services().get<ControlService>().readyToQuit(QuitRequest::Me);
64+
65+
++mProcessedTFs;
66+
LOGP(info, "Number of processed time frames: {}", mProcessedTFs);
12667
}
12768

12869
private:
129-
std::vector<std::vector<KrCluster>> mClusters;
13070
std::unique_ptr<KrBoxClusterFinder> mClusterFinder;
131-
int mLastSector{-1};
132-
rawreader::RawReaderCRUManager mRawReader;
133-
int mLane{0}; ///< lane number of processor
134-
std::vector<int> mSectors{}; ///< sectors to process in this instance
135-
uint32_t mMaxEvents{0};
13671
uint32_t mProcessedTFs{0};
137-
bool mReadyToQuit{false};
138-
bool mCalibDumped{false};
139-
bool mForceQuit{false};
140-
uint64_t mActiveSectors{0}; ///< bit mask of active sectors
14172

14273
//____________________________________________________________________________
143-
void snapshotClusters(DataAllocator& output)
74+
void snapshotClusters(DataAllocator& output, const std::vector<o2::tpc::KrCluster>& clusters, int sector)
14475
{
145-
for (const int sector : mSectors) {
146-
o2::tpc::TPCSectorHeader header{sector};
147-
header.activeSectors = mActiveSectors;
148-
// digit for now are transported per sector, not per lane
149-
output.snapshot(Output{"TPC", "KRCLUSTERS", static_cast<SubSpecificationType>(sector), Lifetime::Timeframe, header},
150-
mClusters[sector]);
151-
}
152-
mActiveSectors = 0;
76+
o2::tpc::TPCSectorHeader header{sector};
77+
header.activeSectors = (0x1 << sector);
78+
output.snapshot(Output{gDataOriginTPC, "KRCLUSTERS", static_cast<SubSpecificationType>(sector), Lifetime::Timeframe, header}, clusters);
15379
}
15480
};
15581

156-
o2::framework::DataProcessorSpec getKryptonClustererSpec(const std::string inputSpec, int ilane, std::vector<int> const& sectors)
82+
o2::framework::DataProcessorSpec getKryptonClustererSpec()
15783
{
15884
using device = o2::tpc::KrBoxClusterFinderDevice;
15985

86+
std::vector<InputSpec> inputs{
87+
InputSpec{"digits", gDataOriginTPC, "DIGITS", 0, Lifetime::Timeframe},
88+
};
89+
16090
std::vector<OutputSpec> outputs;
161-
for (auto isector : sectors) {
162-
outputs.emplace_back("TPC", "KRCLUSTERS", static_cast<SubSpecificationType>(isector), Lifetime::Timeframe);
163-
}
91+
outputs.emplace_back(gDataOriginTPC, "KRCLUSTERS", 0, Lifetime::Timeframe);
16492

16593
return DataProcessorSpec{
166-
fmt::format("tpc-krypton-clusterer-{}", ilane),
167-
select(inputSpec.data()),
94+
"tpc-krypton-clusterer",
95+
inputs,
16896
outputs,
169-
AlgorithmSpec{adaptFromTask<device>(ilane, sectors)},
170-
Options{
171-
{"max-events", VariantType::Int, 0, {"maximum number of events to process"}},
172-
{"force-quit", VariantType::Bool, false, {"force quit after max-events have been reached"}},
173-
} // end Options
174-
}; // end DataProcessorSpec
97+
AlgorithmSpec{adaptFromTask<device>()},
98+
Options{} // end Options
99+
}; // end DataProcessorSpec
175100
}
176101
} // namespace tpc
177102
} // namespace o2

0 commit comments

Comments
 (0)