46 static constexpr int MaxNumberOfBunches = 3564;
49 uint32_t lastOrbit{0};
50 uint32_t firstOrbit{0};
52 uint32_t maxEvents{100};
53 uint32_t processedEvents{0};
54 uint64_t activeSectors{0};
55 bool isContinuous{
false};
57 std::vector<int> tpcSectors{};
58 std::array<std::vector<Digit>, Sector::MAXSECTOR> digitsAll{};
63 for (
auto&
digits : digitsAll) {
72 for (
auto&
digits : digitsAll) {
73 std::sort(
digits.begin(),
digits.end(), [](
const auto&
a,
const auto&
b) {
74 if (a.getTimeStamp() < b.getTimeStamp()) {
77 if ((
a.getTimeStamp() ==
b.getTimeStamp()) && (
a.getRow() <
b.getRow())) {
88 auto initFunction = [channel, tpcSectors](
InitContext& ic) {
89 auto processAttributes = std::make_shared<ProcessAttributes>();
92 processAttributes->maxEvents =
static_cast<uint32_t
>(ic.options().get<
int>(
"max-events"));
93 processAttributes->tpcSectors = tpcSectors;
99 if (processAttributes->quit) {
108 auto snapshotDigits = [&pc, processAttributes, channel](std::vector<o2::tpc::Digit>
const&
digits,
int sector) {
114 const_cast<std::vector<o2::tpc::Digit>&
>(
digits));
120 for (
auto& input : pc.inputs()) {
121 const auto* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(input);
130 const auto subSpecification = dh->subSpecification;
131 const auto cruID = subSpecification >> 16;
132 const auto linkID = ((subSpecification + (subSpecification >> 8)) & 0xFF) - 1;
133 const auto dataWrapperID = ((subSpecification >> 8) & 0xFF) > 0;
134 const auto globalLinkID = linkID + dataWrapperID * 12;
135 const auto sector = cruID / 10;
136 const CRU cru(cruID);
137 const int fecLinkOffsetCRU = (mapper.getPartitionInfo(cru.partition()).getNumberOfFECs() + 1) / 2;
138 const int fecInPartition = (globalLinkID % 12) + (globalLinkID > 11) * fecLinkOffsetCRU;
139 const int regionIter = cruID % 2;
141 const int sampaMapping[10] = {0, 0, 1, 1, 2, 3, 3, 4, 4, 2};
142 const int channelOffset[10] = {0, 16, 0, 16, 0, 0, 16, 0, 16, 16};
144 processAttributes->activeSectors |= (0x1 << sector);
146 LOGP(
debug,
"Specifier: {}/{}/{}", dh->dataOrigin, dh->dataDescription, dh->subSpecification);
147 LOGP(
debug,
"Payload size: {}", payloadSize);
148 LOGP(
debug,
"CRU: {}; linkID: {}; dataWrapperID: {}; globalLinkID: {}", cruID, linkID, dataWrapperID, globalLinkID);
153 for (
auto it = parser.begin(),
end = parser.end(); it !=
end; ++it) {
159 const auto& rdh = *rdhPtr;
162 if (o2::raw::RDHUtils::getTriggerType(rdhPtr) != 0x10) {
171 const auto hbOrbit = o2::raw::RDHUtils::getHeartBeatOrbit(rdhPtr);
172 const auto lastOrbit = processAttributes->lastOrbit;
174 if (!processAttributes->firstOrbit) {
175 processAttributes->firstOrbit = hbOrbit;
176 if (!processAttributes->isContinuous) {
177 processAttributes->firstBC = o2::raw::RDHUtils::getHeartBeatBC(rdhPtr);
181 const auto globalBCoffset = ((hbOrbit - processAttributes->firstOrbit) * MaxNumberOfBunches - processAttributes->firstBC);
183 if ((lastOrbit > 0) && (hbOrbit > (lastOrbit + 3))) {
184 ++processAttributes->processedEvents;
185 LOG(info) << fmt::format(
"Number of processed events: {} ({})", processAttributes->processedEvents, processAttributes->maxEvents);
186 processAttributes->sortDigits();
189 for (
auto isector : processAttributes->tpcSectors) {
190 snapshotDigits(processAttributes->digitsAll[isector], isector);
192 processAttributes->clearDigits();
194 processAttributes->activeSectors = 0;
195 if (processAttributes->processedEvents >= processAttributes->maxEvents) {
196 LOGP(info,
"Maximum number of events reached ({}), no more processing will be done", processAttributes->maxEvents);
197 processAttributes->quit =
true;
205 processAttributes->lastOrbit = hbOrbit;
206 const auto size = it.size();
207 auto data = it.data();
208 LOGP(
debug,
"Raw data block payload size: {}",
size);
214 while (zsdata < zsdataEnd) {
215 const auto channelBits = zsdata->cont.header.getChannelBits();
216 const uint32_t numberOfWords = zsdata->cont.header.numWordsPayload;
217 assert((channelBits.count() - 1) / 10 == numberOfWords - 1);
219 std::size_t processedChannels = 0;
220 for (std::size_t ichannel = 0; ichannel < channelBits.size(); ++ichannel) {
221 if (!channelBits[ichannel]) {
226 const auto adcValue = zsdata->getADCValueFloat(processedChannels);
262 const int istreamm = ((ichannel % 10) / 2);
263 const int partitionStream = istreamm + regionIter * 5;
264 const int sampaOnFEC = sampaMapping[partitionStream];
265 const int channel = (ichannel % 2) + 2 * (ichannel / 10);
266 const int channelOnSAMPA = channel + channelOffset[partitionStream];
268 const auto padSecPos = mapper.padSecPos(cru, fecInPartition, sampaOnFEC, channelOnSAMPA);
269 const auto& padPos = padSecPos.getPadPos();
270 int timebin = (globalBCoffset + zsdata->cont.header.bunchCrossing) / 8;
273 processAttributes->digitsAll[sector].emplace_back(cruID, adcValue, padPos.getRow(), padPos.getPad(), timebin);
278 zsdata = zsdata->next();
282 }
catch (
const std::runtime_error& e) {
283 LOG(alarm) <<
"can not create raw parser form input data";
285 LOG(alarm) << e.what();
290 return processingFct;
293 std::stringstream
id;
294 id <<
"TPCDigitizer" << channel;
296 std::vector<OutputSpec> outputs;
297 for (
auto isector : tpcSectors) {
298 outputs.emplace_back(
"TPC",
"DIGITS",
static_cast<SubSpecificationType>(isector), Lifetime::Timeframe);
307 {
"max-events", VariantType::Int, 100, {
"maximum number of events to process"}},
308 {
"pedestal-file", VariantType::String,
"", {
"file with pedestals and noise for zero suppression"}}}};