35int main(
int argc,
char* argv[])
37 std::string inputAO2D(
"AO2D.root");
38 std::string outputFileName{
"AO2D_strained.root"};
39 std::string tables{
"O2bc,O2calotrigger,O2collision,O2fdd,O2ft0,O2fv0a"};
40 double downsampling = 1.0;
43 int compression = 505;
45 std::random_device
rd;
46 std::mt19937
gen(
rd());
47 std::uniform_real_distribution<> dis(0.0, 1.0);
50 static struct option long_options[] = {
51 {
"input", required_argument,
nullptr, 0},
52 {
"output", required_argument,
nullptr, 1},
53 {
"verbosity", required_argument,
nullptr, 2},
54 {
"tables", required_argument,
nullptr, 3},
55 {
"downsampling", required_argument,
nullptr, 4},
56 {
"compression", required_argument,
nullptr, 5},
57 {
"help", no_argument,
nullptr,
'h'},
58 {
nullptr, 0,
nullptr, 0}};
61 int c = getopt_long(argc, argv,
"", long_options, &option_index);
67 outputFileName = optarg;
73 downsampling = atof(optarg);
75 compression = atoi(optarg);
76 }
else if (
c ==
'h') {
77 printf(
"AO2D strainer tool. Options: \n");
78 printf(
" --input <%s> Contains path to files to be merged. Default: %s\n", inputAO2D.c_str(), inputAO2D.c_str());
79 printf(
" --output <%s> Target output ROOT file. Default: %s\n", outputFileName.c_str(), outputFileName.c_str());
80 printf(
" --verbosity <flag> Verbosity of output (default: %d).\n",
verbosity);
81 printf(
" --tables <list of tables> Comma separated list of tables (default: %s).\n", tables.c_str());
82 printf(
" --downsampling <downsample> Fraction of DF to be kept (default: %f)\n", downsampling);
83 printf(
" --compression <root compression id> Compression algorithm / level to use (default: %d)\n", compression);
90 printf(
"AOD strainer started with:\n");
91 printf(
" Input file: %s\n", inputAO2D.c_str());
92 printf(
" Output file name: %s\n", outputFileName.c_str());
93 printf(
" Tables to be kept: %s\n", tables.c_str());
94 printf(
" Downsampling: %f\n", downsampling);
96 std::vector<std::string> listOfTables;
97 std::stringstream ss(tables);
100 while (std::getline(ss, token,
',')) {
101 listOfTables.push_back(token);
104 auto outputFile = TFile::Open(outputFileName.c_str(),
"RECREATE",
"", compression);
105 TDirectory* outputDir =
nullptr;
106 TString line(inputAO2D.c_str());
107 if (line.BeginsWith(
"alien://") && !gGrid && !TGrid::Connect(
"alien:")) {
108 printf(
"Error: Could not connect to AliEn.\n");
111 printf(
"Processing input file: %s\n", line.Data());
112 auto inputFile = TFile::Open(line);
114 printf(
"Error: Could not open input file %s.\n", line.Data());
118 TList* keyList = inputFile->GetListOfKeys();
121 for (
auto key1 : *keyList) {
122 if (((TObjString*)key1)->GetString().EqualTo(
"metaData")) {
123 auto metaDataCurrentFile = (TMap*)inputFile->Get(
"metaData");
125 metaDataCurrentFile->Write(
"metaData", TObject::kSingleKey);
128 if (((TObjString*)key1)->GetString().EqualTo(
"parentFiles")) {
129 auto parentFilesCurrentFile = (TMap*)inputFile->Get(
"parentFiles");
131 parentFilesCurrentFile->Write(
"parentFiles", TObject::kSingleKey);
134 if (!((TObjString*)key1)->GetString().BeginsWith(
"DF_") || dis(
gen) > downsampling) {
138 auto dfName = ((TObjString*)key1)->GetString().Data();
140 printf(
" Processing folder %s\n", dfName);
142 outputDir = outputFile->mkdir(dfName);
143 auto folder = (TDirectoryFile*)inputFile->Get(dfName);
144 auto treeList = folder->GetListOfKeys();
149 for (
auto i = 0;
i < treeList->GetEntries(); ++
i) {
150 TKey* ki = (TKey*)treeList->At(
i);
151 for (
int j =
i + 1;
j < treeList->GetEntries(); ++
j) {
152 TKey* kj = (TKey*)treeList->At(
j);
153 if (std::strcmp(ki->GetName(), kj->GetName()) == 0 && std::strcmp(ki->GetTitle(), kj->GetTitle()) == 0) {
154 if (ki->GetCycle() < kj->GetCycle()) {
155 printf(
" *** FATAL *** we had ordered the keys, first cycle should be higher, please check");
159 treeList->Remove(kj);
169 std::list<std::string> foundTrees;
171 for (
auto key2 : *treeList) {
172 auto treeName = ((TObjString*)key2)->GetString().Data();
173 bool found = (std::find(foundTrees.begin(), foundTrees.end(), treeName) != foundTrees.end());
175 printf(
" ***WARNING*** Tree %s was already merged (even if we purged duplicated trees before, so this should not happen), skipping\n", treeName);
178 bool foundTable =
false;
179 for (
auto const& table : listOfTables) {
181 foundTrees.push_back(treeName);
188 printf(
" Skipping tree %s\n", treeName);
193 auto inputTree = (TTree*)inputFile->Get(Form(
"%s/%s", dfName, treeName));
195 printf(
" Processing tree %s with %lld entries with total size %lld\n", treeName, inputTree->GetEntries(), inputTree->GetTotBytes());
199 auto outputTree = inputTree->CloneTree(-1,
"fast");
205 printf(
"Removing incomplete output file %s.\n", outputFile->GetName());
206 gSystem->Unlink(outputFile->GetName());