Project
Loading...
Searching...
No Matches
DigitWriterSpec.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
13
16#include "Framework/DataRef.h"
21#include "Headers/DataHeader.h"
26#include "Framework/Logger.h"
28#include <vector>
29#include <string>
30#include <algorithm>
31
32using namespace o2::framework;
34
35namespace o2
36{
37namespace itsmft
38{
39
40template <typename T>
43
46template <int N>
47DataProcessorSpec getDigitWriterSpec(bool mctruth, bool doStag, bool dec, bool calib)
48{
50 int mLayers = doStag ? o2::itsmft::DPLAlpideParam<N>::getNLayers() : 1;
51 std::string detStr = o2::detectors::DetID::getName(N);
52 std::string detStrL = dec ? "o2_" : ""; // for decoded digits prepend by o2
53 detStrL += detStr;
54 std::transform(detStrL.begin(), detStrL.end(), detStrL.begin(), ::tolower);
55 auto digitSizes = std::make_shared<std::vector<size_t>>(mLayers, 0);
56 auto digitSizeGetter = [digitSizes](std::vector<o2::itsmft::Digit> const& inDigits, DataRef const& ref) {
57 auto const* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
58 (*digitSizes)[dh->subSpecification] = inDigits.size();
59 };
60 auto rofSizes = std::make_shared<std::vector<size_t>>(mLayers, 0);
61 auto rofSizeGetter = [rofSizes](std::vector<o2::itsmft::ROFRecord> const& inROFs, DataRef const& ref) {
62 auto const* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
63 (*rofSizes)[dh->subSpecification] = inROFs.size();
64 };
65
66 // the callback to be set as hook for custom action when the writer is closed
67 auto finishWriting = [](TFile* outputfile, TTree* outputtree) {
68 const auto* brArr = outputtree->GetListOfBranches();
69 int64_t nent = 0;
70 for (const auto* brc : *brArr) {
71 int64_t n = ((const TBranch*)brc)->GetEntries();
72 if (nent && (nent != n)) {
73 LOG(error) << "Branches have different number of entries";
74 }
75 nent = n;
76 }
77 if (nent == 0) {
78 // A timeframe holds no collision at all whenever the interaction rate is low enough, and no
79 // branch is then filled. Write one empty entry in every branch, so that the file has the same
80 // shape as an ordinary timeframe that happens to contain nothing. The label branch matters
81 // here: it is declared as std::vector<char> and only becomes an IOMCTruthContainerView when a
82 // fill remaps it, so without this a reader binding that type gets a class mismatch instead of
83 // an empty tree.
84 LOG(info) << "No branch was filled, writing one empty entry per branch";
85 std::vector<TBranch*> branches;
86 for (auto* o : *brArr) {
87 branches.push_back((TBranch*)o);
88 }
90 auto* labelptr = &emptyLabels;
91 for (auto* br : branches) {
92 if (TString(br->GetName()).Contains("MCTruth")) {
93 auto* remapped = framework::RootTreeWriter::remapBranch(*br, &labelptr);
94 remapped->Fill();
95 remapped->ResetAddress();
96 } else {
97 br->Fill();
98 }
99 }
100 nent = 1;
101 }
102 outputtree->SetEntries(nent);
103 // do not use TTree::Write .. as this writes to default directory (not the associated file)
104 // instead of outputtree->Write("", TObject::kOverwrite)
105 // --> better use TFile::Write or TFile::WriteObject
106 outputfile->Write("", TObject::kOverwrite);
107 outputfile->Close();
108 };
109
110 // handler for labels
111 // This is necessary since we can't store the original label buffer in a ROOT entry -- as is -- if it exceeds a certain size.
112 // We therefore convert it to a special split class.
113 auto fillLabels = [detStr, doStag, digitSizes, rofSizes](TBranch& branch, std::vector<char> const& labelbuffer, DataRef const& ref) {
115 auto const* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
116 auto layer = static_cast<size_t>(dh->subSpecification);
117 LOG(info) << detStr << ": WRITING " << labels.getNElements() << " LABELS" << (doStag ? std::format(" FOR LAYER {}", layer) : "") << " WITH " << (*digitSizes)[layer] << " DIGITS IN " << (*rofSizes)[layer] << " ROFS";
118
120 auto ptr = &outputcontainer;
122 outputcontainer.adopt(labelbuffer);
123 br->Fill();
124 br->ResetAddress();
125 };
126
127 auto getIndex = [](DataRef const& ref) -> size_t {
128 auto const* dh = DataRefUtils::getHeader<o2::header::DataHeader*>(ref);
129 return static_cast<size_t>(dh->subSpecification);
130 };
131 auto getName = [doStag](std::string base, size_t index) -> std::string {
132 if (doStag) {
133 return base += "_" + std::to_string(index);
134 }
135 return base;
136 };
137
138 std::vector<InputSpec> vecInpSpecDig, vecInpSpecROF, vecInpSpecLbl;
139 vecInpSpecDig.reserve(mLayers);
140 vecInpSpecROF.reserve(mLayers);
141 vecInpSpecLbl.reserve(mLayers);
142 for (int iLayer = 0; iLayer < mLayers; iLayer++) {
143 vecInpSpecDig.emplace_back(getName(detStr + "digits", iLayer), Origin, "DIGITS", iLayer);
144 vecInpSpecROF.emplace_back(getName(detStr + "digitsROF", iLayer), Origin, "DIGITSROF", iLayer);
145 vecInpSpecLbl.emplace_back(getName(detStr + "_digitsMCTR", iLayer), Origin, "DIGITSMCTR", iLayer);
146 }
147
148 return MakeRootTreeWriterSpec((detStr + "DigitWriter" + (dec ? "_dec" : "")).c_str(),
149 (detStrL + "digits.root").c_str(),
150 MakeRootTreeWriterSpec::TreeAttributes{.name = "o2sim", .title = detStr + " Digits tree"},
153 detStr + "Digit", "digit-branch",
154 mLayers,
155 digitSizeGetter,
156 getIndex,
157 getName},
159 detStr + "DigitROF", "digit-rof-branch",
160 mLayers,
161 rofSizeGetter,
162 getIndex,
163 getName},
165 detStr + "DigitMCTruth", "digit-mctruth-branch",
166 (mctruth ? mLayers : 0),
167 fillLabels,
168 getIndex,
169 getName},
170 BranchDefinition<std::vector<itsmft::MC2ROFRecord>>{InputSpec{detStr + "_digitsMC2ROF", ConcreteDataTypeMatcher{Origin, "DIGITSMC2ROF"}},
171 detStr + "DigitMC2ROF", "digit-mc2rof-branch",
172 (mctruth ? mLayers : 0),
173 getIndex,
174 getName},
176 detStr + "Calib", "digit-calib-branch",
177 (calib ? 1 : 0)})();
178}
179
180DataProcessorSpec getITSDigitWriterSpec(bool mctruth, bool doStag, bool dec, bool calib)
181{
182 return getDigitWriterSpec<o2::detectors::DetID::ITS>(mctruth, doStag, dec, calib);
183}
184
185DataProcessorSpec getMFTDigitWriterSpec(bool mctruth, bool doStag, bool dec, bool calib)
186{
187 return getDigitWriterSpec<o2::detectors::DetID::MFT>(mctruth, doStag, dec, calib);
188}
189
190} // end namespace itsmft
191} // end namespace o2
std::vector< std::string > labels
std::string getName(const TDataMember *dm, int index, int size)
A const (ready only) version of MCTruthContainer.
Definition of the ITSMFT digit.
o2::framework::DataAllocator::SubSpecificationType SubSpecificationType
Calibration data from GBT data.
A special IO container - splitting a given vector to enable ROOT IO.
Definition of the ITSMFT ROFrame (trigger) record.
Configurable generator for RootTreeWriter processor spec.
TBranch * ptr
A read-only version of MCTruthContainer allowing for storage optimisation.
void adopt(gsl::span< const char > const input)
"adopt" (without taking ownership) from an existing buffer
static constexpr const char * getName(ID id)
names of defined detectors
Definition DetID.h:146
static constexpr ID ITS
Definition DetID.h:63
o2::header::DataHeader::SubSpecificationType SubSpecificationType
Generate a processor spec for the RootTreeWriter utility.
static TBranch * remapBranch(TBranch &branchRef, T **newdata)
GLdouble n
Definition glcorearb.h:1982
GLuint index
Definition glcorearb.h:781
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLint ref
Definition glcorearb.h:291
constexpr o2::header::DataOrigin gDataOriginMFT
Definition DataHeader.h:572
constexpr o2::header::DataOrigin gDataOriginITS
Definition DataHeader.h:570
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
o2::framework::DataProcessorSpec getMFTDigitWriterSpec(bool mctruth=true, bool doStag=false, bool dec=false, bool calib=false)
o2::framework::DataProcessorSpec getITSDigitWriterSpec(bool mctruth=true, bool doStag=false, bool dec=false, bool calib=false)
DataProcessorSpec getDigitWriterSpec(bool mctruth, bool doStag, bool dec, bool calib)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
static constexpr int getNLayers()
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"