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