Skip to content

Commit 4fbd7bd

Browse files
committed
Macro to extract per-detector CTF dictionaries good for CCDB
1 parent 17d075e commit 4fbd7bd

3 files changed

Lines changed: 111 additions & 1 deletion

File tree

Detectors/CTF/README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ o2-its-reco-workflow --entropy-encoding | o2-ctf-writer-workflow --onlyDet ITS
1818

1919
For the storage optimization reason one can request multiple CTFs stored in the same output file (as entries of the `ctf` tree):
2020
```bash
21-
o2-ctf-writer --min-file-size <min> --max-file-size <max> ...
21+
o2-ctf-writer-workflow --min-file-size <min> --max-file-size <max> ...
2222
```
2323
will accumulate CTFs in entries of the same tree/file until its size fits exceeds `min` and does not exceed `max` (`max` check is disabled if `max<=min`) or EOS received.
2424
The `--max-file-size` limit will be ignored if the very first CTF already exceeds it.
@@ -42,6 +42,14 @@ In the dictionaries creation mode their data are accumulated over all CTFs procs
4242

4343
Option `--ctf-dict-dir <dir>` can be provided to indicate the (existing) directory where the dictionary will be stored.
4444

45+
The external dictionaries created by the `o2-ctf-writer-workflow` containes a TTree (one for all participating detectos or single file per detector if `--dict-per-det` was provided). Since the TTrees cannot be used with CcdbAPI, one can
46+
run the macro `O2/Detectors/CTF/utils/CTFdict2CCDBfiles.C` (installed to $O2_ROOT/share/macro/CTFdict2CCDBfiles.C) which extracts the dictionary for every detector into separate file containing plain `vector<char>`. These files can be directly
47+
uploaded to CCDB and accessed via `CcdbAPI` (the reference of the vector should be provided to corresponding detector CTFCoder::createCoders method to build the run-time dictionary). These files can be also used as per-detector command-line
48+
parameters, on the same footing as tree-based dictionaries, e.g.
49+
```
50+
o2-ctf-reader-workflow --ctf-input input.lst --onlyDet ITS,TPC,TOF --its-entropy-decoder ' --ctf-dict ctfdict_ITS_v1.0_1626472046.root' --tpc-entropy-decoder ' --ctf-dict ctfdict_TPC_v1.0_1626472048.root' --tof-entropy-decoder ' --ctf-dict ctfdict_TOF_v1.0_1626472048.root'
51+
```
52+
4553
## CTF reader workflow
4654

4755
`o2-ctf-reader-workflow` should be the 1st workflow in the piped chain of CTF processing.

Detectors/CTF/utils/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
install(FILES extractCTF.C
1717
dumpCTF.C
18+
CTFdict2CCDBfiles.C
1819
DESTINATION share/macro/)
1920

