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;
73 LOG(info) <<
"Setting entries to " << entries;
74 outputtree->SetEntries(entries);
81 using DigitsOutputType = std::vector<o2::tpc::Digit>;
82 using CommonModeOutputType = std::vector<o2::tpc::CommonMode>;
85 auto extractSector = [](
auto const&
ref) {
86 auto sectorHeader = DataRefUtils::getHeader<o2::tpc::TPCSectorHeader*>(
ref);
88 throw std::runtime_error(
"Missing sector header in TPC data");
94 throw std::runtime_error(
"Digitizer can only work on single sectors");
96 return sectorHeader->sector();
103 auto sector = extractSector(
ref);
109 for (
auto const& s : laneConfiguration) {
115 throw std::runtime_error(
"sector " +
std::to_string(sector) +
" not configured for writing");
119 auto getName = [laneConfiguration](std::string base,
size_t index) -> std::string {
124 auto trigP2Sect = std::make_shared<std::array<std::vector<DigiGroupRef>, 36>>();
129 for (
auto& cont : *trigP2Sect) {
132 std::vector<InputSpec>
filter = {
136 auto sector = extractSector(
ref);
137 auto const* dh = DataRefUtils::getHeader<DataHeader*>(
ref);
138 LOG(info) <<
"HAVE TRIGGER DATA FOR SECTOR " << sector <<
" ON CHANNEL " << dh->subSpecification;
141 auto triggers = pc.inputs().get<std::vector<DigiGroupRef>>(
ref);
142 (*trigP2Sect)[sector].assign(triggers.begin(), triggers.end());
143 const auto& trigS = (*trigP2Sect)[sector];
144 LOG(info) <<
"GOT Triggers of sector " << sector <<
" | SIZE " << trigS.size();
151 auto fillDigits = [extractSector, trigP2Sect](TBranch& branch, DigitsOutputType
const& digiData,
DataRef const&
ref) {
152 auto sector = extractSector(
ref);
153 auto const* dh = DataRefUtils::getHeader<DataHeader*>(
ref);
154 LOG(info) <<
"HAVE DIGIT DATA FOR SECTOR " << sector <<
" ON CHANNEL " << dh->subSpecification;
156 LOG(info) <<
"DIGIT SIZE " << digiData.size();
157 const auto& trigS = (*trigP2Sect.get())[sector];
160 std::runtime_error(
"Digits for sector " +
std::to_string(sector) +
" are received w/o info on grouping in triggers");
162 int nExp = trigS.back().getFirstEntry() + trigS.back().getEntries() - trigS.front().getFirstEntry();
163 if (nExp != digiData.size()) {
164 LOG(error) <<
"Number of digits " << digiData.size() <<
" is inconsistent with expectation " << nExp
165 <<
" from digits grouping for sector " << sector;
170 if (trigS.size() == 1) {
171 auto ptr = &digiData;
172 branch.SetAddress(&
ptr);
175 branch.ResetAddress();
176 branch.DropBaskets(
"all");
178 std::vector<o2::tpc::Digit> digGroup;
179 auto ptr = &digGroup;
180 branch.SetAddress(&
ptr);
181 for (
auto const&
group : trigS) {
183 for (
int i = 0;
i <
group.getEntries();
i++) {
184 digGroup.emplace_back(digiData[
group.getFirstEntry() +
i]);
189 branch.ResetAddress();
190 branch.DropBaskets(
"all");
193 auto tree = branch.GetTree();
194 tree->SetEntries(entries);
195 tree->Write(
"", TObject::kOverwrite);
201 auto fillLabels = [extractSector, trigP2Sect](TBranch& branch, std::vector<char>
const& labelbuffer,
DataRef const&
ref) {
205 auto tree = branch.GetTree();
206 auto sector = extractSector(
ref);
207 auto ptr = &outputcontainer;
210 auto const* dh = DataRefUtils::getHeader<DataHeader*>(
ref);
211 LOG(info) <<
"HAVE LABEL DATA FOR SECTOR " << sector <<
" ON CHANNEL " << dh->subSpecification;
216 const auto& trigS = (*trigP2Sect.get())[sector];
218 throw std::runtime_error(
"MCTruth for sector " +
std::to_string(sector) +
" are received w/o info on grouping in triggers");
220 int nExp = trigS.back().getFirstEntry() + trigS.back().getEntries() - trigS.front().getFirstEntry();
223 <<
" is inconsistent with expectation " << nExp
224 <<
" from digits grouping for sector " << sector;
228 if (trigS.size() == 1) {
229 outputcontainer.
adopt(labelbuffer);
232 br->DropBaskets(
"all");
236 for (
auto const&
group : trigS) {
238 for (
int i = 0;
i <
group.getEntries();
i++) {
243 std::vector<char> flatbuffer;
245 outputcontainer.
adopt(flatbuffer);
247 br->DropBaskets(
"all");
253 tree->SetEntries(entries);
254 tree->Write(
"", TObject::kOverwrite);
259 auto commonModeSpectator = [extractSector](CommonModeOutputType
const& commonModeData,
DataRef const&
ref) {
260 auto sector = extractSector(
ref);
261 auto const* dh = DataRefUtils::getHeader<DataHeader*>(
ref);
262 LOG(info) <<
"HAVE COMMON MODE DATA FOR SECTOR " << sector <<
" ON CHANNEL " << dh->subSpecification;
263 LOG(info) <<
"COMMON MODE SIZE " << commonModeData.size();
267 "TPCDigit",
"digits-branch-name",
268 laneConfiguration.size(),
274 "TPCDigitMCTruth",
"labels-branch-name",
276 (mctruth ? laneConfiguration.size() : 0),
282 "TPCCommonMode",
"common-mode-branch-name",
283 laneConfiguration.size(),
298 std::move(digitsdef), std::move(labelsdef), std::move(commddef))();