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 }
128 if (writeTrackData) {
129 treeOutTrackData = std::make_unique<TTree>("trackData", "Track information incl cluster range ref");
130 treeOutTrackData->Branch("trk", &trkDataPtr);
131 }
132 if (writeBinnedResid) {
133 treeOutResiduals = std::make_unique<TTree>("resid", "TPC binned residuals");
134 treeOutStats = std::make_unique<TTree>("stats", "Voxel statistics mean position and nEntries");
135 for (int iSec = 0; iSec < SECTORSPERSIDE * SIDES; ++iSec) {
136 residualsPtr[iSec] = &residuals[iSec];
137 statsPtr[iSec] = &stats[iSec];
139 for (int ix = 0; ix < trackResiduals->getNXBins(); ++ix) {
140 for (int ip = 0; ip < trackResiduals->getNY2XBins(); ++ip) {
141 for (int iz = 0; iz < trackResiduals->getNZ2XBins(); ++iz) {
142 auto& statsVoxel = stats[iSec][trackResiduals->getGlbVoxBin(ix, ip, iz)];
143 // COG estimates are set to the bin center by default
144 trackResiduals->getVoxelCoordinates(iSec, ix, ip, iz, statsVoxel.meanPos[TrackResiduals::VoxX], statsVoxel.meanPos[TrackResiduals::VoxF], statsVoxel.meanPos[TrackResiduals::VoxZ]);
145 }
146 }
147 }
148 treeOutResiduals->Branch(Form("sec%d", iSec), &residualsPtr[iSec]);
149 treeOutStats->Branch(Form("sec%d", iSec), &statsPtr[iSec]);
150 }
151 }
152 treeOutRecords = std::make_unique<TTree>("records", "Statistics per TF slot");
153 treeOutRecords->Branch("firstTForbit", &tfOrbitsPtr);
154 treeOutRecords->Branch("sumOfBinnedResiduals", &sumBinnedResidPtr);
155 treeOutRecords->Branch("sumOfUnbinnedResiduals", &sumUnbinnedResidPtr);
156 treeOutRecords->Branch("CTPLumi", &lumiPtr);
157 treeOutRecords->Branch("TPCVDriftRef", &TPCVDriftRef);
158 treeOutRecords->Branch("TPCDriftTimeOffsetRef", &TPCDriftTimeOffsetRef);
159 LOG(debug) << "Done initializing residuals container for file named " << fileName;
160}
161
163{
164 // only called when the slot is finalized, otherwise treeOutStats
165 // remains empty and we keep the statistics in memory in the vectors
166 // (since their size anyway does not change)
167 treeOutRecords->Fill();
168 if (writeBinnedResid) {
169 treeOutStats->Fill();
170 }
171}
172
173void ResidualsContainer::fill(const o2::dataformats::TFIDInfo& ti, const gsl::span<const UnbinnedResid> resid, const gsl::span<const o2::tpc::TrackDataCompact> trkRefsIn, const gsl::span<const o2::tpc::TrackData>* trkDataIn, const o2::ctp::LumiInfo* lumiInput)
174{
175 // receives large vector of unbinned residuals and fills the sector-wise vectors
176 // with binned residuals and statistics
177 LOG(debug) << "Filling ResidualsContainer with vector of size " << resid.size();
178 uint32_t nUnbinnedResidualsInTF = 0;
179 uint32_t nBinnedResidualsInTF = 0;
180 if (ti.tfCounter > lastSeenTF) {
182 }
183 if (ti.tfCounter < firstSeenTF) {
186 }
187 for (const auto& residIn : resid) {
188 ++nUnbinnedResidualsInTF;
189 bool counterIncremented = false;
191 unbinnedRes.push_back(residIn);
193 counterIncremented = true;
194 }
195 if (!writeBinnedResid) {
196 continue;
197 }
198 int sec = residIn.sec;
199 auto& residVecOut = residuals[sec];
200 auto& statVecOut = stats[sec];
201 std::array<unsigned char, TrackResiduals::VoxDim> bvox;
202 float xPos = param::RowX[residIn.row];
203 float yPos = residIn.y * param::MaxY / 0x7fff + residIn.dy * param::MaxResid / 0x7fff;
204 float zPos = residIn.z * param::MaxZ / 0x7fff + residIn.dz * param::MaxResid / 0x7fff;
205 if (!trackResiduals->findVoxelBin(sec, xPos, yPos, zPos, bvox)) {
206 // we are not inside any voxel
207 LOGF(debug, "Dropping residual in sec(%i), x(%f), y(%f), z(%f)", sec, xPos, yPos, zPos);
208 continue;
209 }
210 residVecOut.emplace_back(residIn.dy, residIn.dz, residIn.tgSlp, bvox);
211 auto& stat = statVecOut[trackResiduals->getGlbVoxBin(bvox)];
212 float& binEntries = stat.nEntries;
213 float oldEntries = binEntries++;
214 float norm = 1.f / binEntries;
215 // update COG for voxel bvox (update for X only needed in case binning is not per pad row)
216 float xPosInv = 1.f / xPos;
217 stat.meanPos[TrackResiduals::VoxX] = (stat.meanPos[TrackResiduals::VoxX] * oldEntries + xPos) * norm;
218 stat.meanPos[TrackResiduals::VoxF] = (stat.meanPos[TrackResiduals::VoxF] * oldEntries + yPos * xPosInv) * norm;
219 stat.meanPos[TrackResiduals::VoxZ] = (stat.meanPos[TrackResiduals::VoxZ] * oldEntries + zPos * xPosInv) * norm;
220 if (!counterIncremented) {
222 }
223 ++nBinnedResidualsInTF;
224 }
225 for (const auto& trkRef : trkRefsIn) {
226 trackInfo.push_back(trkRef);
227 }
228 sumBinnedResid.push_back(nBinnedResidualsInTF);
229 sumUnbinnedResid.push_back(nUnbinnedResidualsInTF);
230 if (writeBinnedResid) {
231 treeOutResiduals->Fill();
232 }
233 for (auto& residVecOut : residuals) {
234 residVecOut.clear();
235 }
236 if (writeTrackData) {
237 for (const auto& trkIn : *trkDataIn) {
238 trkData.push_back(trkIn);
239 }
240 treeOutTrackData->Fill();
241 trkData.clear();
242 }
244 if (lumiInput) {
245 lumiTF = *lumiInput;
246 }
249 unbinnedRes.clear();
250 trackInfo.clear();
251 }
252 tfOrbits.push_back(ti.firstTForbit);
253 if (lumiInput) {
254 lumi.push_back(*lumiInput);
255 }
256
257 if (autosaveInterval > 0 && (tfOrbits.size() % autosaveInterval) == 0 && writeToRootFile) {
258 writeToFile(false);
259 }
260}
261
262void ResidualsContainer::writeToFile(bool closeFileAfterwards)
263{
264 LOG(info) << "Writing results to file. Closing afterwards? " << closeFileAfterwards;
265 fillStatisticsBranches(); // these would need to be filled only once, so only the last entry is important
266 fileOut->cd();
267 treeOutRecords->Write();
268 if (writeBinnedResid) {
269 treeOutResiduals->Write();
270 treeOutStats->Write();
271 }
274 }
275 if (writeTrackData) {
276 treeOutTrackData->Write();
277 }
278
279 if (closeFileAfterwards) {
280 treeOutRecords.reset();
281 if (writeBinnedResid) {
282 treeOutResiduals.reset();
283 treeOutStats.reset();
284 }
287 }
288 if (writeTrackData) {
289 treeOutTrackData.reset();
290 }
291 fileOut->Close();
292 fileOut.reset();
293 }
294}
295
297{
298 // the previous slot is merged to this one and afterwards
299 // the previous one will be deleted
300 LOGP(debug, "Merging previous slot with {} entries into current one with {} entries", prev->getNEntries(), getNEntries());
301 if (writeBinnedResid) {
302 for (int iSec = 0; iSec < SECTORSPERSIDE * SIDES; ++iSec) {
303 // merge statistics
304 const auto& statVecPrev = prev->stats[iSec];
305 auto& statVec = stats[iSec];
306 for (int iVox = 0; iVox < trackResiduals->getNVoxelsPerSector(); ++iVox) {
307 const auto& statPrev = statVecPrev[iVox];
308 auto& stat = statVec[iVox];
309 float norm = 1.f;
310 if (statPrev.nEntries + stat.nEntries > 0.1) {
311 // if there is at least a single entry in either of the containers we need the proper norm
312 norm /= (statPrev.nEntries + stat.nEntries);
313 }
314 stat.meanPos[TrackResiduals::VoxX] = (stat.meanPos[TrackResiduals::VoxX] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxX] * statPrev.nEntries) * norm;
315 stat.meanPos[TrackResiduals::VoxF] = (stat.meanPos[TrackResiduals::VoxF] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxF] * statPrev.nEntries) * norm;
316 stat.meanPos[TrackResiduals::VoxZ] = (stat.meanPos[TrackResiduals::VoxZ] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxZ] * statPrev.nEntries) * norm;
317 stat.nEntries += statPrev.nEntries;
318 }
319 // prepare merging of residuals
320 prev->treeOutResiduals->SetBranchAddress(Form("sec%d", iSec), &residualsPtr[iSec]);
321 }
322 // We append the entries of the tree of the following slot to the
323 // previous slot and afterwards move the merged tree to this slot.
324 // This way the order of the entries is preserved
325 for (int i = 0; i < treeOutResiduals->GetEntries(); ++i) {
326 treeOutResiduals->GetEntry(i);
327 prev->treeOutResiduals->Fill();
328 }
329 }
330
331 if (writeTrackData) {
332 prev->treeOutTrackData->SetBranchAddress("trk", &trkDataPtr);
333 for (int i = 0; i < treeOutTrackData->GetEntries(); ++i) {
334 treeOutTrackData->GetEntry(i);
335 prev->treeOutTrackData->Fill();
336 }
337 }
339 prev->treeOutResidualsUnbinned->SetBranchAddress("res", &unbinnedResPtr);
340 prev->treeOutResidualsUnbinned->SetBranchAddress("trackInfo", &trackInfoPtr);
341 for (int i = 0; i < treeOutResidualsUnbinned->GetEntries(); ++i) {
342 treeOutResidualsUnbinned->GetEntry(i);
343 prev->treeOutResidualsUnbinned->Fill();
344 }
345 }
346
347 treeOutResiduals = std::move(prev->treeOutResiduals);
348 treeOutTrackData = std::move(prev->treeOutTrackData);
350
351 // since we want to continue using the TTrees of the previous slot, we must
352 // avoid that ROOT deletes them when the TFile of the previous slot is erased
353 treeOutResiduals->SetDirectory(fileOut.get());
354 treeOutTrackData->SetDirectory(fileOut.get());
355 treeOutResidualsUnbinned->SetDirectory(fileOut.get());
356
358
359 // append the current vector to the vector of the previous container and afterwards swap them,
360 // since the vector of the previous container will be deleted
361 prev->tfOrbits.insert(prev->tfOrbits.end(), tfOrbits.begin(), tfOrbits.end());
362 std::swap(prev->tfOrbits, tfOrbits);
363 prev->sumBinnedResid.insert(prev->sumBinnedResid.end(), sumBinnedResid.begin(), sumBinnedResid.end());
364 std::swap(prev->sumBinnedResid, sumBinnedResid);
365 prev->sumUnbinnedResid.insert(prev->sumUnbinnedResid.end(), sumUnbinnedResid.begin(), sumUnbinnedResid.end());
366 std::swap(prev->sumUnbinnedResid, sumUnbinnedResid);
367 prev->lumi.insert(prev->lumi.end(), lumi.begin(), lumi.end());
368 std::swap(prev->lumi, lumi);
369
370 firstSeenTF = prev->firstSeenTF;
371 LOGP(debug, "Done with the merge. Current slot has {} entries", getNEntries());
372}
373
375{
376 LOG(info) << "There are in total " << nResidualsTotal << " residuals stored in the container";
377}
378
380
382{
383 auto& slots = getSlots();
384 slots.clear();
385}
386
388{
389 LOG(debug) << "There are " << slot.getContainer()->getNEntries() << " entries currently. Min entries per voxel: " << mMinEntries;
390 auto entriesPerVoxel = slot.getContainer()->getNEntries() / (mTrackResiduals.getNVoxelsPerSector() * SECTORSPERSIDE * SIDES);
391 LOGP(debug, "Slot has {} entries per voxel, at least {} are required", entriesPerVoxel, mMinEntries);
392 return entriesPerVoxel >= mMinEntries;
393}
394
396{
397 // nothing to be done here, but method needs to be overwritten
398}
399
401{
402 LOG(info) << "Finalizing slot";
403 auto finalizeStartTime = std::chrono::high_resolution_clock::now();
404 auto cont = slot.getContainer();
405 cont->print();
406 if (!mWriteOutput || cont->getNEntries() == 0 || !cont->writeToRootFile) {
407 LOGP(info, "Skip writing output with {} entries, since file output is disabled or slot is empty", cont->getNEntries());
408 return;
409 }
410 cont->TPCVDriftRef = mTPCVDriftRef;
411 cont->TPCDriftTimeOffsetRef = mTPCDriftTimeOffsetRef;
412 cont->writeToFile(true);
413
414 long orbitOffsetStart = (cont->firstSeenTF - slot.getTFStart()) * o2::base::GRPGeomHelper::getNHBFPerTF();
415 long orbitOffsetEnd = (slot.getTFEnd() - cont->firstSeenTF) * o2::base::GRPGeomHelper::getNHBFPerTF();
416 long timeStartMS = mOrbitResetTime + (cont->firstTForbit - orbitOffsetStart) * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
417 long timeEndMS = mOrbitResetTime + (cont->firstTForbit + orbitOffsetEnd) * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
418 auto fileName = fmt::format("o2tpc_residuals_{}_{}_{}_{}.root", timeStartMS, timeEndMS, slot.getTFStart(), slot.getTFEnd());
419 auto fileNameWithPath = mOutputDir + fileName;
420 std::filesystem::rename(o2::utils::Str::concat_string(mOutputDir, cont->fileName, ".part"), fileNameWithPath);
421 if (mStoreMetaData) {
422 o2::dataformats::FileMetaData fileMetaData; // object with information for meta data file
423 fileMetaData.fillFileData(fileNameWithPath);
424 fileMetaData.setDataTakingContext(mDataTakingContext);
425 fileMetaData.type = "calib";
426 fileMetaData.priority = "high";
427 auto metaFileNameTmp = fmt::format("{}{}.tmp", mMetaOutputDir, fileName);
428 auto metaFileName = fmt::format("{}{}.done", mMetaOutputDir, fileName);
429 try {
430 std::ofstream metaFileOut(metaFileNameTmp);
431 metaFileOut << fileMetaData;
432 metaFileOut.close();
433 std::filesystem::rename(metaFileNameTmp, metaFileName);
434 } catch (std::exception const& e) {
435 LOG(error) << "Failed to store residuals meta data file " << metaFileName << ", reason: " << e.what();
436 }
437 }
438 std::chrono::duration<double, std::milli> finalizeDuration = std::chrono::high_resolution_clock::now() - finalizeStartTime;
439 LOGP(info, "Finalizing calibration slot took: {} ms", std::chrono::duration_cast<std::chrono::milliseconds>(finalizeDuration).count());
440}
441
443{
444 auto emplaceStartTime = std::chrono::high_resolution_clock::now();
445 auto& cont = getSlots();
446 auto& slot = front ? cont.emplace_front(tStart, tEnd) : cont.emplace_back(tStart, tEnd);
447 slot.setContainer(std::make_unique<ResidualsContainer>());
448 slot.getContainer()->init(&mTrackResiduals, mOutputDir, mWriteOutput, mWriteBinnedResiduals, mWriteUnbinnedResiduals, mWriteTrackData, mAutosaveInterval, mCompressionSetting, mOrbitResetTime);
449 std::chrono::duration<double, std::milli> emplaceDuration = std::chrono::high_resolution_clock::now() - emplaceStartTime;
450 LOGP(info, "Emplacing new calibration slot took: {} ms", std::chrono::duration_cast<std::chrono::milliseconds>(emplaceDuration).count());
451 return slot;
452}
453
455{
456 // for the residual extraction we are using the reference vDrift and time offset values only
457 if (v.refVDrift != mTPCVDriftRef) {
458 mTPCVDriftRef = v.refVDrift;
459 mTPCDriftTimeOffsetRef = v.refTimeOffset;
460 LOGP(info, "Imposing reference VDrift={}/TDrift={} for TPC residuals extraction", mTPCVDriftRef, mTPCDriftTimeOffsetRef);
461 }
462}
int32_t i
Collects local TPC cluster residuals from EPNs.
Parameters used for TPC space point calibration.
calibration data from laser track calibration
std::ostringstream debug
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
constexpr double LHCOrbitMUS
Global TPC definitions and constants.
Definition SimTraits.h:167
constexpr unsigned char SECTORSPERSIDE
Definition Defs.h:40
constexpr unsigned char SIDES
Definition Defs.h:41
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< 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
void fill(const o2::dataformats::TFIDInfo &ti, const gsl::span< const UnbinnedResid > resid, const gsl::span< const o2::tpc::TrackDataCompact > trkRefsIn, const gsl::span< const o2::tpc::TrackData > *trkDataIn, const o2::ctp::LumiInfo *lumiInput)
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.
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::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