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 int sec = residIn.sec;
201 auto& residVecOut = residuals[sec];
202 auto& statVecOut = stats[sec];
203 std::array<unsigned char, TrackResiduals::VoxDim> bvox;
204 float xPos = param::RowX[residIn.row];
205 float yPos = residIn.y * param::MaxY / 0x7fff + residIn.dy * param::MaxResid / 0x7fff;
206 float zPos = residIn.z * param::MaxZ / 0x7fff + residIn.dz * param::MaxResid / 0x7fff;
207 if (!trackResiduals->findVoxelBin(sec, xPos, yPos, zPos, bvox)) {
208 // we are not inside any voxel
209 LOGF(debug, "Dropping residual in sec(%i), x(%f), y(%f), z(%f)", sec, xPos, yPos, zPos);
210 continue;
211 }
212 residVecOut.emplace_back(residIn.dy, residIn.dz, residIn.tgSlp, bvox);
213 auto& stat = statVecOut[trackResiduals->getGlbVoxBin(bvox)];
214 float& binEntries = stat.nEntries;
215 float oldEntries = binEntries++;
216 float norm = 1.f / binEntries;
217 // update COG for voxel bvox (update for X only needed in case binning is not per pad row)
218 float xPosInv = 1.f / xPos;
219 stat.meanPos[TrackResiduals::VoxX] = (stat.meanPos[TrackResiduals::VoxX] * oldEntries + xPos) * norm;
220 stat.meanPos[TrackResiduals::VoxF] = (stat.meanPos[TrackResiduals::VoxF] * oldEntries + yPos * xPosInv) * norm;
221 stat.meanPos[TrackResiduals::VoxZ] = (stat.meanPos[TrackResiduals::VoxZ] * oldEntries + zPos * xPosInv) * norm;
222 if (!counterIncremented) {
224 }
225 ++nBinnedResidualsInTF;
226 }
227 for (const auto& trkRef : trkRefsIn) {
228 trackInfo.push_back(trkRef);
229 }
230 sumBinnedResid.push_back(nBinnedResidualsInTF);
231 sumUnbinnedResid.push_back(nUnbinnedResidualsInTF);
232 if (writeBinnedResid) {
233 treeOutResiduals->Fill();
234 }
235 for (auto& residVecOut : residuals) {
236 residVecOut.clear();
237 }
238 if (writeTrackData) {
239 for (const auto& trkIn : *trkDataIn) {
240 trkData.push_back(trkIn);
241 }
242 treeOutTrackData->Fill();
243 trkData.clear();
244 }
246 if (lumiInput) {
247 lumiTF = *lumiInput;
248 }
251 unbinnedRes.clear();
252 detInfoUnbRes.clear();
253 trackInfo.clear();
254 }
255 tfOrbits.push_back(ti.firstTForbit);
256 if (lumiInput) {
257 lumi.push_back(*lumiInput);
258 }
259
260 if (autosaveInterval > 0 && (tfOrbits.size() % autosaveInterval) == 0 && writeToRootFile) {
261 writeToFile(false);
262 }
263}
264
265void ResidualsContainer::writeToFile(bool closeFileAfterwards)
266{
267 LOG(info) << "Writing results to file. Closing afterwards? " << closeFileAfterwards;
268 fillStatisticsBranches(); // these would need to be filled only once, so only the last entry is important
269 fileOut->cd();
270 treeOutRecords->Write();
271 if (writeBinnedResid) {
272 treeOutResiduals->Write();
273 treeOutStats->Write();
274 }
277 }
278 if (writeTrackData) {
279 treeOutTrackData->Write();
280 }
281
282 if (closeFileAfterwards) {
283 treeOutRecords.reset();
284 if (writeBinnedResid) {
285 treeOutResiduals.reset();
286 treeOutStats.reset();
287 }
290 }
291 if (writeTrackData) {
292 treeOutTrackData.reset();
293 }
294 fileOut->Close();
295 fileOut.reset();
296 }
297}
298
300{
301 // the previous slot is merged to this one and afterwards
302 // the previous one will be deleted
303 LOGP(debug, "Merging previous slot with {} entries into current one with {} entries", prev->getNEntries(), getNEntries());
304 if (writeBinnedResid) {
305 for (int iSec = 0; iSec < SECTORSPERSIDE * SIDES; ++iSec) {
306 // merge statistics
307 const auto& statVecPrev = prev->stats[iSec];
308 auto& statVec = stats[iSec];
309 for (int iVox = 0; iVox < trackResiduals->getNVoxelsPerSector(); ++iVox) {
310 const auto& statPrev = statVecPrev[iVox];
311 auto& stat = statVec[iVox];
312 float norm = 1.f;
313 if (statPrev.nEntries + stat.nEntries > 0.1) {
314 // if there is at least a single entry in either of the containers we need the proper norm
315 norm /= (statPrev.nEntries + stat.nEntries);
316 }
317 stat.meanPos[TrackResiduals::VoxX] = (stat.meanPos[TrackResiduals::VoxX] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxX] * statPrev.nEntries) * norm;
318 stat.meanPos[TrackResiduals::VoxF] = (stat.meanPos[TrackResiduals::VoxF] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxF] * statPrev.nEntries) * norm;
319 stat.meanPos[TrackResiduals::VoxZ] = (stat.meanPos[TrackResiduals::VoxZ] * stat.nEntries + statPrev.meanPos[TrackResiduals::VoxZ] * statPrev.nEntries) * norm;
320 stat.nEntries += statPrev.nEntries;
321 }
322 // prepare merging of residuals
323 prev->treeOutResiduals->SetBranchAddress(Form("sec%d", iSec), &residualsPtr[iSec]);
324 }
325 // We append the entries of the tree of the following slot to the
326 // previous slot and afterwards move the merged tree to this slot.
327 // This way the order of the entries is preserved
328 for (int i = 0; i < treeOutResiduals->GetEntries(); ++i) {
329 treeOutResiduals->GetEntry(i);
330 prev->treeOutResiduals->Fill();
331 }
332 }
333
334 if (writeTrackData) {
335 prev->treeOutTrackData->SetBranchAddress("trk", &trkDataPtr);
336 for (int i = 0; i < treeOutTrackData->GetEntries(); ++i) {
337 treeOutTrackData->GetEntry(i);
338 prev->treeOutTrackData->Fill();
339 }
340 }
342 prev->treeOutResidualsUnbinned->SetBranchAddress("res", &unbinnedResPtr);
343 prev->treeOutResidualsUnbinned->SetBranchAddress("trackInfo", &trackInfoPtr);
344 prev->treeOutResidualsUnbinned->SetBranchAddress("CTPLumi", &lumiTF);
345 prev->treeOutResidualsUnbinned->SetBranchAddress("timeMS", &timeMS);
346 prev->treeOutResidualsUnbinned->SetBranchAddress("detInfo", &detInfoUnbResPtr);
347 for (int i = 0; i < treeOutResidualsUnbinned->GetEntries(); ++i) {
348 treeOutResidualsUnbinned->GetEntry(i);
349 prev->treeOutResidualsUnbinned->Fill();
350 }
351 }
352
353 treeOutResiduals = std::move(prev->treeOutResiduals);
354 treeOutTrackData = std::move(prev->treeOutTrackData);
356
357 // since we want to continue using the TTrees of the previous slot, we must
358 // avoid that ROOT deletes them when the TFile of the previous slot is erased
359 treeOutResiduals->SetDirectory(fileOut.get());
360 treeOutTrackData->SetDirectory(fileOut.get());
361 treeOutResidualsUnbinned->SetDirectory(fileOut.get());
362
364
365 // append the current vector to the vector of the previous container and afterwards swap them,
366 // since the vector of the previous container will be deleted
367 prev->tfOrbits.insert(prev->tfOrbits.end(), tfOrbits.begin(), tfOrbits.end());
368 std::swap(prev->tfOrbits, tfOrbits);
369 prev->sumBinnedResid.insert(prev->sumBinnedResid.end(), sumBinnedResid.begin(), sumBinnedResid.end());
370 std::swap(prev->sumBinnedResid, sumBinnedResid);
371 prev->sumUnbinnedResid.insert(prev->sumUnbinnedResid.end(), sumUnbinnedResid.begin(), sumUnbinnedResid.end());
372 std::swap(prev->sumUnbinnedResid, sumUnbinnedResid);
373 prev->lumi.insert(prev->lumi.end(), lumi.begin(), lumi.end());
374 std::swap(prev->lumi, lumi);
375
376 firstSeenTF = prev->firstSeenTF;
377 LOGP(debug, "Done with the merge. Current slot has {} entries", getNEntries());
378}
379
381{
382 LOG(info) << "There are in total " << nResidualsTotal << " residuals stored in the container";
383}
384
386
388{
389 auto& slots = getSlots();
390 slots.clear();
391}
392
394{
395 LOG(debug) << "There are " << slot.getContainer()->getNEntries() << " entries currently. Min entries per voxel: " << mMinEntries;
396 auto entriesPerVoxel = slot.getContainer()->getNEntries() / (mTrackResiduals.getNVoxelsPerSector() * SECTORSPERSIDE * SIDES);
397 LOGP(debug, "Slot has {} entries per voxel, at least {} are required", entriesPerVoxel, mMinEntries);
398 return entriesPerVoxel >= mMinEntries;
399}
400
402{
403 // nothing to be done here, but method needs to be overwritten
404}
405
407{
408 LOG(info) << "Finalizing slot";
409 auto finalizeStartTime = std::chrono::high_resolution_clock::now();
410 auto cont = slot.getContainer();
411 cont->print();
412 if (!mWriteOutput || cont->getNEntries() == 0 || !cont->writeToRootFile) {
413 LOGP(info, "Skip writing output with {} entries, since file output is disabled or slot is empty", cont->getNEntries());
414 return;
415 }
416 cont->TPCVDriftRef = mTPCVDriftRef;
417 cont->TPCDriftTimeOffsetRef = mTPCDriftTimeOffsetRef;
418 cont->writeToFile(true);
419
420 long orbitOffsetStart = (cont->firstSeenTF - slot.getTFStart()) * o2::base::GRPGeomHelper::getNHBFPerTF();
421 long orbitOffsetEnd = (slot.getTFEnd() - cont->firstSeenTF) * o2::base::GRPGeomHelper::getNHBFPerTF();
422 long timeStartMS = mOrbitResetTime + (cont->firstTForbit - orbitOffsetStart) * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
423 long timeEndMS = mOrbitResetTime + (cont->firstTForbit + orbitOffsetEnd) * o2::constants::lhc::LHCOrbitMUS * 1.e-3;
424 auto fileName = fmt::format("o2tpc_residuals_{}_{}_{}_{}.root", timeStartMS, timeEndMS, slot.getTFStart(), slot.getTFEnd());
425 auto fileNameWithPath = mOutputDir + fileName;
426 std::filesystem::rename(o2::utils::Str::concat_string(mOutputDir, cont->fileName, ".part"), fileNameWithPath);
427 if (mStoreMetaData) {
428 o2::dataformats::FileMetaData fileMetaData; // object with information for meta data file
429 fileMetaData.fillFileData(fileNameWithPath);
430 fileMetaData.setDataTakingContext(mDataTakingContext);
431 fileMetaData.type = "calib";
432 fileMetaData.priority = "high";
433 auto metaFileNameTmp = fmt::format("{}{}.tmp", mMetaOutputDir, fileName);
434 auto metaFileName = fmt::format("{}{}.done", mMetaOutputDir, fileName);
435 try {
436 std::ofstream metaFileOut(metaFileNameTmp);
437 metaFileOut << fileMetaData;
438 metaFileOut.close();
439 std::filesystem::rename(metaFileNameTmp, metaFileName);
440 } catch (std::exception const& e) {
441 LOG(error) << "Failed to store residuals meta data file " << metaFileName << ", reason: " << e.what();
442 }
443 }
444 std::chrono::duration<double, std::milli> finalizeDuration = std::chrono::high_resolution_clock::now() - finalizeStartTime;
445 LOGP(info, "Finalizing calibration slot took: {} ms", std::chrono::duration_cast<std::chrono::milliseconds>(finalizeDuration).count());
446}
447
449{
450 auto emplaceStartTime = std::chrono::high_resolution_clock::now();
451 auto& cont = getSlots();
452 auto& slot = front ? cont.emplace_front(tStart, tEnd) : cont.emplace_back(tStart, tEnd);
453 slot.setContainer(std::make_unique<ResidualsContainer>());
454 slot.getContainer()->init(&mTrackResiduals, mOutputDir, mWriteOutput, mWriteBinnedResiduals, mWriteUnbinnedResiduals, mWriteTrackData, mAutosaveInterval, mCompressionSetting, mOrbitResetTime);
455 std::chrono::duration<double, std::milli> emplaceDuration = std::chrono::high_resolution_clock::now() - emplaceStartTime;
456 LOGP(info, "Emplacing new calibration slot took: {} ms", std::chrono::duration_cast<std::chrono::milliseconds>(emplaceDuration).count());
457 return slot;
458}
459
461{
462 // for the residual extraction we are using the reference vDrift and time offset values only
463 if (v.refVDrift != mTPCVDriftRef) {
464 mTPCVDriftRef = v.refVDrift;
465 mTPCDriftTimeOffsetRef = v.refTimeOffset;
466 LOGP(info, "Imposing reference VDrift={}/TDrift={} for TPC residuals extraction", mTPCVDriftRef, mTPCDriftTimeOffsetRef);
467 }
468}
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
constexpr double LHCOrbitMUS
Global TPC definitions and constants.
Definition SimTraits.h:168
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< 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