1717#include " MCHIO/DigitReaderSpec.h"
1818
1919#include < memory>
20- #include < sstream >
20+ #include < stdexcept >
2121#include < string>
22- #include " DPLUtils/RootTreeReader.h"
22+ #include < vector>
23+
24+ #include < fmt/format.h>
25+
26+ #include < gsl/span>
27+
28+ #include < TFile.h>
29+ #include < TTree.h>
30+ #include < TTreeReader.h>
31+ #include < TTreeReaderValue.h>
32+
33+ #include " CommonDataFormat/IRFrame.h"
34+ #include " CommonUtils/IRFrameSelector.h"
35+ #include " CommonUtils/StringUtils.h"
36+ #include " DataFormatsMCH/Digit.h"
37+ #include " DataFormatsMCH/ROFRecord.h"
2338#include " Framework/ConfigParamRegistry.h"
2439#include " Framework/ControlService.h"
2540#include " Framework/DataSpecUtils.h"
26- #include " Framework/Logger.h"
27- #include " Framework/Output.h"
2841#include " Framework/Task.h"
2942#include " Framework/WorkflowSpec.h"
30- #include " SimulationDataFormat/MCTruthContainer .h"
43+ #include " MCHDigitFiltering/DigitFilterParam .h"
3144#include " SimulationDataFormat/MCCompLabel.h"
32- #include " DataFormatsMCH/Digit.h"
33- #include " DataFormatsMCH/ROFRecord.h"
34- #include " CommonUtils/StringUtils.h"
45+ #include " SimulationDataFormat/MCTruthContainer.h"
3546
3647using namespace o2 ::framework;
3748
@@ -43,72 +54,171 @@ namespace mch
4354class DigitsReaderDeviceDPL
4455{
4556 public:
46- DigitsReaderDeviceDPL (bool useMC, const std::vector<header::DataDescription>& descriptions)
47- : mUseMC (useMC), mDescriptions (descriptions) {}
57+ DigitsReaderDeviceDPL (bool useMC) : mUseMC (useMC)
58+ {
59+ if (mUseMC ) {
60+ mLabels = std::make_unique<TTreeReaderValue<dataformats::MCTruthContainer<MCCompLabel>>>(mTreeReader , " MCHMCLabels" );
61+ }
62+ }
4863
4964 void init (InitContext& ic)
5065 {
51- auto filename = o2::utils::Str::concat_string (o2::utils::Str::rectifyDirectory (ic.options ().get <std::string>(" input-dir" )), ic.options ().get <std::string>(" mch-digit-infile" ));
66+ auto fileName = utils::Str::concat_string (utils::Str::rectifyDirectory (ic.options ().get <std::string>(" input-dir" )),
67+ ic.options ().get <std::string>(" mch-digit-infile" ));
68+ connectTree (fileName);
5269
53- if (mUseMC ) {
54- mReader = std::make_unique<RootTreeReader>(" o2sim" , filename.c_str (), -1 ,
55- RootTreeReader::PublishingMode::Single,
56- RootTreeReader::BranchDefinition<std::vector<Digit>>{
57- Output{header::gDataOriginMCH , mDescriptions [0 ], 0 , Lifetime::Timeframe}, " MCHDigit" },
58- RootTreeReader::BranchDefinition<std::vector<ROFRecord>>{
59- Output{header::gDataOriginMCH , mDescriptions [1 ], 0 , Lifetime::Timeframe}, " MCHROFRecords" },
60- RootTreeReader::BranchDefinition<dataformats::MCTruthContainer<MCCompLabel>>{
61- Output{header::gDataOriginMCH , mDescriptions [2 ], 0 , Lifetime::Timeframe}, " MCHMCLabels" });
62- } else {
63- mReader = std::make_unique<RootTreeReader>(" o2sim" , filename.c_str (), -1 ,
64- RootTreeReader::PublishingMode::Single,
65- RootTreeReader::BranchDefinition<std::vector<Digit>>{
66- Output{header::gDataOriginMCH , mDescriptions [0 ], 0 , Lifetime::Timeframe}, " MCHDigit" },
67- RootTreeReader::BranchDefinition<std::vector<ROFRecord>>{
68- Output{header::gDataOriginMCH , mDescriptions [1 ], 0 , Lifetime::Timeframe}, " MCHROFRecords" });
70+ if (ic.options ().hasOption (" ignore-irframes" ) && !ic.options ().get <bool >(" ignore-irframes" )) {
71+ mUseIRFrames = true ;
6972 }
73+
74+ mTimeOffset = ic.options ().get <bool >(" no-time-offset" ) ? 0 : DigitFilterParam::Instance ().timeOffset ;
7075 }
7176
7277 void run (ProcessingContext& pc)
7378 {
74- if ((++(*mReader ))(pc) == false ) {
75- pc.services ().get <ControlService>().endOfStream ();
79+ if (mUseIRFrames ) {
80+ sendNextIRFrames (pc);
81+ } else {
82+ sendNextTF (pc);
7683 }
7784 }
7885
7986 private:
80- std::unique_ptr<RootTreeReader> mReader {};
81- std::vector<header::DataDescription> mDescriptions {};
87+ TTreeReader mTreeReader {};
88+ TTreeReaderValue<std::vector<ROFRecord>> mRofs = {mTreeReader , " MCHROFRecords" };
89+ TTreeReaderValue<std::vector<Digit>> mDigits = {mTreeReader , " MCHDigit" };
90+ std::unique_ptr<TTreeReaderValue<dataformats::MCTruthContainer<MCCompLabel>>> mLabels {};
8291 bool mUseMC = true ;
92+ bool mUseIRFrames = false ;
93+ int mTimeOffset = 0 ;
94+
95+ void connectTree (std::string fileName)
96+ {
97+ auto file = TFile::Open (fileName.c_str ());
98+ if (!file || file->IsZombie ()) {
99+ throw std::invalid_argument (fmt::format (" Opening file {} failed" , fileName));
100+ }
101+
102+ auto tree = file->Get <TTree>(" o2sim" );
103+ if (!tree) {
104+ throw std::invalid_argument (fmt::format (" Tree o2sim not found in {}" , fileName));
105+ }
106+ mTreeReader .SetTree (tree);
107+ mTreeReader .Restart ();
108+ }
109+
110+ void sendNextTF (ProcessingContext& pc)
111+ {
112+ // load the next TF and check its validity (missing branch, ...)
113+ if (!mTreeReader .Next ()) {
114+ throw std::invalid_argument (mTreeReader .fgEntryStatusText [mTreeReader .GetEntryStatus ()]);
115+ }
116+
117+ // send the whole TF
118+ pc.outputs ().snapshot (OutputRef{" rofs" }, *mRofs );
119+ pc.outputs ().snapshot (OutputRef{" digits" }, *mDigits );
120+ if (mUseMC ) {
121+ pc.outputs ().snapshot (OutputRef{" labels" }, **mLabels );
122+ }
123+
124+ // stop here if it was the last one
125+ if (mTreeReader .GetCurrentEntry () + 1 >= mTreeReader .GetEntries ()) {
126+ pc.services ().get <ControlService>().endOfStream ();
127+ pc.services ().get <ControlService>().readyToQuit (QuitRequest::Me);
128+ }
129+ }
130+
131+ void sendNextIRFrames (ProcessingContext& pc)
132+ {
133+ std::vector<ROFRecord> rofs{};
134+ std::vector<Digit> digits{};
135+ dataformats::MCTruthContainer<MCCompLabel> labels{};
136+
137+ // get the IR frames to select
138+ auto irFrames = pc.inputs ().get <gsl::span<dataformats::IRFrame>>(" driverInfo" );
139+
140+ if (!irFrames.empty ()) {
141+ utils::IRFrameSelector irfSel{};
142+ irfSel.setSelectedIRFrames (irFrames, 0 , 0 , -mTimeOffset , true );
143+ const auto irMin = irfSel.getIRFrames ().front ().getMin ();
144+ const auto irMax = irfSel.getIRFrames ().back ().getMax ();
145+
146+ // load the first TF if not already done
147+ bool loadNextTF = mTreeReader .GetCurrentEntry () < 0 ;
148+
149+ while (true ) {
150+ // load the next TF if requested
151+ if (loadNextTF && !mTreeReader .Next ()) {
152+ throw std::invalid_argument (mTreeReader .fgEntryStatusText [mTreeReader .GetEntryStatus ()]);
153+ }
154+
155+ // look for selected ROFs in this TF and copy them
156+ if (!mRofs ->empty () && mRofs ->front ().getBCData () <= irMax &&
157+ mRofs ->back ().getBCData () + mRofs ->back ().getBCWidth () - 1 >= irMin) {
158+ for (const auto & rof : *mRofs ) {
159+ if (irfSel.check ({rof.getBCData (), rof.getBCData () + rof.getBCWidth () - 1 }) != -1 ) {
160+ rofs.emplace_back (rof);
161+ rofs.back ().setDataRef (digits.size (), rof.getNEntries ());
162+ digits.insert (digits.end (), mDigits ->begin () + rof.getFirstIdx (), mDigits ->begin () + rof.getFirstIdx () + rof.getNEntries ());
163+ if (mUseMC ) {
164+ for (auto i = 0 ; i < rof.getNEntries (); ++i) {
165+ labels.addElements (labels.getIndexedSize (), (*mLabels )->getLabels (rof.getFirstIdx () + i));
166+ }
167+ }
168+ }
169+ }
170+ }
171+
172+ // move to the next TF if needed and if any
173+ if ((mRofs ->empty () || mRofs ->back ().getBCData () + mRofs ->back ().getBCWidth () - 1 < irMax) &&
174+ mTreeReader .GetCurrentEntry () + 1 < mTreeReader .GetEntries ()) {
175+ loadNextTF = true ;
176+ continue ;
177+ }
178+
179+ break ;
180+ }
181+ }
182+
183+ // send the selected data
184+ pc.outputs ().snapshot (OutputRef{" rofs" }, rofs);
185+ pc.outputs ().snapshot (OutputRef{" digits" }, digits);
186+ if (mUseMC ) {
187+ pc.outputs ().snapshot (OutputRef{" labels" }, labels);
188+ }
189+
190+ // stop here if they were the last IR frames to select
191+ if (irFrames.empty () || irFrames.back ().isLast ()) {
192+ pc.services ().get <ControlService>().endOfStream ();
193+ pc.services ().get <ControlService>().readyToQuit (QuitRequest::Me);
194+ }
195+ }
83196};
84197
85- framework::DataProcessorSpec getDigitReaderSpec (
86- bool useMC,
87- std::string_view specName,
88- std::string_view outputDigitDataDescription,
89- std::string_view outputDigitRofDataDescription)
198+ DataProcessorSpec getDigitReaderSpec (bool useMC, std::string_view specName,
199+ std::string_view outputDigitDataDescription,
200+ std::string_view outputDigitRofDataDescription,
201+ std::string_view outputDigitLabelDataDescription)
90202{
91- std::vector<OutputSpec> outputs;
92- std::vector<header::DataDescription> descriptions;
93- std::stringstream ss;
94- ss << " A:" << header::gDataOriginMCH .as <std::string>() << " /" << outputDigitDataDescription << " /0" ;
95- ss << " ;B:" << header::gDataOriginMCH .as <std::string>() << " /" << outputDigitRofDataDescription << " /0" ;
203+ std::string output = fmt::format (" digits:MCH/{}/0;rofs:MCH/{}/0" , outputDigitDataDescription, outputDigitRofDataDescription);
96204 if (useMC) {
97- ss << " ;C: " << header:: gDataOriginMCH . as <std::string>() << " /DIGITLABELS /0" ;
205+ output += fmt::format ( " ;labels:MCH/{} /0" , outputDigitLabelDataDescription) ;
98206 }
99- auto matchers = select (ss.str ().c_str ());
207+
208+ std::vector<OutputSpec> outputs;
209+ auto matchers = select (output.c_str ());
100210 for (auto & matcher : matchers) {
101211 outputs.emplace_back (DataSpecUtils::asOutputSpec (matcher));
102- descriptions.emplace_back (DataSpecUtils::asConcreteDataDescription (matcher));
103212 }
104213
105214 return DataProcessorSpec{
106215 std::string (specName),
107216 Inputs{},
108217 outputs,
109- AlgorithmSpec{adaptFromTask<DigitsReaderDeviceDPL>(useMC, descriptions )},
218+ AlgorithmSpec{adaptFromTask<DigitsReaderDeviceDPL>(useMC)},
110219 Options{{" mch-digit-infile" , VariantType::String, " mchdigits.root" , {" Name of the input file" }},
111- {" input-dir" , VariantType::String, " none" , {" Input directory" }}}};
220+ {" input-dir" , VariantType::String, " none" , {" Input directory" }},
221+ {" no-time-offset" , VariantType::Bool, false , {" no time offset between IRFrames and digits" }}}};
112222}
113223} // namespace mch
114224} // namespace o2
0 commit comments