58 auto finishWriting = [](TFile* outputfile, TTree* outputtree) {
62 const auto brlist = outputtree->GetListOfBranches();
65 auto br =
static_cast<TBranch*
>(
entry);
66 int brentries = br->GetEntries();
67 entries = std::max(entries, brentries);
68 if (brentries != entries && !TString(br->GetName()).Contains(
"CommonMode")) {
69 LOG(warning) <<
"INCONSISTENT NUMBER OF ENTRIES IN BRANCH " << br->GetName() <<
": " << entries <<
" vs " << brentries;
78 LOG(info) <<
"No branch was filled, writing one empty entry per branch";
84 LOG(info) <<
"Setting entries to " << entries;
85 outputtree->SetEntries(entries);
89 outputfile->Write(
"", TObject::kOverwrite);
94 using DigitsOutputType = std::vector<o2::tpc::Digit>;
95 using CommonModeOutputType = std::vector<o2::tpc::CommonMode>;
98 auto extractSector = [](
auto const&
ref) {
99 auto sectorHeader = DataRefUtils::getHeader<o2::tpc::TPCSectorHeader*>(
ref);
101 throw std::runtime_error(
"Missing sector header in TPC data");
107 throw std::runtime_error(
"Digitizer can only work on single sectors");
109 return sectorHeader->sector();
116 auto sector = extractSector(
ref);
122 for (
auto const& s : laneConfiguration) {
128 throw std::runtime_error(
"sector " +
std::to_string(sector) +
" not configured for writing");
132 auto getName = [laneConfiguration](std::string base,
size_t index) -> std::string {
137 auto trigP2Sect = std::make_shared<std::array<std::vector<DigiGroupRef>, 36>>();
142 for (
auto& cont : *trigP2Sect) {
145 std::vector<InputSpec>
filter = {
149 auto sector = extractSector(
ref);
150 auto const* dh = DataRefUtils::getHeader<DataHeader*>(
ref);
151 LOG(info) <<
"HAVE TRIGGER DATA FOR SECTOR " << sector <<
" ON CHANNEL " << dh->subSpecification;
154 auto triggers = pc.inputs().get<std::vector<DigiGroupRef>>(
ref);
155 (*trigP2Sect)[sector].assign(triggers.begin(), triggers.end());
156 const auto& trigS = (*trigP2Sect)[sector];
157 LOG(info) <<
"GOT Triggers of sector " << sector <<
" | SIZE " << trigS.size();
164 auto fillDigits = [extractSector, trigP2Sect](TBranch& branch, DigitsOutputType
const& digiData,
DataRef const&
ref) {
165 auto sector = extractSector(
ref);
166 auto const* dh = DataRefUtils::getHeader<DataHeader*>(
ref);
167 LOG(info) <<
"HAVE DIGIT DATA FOR SECTOR " << sector <<
" ON CHANNEL " << dh->subSpecification;
169 LOG(info) <<
"DIGIT SIZE " << digiData.size();
170 const auto& trigS = (*trigP2Sect.get())[sector];
172 if (trigS.size() == 0) {
173 LOG(warn) <<
"Digits for sector " +
std::to_string(sector) +
" are received w/o trigger info. Will assume continuous mode";
175 int nExp = trigS.back().getFirstEntry() + trigS.back().getEntries() - trigS.front().getFirstEntry();
176 if (nExp != digiData.size()) {
177 LOG(error) <<
"Number of digits " << digiData.size() <<
" is inconsistent with expectation " << nExp
178 <<
" from digits grouping for sector " << sector;
183 if (trigS.size() <= 1) {
184 auto ptr = &digiData;
185 branch.SetAddress(&
ptr);
188 branch.ResetAddress();
189 branch.DropBaskets(
"all");
191 std::vector<o2::tpc::Digit> digGroup;
192 auto ptr = &digGroup;
193 branch.SetAddress(&
ptr);
194 for (
auto const&
group : trigS) {
196 for (
int i = 0;
i <
group.getEntries();
i++) {
197 digGroup.emplace_back(digiData[
group.getFirstEntry() +
i]);
202 branch.ResetAddress();
203 branch.DropBaskets(
"all");
206 auto tree = branch.GetTree();
207 tree->SetEntries(entries);
208 tree->Write(
"", TObject::kOverwrite);
214 auto fillLabels = [extractSector, trigP2Sect](TBranch& branch, std::vector<char>
const& labelbuffer,
DataRef const&
ref) {
218 auto tree = branch.GetTree();
219 auto sector = extractSector(
ref);
220 auto ptr = &outputcontainer;
223 auto const* dh = DataRefUtils::getHeader<DataHeader*>(
ref);
224 LOG(info) <<
"HAVE LABEL DATA FOR SECTOR " << sector <<
" ON CHANNEL " << dh->subSpecification;
229 const auto& trigS = (*trigP2Sect.get())[sector];
230 if (trigS.size() == 0) {
231 LOG(warn) <<
"MCTruth for sector " +
std::to_string(sector) +
" received w/o trigger info. Will assume continuous mode";
233 int nExp = trigS.back().getFirstEntry() + trigS.back().getEntries() - trigS.front().getFirstEntry();
236 <<
" is inconsistent with expectation " << nExp
237 <<
" from digits grouping for sector " << sector;
241 if (trigS.size() <= 1) {
242 outputcontainer.
adopt(labelbuffer);
245 br->DropBaskets(
"all");
249 for (
auto const&
group : trigS) {
251 for (
int i = 0;
i <
group.getEntries();
i++) {
256 std::vector<char> flatbuffer;
258 outputcontainer.
adopt(flatbuffer);
260 br->DropBaskets(
"all");
266 tree->SetEntries(entries);
267 tree->Write(
"", TObject::kOverwrite);
272 auto commonModeSpectator = [extractSector](CommonModeOutputType
const& commonModeData,
DataRef const&
ref) {
273 auto sector = extractSector(
ref);
274 auto const* dh = DataRefUtils::getHeader<DataHeader*>(
ref);
275 LOG(info) <<
"HAVE COMMON MODE DATA FOR SECTOR " << sector <<
" ON CHANNEL " << dh->subSpecification;
276 LOG(info) <<
"COMMON MODE SIZE " << commonModeData.size();
280 "TPCDigit",
"digits-branch-name",
281 laneConfiguration.size(),
287 "TPCDigitMCTruth",
"labels-branch-name",
289 (mctruth ? laneConfiguration.size() : 0),
295 "TPCCommonMode",
"common-mode-branch-name",
296 laneConfiguration.size(),
311 std::move(digitsdef), std::move(labelsdef), std::move(commddef))();