2021
o2_add_test_root_macro(extractCTF.C
@@ -24,3 +25,7 @@ o2_add_test_root_macro(extractCTF.C
2425
o2_add_test_root_macro(dumpCTF.C
2526
PUBLIC_LINK_LIBRARIES O2::CTFWorkflow
2627
LABELS ctf)
28+
29+
o2_add_test_root_macro(CTFdict2CCDBfiles.C
30+
PUBLIC_LINK_LIBRARIES O2::CTFWorkflow
31+
LABELS ctf COMPILE_ONLY)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#if !defined(__CLING__) || defined(__ROOTCLING__)
2+
#include "DetectorsBase/CTFCoderBase.h"
3+
#include "DetectorsCommonDataFormats/CTFDictHeader.h"
4+
#include "DetectorsCommonDataFormats/CTFHeader.h"
5+
#include "DetectorsCommonDataFormats/NameConf.h"
6+
#include "DataFormatsITSMFT/CTF.h"
7+
#include "DataFormatsTPC/CTF.h"
8+
#include "DataFormatsTRD/CTF.h"
9+
#include "DataFormatsFT0/CTF.h"
10+
#include "DataFormatsFV0/CTF.h"
11+
#include "DataFormatsFDD/CTF.h"
12+
#include "DataFormatsTOF/CTF.h"
13+
#include "DataFormatsMID/CTF.h"
14+
#include "DataFormatsMCH/CTF.h"
15+
#include "DataFormatsEMCAL/CTF.h"
16+
#include "DataFormatsPHOS/CTF.h"
17+
#include "DataFormatsCPV/CTF.h"
18+
#include "DataFormatsZDC/CTF.h"
19+
#include "DataFormatsHMP/CTF.h"
20+
#include "DataFormatsCTP/CTF.h"
21+
#endif
22+
23+
using DetID = o2::detectors::DetID;
24+
25+
template <typename T>
26+
bool readFromTree(TTree& tree, const std::string brname, T& dest, int ev = 0)
27+
{
28+
auto* br = tree.GetBranch(brname.c_str());
29+
if (br && br->GetEntries() > ev) {
30+
auto* ptr = &dest;
31+
br->SetAddress(&ptr);
32+
br->GetEntry(ev);
33+
br->ResetAddress();
34+
return true;
35+
}
36+
return false;
37+
}
38+
39+
template <typename C>
40+
void extractDictionary(TTree& tree, o2::detectors::DetID det, DetID::mask_t detMask)
41+
{
42+
std::vector<char> bufVec;
43+
if (!detMask[det]) {
44+
return;
45+
}
46+
o2::ctf::CTFHeader ctfHeader;
47+
readFromTree(tree, "CTFHeader", ctfHeader);
48+
if (!ctfHeader.detectors[det]) {
49+
LOGP(warning, "Dictionary for {} was requested but absent", det.getName());
50+
return;
51+
}
52+
C::readFromTree(bufVec, tree, det.getName());
53+
auto& dictHeader = static_cast<o2::ctf::CTFDictHeader&>(C::get(bufVec.data())->getHeader());
54+
dictHeader.det = det; // impose detector, since in early versions it is absent
55+
std::string outName = fmt::format("ctfdict_{}_v{}.{}_{}.root", det.getName(), int(dictHeader.majorVersion), int(dictHeader.minorVersion), dictHeader.dictTimeStamp);
56+
TFile flout(outName.c_str(), "recreate");
57+
flout.WriteObject(&bufVec, o2::base::NameConf::CCDBOBJECT.data());
58+
flout.Close();
59+
LOG(info) << "Wrote " << dictHeader.asString() << " to " << outName;
60+
}
61+
62+
// This macro allows to convert tree-based CTF dictionary (produced by the ctf-writer-workflow) to per-detector files with plain vector, suitable for the CCDB use.
63+
void CTFdict2CCDBfiles(const std::string& fname = "ctf_dictionary.root", const std::string dets = "all")
64+
{
65+
std::string allowedDetectors = "ITS,TPC,TRD,TOF,PHS,CPV,EMC,HMP,MFT,MCH,MID,ZDC,FT0,FV0,FDD,CTP";
66+
auto detMask = DetID::getMask(dets) & DetID::getMask(allowedDetectors);
67+
68+
std::unique_ptr<TFile> dictFile(TFile::Open(fname.c_str()));
69+
if (!dictFile) {
70+
LOG(error) << "Failed to open CTF dictionary file " << fname;
71+
return;
72+
}
73+
std::unique_ptr<TTree> tree((TTree*)dictFile->Get(std::string(o2::base::NameConf::CTFDICT).c_str()));
74+
if (!tree) {
75+
LOG(error) << "Did not find CTF dictionary tree in " << fname;
76+
return;
77+
}
78+
extractDictionary<o2::itsmft::CTF>(*tree, DetID::ITS, detMask);
79+
extractDictionary<o2::itsmft::CTF>(*tree, DetID::MFT, detMask);
80+
extractDictionary<o2::emcal::CTF>(*tree, DetID::EMC, detMask);
81+
extractDictionary<o2::hmpid::CTF>(*tree, DetID::HMP, detMask);
82+
extractDictionary<o2::phos::CTF>(*tree, DetID::PHS, detMask);
83+
extractDictionary<o2::tpc::CTF>(*tree, DetID::TPC, detMask);
84+
extractDictionary<o2::trd::CTF>(*tree, DetID::TRD, detMask);
85+
extractDictionary<o2::ft0::CTF>(*tree, DetID::FT0, detMask);
86+
extractDictionary<o2::fv0::CTF>(*tree, DetID::FV0, detMask);
87+
extractDictionary<o2::fdd::CTF>(*tree, DetID::FDD, detMask);
88+
extractDictionary<o2::tof::CTF>(*tree, DetID::TOF, detMask);
89+
extractDictionary<o2::mid::CTF>(*tree, DetID::MID, detMask);
90+
extractDictionary<o2::mch::CTF>(*tree, DetID::MCH, detMask);
91+
extractDictionary<o2::cpv::CTF>(*tree, DetID::CPV, detMask);
92+
extractDictionary<o2::zdc::CTF>(*tree, DetID::ZDC, detMask);
93+
extractDictionary<o2::ctp::CTF>(*tree, DetID::CTP, detMask);
94+
95+
tree.reset();
96+
dictFile.reset();
97+
}

0 commit comments

Comments
 (0)