Project
Loading...
Searching...
No Matches
ResidualAggregator.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
15
20
21#include <filesystem>
22#include <numeric>
23#include <algorithm>
24#include <chrono>
25#include <random>
26#include <fmt/format.h>
27
28using namespace o2::tpc;
29
31{
32 // trees must be deleted before the file is closed, otherwise segfaults
33 LOGP(debug, "Deleting ResidualsContainer with {} entries. File name is {}", getNEntries(), fileName);
35 treeOutTrackData.reset();
36 treeOutResiduals.reset();
37 treeOutStats.reset();
38 treeOutRecords.reset();
39 if (fileOut) {
40 LOG(debug) << "Removing output file of discarded slot";
41 // this slot was not finalized, need to close and remove the file
42 fileOut->Close();
43 fileOut.reset();
44 std::string fileToRemove = fileName + ".part";
45 if (!std::filesystem::remove(fileToRemove)) {
46 LOG(warning) << "Tried to delete, but could not find file named " << fileToRemove;
47 }
48 }
49}
50
52{
53 LOG(error) << "Must not call copy constructor of ResidualsContainer";
54 // the copy constructor is needed because of ROOT's ClassDef
55 // but should never actually be called
56}
57
59{
60 LOGP(debug, "Move operator called for rhs with {} entries", rhs.nResidualsTotal);
61 trackResiduals = rhs.trackResiduals;
62 fileOut = std::move(rhs.fileOut);
63 fileName = std::move(rhs.fileName);
64 treeOutResidualsUnbinned = std::move(rhs.treeOutResidualsUnbinned);
65 treeOutTrackData = std::move(rhs.treeOutTrackData);
66 treeOutResiduals = std::move(rhs.treeOutResiduals);
67 treeOutStats = std::move(rhs.treeOutStats);
68 treeOutRecords = std::move(rhs.treeOutRecords);
69 for (int iSec = 0; iSec < SECTORSPERSIDE * SIDES; ++iSec) {
70 residuals[iSec] = std::move(rhs.residuals[iSec]);
71 stats[iSec] = std::move(rhs.stats[iSec]);
72 }
73 tfOrbits = std::move(rhs.tfOrbits);
74 sumBinnedResid = std::move(rhs.sumBinnedResid);
75 sumUnbinnedResid = std::move(rhs.sumUnbinnedResid);
76 lumi = std::move(rhs.lumi);
77 unbinnedRes = std::move(rhs.unbinnedRes);
78 trackInfo = std::move(rhs.trackInfo);
79 trkData = std::move(rhs.trkData);
80 orbitReset = rhs.orbitReset;
81 firstTForbit = rhs.firstTForbit;
82 firstSeenTF = rhs.firstSeenTF;
83 lastSeenTF = rhs.lastSeenTF;
84 nResidualsTotal = rhs.nResidualsTotal;
85}
86
87void ResidualsContainer::init(const TrackResiduals* residualsEngine, std::string outputDir, bool wFile, bool wBinnedResid, bool wUnbinnedResid, bool wTrackData, int autosave, int compression, long orbitResetTime)
88{
89 trackResiduals = residualsEngine;
90 writeToRootFile = wFile;
91 writeBinnedResid = wBinnedResid;
92 writeUnbinnedResiduals = wUnbinnedResid;
93 writeTrackData = wTrackData;
94 autosaveInterval = autosave;
95 orbitReset = orbitResetTime;
96 if (writeToRootFile) {
97 bool outFileCreated = false;
98 int nTries = 0;
99 fileName += std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
100 while (!outFileCreated && nTries < 100) {
101 std::random_device rd;
102 std::mt19937 g(rd());
103 std::uniform_int_distribution<> distr(0, 99);
104 fileName += fmt::format("_{:03}", distr(g)); // add some random number in case multiple slots are opened in an offline job simultaneously
105 fileName += ".root";
106 std::string fileNameTmp = outputDir + fileName;
107 fileNameTmp += ".part"; // to prevent premature external usage of the file use temporary name
108 if (std::filesystem::exists(fileNameTmp)) {
109 fileName.erase(fileName.length() - 9); // remove the _XXX.root from fileName, try with other XXX
110 ++nTries;
111 continue;
112 }
113 fileOut = std::make_unique<TFile>(fileNameTmp.c_str(), "recreate", "", compression);
114 outFileCreated = true;
115 }
116 if (!outFileCreated) {
117 LOG(error) << "Could not create output file for this slot after 100 tries. Disable file writing for this slot";
118 writeToRootFile = false;
119 }
120 }
122 treeOutResidualsUnbinned = std::make_unique<TTree>("unbinnedResid", "TPC unbinned residuals");
124 treeOutResidualsUnbinned->Branch("trackInfo", &trackInfoPtr);
125 treeOutResidualsUnbinned->Branch("CTPLumi", &lumiTF);
126 treeOutResidualsUnbinned->Branch("timeMS", &timeMS);
127 treeOutResidualsUnbinned->Branch("detInfo", &detInfoUnbResPtr);
128 }
129 if (writeTrackData) {
130 treeOutTrackData = std::make_unique<TTree>("trackData", "Track information incl cluster range ref");
131 treeOutTrackData->Branch("trk", &trkDataPtr);
132 }
133 if (writeBinnedResid) {
134 treeOutResiduals = std::make_unique<TTree>("resid", "TPC binned residuals");
135 treeOutStats = std::make_unique<TTree>("stats", "Voxel statistics mean position and nEntries");
136 for (int iSec = 0; iSec < SECTORSPERSIDE * SIDES; ++iSec) {
137 residualsPtr[iSec] = &residuals[iSec];
138 statsPtr[iSec] = &stats[iSec];
140 for (int ix = 0; ix < trackResiduals->getNXBins(); ++ix) {
141 for (int ip = 0; ip < trackResiduals->getNY2XBins(); ++ip) {
142 for (int iz = 0; iz < trackResiduals->getNZ2XBins(); ++iz) {
143 auto& statsVoxel = stats[iSec][trackResiduals->getGlbVoxBin(ix, ip, iz)];
144 // COG estimates are set to the bin center by default
145 trackResiduals->getVoxelCoordinates(iSec, ix, ip, iz, statsVoxel.meanPos[TrackResiduals::VoxX], statsVoxel.meanPos[TrackResiduals::VoxF], statsVoxel.meanPos[TrackResiduals::VoxZ]);
146 }
147 }
148 }
149 treeOutResiduals->Branch(Form("sec%d", iSec), &residualsPtr[iSec]);
150 treeOutStats->Branch(Form("sec%d", iSec), &statsPtr[iSec]);
151 }
152 }
153 treeOutRecords = std::make_unique<TTree>("records", "Statistics per TF slot");
154 treeOutRecords->Branch("firstTForbit", &tfOrbitsPtr);
155 treeOutRecords->Branch("sumOfBinnedResiduals", &sumBinnedResidPtr);
156 treeOutRecords->Branch("sumOfUnbinnedResiduals", &sumUnbinnedResidPtr);
157 treeOutRecords->Branch("CTPLumi", &lumiPtr);
158 treeOutRecords->Branch("TPCVDriftRef", &TPCVDriftRef);
159 treeOutRecords->Branch("TPCDriftTimeOffsetRef", &TPCDriftTimeOffsetRef);
160 LOG(debug) << "Done initializing residuals container for file named " << fileName;
161}
162
164{
165 // only called when the slot is finalized, otherwise treeOutStats
166 // remains empty and we keep the statistics in memory in the vectors
167 // (since their size anyway does not change)
168 treeOutRecords->Fill();
169 if (writeBinnedResid) {
170 treeOutStats->Fill();
171 }
172}
173
174void ResidualsContainer::fill(const o2::dataformats::TFIDInfo& ti, const gsl::span<const UnbinnedResid> resid, const gsl::span<const DetInfoResid> detInfoRes, const gsl::span<const o2::tpc::TrackDataCompact> trkRefsIn, const gsl::span<const o2::tpc::TrackData>* trkDataIn, const o2::ctp::LumiInfo* lumiInput)
175{
176 // receives large vector of unbinned residuals and fills the sector-wise vectors
177 // with binned residuals and statistics
178 LOG(debug) << "Filling ResidualsContainer with vector of size " << resid.size();
179 uint32_t nUnbinnedResidualsInTF = 0;
180 uint32_t nBinnedResidualsInTF = 0;
181 if (ti.tfCounter > lastSeenTF) {
183 }
184 if (ti.tfCounter < firstSeenTF) {
187 }
188 for (const auto& residIn : resid) {
189 bool counterIncremented = false;
191 unbinnedRes.push_back(residIn);
192 detInfoUnbRes.push_back(detInfoRes.size() ? detInfoRes[nUnbinnedResidualsInTF] : DetInfoResid{});
194 counterIncremented = true;
195 }
196 ++nUnbinnedResidualsInTF;
197 if (!writeBinnedResid) {
198 continue;
199 }
200 if (residIn.isTgSlpClamped()) {
201 // scdcalib.clampTgSlp: kept in the unbinned output, but its tgSlp is saturated and the voxel fit uses tgSlp (dX from
202 // dY vs tan(phi)), so it must not enter the binned residuals
203 continue;
204 }
205 int sec = residIn.sec;
206 auto& residVecOut = residuals[sec];
207 auto& statVecOut = stats[sec];
208 std::array<unsigned char, TrackResiduals::VoxDim> bvox;
209 float xPos = param::RowX[residIn.row];
210 float yPos = residIn.y * param::MaxY / 0x7fff + residIn.dy * param::MaxResid / 0x7fff;
211 float zPos = residIn.z * param::MaxZ / 0x7fff + residIn.dz * param::MaxResid / 0x7fff;
212 if (!trackResiduals->findVoxelBin(sec, xPos, yPos, zPos, bvox)) {
213 // we are not inside any voxel
214 LOGF(debug, "Dropping residual in sec(%i), x(%f), y(%f), z(%f)", sec, xPos, yPos, zPos);
215 continue;
216 }
217 residVecOut.emplace_back(residIn.dy, residIn.dz, residIn.tgSlp, bvox);
218 auto& stat = statVecOut[trackResiduals->getGlbVoxBin(bvox)];
219 float& binEntries = stat.nEntries;
220 float oldEntries = binEntries++;
221 float norm = 1.f / binEntries;
222 // update COG for voxel bvox (update for X only needed in case binning is not per pad row)
223 float xPosInv = 1.f / xPos;
224 stat.meanPos[TrackResiduals::VoxX] = (stat.meanPos[TrackResiduals::VoxX] * oldEntries + xPos) * norm;
225 stat.meanPos[TrackResiduals::VoxF] = (stat.meanPos[TrackResiduals::VoxF] * oldEntries + yPos * xPosInv) * norm;
226 stat.meanPos[TrackResiduals::VoxZ] = (stat.meanPos[TrackResiduals::VoxZ] * oldEntries + zPos * xPosInv) * norm;
227 if (!counterIncremented) {
229 }
230 ++nBinnedResidualsInTF;
231 }
232 for (const auto& trkRef : trkRefsIn) {
233 trackInfo.push_back(trkRef);
234 }
235 sumBinnedResid.push_back(nBinnedResidualsInTF);
236 sumUnbinnedResid.push_back(nUnbinnedResidualsInTF);
237 if (writeBinnedResid) {
238 treeOutResiduals->Fill();
239 }
240 for (auto& residVecOut : residuals) {
241 residVecOut.clear();
242 }
243 if (writeTrackData) {
244 for (const auto& trkIn : *trkDataIn) {
245 trkData.push_back(trkIn);
246 }
247 treeOutTrackData->Fill();
248 trkData.clear();
249 }
251 if (lumiInput) {
252 lumiTF = *lumiInput;
253 }
254 timeMS = orbitReset + ti.tfCounter * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
256 unbinnedRes.clear();
257 detInfoUnbRes.clear();
258 trackInfo.clear();
259 }
260 tfOrbits.push_back(ti.firstTForbit);
261 if (lumiInput) {
262 lumi.push_back(*lumiInput);
263 }
264
265 if (autosaveInterval > 0 && (tfOrbits.size() % autosaveInterval) == 0 && writeToRootFile) {
266 writeToFile(false);
267 }
268}
269
270void ResidualsContainer::writeToFile(bool closeFileAfterwards)
271{
272 LOG(info) << "Writing results to file. Closing afterwards? " << closeFileAfterwards;
273 fillStatisticsBranches(); // these would need to be filled only once, so only the last entry is important
274 fileOut->cd();
275 treeOutRecords->Write();
276 if (writeBinnedResid) {
277 treeOutResiduals->Write();
278 treeOutStats->Write();
279 }
282 }
283 if (writeTrackData) {
284 treeOutTrackData->Write();
285 }
286
287 if (closeFileAfterwards) {
288 treeOutRecords.reset();
289 if (writeBinnedResid) {
290 treeOutResiduals.reset();
291 treeOutStats.reset();
292 }
295 }
296 if (writeTrackData) {
297 treeOutTrackData.reset();
298 }
299 fileOut->Close();
300 fileOut.reset();
301 }
302}
303
305{
306 // the previous slot is merged to this one and afterwards
307 // the previous one will be deleted
308 LOGP(debug, "Merging previous slot with {} entries into current one with {} entries", prev->getNEntries(), getNEntries());
309 if (writeBinnedResid) {
310 for (int iSec = 0; iSec < SECTORSPERSIDE * SIDES; ++iSec) {
311 // merge statistics
312 const auto& statVecPrev = prev->stats[iSec];
313 auto& statVec = stats[iSec];
314 for (int iVox = 0; iVox < trackResiduals->getNVoxelsPerSector(); ++iVox) {
315 const auto& statPrev = statVecPrev[iVox];
316 auto& stat = statVec[iVox];
317 float norm = 1.f;
318 if (statPrev.nEntries + stat.nEntries > 0.1) {
319 // if there is at least a single entry in either of the containers we need the proper norm
320 norm /= (statPrev.nEntries + stat.nEntries);
321 }
322 stat.meanPos[TrackResiduals::VoxX] = (stat.meanPos[TrackResiduals::VoxX] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxX] * statPrev.nEntries) * norm;
323 stat.meanPos[TrackResiduals::VoxF] = (stat.meanPos[TrackResiduals::VoxF] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxF] * statPrev.nEntries) * norm;
324 stat.meanPos[TrackResiduals::VoxZ] = (stat.meanPos[TrackResiduals::VoxZ] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxZ] * statPrev.nEntries) * norm;
325 stat.nEntries += statPrev.nEntries;
326 }
327 // prepare merging of residuals
328 prev->treeOutResiduals->SetBranchAddress(Form("sec%d", iSec), &residualsPtr[iSec]);
329 }
330 // We append the entries of the tree of the following slot to the
331 // previous slot and afterwards move the merged tree to this slot.
332 // This way the order of the entries is preserved
333 for (int i = 0; i < treeOutResiduals->GetEntries(); ++i) {
334 treeOutResiduals->GetEntry(i);
335 prev->treeOutResiduals->Fill();
336 }
337 }
338
339 if (writeTrackData) {
340 prev->treeOutTrackData->SetBranchAddress("trk", &trkDataPtr);
341 for (int i = 0; i < treeOutTrackData->GetEntries(); ++i) {
342 treeOutTrackData->GetEntry(i);
343 prev->treeOutTrackData->Fill();
344 }
345 }
347 prev->treeOutResidualsUnbinned->SetBranchAddress("res", &unbinnedResPtr);
348 prev->treeOutResidualsUnbinned->SetBranchAddress("trackInfo", &trackInfoPtr);
349 prev->treeOutResidualsUnbinned->SetBranchAddress("CTPLumi", &lumiTF);
350 prev->treeOutResidualsUnbinned->SetBranchAddress("timeMS", &timeMS);
351 prev->treeOutResidualsUnbinned->SetBranchAddress("detInfo", &detInfoUnbResPtr);
352 for (int i = 0; i < treeOutResidualsUnbinned->GetEntries(); ++i) {
353 treeOutResidualsUnbinned->GetEntry(i);
354 prev->treeOutResidualsUnbinned->Fill();
355 }
356 }
357
358 treeOutResiduals = std::move(prev->treeOutResiduals);
359 treeOutTrackData = std::move(prev->treeOutTrackData);
361
362 // since we want to continue using the TTrees of the previous slot, we must
363 // avoid that ROOT deletes them when the TFile of the previous slot is erased
364 treeOutResiduals->SetDirectory(fileOut.get());
365 treeOutTrackData->SetDirectory(fileOut.get());
366 treeOutResidualsUnbinned->SetDirectory(fileOut.get());
367
369
370 // append the current vector to the vector of the previous container and afterwards swap them,
371 // since the vector of the previous container will be deleted
372 prev->tfOrbits.insert(prev->tfOrbits.end(), tfOrbits.begin(), tfOrbits.end());
373 std::swap(prev->tfOrbits, tfOrbits);
374 prev->sumBinnedResid.insert(prev->sumBinnedResid.end(), sumBinnedResid.begin(), sumBinnedResid.end());
375 std::swap(prev->sumBinnedResid, sumBinnedResid);
376 prev->sumUnbinnedResid.insert(prev->sumUnbinnedResid.end(), sumUnbinnedResid.begin(), sumUnbinnedResid.end());
377 std::swap(prev->sumUnbinnedResid, sumUnbinnedResid);
378 prev->lumi.insert(prev->lumi.end(), lumi.begin(), lumi.end());
379 std::swap(prev->lumi, lumi);
380
381 firstSeenTF = prev->firstSeenTF;
382 LOGP(debug, "Done with the merge. Current slot has {} entries", getNEntries());
383}
384
386{
387 LOG(info) << "There are in total " << nResidualsTotal << " residuals stored in the container";
388}
389
391
393{
394 auto& slots = getSlots();
395 slots.clear();
396}
397
399{
400 LOG(debug) << "There are " << slot.getContainer()->getNEntries() << " entries currently. Min entries per voxel: " << mMinEntries;
401 auto entriesPerVoxel = slot.getContainer()->getNEntries() / (mTrackResiduals.getNVoxelsPerSector() * SECTORSPERSIDE * SIDES);
402 LOGP(debug, "Slot has {} entries per voxel, at least {} are required", entriesPerVoxel, mMinEntries);
403 return entriesPerVoxel >= mMinEntries;
404}
405
407{
408 // nothing to be done here, but method needs to be overwritten
409}
410
412{
413 LOG(info) << "Finalizing slot";
414 auto finalizeStartTime = std::chrono::high_resolution_clock::now();
415 auto cont = slot.getContainer();
416 cont->print();
417 if (!mWriteOutput || cont->getNEntries() == 0 || !cont->writeToRootFile) {
418 LOGP(info, "Skip writing output with {} entries, since file output is disabled or slot is empty", cont->getNEntries());
419 return;
420 }
421 cont->TPCVDriftRef = mTPCVDriftRef;
422 cont->TPCDriftTimeOffsetRef = mTPCDriftTimeOffsetRef;
423 cont->writeToFile(true);
424
425 long orbitOffsetStart = (cont->firstSeenTF - slot.getTFStart()) * o2::base::GRPGeomHelper::getNHBFPerTF();
426 long orbitOffsetEnd = (slot.getTFEnd() - cont->firstSeenTF) * o2::base::GRPGeomHelper::getNHBFPerTF();
427 long timeStartMS = mOrbitResetTime + (cont->firstTForbit - orbitOffsetStart) * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
428 long timeEndMS = mOrbitResetTime + (cont->firstTForbit + orbitOffsetEnd) * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
429 auto fileName = fmt::format("o2tpc_residuals_{}_{}_{}_{}.root", timeStartMS, timeEndMS, slot.getTFStart(), slot.getTFEnd());
430 auto fileNameWithPath = mOutputDir + fileName;
431 std::filesystem::rename(o2::utils::Str::concat_string(mOutputDir, cont->fileName, ".part"), fileNameWithPath);
432 if (mStoreMetaData) {
433 o2::dataformats::FileMetaData fileMetaData; // object with information for meta data file
434 fileMetaData.fillFileData(fileNameWithPath);
435 fileMetaData.setDataTakingContext(mDataTakingContext);
436 fileMetaData.type = "calib";
437 fileMetaData.priority = "high";
438 auto metaFileNameTmp = fmt::format("{}{}.tmp", mMetaOutputDir, fileName);
439 auto metaFileName = fmt::format("{}{}.done", mMetaOutputDir, fileName);
440 try {
441 std::ofstream metaFileOut(metaFileNameTmp);
442 metaFileOut << fileMetaData;
443 metaFileOut.close();
444 std::filesystem::rename(metaFileNameTmp, metaFileName);
445 } catch (std::exception const& e) {
446 LOG(error) << "Failed to store residuals meta data file " << metaFileName << ", reason: " << e.what();
447 }
448 }
449 std::chrono::duration<double, std::milli> finalizeDuration = std::chrono::high_resolution_clock::now() - finalizeStartTime;
450 LOGP(info, "Finalizing calibration slot took: {} ms", std::chrono::duration_cast<std::chrono::milliseconds>(finalizeDuration).count());
451}
452
454{
455 auto emplaceStartTime = std::chrono::high_resolution_clock::now();
456 auto& cont = getSlots();
457 auto& slot = front ? cont.emplace_front(tStart, tEnd) : cont.emplace_back(tStart, tEnd);
458 slot.setContainer(std::make_unique<ResidualsContainer>());
459 slot.getContainer()->init(&mTrackResiduals, mOutputDir, mWriteOutput, mWriteBinnedResiduals, mWriteUnbinnedResiduals, mWriteTrackData, mAutosaveInterval, mCompressionSetting, mOrbitResetTime);
460 std::chrono::duration<double, std::milli> emplaceDuration = std::chrono::high_resolution_clock::now() - emplaceStartTime;
461 LOGP(info, "Emplacing new calibration slot took: {} ms", std::chrono::duration_cast<std::chrono::milliseconds>(emplaceDuration).count());
462 return slot;
463}
464
466{
467 // for the residual extraction we are using the reference vDrift and time offset values only
468 if (v.refVDrift != mTPCVDriftRef) {
469 mTPCVDriftRef = v.refVDrift;
470 mTPCDriftTimeOffsetRef = v.refTimeOffset;
471 LOGP(info, "Imposing reference VDrift={}/TDrift={} for TPC residuals extraction", mTPCVDriftRef, mTPCDriftTimeOffsetRef);
472 }
473}
std::ostringstream debug
int32_t i
Collects local TPC cluster residuals from EPNs.
Parameters used for TPC space point calibration.
calibration data from laser track calibration
TFType getTFEnd() const
Definition TimeSlot.h:47
const Container * getContainer() const
Definition TimeSlot.h:53
TFType getTFStart() const
Definition TimeSlot.h:46
Slot & emplaceNewSlot(bool front, TFType tStart, TFType tEnd) final
bool hasEnoughData(const Slot &slot) const final
void setTPCVDrift(const o2::tpc::VDriftCorrFact &v)
void finalizeSlot(Slot &slot) final
size_t getGlbVoxBin(int ix, int ip, int iz) const
int getNVoxelsPerSector() const
Get the total number of voxels per TPC sector (mNXBins * mNY2XBins * mNZ2XBins)
void getVoxelCoordinates(int isec, int ix, int ip, int iz, float &x, float &p, float &z) const
bool findVoxelBin(int secID, float x, float y, float z, std::array< unsigned char, VoxDim > &bvox) const
Calculates the bin indices for given x, y, z in sector coordinates.
GLint GLsizei count
Definition glcorearb.h:399
const GLdouble * v
Definition glcorearb.h:832
GLboolean GLboolean g
Definition glcorearb.h:1233
Global TPC definitions and constants.
Definition SimTraits.h:172
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
bool fillFileData(const std::string &fname, bool fillmd5=false, const std::string &tmpEnding="")
void setDataTakingContext(const o2::framework::DataTakingContext &dtc)
std::unique_ptr< TTree > treeOutResidualsUnbinned
std::vector< TrackDataCompact > * trackInfoPtr
allows to obtain track type for each unbinned residual downstream
long orbitReset
current orbit reset time in ms
std::array< std::vector< TrackResiduals::VoxStats > *, SECTORSPERSIDE *SIDES > statsPtr
std::vector< TrackData > * trkDataPtr
track data and cluster ranges
std::unique_ptr< TTree > treeOutRecords
float TPCVDriftRef
TPC nominal drift speed in cm/microseconds.
std::vector< uint32_t > sumBinnedResid
void init(const TrackResiduals *residualsEngine, std::string outputDir, bool wFile, bool wBinnedResid, bool wUnbinnedResid, bool wTrackData, int autosave, int compression, long orbitResetTime)
TFType lastSeenTF
the last TF which was added to this container
uint64_t timeMS
for each processed TF we store its absolute time in ms in the tree of unbinned residuals
std::vector< DetInfoResid > * detInfoUnbResPtr
detector info associated to unbinned residuals which are sent to the aggregator
std::vector< UnbinnedResid > * unbinnedResPtr
unbinned residuals which are sent to the aggregator
std::vector< uint32_t > tfOrbits
std::vector< uint32_t > * sumBinnedResidPtr
sum of binned residuals for each TF
uint32_t firstTForbit
stored for the first seen TF to allow conversion to time stamp
std::vector< o2::ctp::LumiInfo > * lumiPtr
luminosity information from CTP per TF
std::array< std::vector< TrackResiduals::LocalResid > *, SECTORSPERSIDE *SIDES > residualsPtr
bool writeBinnedResid
flag, whether binned residuals should be written out
std::vector< o2::ctp::LumiInfo > lumi
bool writeTrackData
flag, whether full seeding track information should be written out
std::vector< TrackDataCompact > trackInfo
std::vector< uint32_t > * tfOrbitsPtr
first TF orbit
bool writeUnbinnedResiduals
flag, whether unbinned residuals should be written out
void writeToFile(bool closeFileAfterwards)
o2::ctp::LumiInfo lumiTF
for each processed TF we store the lumi information in the tree of unbinned residuals
std::array< std::vector< TrackResiduals::LocalResid >, SECTORSPERSIDE *SIDES > residuals
local (binned) residuals per sector
void merge(ResidualsContainer *prev)
std::vector< UnbinnedResid > unbinnedRes
float TPCDriftTimeOffsetRef
TPC nominal (e.g. at the start of run) drift time bias in cm/mus.
void fill(const o2::dataformats::TFIDInfo &ti, const gsl::span< const UnbinnedResid > resid, const gsl::span< const DetInfoResid > detInfoRes, const gsl::span< const o2::tpc::TrackDataCompact > trkRefsIn, const gsl::span< const o2::tpc::TrackData > *trkDataIn, const o2::ctp::LumiInfo *lumiInput)
std::unique_ptr< TFile > fileOut
std::vector< uint32_t > sumUnbinnedResid
std::array< std::vector< TrackResiduals::VoxStats >, SECTORSPERSIDE *SIDES > stats
voxel statistics per sector
std::unique_ptr< TTree > treeOutStats
const TrackResiduals * trackResiduals
TFType firstSeenTF
the first TF which was added to this container
uint64_t nResidualsTotal
the total number of residuals for this container
std::vector< uint32_t > * sumUnbinnedResidPtr
sum of unbinned residuals for each TF
std::unique_ptr< TTree > treeOutResiduals
int autosaveInterval
if > 0, then the output written to file for every n-th TF
std::vector< DetInfoResid > detInfoUnbRes
std::unique_ptr< TTree > treeOutTrackData
std::vector< TrackData > trkData
bool writeToRootFile
set to false to avoid that any output file is produced
static std::string concat_string(Ts const &... ts)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::uniform_int_distribution< unsigned long long > distr
std::random_device rd