From 16147b5798ec5641874a7f03070378b78d2b1bc9 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu Date: Tue, 9 Jul 2019 07:23:33 +0000 Subject: [PATCH 1/3] MFT: add macro for conversion digits to raw --- macro/run_digi2raw_mft.C | 148 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 macro/run_digi2raw_mft.C diff --git a/macro/run_digi2raw_mft.C b/macro/run_digi2raw_mft.C new file mode 100644 index 0000000000000..ca044595b1b42 --- /dev/null +++ b/macro/run_digi2raw_mft.C @@ -0,0 +1,148 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) +#include +#include +#include +#include +#include +#include +#include +#include +#include "ITSMFTReconstruction/ChipMappingMFT.h" +#include "ITSMFTReconstruction/GBTWord.h" +#include "ITSMFTReconstruction/PayLoadCont.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "ITSMFTBase/Digit.h" +#endif + +#include "ITSMFTReconstruction/RawPixelReader.h" + +void run_digi2raw_mft(std::string outName = "rawmft.bin", // name of the output binary file + std::string inpName = "mftdigits.root", // name of the input MFT digits + std::string digTreeName = "o2sim", // name of the digits tree + std::string digBranchName = "MFTDigit", // name of the digits branch + std::string rofRecName = "MFTDigitROF", // name of the ROF records tree and its branch + uint8_t ruSWMin = 0, uint8_t ruSWMax = 0xff, // seq.ID of 1st and last RU (stave) to convert + uint8_t superPageSize = o2::itsmft::NCRUPagesPerSuperpage / 2 // CRU superpage size, max = 256 +) +{ + TStopwatch swTot; + swTot.Start(); + using ROFR = o2::itsmft::ROFRecord; + using ROFRVEC = std::vector; + + ///-------> input + TChain digTree(digTreeName.c_str()); + TChain rofTree(rofRecName.c_str()); + + digTree.AddFile(inpName.c_str()); + rofTree.AddFile(inpName.c_str()); + + std::vector digiVec, *digiVecP = &digiVec; + if (!digTree.GetBranch(digBranchName.c_str())) { + LOG(FATAL) << "Failed to find the branch " << digBranchName << " in the tree " << digTreeName; + } + digTree.SetBranchAddress(digBranchName.c_str(), &digiVecP); + + // ROF record entries in the digit tree + ROFRVEC rofRecVec, *rofRecVecP = &rofRecVec; + if (!rofTree.GetBranch(rofRecName.c_str())) { + LOG(FATAL) << "Failed to find the branch " << rofRecName << " in the tree " << rofRecName; + } + rofTree.SetBranchAddress(rofRecName.c_str(), &rofRecVecP); + ///-------< input + + ///-------> output + if (outName.empty()) { + outName = "raw" + digBranchName + ".raw"; + LOG(INFO) << "Output file name is not provided, set to " << outName << FairLogger::endl; + } + auto outFl = fopen(outName.c_str(), "wb"); + if (!outFl) { + LOG(FATAL) << "failed to open raw data output file " << outName; + ; + } else { + LOG(INFO) << "opened raw data output file " << outName; + } + o2::itsmft::PayLoadCont outBuffer; + ///-------< output + + o2::itsmft::RawPixelReader rawReader; + rawReader.setPadding128(true); + rawReader.setVerbosity(0); + + //------------------------------------------------------------------------------->>>> + // just as an example, we require here that the IB staves are read via 3 links, + // while OB staves use only 1 link. + // Note, that if the RU container is not defined, it will be created automatically + // during encoding. + // If the links of the container are not defined, a single link readout will be assigned + const auto& mp = rawReader.getMapping(); + LOG(INFO) << "Number of RUs = " << mp.getNRUs(); + for (int ir = 0; ir < mp.getNRUs(); ir++) { + auto& ru = rawReader.getCreateRUDecode(ir); // create RU container + uint32_t lanes = mp.getCablesOnRUType(ru.ruInfo->ruType); // lanes patter of this RU + ru.links[0] = std::make_unique(); + ru.links[0]->lanes = lanes; // single link reads all lanes + LOG(INFO) << "RU " << std::setw(3) << ir << " type " << int(ru.ruInfo->ruType) << " on lr" << int(ru.ruInfo->layer) + << " : FEEId 0x" << std::hex << std::setfill('0') << std::setw(6) << mp.RUSW2FEEId(ir, int(ru.ruInfo->layer)) + << " reads lanes " << std::bitset<25>(ru.links[0]->lanes); + } + + //-------------------------------------------------------------------------------<<<< + int lastTreeID = -1; + long offs = 0, nEntProc = 0; + for (int i = 0; i < rofTree.GetEntries(); i++) { + rofTree.GetEntry(i); + if (rofTree.GetTreeNumber() > lastTreeID) { // this part is needed for chained input + if (lastTreeID > 0) { // new chunk, increase the offset + offs += digTree.GetTree()->GetEntries(); + } + lastTreeID = rofTree.GetTreeNumber(); + } + + for (const auto& rofRec : rofRecVec) { + auto rofEntry = rofRec.getROFEntry(); + int nDigROF = rofRec.getNROFEntries(); + LOG(INFO) << "Processing ROF:" << rofRec.getROFrame() << " with " << nDigROF << " entries"; + if (!nDigROF) { + LOG(INFO) << "Frame is empty"; // ?? + continue; + } + if (rofEntry.getEvent() != digTree.GetReadEntry() + offs || !nEntProc) { + digTree.GetEntry(rofEntry.getEvent() + offs); // read tree entry containing needed ROF data + nEntProc++; + } + int digIndex = rofEntry.getIndex(); // needed ROF digits start from this one + int maxDigIndex = digIndex + nDigROF; + LOG(INFO) << "BV===== digIndex " << digIndex << " maxDigIndex " << maxDigIndex << "\n"; + + int nPagesCached = rawReader.digits2raw(digiVec, rofEntry.getIndex(), nDigROF, rofRec.getBCData(), + ruSWMin, ruSWMax); + + if (nPagesCached >= superPageSize) { + int nPagesFlushed = rawReader.flushSuperPages(superPageSize, outBuffer); + fwrite(outBuffer.data(), 1, outBuffer.getSize(), outFl); //write to file + outBuffer.clear(); + LOG(INFO) << "Flushed " << nPagesFlushed << " CRU pages"; + } + //printf("BV===== stop after the first ROF!\n"); + //break; + } + } // loop over multiple ROFvectors (in case of chaining) + + // flush the rest + int flushed = 0; + do { + flushed = rawReader.flushSuperPages(o2::itsmft::NCRUPagesPerSuperpage, outBuffer); + fwrite(outBuffer.data(), 1, outBuffer.getSize(), outFl); //write to file + if (flushed) { + LOG(INFO) << "Flushed final " << flushed << " CRU pages"; + } + outBuffer.clear(); + } while (flushed); + + fclose(outFl); + // + swTot.Stop(); + swTot.Print(); +} From 125bd9cff91499469a0bd4b7d389d8c39c01e376 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu Date: Tue, 9 Jul 2019 16:34:30 +0200 Subject: [PATCH 2/3] MFT: add macro for decoding MFT raw data --- macro/run_rawdecoding_mft.C | 124 ++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 macro/run_rawdecoding_mft.C diff --git a/macro/run_rawdecoding_mft.C b/macro/run_rawdecoding_mft.C new file mode 100644 index 0000000000000..13e8d328b494d --- /dev/null +++ b/macro/run_rawdecoding_mft.C @@ -0,0 +1,124 @@ +#if !defined(__CLING__) || defined(__ROOTCLING__) + +#include +#include +#include +#include +#include +#include + +#include "ITSMFTReconstruction/ChipMappingMFT.h" +#include "ITSMFTReconstruction/GBTWord.h" +#include "ITSMFTReconstruction/PayLoadCont.h" +#include "ITSMFTReconstruction/PixelData.h" +#include "DataFormatsITSMFT/ROFRecord.h" +#include "ITSMFTReconstruction/RawPixelReader.h" +#include "CommonDataFormat/InteractionRecord.h" + +#endif + +// example of MFT raw data decoding +// Data can be prepared from the MC digits using run_digi2raw_mft.C +// The padding parameter should be set to "true" for CRU data and to "false" for +// the data obtained by the removing the 128 bit padding from GBT words + +void run_rawdecoding_mft(std::string inpName = "06282019_1854_output.bin", // input binary data file name + std::string outDigName = "raw2mftdigits.root", // name for optinal digits tree + bool outDigPerROF = false, // in case digits are requested, create separate tree entry for each ROF + bool padding = true, // payload in raw data comes in 128 bit CRU words + bool page8kb = true, // full 8KB CRU pages are provided (no skimming applied) + int nTriggersToCache = 1025, // number of triggers per link to cache (> N 8KB CRU pages per superpage) + int verbose = 0) +{ + + o2::itsmft::RawPixelReader rawReader; + rawReader.openInput(inpName); + rawReader.setPadding128(padding); // payload GBT words are padded to 16B + rawReader.imposeMaxPage(page8kb); // pages are 8kB in size (no skimming) + rawReader.setMinTriggersToCache(nTriggersToCache); + rawReader.setVerbosity(verbose); + + o2::itsmft::ChipPixelData chipData; + TStopwatch sw; + sw.Start(); + uint32_t roFrame = 0; + o2::InteractionRecord irHB, irTrig; + std::vector digits, *digitsPtr = &digits; + std::vector rofRecVec, *rofRecVecPtr = &rofRecVec; + std::size_t rofEntry = 0, nrofdig = 0; + std::unique_ptr outFileDig; + std::unique_ptr outTreeDig; // output tree with digits + std::unique_ptr outTreeROF; // output tree with ROF records + + if (!outDigName.empty()) { // output to digit is requested + outFileDig = std::make_unique(outDigName.c_str(), "recreate"); + outTreeDig = std::make_unique("o2sim", "Digits tree"); + outTreeDig->Branch("MFTDigit", &digitsPtr); + outTreeROF = std::make_unique("MFTDigitROF", "ROF records tree"); + outTreeROF->Branch("MFTDigitROF", &rofRecVecPtr); + } + + while (rawReader.getNextChipData(chipData)) { + if (verbose >= 10) { + chipData.print(); + } + + if (outTreeDig) { // >> store digits + if (irHB != rawReader.getInteractionRecordHB() || irTrig != rawReader.getInteractionRecord()) { + if (!irTrig.isDummy()) { + o2::dataformats::EvIndex evId(outTreeDig->GetEntries(), rofEntry); + rofRecVec.emplace_back(irHB, roFrame, evId, nrofdig); // registed finished ROF + if (outDigPerROF) { + outTreeDig->Fill(); + digits.clear(); + } + roFrame++; + } + irHB = rawReader.getInteractionRecordHB(); + irTrig = rawReader.getInteractionRecord(); + rofEntry = digits.size(); + nrofdig = 0; + } + const auto& pixdata = chipData.getData(); + for (const auto& pix : pixdata) { + digits.emplace_back(chipData.getChipID(), roFrame, pix.getRowDirect(), pix.getCol()); + nrofdig++; + } + + printf("ROF %7d ch: %5d IR: ", roFrame, chipData.getChipID()); + irHB.print(); + + } // << store digits + // + } + + if (outTreeDig) { + // register last ROF + o2::dataformats::EvIndex evId(outTreeDig->GetEntries(), rofEntry); + rofRecVec.emplace_back(irHB, roFrame, evId, nrofdig); // registed finished ROF + + // fill last (and the only one?) entry + outTreeDig->Fill(); + outTreeROF->Fill(); + + // and store trees + outTreeDig->Write(); + outTreeROF->Write(); + } + + sw.Stop(); + + const auto& MAP = rawReader.getMapping(); + for (int ir = 0; ir < MAP.getNRUs(); ir++) { + for (int il = 0; il < o2::itsmft::MaxLinksPerRU; il++) { + const auto ruStat = rawReader.getRUDecodingStatSW(ir, il); + if (ruStat && ruStat->nPackets) { + printf("\nStatistics for RU%3d (HWID:0x%4x) GBTLink%d\n", ir, MAP.RUSW2FEEId(ir, il), il); + ruStat->print(); + } + } + } + rawReader.getDecodingStat().print(); + + sw.Print(); +} From 1b07d27c711a554800ce02a78452c8a92aa9a768 Mon Sep 17 00:00:00 2001 From: Bogdan Vulpescu Date: Wed, 10 Jul 2019 17:05:53 +0200 Subject: [PATCH 3/3] MFT: add new macros to CMakeLists --- macro/CMakeLists.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index 51d770f88cfed..26d8c1e87cb1c 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -38,12 +38,14 @@ install(FILES CheckClusters_mft.C run_collect_calib_tof.C run_digi.C run_digi2raw_its.C + run_digi2raw_mft.C run_digi_mft.C run_digi_tof.C run_match_TPCITS.C run_match_tof.C run_primary_vertexer_ITS.C run_rawdecoding_its.C + run_rawdecoding_mft.C run_sim.C run_sim_emcal.C run_sim_mft.C @@ -227,6 +229,14 @@ o2_add_test_root_macro(run_digi2raw_its.C O2::ITSMFTReconstruction LABELS its) +# FIXME: move to subsystem dir +o2_add_test_root_macro(run_digi2raw_mft.C + PUBLIC_LINK_LIBRARIES O2::ITSMFTReconstruction + O2::DataFormatsITSMFT + O2::ITSMFTBase + O2::ITSMFTReconstruction + LABELS mft) + # FIXME: move to subsystem dir o2_add_test_root_macro(run_digi_mft.C PUBLIC_LINK_LIBRARIES O2::DataFormatsParameters @@ -270,6 +280,13 @@ o2_add_test_root_macro(run_rawdecoding_its.C O2::CommonDataFormat LABELS its) +# FIXME: move to subsystem dir +o2_add_test_root_macro(run_rawdecoding_mft.C + PUBLIC_LINK_LIBRARIES O2::ITSMFTReconstruction + O2::DataFormatsITSMFT + O2::CommonDataFormat + LABELS mft) + # FIXME: move to subsystem dir + check compilation o2_add_test_root_macro( # run_rec_ca.C PUBLIC_LINK_LIBRARIES O2::DetectorsCommonDataFormats # O2::DataFormatsITSMFT O2::DataFormatsParameters O2::DetectorsBase O2::Field