71 mWriteDebug = ic.options().get<
bool>(
"write-debug");
72 mWriteDebugOnError = ic.options().get<
bool>(
"write-debug-on-error");
73 mWriteRawDataOnError = ic.options().get<
bool>(
"write-raw-data-on-error");
74 mRawDataType = ic.options().get<
int>(
"raw-data-type");
76 mDebugStreamFileName = ic.options().get<std::string>(
"debug-file-name").
data();
77 mRawOutputFileName = ic.options().get<std::string>(
"raw-file-name").
data();
79 mSwapLinks = ic.options().get<
bool>(
"swap-links");
81 auto pedestalFile = ic.options().get<std::string>(
"pedestal-url");
82 if (pedestalFile.length()) {
85 const auto tsPos = pedestalFile.find(
"@");
86 std::string pedestalURL = pedestalFile.substr(0, tsPos);
87 if (pedestalURL.find(
"ccdb") != std::string::npos) {
88 if (pedestalURL.find(
"-default") != std::string::npos) {
91 LOGP(info,
"Loading pedestals from ccdb: {}", pedestalURL);
92 cdb.setURL(pedestalURL);
93 if (cdb.isHostReachable()) {
94 if (tsPos != std::string::npos) {
95 timeStamp = std::stol(pedestalFile.substr(tsPos + 1));
96 LOGP(info,
"Using custom time stamp {}", timeStamp);
98 auto pedestalNoise = cdb.getForTimeStamp<std::unordered_map<std::string, CalPad>>(
"TPC/Calib/PedestalNoise", timeStamp);
100 if (!pedestalNoise) {
101 throw std::runtime_error(
"Couldn't retrieve PedestaNoise map");
103 mPedestal = std::make_unique<CalPad>(pedestalNoise->at(
"Pedestals"));
104 }
catch (
const std::exception& e) {
105 LOGP(fatal,
"could not load pedestals from {} ({}), required for IDC processing", pedestalURL, e.what());
108 LOGP(fatal,
"ccdb access to {} requested, but host is not reachable. Cannot load pedestals, required for IDC processing", pedestalURL);
111 LOGP(info,
"Loading pedestals from file: {}", pedestalURL);
113 if (calPads.size() != 1) {
114 LOGP(fatal,
"Pedestal could not be loaded from file {}, required for IDC processing", pedestalURL);
116 mPedestal.reset(calPads[0]);
120 LOGP(error,
"No pedestal file set, IDCs will be without pedestal subtraction!");
133 if ((mWriteDebug || mWriteDebugOnError) && !mDebugStream) {
134 const auto debugFileName = fmt::format(fmt::runtime(mDebugStreamFileName), fmt::arg(
"run", runNumber));
135 LOGP(info,
"creating debug stream {}", debugFileName);
136 mDebugStream = std::make_unique<o2::utils::TreeStreamRedirector>(debugFileName.data(),
"recreate");
139 if (mWriteRawDataOnError && !mRawOutputFile.is_open()) {
140 std::string_view rawType = (mRawDataType < 2) ?
"tf" :
"raw";
141 if (mRawDataType == 4) {
144 const auto rawFileName = fmt::format(fmt::runtime(mRawOutputFileName), fmt::arg(
"run", runNumber), fmt::arg(
"raw_type", rawType));
145 LOGP(info,
"creating raw debug file {}", rawFileName);
146 mRawOutputFile.open(rawFileName, std::ios::binary);
149 uint32_t heartbeatOrbit = 0;
150 uint32_t heartbeatBC = 0;
151 uint32_t tfCounter = 0;
153 bool hasErrors =
false;
155 CalPad* pedestals = mPedestal.get();
158 const auto* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(
ref);
159 tfCounter = dh->tfCounter;
160 const auto subSpecification = dh->subSpecification;
164 const gsl::span<const char> raw = pc.inputs().get<gsl::span<char>>(
ref);
167 size_t lastErrorCount = 0;
169 for (
auto it = parser.
begin(),
end = parser.
end(); it !=
end; ++it) {
170 const auto size = it.size();
184 if (!rdhPtr || rdhVersion < 6) {
185 throw std::runtime_error(fmt::format(
"could not get RDH from packet, or version {} < 6", rdhVersion).
data());
189 const auto feeId = (
FEEIDType)RDHUtils::getFEEID(*rdhPtr);
190 const auto link = rdh_utils::getLink(feeId);
191 const uint32_t cruID = rdh_utils::getCRU(feeId);
192 const auto endPoint = rdh_utils::getEndPoint(feeId);
193 const auto detField = RDHUtils::getDetectorField(*rdhPtr);
197 if ((detField != (
decltype(detField))RawDataType::IDC) || (link != rdh_utils::IDCLinkID)) {
200 LOGP(
debug,
"IDC Processing firstTForbit {:9}, tfCounter {:5}, run {:6}, feeId {:6} ({:3}/{}/{:2})", dh->firstTForbit, dh->tfCounter, dh->runNumber, feeId, cruID, endPoint, link);
202 if (std::find(mCRUs.begin(), mCRUs.end(), cruID) == mCRUs.end()) {
203 LOGP(error,
"IDC CRU {:3} not configured in CRUs, skipping", cruID);
207 const CRU cru(cruID);
208 const int sector = cru.
sector();
209 const auto& partInfo = mapper.getPartitionInfo(cru.
partition());
210 const int fecLinkOffsetCRU = (partInfo.getNumberOfFECs() + 1) / 2;
211 const int fecSectorOffset = partInfo.getSectorFECOffset();
214 int sampaOnFEC{}, channelOnSAMPA{};
215 auto& idcVec = mIDCvectors[cruID];
216 auto& infoVec = mIDCInfos[cruID];
219 auto data = it.data();
221 const uint32_t
orbit = idcs.header.heartbeatOrbit;
222 const uint32_t
bc = idcs.header.heartbeatBC;
225 auto infoIt = std::find(infoVec.begin(), infoVec.end(),
orbit);
226 if (!infoVec.size()) {
227 infoVec.emplace_back(
orbit,
bc);
228 infoIt = infoVec.end() - 1;
229 }
else if (infoIt == infoVec.end()) {
230 auto& lastInfo = infoVec.back();
231 if ((
orbit - lastInfo.heartbeatOrbit) != mNOrbitsIDC) {
232 LOGP(error,
"received packet with invalid jump in idc orbit ({} - {} == {} != {})",
orbit, lastInfo.heartbeatOrbit,
int(
orbit) -
int(lastInfo.heartbeatOrbit), mNOrbitsIDC);
235 infoVec.emplace_back(
orbit,
bc);
236 infoIt = infoVec.end() - 1;
240 auto& lastInfo = *infoIt;
241 if (lastInfo.wasEPseen(endPoint)) {
242 LOGP(
debug,
"Already received another data packet for CRU {}, ep {}, orbit {}, bc {}", cruID, endPoint,
orbit,
bc);
246 lastInfo.setEPseen(endPoint);
248 const size_t idcOffset = std::distance(infoVec.begin(), infoIt);
253 const float norm = 1. / float(mTimeStampsPerIntegrationInterval);
255 const uint32_t iLink = mSwapLinks ? (idc::Links - iLinkTmp - 1) : iLinkTmp;
257 if (!idcs.hasLink(iLink)) {
261 const int fecInSector = iLinkTmp + endPoint * fecLinkOffsetCRU + fecSectorOffset;
263 for (uint32_t iChannel = 0; iChannel < idc::Channels; ++iChannel) {
264 auto val = idcs.getChannelValueFloat(iLink, iChannel);
266 const GlobalPadNumber padInSector = mapper.globalPadNumber(fecInSector, sampaOnFEC, channelOnSAMPA);
268 val -= pedestals->
getValue(sector, padInSector) * mTimeStampsPerIntegrationInterval;
272 const GlobalPadNumber vectorPosition = padInRegion + idcOffset * numberPads;
277 idcVec[vectorPosition] =
val;
281 }
catch (
const std::exception& e) {
283 using namespace std::literals::chrono_literals;
284 static std::unordered_map<uint32_t, size_t> nErrorPerSubspec;
285 static std::chrono::time_point<std::chrono::steady_clock> lastReport = std::chrono::steady_clock::now();
286 const auto now = std::chrono::steady_clock::now();
287 static size_t reportedErrors = 0;
288 const size_t MAXERRORS = 10;
290 ++nErrorPerSubspec[subSpecification];
293 if (reportedErrors < MAXERRORS) {
295 std::string sleepInfo;
296 if (reportedErrors == MAXERRORS) {
297 sleepInfo = fmt::format(
", maximum error count ({}) reached, not reporting for the next {}", MAXERRORS,
sleepTime);
299 LOGP(alarm,
"EXCEPTIION in processRawData: {} -> skipping part:{}/{} of spec:{}/{}/{}, size:{}, error count for subspec: {}{}", e.what(), dh->splitPayloadIndex, dh->splitPayloadParts,
300 dh->dataOrigin, dh->dataDescription, subSpecification, payloadSize, nErrorPerSubspec.at(subSpecification), sleepInfo);
311 hasErrors |= snapshotIDCs(pc.outputs(), tfCounter);
313 if (mWriteDebug || (mWriteDebugOnError && hasErrors)) {
314 writeDebugOutput(tfCounter);
317 if (mWriteRawDataOnError && hasErrors) {
318 writeRawData(pc.inputs());