Skip to content

Commit fb06c59

Browse files
Bogdan Vulpescudavidrohr
authored andcommitted
MFT: add macro for conversion digits to raw (#2176)
* MFT: add macro for conversion digits to raw * MFT: add macro for decoding MFT raw data * MFT: add new macros to CMakeLists
1 parent 1296c67 commit fb06c59

File tree

3 files changed

+289
-0
lines changed

3 files changed

+289
-0
lines changed

macro/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,14 @@ install(FILES CheckClusters_mft.C
3838
run_collect_calib_tof.C
3939
run_digi.C
4040
run_digi2raw_its.C
41+
run_digi2raw_mft.C
4142
run_digi_mft.C
4243
run_digi_tof.C
4344
run_match_TPCITS.C
4445
run_match_tof.C
4546
run_primary_vertexer_ITS.C
4647
run_rawdecoding_its.C
48+
run_rawdecoding_mft.C
4749
run_sim.C
4850
run_sim_emcal.C
4951
run_sim_mft.C
@@ -227,6 +229,14 @@ o2_add_test_root_macro(run_digi2raw_its.C
227229
O2::ITSMFTReconstruction
228230
LABELS its)
229231

232+
# FIXME: move to subsystem dir
233+
o2_add_test_root_macro(run_digi2raw_mft.C
234+
PUBLIC_LINK_LIBRARIES O2::ITSMFTReconstruction
235+
O2::DataFormatsITSMFT
236+
O2::ITSMFTBase
237+
O2::ITSMFTReconstruction
238+
LABELS mft)
239+
230240
# FIXME: move to subsystem dir
231241
o2_add_test_root_macro(run_digi_mft.C
232242
PUBLIC_LINK_LIBRARIES O2::DataFormatsParameters
@@ -270,6 +280,13 @@ o2_add_test_root_macro(run_rawdecoding_its.C
270280
O2::CommonDataFormat
271281
LABELS its)
272282

283+
# FIXME: move to subsystem dir
284+
o2_add_test_root_macro(run_rawdecoding_mft.C
285+
PUBLIC_LINK_LIBRARIES O2::ITSMFTReconstruction
286+
O2::DataFormatsITSMFT
287+
O2::CommonDataFormat
288+
LABELS mft)
289+
273290
# FIXME: move to subsystem dir + check compilation o2_add_test_root_macro(
274291
# run_rec_ca.C PUBLIC_LINK_LIBRARIES O2::DetectorsCommonDataFormats
275292
# O2::DataFormatsITSMFT O2::DataFormatsParameters O2::DetectorsBase O2::Field

macro/run_digi2raw_mft.C

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#if !defined(__CLING__) || defined(__ROOTCLING__)
2+
#include <TTree.h>
3+
#include <TChain.h>
4+
#include <TFile.h>
5+
#include <TStopwatch.h>
6+
#include <FairLogger.h>
7+
#include <vector>
8+
#include <string>
9+
#include <iomanip>
10+
#include "ITSMFTReconstruction/ChipMappingMFT.h"
11+
#include "ITSMFTReconstruction/GBTWord.h"
12+
#include "ITSMFTReconstruction/PayLoadCont.h"
13+
#include "DataFormatsITSMFT/ROFRecord.h"
14+
#include "ITSMFTBase/Digit.h"
15+
#endif
16+
17+
#include "ITSMFTReconstruction/RawPixelReader.h"
18+
19+
void run_digi2raw_mft(std::string outName = "rawmft.bin", // name of the output binary file
20+
std::string inpName = "mftdigits.root", // name of the input MFT digits
21+
std::string digTreeName = "o2sim", // name of the digits tree
22+
std::string digBranchName = "MFTDigit", // name of the digits branch
23+
std::string rofRecName = "MFTDigitROF", // name of the ROF records tree and its branch
24+
uint8_t ruSWMin = 0, uint8_t ruSWMax = 0xff, // seq.ID of 1st and last RU (stave) to convert
25+
uint8_t superPageSize = o2::itsmft::NCRUPagesPerSuperpage / 2 // CRU superpage size, max = 256
26+
)
27+
{
28+
TStopwatch swTot;
29+
swTot.Start();
30+
using ROFR = o2::itsmft::ROFRecord;
31+
using ROFRVEC = std::vector<o2::itsmft::ROFRecord>;
32+
33+
///-------> input
34+
TChain digTree(digTreeName.c_str());
35+
TChain rofTree(rofRecName.c_str());
36+
37+
digTree.AddFile(inpName.c_str());
38+
rofTree.AddFile(inpName.c_str());
39+
40+
std::vector<o2::itsmft::Digit> digiVec, *digiVecP = &digiVec;
41+
if (!digTree.GetBranch(digBranchName.c_str())) {
42+
LOG(FATAL) << "Failed to find the branch " << digBranchName << " in the tree " << digTreeName;
43+
}
44+
digTree.SetBranchAddress(digBranchName.c_str(), &digiVecP);
45+
46+
// ROF record entries in the digit tree
47+
ROFRVEC rofRecVec, *rofRecVecP = &rofRecVec;
48+
if (!rofTree.GetBranch(rofRecName.c_str())) {
49+
LOG(FATAL) << "Failed to find the branch " << rofRecName << " in the tree " << rofRecName;
50+
}
51+
rofTree.SetBranchAddress(rofRecName.c_str(), &rofRecVecP);
52+
///-------< input
53+
54+
///-------> output
55+
if (outName.empty()) {
56+
outName = "raw" + digBranchName + ".raw";
57+
LOG(INFO) << "Output file name is not provided, set to " << outName << FairLogger::endl;
58+
}
59+
auto outFl = fopen(outName.c_str(), "wb");
60+
if (!outFl) {
61+
LOG(FATAL) << "failed to open raw data output file " << outName;
62+
;
63+
} else {
64+
LOG(INFO) << "opened raw data output file " << outName;
65+
}
66+
o2::itsmft::PayLoadCont outBuffer;
67+
///-------< output
68+
69+
o2::itsmft::RawPixelReader<o2::itsmft::ChipMappingMFT> rawReader;
70+
rawReader.setPadding128(true);
71+
rawReader.setVerbosity(0);
72+
73+
//------------------------------------------------------------------------------->>>>
74+
// just as an example, we require here that the IB staves are read via 3 links,
75+
// while OB staves use only 1 link.
76+
// Note, that if the RU container is not defined, it will be created automatically
77+
// during encoding.
78+
// If the links of the container are not defined, a single link readout will be assigned
79+
const auto& mp = rawReader.getMapping();
80+
LOG(INFO) << "Number of RUs = " << mp.getNRUs();
81+
for (int ir = 0; ir < mp.getNRUs(); ir++) {
82+
auto& ru = rawReader.getCreateRUDecode(ir); // create RU container
83+
uint32_t lanes = mp.getCablesOnRUType(ru.ruInfo->ruType); // lanes patter of this RU
84+
ru.links[0] = std::make_unique<o2::itsmft::GBTLink>();
85+
ru.links[0]->lanes = lanes; // single link reads all lanes
86+
LOG(INFO) << "RU " << std::setw(3) << ir << " type " << int(ru.ruInfo->ruType) << " on lr" << int(ru.ruInfo->layer)
87+
<< " : FEEId 0x" << std::hex << std::setfill('0') << std::setw(6) << mp.RUSW2FEEId(ir, int(ru.ruInfo->layer))
88+
<< " reads lanes " << std::bitset<25>(ru.links[0]->lanes);
89+
}
90+
91+
//-------------------------------------------------------------------------------<<<<
92+
int lastTreeID = -1;
93+
long offs = 0, nEntProc = 0;
94+
for (int i = 0; i < rofTree.GetEntries(); i++) {
95+
rofTree.GetEntry(i);
96+
if (rofTree.GetTreeNumber() > lastTreeID) { // this part is needed for chained input
97+
if (lastTreeID > 0) { // new chunk, increase the offset
98+
offs += digTree.GetTree()->GetEntries();
99+
}
100+
lastTreeID = rofTree.GetTreeNumber();
101+
}
102+
103+
for (const auto& rofRec : rofRecVec) {
104+
auto rofEntry = rofRec.getROFEntry();
105+
int nDigROF = rofRec.getNROFEntries();
106+
LOG(INFO) << "Processing ROF:" << rofRec.getROFrame() << " with " << nDigROF << " entries";
107+
if (!nDigROF) {
108+
LOG(INFO) << "Frame is empty"; // ??
109+
continue;
110+
}
111+
if (rofEntry.getEvent() != digTree.GetReadEntry() + offs || !nEntProc) {
112+
digTree.GetEntry(rofEntry.getEvent() + offs); // read tree entry containing needed ROF data
113+
nEntProc++;
114+
}
115+
int digIndex = rofEntry.getIndex(); // needed ROF digits start from this one
116+
int maxDigIndex = digIndex + nDigROF;
117+
LOG(INFO) << "BV===== digIndex " << digIndex << " maxDigIndex " << maxDigIndex << "\n";
118+
119+
int nPagesCached = rawReader.digits2raw(digiVec, rofEntry.getIndex(), nDigROF, rofRec.getBCData(),
120+
ruSWMin, ruSWMax);
121+
122+
if (nPagesCached >= superPageSize) {
123+
int nPagesFlushed = rawReader.flushSuperPages(superPageSize, outBuffer);
124+
fwrite(outBuffer.data(), 1, outBuffer.getSize(), outFl); //write to file
125+
outBuffer.clear();
126+
LOG(INFO) << "Flushed " << nPagesFlushed << " CRU pages";
127+
}
128+
//printf("BV===== stop after the first ROF!\n");
129+
//break;
130+
}
131+
} // loop over multiple ROFvectors (in case of chaining)
132+
133+
// flush the rest
134+
int flushed = 0;
135+
do {
136+
flushed = rawReader.flushSuperPages(o2::itsmft::NCRUPagesPerSuperpage, outBuffer);
137+
fwrite(outBuffer.data(), 1, outBuffer.getSize(), outFl); //write to file
138+
if (flushed) {
139+
LOG(INFO) << "Flushed final " << flushed << " CRU pages";
140+
}
141+
outBuffer.clear();
142+
} while (flushed);
143+
144+
fclose(outFl);
145+
//
146+
swTot.Stop();
147+
swTot.Print();
148+
}

macro/run_rawdecoding_mft.C

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#if !defined(__CLING__) || defined(__ROOTCLING__)
2+
3+
#include <TTree.h>
4+
#include <TFile.h>
5+
#include <TStopwatch.h>
6+
#include <FairLogger.h>
7+
#include <vector>
8+
#include <string>
9+
10+
#include "ITSMFTReconstruction/ChipMappingMFT.h"
11+
#include "ITSMFTReconstruction/GBTWord.h"
12+
#include "ITSMFTReconstruction/PayLoadCont.h"
13+
#include "ITSMFTReconstruction/PixelData.h"
14+
#include "DataFormatsITSMFT/ROFRecord.h"
15+
#include "ITSMFTReconstruction/RawPixelReader.h"
16+
#include "CommonDataFormat/InteractionRecord.h"
17+
18+
#endif
19+
20+
// example of MFT raw data decoding
21+
// Data can be prepared from the MC digits using run_digi2raw_mft.C
22+
// The padding parameter should be set to "true" for CRU data and to "false" for
23+
// the data obtained by the removing the 128 bit padding from GBT words
24+
25+
void run_rawdecoding_mft(std::string inpName = "06282019_1854_output.bin", // input binary data file name
26+
std::string outDigName = "raw2mftdigits.root", // name for optinal digits tree
27+
bool outDigPerROF = false, // in case digits are requested, create separate tree entry for each ROF
28+
bool padding = true, // payload in raw data comes in 128 bit CRU words
29+
bool page8kb = true, // full 8KB CRU pages are provided (no skimming applied)
30+
int nTriggersToCache = 1025, // number of triggers per link to cache (> N 8KB CRU pages per superpage)
31+
int verbose = 0)
32+
{
33+
34+
o2::itsmft::RawPixelReader<o2::itsmft::ChipMappingMFT> rawReader;
35+
rawReader.openInput(inpName);
36+
rawReader.setPadding128(padding); // payload GBT words are padded to 16B
37+
rawReader.imposeMaxPage(page8kb); // pages are 8kB in size (no skimming)
38+
rawReader.setMinTriggersToCache(nTriggersToCache);
39+
rawReader.setVerbosity(verbose);
40+
41+
o2::itsmft::ChipPixelData chipData;
42+
TStopwatch sw;
43+
sw.Start();
44+
uint32_t roFrame = 0;
45+
o2::InteractionRecord irHB, irTrig;
46+
std::vector<o2::itsmft::Digit> digits, *digitsPtr = &digits;
47+
std::vector<o2::itsmft::ROFRecord> rofRecVec, *rofRecVecPtr = &rofRecVec;
48+
std::size_t rofEntry = 0, nrofdig = 0;
49+
std::unique_ptr<TFile> outFileDig;
50+
std::unique_ptr<TTree> outTreeDig; // output tree with digits
51+
std::unique_ptr<TTree> outTreeROF; // output tree with ROF records
52+
53+
if (!outDigName.empty()) { // output to digit is requested
54+
outFileDig = std::make_unique<TFile>(outDigName.c_str(), "recreate");
55+
outTreeDig = std::make_unique<TTree>("o2sim", "Digits tree");
56+
outTreeDig->Branch("MFTDigit", &digitsPtr);
57+
outTreeROF = std::make_unique<TTree>("MFTDigitROF", "ROF records tree");
58+
outTreeROF->Branch("MFTDigitROF", &rofRecVecPtr);
59+
}
60+
61+
while (rawReader.getNextChipData(chipData)) {
62+
if (verbose >= 10) {
63+
chipData.print();
64+
}
65+
66+
if (outTreeDig) { // >> store digits
67+
if (irHB != rawReader.getInteractionRecordHB() || irTrig != rawReader.getInteractionRecord()) {
68+
if (!irTrig.isDummy()) {
69+
o2::dataformats::EvIndex<int, int> evId(outTreeDig->GetEntries(), rofEntry);
70+
rofRecVec.emplace_back(irHB, roFrame, evId, nrofdig); // registed finished ROF
71+
if (outDigPerROF) {
72+
outTreeDig->Fill();
73+
digits.clear();
74+
}
75+
roFrame++;
76+
}
77+
irHB = rawReader.getInteractionRecordHB();
78+
irTrig = rawReader.getInteractionRecord();
79+
rofEntry = digits.size();
80+
nrofdig = 0;
81+
}
82+
const auto& pixdata = chipData.getData();
83+
for (const auto& pix : pixdata) {
84+
digits.emplace_back(chipData.getChipID(), roFrame, pix.getRowDirect(), pix.getCol());
85+
nrofdig++;
86+
}
87+
88+
printf("ROF %7d ch: %5d IR: ", roFrame, chipData.getChipID());
89+
irHB.print();
90+
91+
} // << store digits
92+
//
93+
}
94+
95+
if (outTreeDig) {
96+
// register last ROF
97+
o2::dataformats::EvIndex<int, int> evId(outTreeDig->GetEntries(), rofEntry);
98+
rofRecVec.emplace_back(irHB, roFrame, evId, nrofdig); // registed finished ROF
99+
100+
// fill last (and the only one?) entry
101+
outTreeDig->Fill();
102+
outTreeROF->Fill();
103+
104+
// and store trees
105+
outTreeDig->Write();
106+
outTreeROF->Write();
107+
}
108+
109+
sw.Stop();
110+
111+
const auto& MAP = rawReader.getMapping();
112+
for (int ir = 0; ir < MAP.getNRUs(); ir++) {
113+
for (int il = 0; il < o2::itsmft::MaxLinksPerRU; il++) {
114+
const auto ruStat = rawReader.getRUDecodingStatSW(ir, il);
115+
if (ruStat && ruStat->nPackets) {
116+
printf("\nStatistics for RU%3d (HWID:0x%4x) GBTLink%d\n", ir, MAP.RUSW2FEEId(ir, il), il);
117+
ruStat->print();
118+
}
119+
}
120+
}
121+
rawReader.getDecodingStat().print();
122+
123+
sw.Print();
124+
}

0 commit comments

Comments
 (0)