1515
1616#include " TPCDigitRootWriterSpec.h"
1717#include " DataFormatsTPC/TPCSectorHeader.h"
18+ #include " CommonDataFormat/RangeReference.h"
1819#include " Framework/CallbackService.h"
1920#include " Framework/ControlService.h"
2021#include " TPCBase/Sector.h"
2930#include < sstream>
3031#include < string>
3132#include < vector>
33+ #include < utility>
3234
3335using namespace o2 ::framework;
3436using SubSpecificationType = o2::framework::DataAllocator::SubSpecificationType;
37+ using DigiGroupRef = o2::dataformats::RangeReference<int , int >;
3538
3639namespace o2
3740{
@@ -59,31 +62,36 @@ DataProcessorSpec getTPCDigitRootWriterSpec(int numberofsourcedevices)
5962{
6063 // assign input names to each channel
6164 auto digitchannelname = std::make_shared<std::vector<std::string>>();
65+ auto triggerchannelname = std::make_shared<std::vector<std::string>>();
6266 auto labelchannelname = std::make_shared<std::vector<std::string>>();
6367 for (int i = 0 ; i < numberofsourcedevices; ++i) {
6468 {
6569 std::stringstream ss;
6670 ss << " digitinput" << i;
6771 digitchannelname->push_back (ss.str ());
6872 }
73+ {
74+ std::stringstream ss;
75+ ss << " triggerinput" << i;
76+ triggerchannelname->push_back (ss.str ());
77+ }
6978 {
7079 std::stringstream ss;
7180 ss << " labelinput" << i;
7281 labelchannelname->push_back (ss.str ());
7382 }
7483 }
7584
76- auto initFunction = [numberofsourcedevices, digitchannelname, labelchannelname](InitContext& ic) {
85+ auto initFunction = [numberofsourcedevices, digitchannelname, labelchannelname, triggerchannelname ](InitContext& ic) {
7786 // get the option from the init context
7887 auto filename = ic.options ().get <std::string>(" tpc-digit-outfile" );
7988 auto treename = ic.options ().get <std::string>(" treename" );
8089
8190 auto outputfile = std::make_shared<TFile>(filename.c_str (), " RECREATE" );
8291 auto outputtree = std::make_shared<TTree>(treename.c_str (), treename.c_str ());
8392
84- // container for incoming digits + label
85- auto digits = std::make_shared<std::vector<o2::TPC::Digit>>();
86- auto labels = std::make_shared<o2::dataformats::MCTruthContainer<o2::MCCompLabel>>();
93+ // container for cashed grouping of digits
94+ auto trigP2Sect = std::make_shared<std::array<std::vector<DigiGroupRef>, 36 >>();
8795
8896 // the callback to be set as hook at stop of processing for the framework
8997 auto finishWriting = [outputfile, outputtree]() {
@@ -116,8 +124,8 @@ DataProcessorSpec getTPCDigitRootWriterSpec(int numberofsourcedevices)
116124 // using by-copy capture of the worker instance shared pointer
117125 // the shared pointer makes sure to clean up the instance when the processing
118126 // function gets out of scope
119- auto processingFct = [outputfile, outputtree, digits , digitchannelname, labelchannelname,
120- numberofsourcedevices](ProcessingContext& pc) {
127+ auto processingFct = [outputfile, outputtree, trigP2Sect , digitchannelname, labelchannelname,
128+ triggerchannelname, numberofsourcedevices](ProcessingContext& pc) {
121129 static bool finished = false ;
122130 if (finished) {
123131 // avoid being executed again when marked as finished;
@@ -130,9 +138,11 @@ DataProcessorSpec getTPCDigitRootWriterSpec(int numberofsourcedevices)
130138 // need to record which channel has completed in order to decide when we can shutdown
131139 static std::vector<bool > digitsdone;
132140 static std::vector<bool > labelsdone;
141+ static std::vector<bool > triggersdone;
133142 if (invocation == 1 ) {
134143 digitsdone.resize (numberofsourcedevices, false );
135144 labelsdone.resize (numberofsourcedevices, false );
145+ triggersdone.resize (numberofsourcedevices, false );
136146 }
137147
138148 // find out if all source devices (channels) are done
@@ -157,6 +167,19 @@ DataProcessorSpec getTPCDigitRootWriterSpec(int numberofsourcedevices)
157167 for (int d = 0 ; d < numberofsourcedevices; ++d) {
158168 const auto dname = digitchannelname->operator [](d);
159169 const auto lname = labelchannelname->operator [](d);
170+ const auto tname = triggerchannelname->operator [](d);
171+ if (pc.inputs ().isValid (tname.c_str ())) {
172+ sector = extractSector (tname.c_str ());
173+ LOG (INFO) << " HAVE TRIGGER DATA FOR SECTOR " << sector << " ON CHANNEL " << d;
174+ if (sector == -1 ) {
175+ triggersdone[d] = true ;
176+ } else {
177+ auto triggers = pc.inputs ().get <std::vector<DigiGroupRef>>(tname.c_str ());
178+ (*trigP2Sect.get ())[sector] = std::move (triggers);
179+ const auto & trigS = (*trigP2Sect.get ())[sector];
180+ LOG (INFO) << " GOT Triggers of sector " << sector << " | SIZE " << trigS.size ();
181+ }
182+ }
160183
161184 // probe which channel has data and of what kind
162185 // a) probe for digits:
@@ -168,14 +191,39 @@ DataProcessorSpec getTPCDigitRootWriterSpec(int numberofsourcedevices)
168191 } else {
169192 // have to do work ...
170193 // the digits
171- auto indata = pc.inputs ().get <std::vector<o2::TPC::Digit>>(dname.c_str ());
172- LOG (INFO) << " DIGIT SIZE " << indata.size ();
173- *digits.get () = std::move (indata);
194+ auto digiData = pc.inputs ().get <std::vector<o2::TPC::Digit>>(dname.c_str ());
195+ LOG (INFO) << " DIGIT SIZE " << digiData.size ();
196+ const auto & trigS = (*trigP2Sect.get ())[sector];
197+ if (!trigS.size ()) {
198+ LOG (FATAL) << " Digits for sector " << sector << " are received w/o info on grouping in triggers" ;
199+ } else { // check consistency of Ndigits with that of expected from the trigger
200+ int nExp = trigS.back ().getFirstEntry () + trigS.back ().getEntries () - trigS.front ().getFirstEntry ();
201+ if (nExp != digiData.size ()) {
202+ LOG (ERROR) << " Number of digits " << digiData.size () << " is inconsistent with expectation " << nExp
203+ << " from digits grouping for sector " << sector;
204+ }
205+ }
206+
174207 {
175- // connect this to a particular branch
176- auto br = getOrMakeBranch (*outputtree.get (), " TPCDigit" , sector, digits.get ());
177- br->Fill ();
178- br->ResetAddress ();
208+ if (trigS.size () == 1 ) { // just 1 entry (continous mode?), use digits directly
209+ // connect this to a particular branch
210+ auto digP = &digiData;
211+ auto br = getOrMakeBranch (*outputtree.get (), " TPCDigit" , sector, digP);
212+ br->Fill ();
213+ br->ResetAddress ();
214+ } else { // triggered mode (>1 entrie will be written)
215+ std::vector<o2::TPC::Digit> digGroup; // group of digits related to single trigger
216+ auto digGroupPtr = &digGroup;
217+ auto br = getOrMakeBranch (*outputtree.get (), " TPCDigit" , sector, digGroupPtr);
218+ for (auto grp : trigS) {
219+ digGroup.clear ();
220+ for (int i = 0 ; i < grp.getEntries (); i++) {
221+ digGroup.emplace_back (digiData[grp.getFirstEntry () + i]); // fetch digits of given trigger
222+ }
223+ br->Fill ();
224+ }
225+ br->ResetAddress ();
226+ }
179227 }
180228 }
181229 } // end digit case
@@ -191,15 +239,36 @@ DataProcessorSpec getTPCDigitRootWriterSpec(int numberofsourcedevices)
191239 auto labeldata = pc.inputs ().get <o2::dataformats::MCTruthContainer<o2::MCCompLabel>*>(lname.c_str ());
192240 auto labeldataRaw = labeldata.get ();
193241 LOG (INFO) << " MCTRUTH ELEMENTS " << labeldataRaw->getIndexedSize ()
194- << " WITH " << labeldataRaw->getNElements () << " LABELS " ;
195- if (labeldataRaw->getIndexedSize () != digits->size ()) {
196- LOG (WARNING) << " Inconsistent number of indexed (label) slots "
197- << labeldataRaw->getIndexedSize () << " versus digits " << digits->size ();
242+ << " WITH " << labeldataRaw->getNElements () << " LABELS" ;
243+ const auto & trigS = (*trigP2Sect.get ())[sector];
244+ if (!trigS.size ()) {
245+ LOG (FATAL) << " MCTruth for sector " << sector << " are received w/o info on grouping in triggers" ;
246+ } else {
247+ int nExp = trigS.back ().getFirstEntry () + trigS.back ().getEntries () - trigS.front ().getFirstEntry ();
248+ if (nExp != labeldataRaw->getIndexedSize ()) {
249+ LOG (ERROR) << " Number of indexed (label) slots " << labeldataRaw->getIndexedSize ()
250+ << " is inconsistent with expectation " << nExp
251+ << " from digits grouping for sector " << sector;
252+ }
198253 }
199254 {
200- auto br = getOrMakeBranch (*outputtree.get (), " TPCDigitMCTruth" , sector, &labeldataRaw);
201- br->Fill ();
202- br->ResetAddress ();
255+ if (trigS.size () == 1 ) { // just 1 entry (continous mode?), use labels directly
256+ auto br = getOrMakeBranch (*outputtree.get (), " TPCDigitMCTruth" , sector, &labeldataRaw);
257+ br->Fill ();
258+ br->ResetAddress ();
259+ } else {
260+ o2::dataformats::MCTruthContainer<o2::MCCompLabel> lblGroup; // labels for group of digits related to single trigger
261+ auto lblGroupPtr = &lblGroup;
262+ auto br = getOrMakeBranch (*outputtree.get (), " TPCDigitMCTruth" , sector, &lblGroupPtr);
263+ for (auto grp : trigS) {
264+ lblGroup.clear ();
265+ for (int i = 0 ; i < grp.getEntries (); i++) {
266+ auto lbls = labeldataRaw->getLabels (grp.getFirstEntry () + i);
267+ lblGroup.addElements (i, lbls);
268+ }
269+ br->Fill ();
270+ }
271+ }
203272 }
204273 }
205274 } // end label case
@@ -231,6 +300,8 @@ DataProcessorSpec getTPCDigitRootWriterSpec(int numberofsourcedevices)
231300 for (int d = 0 ; d < numberofsourcedevices; ++d) {
232301 inputs.emplace_back (InputSpec{ (*digitchannelname.get ())[d].c_str (), " TPC" , " DIGITS" ,
233302 static_cast <SubSpecificationType>(d), Lifetime::Timeframe }); // digit input
303+ inputs.emplace_back (InputSpec{ (*triggerchannelname.get ())[d].c_str (), " TPC" , " DIGTRIGGERS" ,
304+ static_cast <SubSpecificationType>(d), Lifetime::Timeframe }); // groupping in triggers
234305 inputs.emplace_back (InputSpec{ (*labelchannelname.get ())[d].c_str (), " TPC" , " DIGITSMCTR" ,
235306 static_cast <SubSpecificationType>(d), Lifetime::Timeframe });
236307 }
0 commit comments