Project
Loading...
Searching...
No Matches
ClusterNativeHelper.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
16
18#include "Algorithm/Parser.h"
19#include <TBranch.h>
20#include <fairlogger/Logger.h>
21#include <iostream>
22
23using namespace o2::tpc;
24using namespace o2::tpc::constants;
25
26void ClusterNativeHelper::convert(const char* fromFile, const char* toFile, const char* toTreeName)
27{
28 Reader reader;
29 TreeWriter writer;
30 reader.init(fromFile);
31 writer.init(toFile, toTreeName);
32 size_t nEntries = reader.getTreeSize();
33 ClusterNativeAccess clusterIndex;
34 std::unique_ptr<ClusterNative[]> clusterBuffer;
36
37 int result = 0;
38 int nClusters = 0;
39 for (size_t entry = 0; entry < nEntries; ++entry) {
40 LOG(info) << "converting entry " << entry;
41 reader.read(entry);
42 result = reader.fillIndex(clusterIndex, clusterBuffer, mcBuffer);
43 if (result >= 0) {
44 LOG(info) << "added " << result << " clusters to index";
45 } else {
46 LOG(error) << "filling of clusters index failed with " << result;
47 }
48 result = writer.fillFrom(clusterIndex);
49 if (result >= 0) {
50 LOG(info) << "wrote " << result << " clusters to tree";
52 } else {
53 LOG(error) << "filling of tree failed with " << result;
54 }
55 }
56 LOG(info) << "... done, converted " << nClusters << " clusters";
57 writer.close();
58}
59
60std::unique_ptr<ClusterNativeAccess> ClusterNativeHelper::createClusterNativeIndex(
61 std::unique_ptr<ClusterNative[]>& buffer, std::vector<ClusterNativeContainer>& clusters,
62 MCLabelContainer* bufferMC, std::vector<MCLabelContainer>* mcTruth)
63{
64 std::unique_ptr<ClusterNativeAccess> retVal(new ClusterNativeAccess);
65 memset(retVal.get(), 0, sizeof(*retVal));
66 for (int i = 0; i < clusters.size(); i++) {
67 if (retVal->nClusters[clusters[i].sector][clusters[i].globalPadRow]) {
68 LOG(error) << "Received two containers for the same sector / row";
69 return std::unique_ptr<ClusterNativeAccess>();
70 }
71 retVal->nClusters[clusters[i].sector][clusters[i].globalPadRow] = clusters[i].clusters.size();
72 retVal->nClustersTotal += clusters[i].clusters.size();
73 }
74 buffer.reset(new ClusterNative[retVal->nClustersTotal]);
75 if (bufferMC) {
76 bufferMC->clear();
77 }
78 retVal->clustersLinear = buffer.get();
79 retVal->setOffsetPtrs();
80 for (int i = 0; i < clusters.size(); i++) {
81 memcpy(&buffer[retVal->clusterOffset[clusters[i].sector][clusters[i].globalPadRow]], clusters[i].clusters.data(), sizeof(*retVal->clustersLinear) * clusters[i].clusters.size());
82 if (mcTruth) {
83 for (unsigned int j = 0; j < clusters[i].clusters.size(); j++) {
84 for (auto const& label : (*mcTruth)[i].getLabels(j)) {
85 bufferMC->addElement(retVal->clusterOffset[clusters[i].sector][clusters[i].globalPadRow] + j, label);
86 }
87 }
88 }
89 }
90 return (std::move(retVal));
91}
92
93ClusterNativeHelper::Reader::~Reader()
94{
95 clear();
96}
97
98ClusterNativeHelper::Reader::Reader()
99{
100 memset(&mSectorRawSize, 0, sizeof(mSectorRawSize));
101 memset(&mSectorRaw, 0, sizeof(mSectorRaw));
102}
103
104void ClusterNativeHelper::Reader::init(const char* filename, const char* treename)
105{
106 if (treename != nullptr && treename[0] != 0) {
107 mTreeName = treename;
108 }
109 mFile.reset(TFile::Open(filename));
110 if (!mFile) {
111 return;
112 }
113 mTree = reinterpret_cast<TTree*>(mFile->GetObjectUnchecked(mTreeName.c_str()));
114 if (!mTree) {
115 LOG(error) << "can not find tree " << mTreeName << " in file " << filename;
116 return;
117 }
118
119 const bool singleBranch = mTree->GetBranch(mDataBranchName.data());
120
121 size_t nofDataBranches = 0;
122 size_t nofMCBranches = 0;
123 for (size_t sector = 0; sector < NSectors; ++sector) {
124 auto branchname = singleBranch ? mDataBranchName : mDataBranchName + "_" + std::to_string(sector);
125 TBranch* branch = mTree->GetBranch(branchname.c_str());
126 if (branch) {
127 TBranch* sizebranch = mTree->GetBranch((branchname + "Size").c_str());
128 if (sizebranch) {
129 branch->SetAddress(&mSectorRaw[sector]);
130 sizebranch->SetAddress(&mSectorRawSize[sector]);
131 ++nofDataBranches;
132 } else {
133 LOG(error) << "can not find corresponding 'Size' branch for data branch " << branchname << ", skipping it";
134 }
135 }
136 branchname = singleBranch ? mMCBranchName : mMCBranchName + "_" + std::to_string(sector);
137 branch = mTree->GetBranch(branchname.c_str());
138 if (branch) {
139 branch->SetAddress(&mSectorMCPtr[sector]);
140 ++nofMCBranches;
141 }
142
143 if (singleBranch) {
144 break;
145 }
146 }
147 LOG(info) << "reading " << nofDataBranches << " data branch(es) and " << nofMCBranches << " mc branch(es)";
148}
149
150void ClusterNativeHelper::Reader::read(size_t entry)
151{
152 if (entry >= getTreeSize()) {
153 return;
154 }
155 clear();
156 mTree->GetEntry(entry);
157}
158
159void ClusterNativeHelper::Reader::clear()
160{
161 memset(&mSectorRawSize, 0, sizeof(mSectorRawSize));
162 for (auto data : mSectorRaw) {
163 if (data) {
164 delete data;
165 }
166 }
167 memset(&mSectorRaw, 0, sizeof(mSectorRaw));
168}
169
170int ClusterNativeHelper::Reader::fillIndex(ClusterNativeAccess& clusterIndex, std::unique_ptr<ClusterNative[]>& clusterBuffer,
172{
173 std::vector<gsl::span<const char>> clustersTPC;
174 std::vector<ConstMCLabelContainer> constMCLabelContainers;
175 std::vector<ConstMCLabelContainerView> constMCLabelContainerViews;
176
177 for (size_t index = 0; index < mSectorRaw.size(); ++index) {
178 if (mSectorRaw[index]) {
179 if (mSectorRaw[index]->size() != mSectorRawSize[index]) {
180 LOG(error) << "inconsistent raw size for sector " << index << ": " << mSectorRaw[index]->size() << " v.s. " << mSectorRawSize[index];
181 mSectorRaw[index]->clear();
182 } else {
183 clustersTPC.emplace_back(mSectorRaw[index]->data(), mSectorRawSize[index]);
184 }
185 }
186 if (mSectorMCPtr[index]) {
187 auto& view = constMCLabelContainers.emplace_back();
188 mSectorMCPtr[index]->copyandflatten(view);
189 constMCLabelContainerViews.emplace_back(view);
190 }
191 }
192
193 int result = fillIndex(clusterIndex, clusterBuffer, mcBuffer, clustersTPC, constMCLabelContainerViews);
194 return result;
195}
196
197int ClusterNativeHelper::Reader::parseSector(const char* buffer, size_t size, gsl::span<ConstMCLabelContainerView const> const& mcinput, ClusterNativeAccess& clusterIndex,
198 const ConstMCLabelContainerView* (&clustersMCTruth)[MAXSECTOR])
199{
200 if (!buffer || size < sizeof(ClusterCountIndex)) {
201 return 0;
202 }
203
204 auto mcIterator = mcinput.begin();
205 ClusterCountIndex const& counts = *reinterpret_cast<const ClusterCountIndex*>(buffer);
206 ClusterNative const* clusters = reinterpret_cast<ClusterNative const*>(buffer + sizeof(ClusterCountIndex));
207 size_t numberOfClusters = 0;
208 for (int i = 0; i < MAXSECTOR; i++) {
209 int nSectorClusters = 0;
210 for (int j = 0; j < MAXGLOBALPADROW; j++) {
211 if (counts.nClusters[i][j] == 0) {
212 continue;
213 }
214 nSectorClusters += counts.nClusters[i][j];
215 if ((numberOfClusters + counts.nClusters[i][j]) * sizeof(ClusterNative) + sizeof(ClusterCountIndex) > size) {
216 throw std::runtime_error("inconsistent buffer size");
217 }
218 clusterIndex.clusters[i][j] = clusters + numberOfClusters;
219 clusterIndex.nClusters[i][j] = counts.nClusters[i][j];
220 numberOfClusters += counts.nClusters[i][j];
221 }
222 if (nSectorClusters > 0) {
223 if (mcIterator != mcinput.end()) {
224 clustersMCTruth[i] = &(*mcIterator);
225 ++mcIterator;
226 if (mcIterator != mcinput.end()) {
227 throw std::runtime_error("can only have one MCLabel block per sector");
228 }
229 }
230 }
231 }
232
233 return numberOfClusters;
234}
235
240
241void ClusterNativeHelper::TreeWriter::init(const char* filename, const char* treename)
242{
243 mFile.reset(TFile::Open(filename, "RECREATE"));
244 if (!mFile) {
245 return;
246 }
247 mTree = std::make_unique<TTree>(treename, treename);
248 if (!mTree) {
249 return;
250 }
251
252 mTree->Branch("event", &mEvent, "Event/I");
253 mTree->Branch("NativeClusters", "std::vector<o2::tpc::ClusterNativeHelper::TreeWriter::BranchData>", &mStore);
254 mEvent = 0;
255 mStoreClusters.clear();
256}
257
259{
260 if (!mTree) {
261 return -1;
262 }
263 int result = 0;
264 for (size_t sector = 0; sector < MAXSECTOR; ++sector) {
265 for (size_t padrow = 0; padrow < MAXGLOBALPADROW; ++padrow) {
266 int locres = fillFrom(sector, padrow, clusterIndex.clusters[sector][padrow], clusterIndex.nClusters[sector][padrow]);
267 if (result >= 0 && locres >= 0) {
268 result += locres;
269 } else if (result >= 0) {
270 result = locres;
271 }
272 }
273 }
274 ++mEvent;
275 return result;
276}
277
279{
280 if (!mTree) {
281 return -1;
282 }
283 mStoreClusters.resize(nClusters);
284 if (clusters != nullptr && nClusters > 0) {
285 std::fill(mStoreClusters.begin(), mStoreClusters.end(), BranchData{sector, padrow});
286 std::copy(clusters, clusters + nClusters, mStoreClusters.begin());
287 mTree->Fill();
288 }
289 return nClusters;
290}
291
293{
294 if (!mFile) {
295 return;
296 }
297 mFile->Write();
298 mFile->Close();
299 mTree.release();
300 mFile.reset();
301}
Helper class to read the binary format of TPC ClusterNative.
int32_t i
int32_t retVal
Utilities for parsing of data sequences.
uint32_t j
Definition RawData.h:0
uint32_t padrow
Definition RawData.h:5
int nClusters
void addElement(uint32_t dataindex, TruthElement const &element, bool noElement=false)
A reader class for the raw cluster native data.
int fillIndex(ClusterNativeAccess &clusterIndex, std::unique_ptr< ClusterNative[]> &clusterBuffer, ConstMCLabelContainerViewWithBuffer &mcBuffer)
void init(const char *filename, const char *treename=nullptr)
Utility to write native cluster format to a ROOT tree.
void init(const char *filename, const char *treename)
int fillFrom(ClusterNativeAccess const &clusterIndex)
fill tree from the full index of cluster arrays
static std::unique_ptr< ClusterNativeAccess > createClusterNativeIndex(std::unique_ptr< ClusterNative[]> &buffer, std::vector< ClusterNativeContainer > &clusters, MCLabelContainer *bufferMC=nullptr, std::vector< MCLabelContainer > *mcTruth=nullptr)
static constexpr unsigned int NSectors
ClusterNativeAccess::ConstMCLabelContainerViewWithBuffer ConstMCLabelContainerViewWithBuffer
static void convert(const char *fromFile, const char *toFile, const char *toTreeName="tpcnative")
GLuint buffer
Definition glcorearb.h:655
GLuint entry
Definition glcorearb.h:5735
GLsizeiptr size
Definition glcorearb.h:659
GLuint index
Definition glcorearb.h:781
GLboolean * data
Definition glcorearb.h:298
GLuint GLsizei const GLchar * label
Definition glcorearb.h:2519
constexpr int MAXSECTOR
Definition Constants.h:28
constexpr int MAXGLOBALPADROW
Definition Constants.h:34
Global TPC definitions and constants.
Definition SimTraits.h:167
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
std::string filename()
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
const ClusterNative * clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters
vec clear()