Project
Loading...
Searching...
No Matches
KryptonRawFilterSpec.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include <fmt/core.h>
13#include <iterator>
14#include <memory>
15#include <unordered_map>
16#include <vector>
17#include <gsl/span>
18
20#include "Framework/Task.h"
22#include "Framework/Logger.h"
24#include "Headers/DataHeader.h"
25
28#include "TPCBase/Mapper.h"
29#include "TPCBase/Sector.h"
31
32using namespace o2::framework;
33using namespace o2::header;
35
36namespace o2::tpc
37{
38
40{
41 public:
42 KrRawFilterDevice(CalPad* noise) : mNoise(noise) {}
43
45 {
46 mThresholdMax = ic.options().get<float>("threshold-max");
47 mThresholdAbs = ic.options().get<float>("threshold-abs");
48 mThresholdSigma = ic.options().get<float>("threshold-sigma");
49 mTimeBinsBefore = ic.options().get<int>("time-bins-before");
50 mTimeBinsAfter = ic.options().get<int>("time-bins-after");
51 mMaxTimeBins = ic.options().get<int>("max-time-bins");
52 mSkipIROCTSensors = ic.options().get<bool>("skip-iroc-tsen");
53 LOGP(info, "threshold-max: {}, threshold-abs: {}, threshold-sigma: {}, time-bins-before: {}, time-bins-after: {}, max-time-bins: {}, skip-iroc-tsen: {}", mThresholdMax, mThresholdAbs, mThresholdSigma, mTimeBinsBefore, mTimeBinsAfter, mMaxTimeBins, mSkipIROCTSensors);
54 }
55
57 {
58 const auto& mapper = Mapper::instance();
59 const size_t MAXROWS = 152;
60 const size_t MAXPADS = 138;
61
62 for (auto const& inputRef : InputRecordWalker(pc.inputs())) {
63 auto const* sectorHeader = DataRefUtils::getHeader<TPCSectorHeader*>(inputRef);
64 if (sectorHeader == nullptr) {
65 LOGP(error, "sector header missing on header stack for input on ", inputRef.spec->binding);
66 continue;
67 }
68
69 const int sector = sectorHeader->sector();
70 auto inDigitsO = pc.inputs().get<gsl::span<o2::tpc::Digit>>(inputRef);
71 LOGP(debug, "processing sector {} with {} input digits", sector, inDigitsO.size());
72
73 // ===| flatten digits for simple access and register interesting digit positions |===
74 // flat digit structure
75 std::vector<float> inDigits(MAXROWS * MAXPADS * mMaxTimeBins);
76
77 // counter how often a pad triggered to filter extremely noisy or struck pads
78 std::vector<size_t> nTriggered(MAXROWS * MAXPADS);
79
80 struct DigitInfo {
81 int row{};
82 int pad{};
83 int time{};
84 };
85 std::vector<DigitInfo> maxDigits;
86
87 for (const auto& digit : inDigitsO) {
88 const auto time = digit.getTimeStamp();
89 if (time >= mMaxTimeBins) {
90 continue;
91 }
92
93 const auto pad = digit.getPad();
94 const auto row = digit.getRow();
95 const auto charge = digit.getChargeFloat();
96
97 const size_t offset = row * MAXPADS * mMaxTimeBins + pad * mMaxTimeBins;
98 inDigits[offset + time] = charge;
99
100 const auto noiseThreshold = mNoise ? mThresholdSigma * mNoise->getValue(Sector(sector), row, pad) : 0.f;
101 if ((charge > mThresholdMax) && (charge > noiseThreshold)) {
102 if (!(mSkipIROCTSensors && (row == 47) && (pad > 40))) {
103 if ((time > mTimeBinsBefore) && (time < (mMaxTimeBins - mTimeBinsAfter))) {
104 maxDigits.emplace_back(DigitInfo{row, pad, time});
105 ++nTriggered[row * MAXPADS + pad];
106 }
107 }
108 }
109 }
110
111 // ===| find local maxima |===
112
113 // simple local maximum detection in time and pad direction
114 auto isLocalMaximum = [&inDigits, this](const int row, const int pad, const int time) {
115 const size_t offset = row * MAXPADS * mMaxTimeBins + pad * mMaxTimeBins + time;
116 const auto testCharge = inDigits[offset];
117
118 // look in time direction
119 if (!(testCharge > inDigits[offset + 1])) {
120 return false;
121 }
122 if (testCharge < inDigits[offset - 1]) {
123 return false;
124 }
125
126 // look in pad direction
127 if (!(testCharge > inDigits[offset + mMaxTimeBins])) {
128 return false;
129 }
130 if (testCharge < inDigits[offset - mMaxTimeBins]) {
131 return false;
132 }
133
134 // check diagonals
135 if (!(testCharge > inDigits[offset + mMaxTimeBins + 1])) {
136 return false;
137 }
138 if (!(testCharge > inDigits[offset + mMaxTimeBins - 1])) {
139 return false;
140 }
141 if (testCharge < inDigits[offset - mMaxTimeBins + 1]) {
142 return false;
143 }
144 if (testCharge < inDigits[offset - mMaxTimeBins - 1]) {
145 return false;
146 }
147
148 return true;
149 };
150
151 // digit filter
152 std::vector<Digit> digits;
153
154 // fill digits and return true if the neigbouring pad should be filtered as well
155 auto fillDigits = [&digits, &inDigits, &sector, this](const size_t row, const size_t pad, const size_t time) {
156 int cru = Mapper::REGION[row] + sector * Mapper::NREGIONS;
157 const size_t offset = row * MAXPADS * mMaxTimeBins + pad * mMaxTimeBins;
158
159 const auto chargeMax = inDigits[offset + time];
160
161 for (int iTime = time - mTimeBinsBefore; iTime < time + mTimeBinsAfter; ++iTime) {
162 const auto charge = inDigits[offset + iTime];
163 if (charge < -999.f) { // avoid double copy
164 continue;
165 }
166 digits.emplace_back(Digit(cru, charge, row, pad, iTime));
167 inDigits[offset + iTime] = -1000.f;
168 }
169
170 const auto noiseThreshold = mNoise ? mThresholdSigma * mNoise->getValue(Sector(sector), row, pad) : 0.f;
171 return (chargeMax > mThresholdAbs) && (chargeMax > noiseThreshold);
172 };
173
174 // filter digits
175 for (const auto& maxDigit : maxDigits) {
176 const auto row = maxDigit.row;
177 const auto pad = maxDigit.pad;
178 // skip extremely noisy pads
179 if (nTriggered[row * MAXPADS + pad] > mMaxTimeBins / 4) {
180 continue;
181 }
182 const auto time = maxDigit.time;
183 const int nPads = mapper.getNumberOfPadsInRowSector(row);
184 // skip edge pads
185 if ((pad == 0) || (pad == nPads - 1)) {
186 continue;
187 }
188
189 if (isLocalMaximum(row, pad, time)) {
190 auto padRef = pad;
191 while ((padRef >= 0) && fillDigits(row, padRef, time)) {
192 --padRef;
193 }
194 padRef = pad + 1;
195 while ((padRef < nPads) && fillDigits(row, padRef, time)) {
196 ++padRef;
197 }
198 }
199 }
200
201 snapshot(pc.outputs(), digits, sector);
202
203 LOGP(info, "processed sector {} with {} input and {} filtered digits", sector, inDigitsO.size(), digits.size());
204 }
205
206 ++mProcessedTFs;
207 LOGP(info, "Number of processed time frames: {}", mProcessedTFs);
208 }
209
210 private:
211 float mThresholdMax{50.f};
212 float mThresholdAbs{20.f};
213 float mThresholdSigma{10.f};
214 int mTimeBinsBefore{10};
215 int mTimeBinsAfter{100};
216 size_t mMaxTimeBins{450};
217 uint32_t mProcessedTFs{0};
218 bool mSkipIROCTSensors{true};
219 CalPad* mNoise{nullptr};
220
221 //____________________________________________________________________________
222 void snapshot(DataAllocator& output, std::vector<Digit>& digits, int sector)
223 {
224 o2::tpc::TPCSectorHeader header{sector};
225 header.activeSectors = (0x1 << sector);
226 output.snapshot(Output{gDataOriginTPC, "FILTERDIG", static_cast<SubSpecificationType>(sector), header}, digits);
227 }
228};
229
231{
232 using device = o2::tpc::KrRawFilterDevice;
233
234 std::vector<InputSpec> inputs{
235 InputSpec{"digits", gDataOriginTPC, "DIGITS", 0, Lifetime::Timeframe},
236 };
237
238 std::vector<OutputSpec> outputs;
239 outputs.emplace_back(gDataOriginTPC, "FILTERDIG", 0, Lifetime::Timeframe);
240
241 return DataProcessorSpec{
242 "tpc-krypton-raw-filter",
243 inputs,
244 outputs,
245 AlgorithmSpec{adaptFromTask<device>(noise)},
246 Options{
247 {"threshold-max", VariantType::Float, 50.f, {"threshold in absolute ADC counts for the maximum digit"}},
248 {"threshold-abs", VariantType::Float, 20.f, {"threshold in absolute ADC counts above which time sequences will be written out"}},
249 {"threshold-sigma", VariantType::Float, 10.f, {"threshold in sigma noise above which time sequences will be written out"}},
250 {"time-bins-before", VariantType::Int, 10, {"time bins before trigger digit to be written"}},
251 {"time-bins-after", VariantType::Int, 100, {"time bins after trigger digit to be written"}},
252 {"max-time-bins", VariantType::Int, 450, {"maximum number of time bins to process"}},
253 {"skip-iroc-tsen", VariantType::Bool, true, {"skip IROC T-Sensor pads in maxima detection"}},
254 } // end Options
255 }; // end DataProcessorSpec
256}
257} // namespace o2::tpc
Definition of the TPC Digit.
o2::framework::DataAllocator::SubSpecificationType SubSpecificationType
int16_t charge
Definition RawEventData.h:5
int16_t time
Definition RawEventData.h:4
A helper class to iteratate over all parts of all input routes.
Processor spec for filtering krypton raw data.
void output(const std::map< std::string, ChannelStat > &channels)
Definition rawdump.cxx:197
std::ostringstream debug
o2::header::DataHeader::SubSpecificationType SubSpecificationType
A helper class to iteratate over all parts of all input routes.
const T getValue(const int sec, const int globalPadInSector) const
Definition CalDet.h:154
void init(o2::framework::InitContext &ic) final
void run(o2::framework::ProcessingContext &pc) final
static Mapper & instance(const std::string mappingDir="")
Definition Mapper.h:44
static constexpr unsigned int NREGIONS
total number of regions in one sector
Definition Mapper.h:527
static constexpr unsigned REGION[PADROWS]
region for global pad row
Definition Mapper.h:537
GLintptr offset
Definition glcorearb.h:660
constexpr o2::header::DataOrigin gDataOriginTPC
Definition DataHeader.h:576
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
std::vector< ConfigParamSpec > Options
O2 data header classes and API, v0.1.
Definition DetID.h:49
Global TPC definitions and constants.
Definition SimTraits.h:167
o2::framework::DataProcessorSpec getKryptonRawFilterSpec(CalPad *noise=nullptr)
CalDet< float > CalPad
Definition CalDet.h:492
std::vector< Digit > digits
std::vector< int > row