diff --git a/Projects/AlPhaPha/DataMacro/Merger.C b/Projects/AlPhaPha/DataMacro/Merger.C new file mode 100644 index 0000000000000000000000000000000000000000..e0acff44cd25a9144b9cbc5ad3152ba310d8cfd5 --- /dev/null +++ b/Projects/AlPhaPha/DataMacro/Merger.C @@ -0,0 +1,27 @@ +void Merger(int N, const char* outputDir, const char* outputFileName, const char* inputBaseName) { + TString outputPath = Form("%s/%s", outputDir, outputFileName); + TFile *outputFile = new TFile(outputPath, "RECREATE"); + TList *fileList = new TList(); + + for (int i = 0; i < N; i++) { + TString fileName = Form("%s%d.root", inputBaseName, i); // Base name + index + .root + TFile *inputFile = TFile::Open(fileName); + if (!inputFile || inputFile->IsZombie()) { + std::cerr << "Error opening file: " << fileName << std::endl; + continue; + } + fileList->Add(inputFile); + + // Display progress + int progress = ((i + 1) * 100) / N; + std::cout << "\rMerging files: " << progress << "% complete." << std::flush; + } + + TFileMerger merger; + merger.OutputFile(outputFile, "RECREATE"); + merger.Merge(fileList); + + std::cout << std::endl << "Merging completed! Output saved at: " << outputPath << std::endl; + outputFile->Close(); +} + diff --git a/Projects/AlPhaPha/DataMacro/ReadMe.md b/Projects/AlPhaPha/DataMacro/ReadMe.md new file mode 100644 index 0000000000000000000000000000000000000000..801884bcac28e9f8ff8302bfd70639c8cae34776 --- /dev/null +++ b/Projects/AlPhaPha/DataMacro/ReadMe.md @@ -0,0 +1,9 @@ +# Macro to handle data analysis +## Secator +This macro subdivide a root file into N subfile with the same number of +entries. +This is useful if you want to parallelize your analysis. +## Merger +Do the opposite of secator. + +# DONT FORGET TO CREATE AN OUTPUT DIR IN THIS DIRECTORY diff --git a/Projects/AlPhaPha/DataMacro/Secator.C b/Projects/AlPhaPha/DataMacro/Secator.C new file mode 100644 index 0000000000000000000000000000000000000000..fb4712a204f4d7012ebbfb94e4d508d53bb37ede --- /dev/null +++ b/Projects/AlPhaPha/DataMacro/Secator.C @@ -0,0 +1,62 @@ +#include <iostream> + +void Secator(const char* inputFileName, const char* outputDir, int N) { + // Open the original ROOT file + TFile* inputFile = TFile::Open(inputFileName, "READ"); + if (!inputFile || inputFile->IsZombie()) { + printf("Error: Cannot open file %s\n", inputFileName); + return; + } + + // Extract the base name of the input file (without path and extension) + TString baseName = gSystem->BaseName(inputFileName); + baseName.ReplaceAll(".root", ""); // Remove the .root extension + + // Ensure the output directory ends with a '/' + TString outputDirStr = outputDir; + if (!outputDirStr.EndsWith("/")) { + outputDirStr.Append("/"); + } + + // Get the tree from the file + TTree* inputTree = (TTree*)inputFile->Get("RawTree"); // replace with actual tree name + Long64_t totalEntries = inputTree->GetEntries(); + + // Calculate entries per subfile + Long64_t entriesPerFile = totalEntries / N; + + // Loop to create N subfiles + for (int i = 0; i < N; ++i) { + // Create output file name by appending a number to the base name + TString outputFileName = TString::Format("%s%s_%d.root", outputDirStr.Data(), baseName.Data(), i); + TFile* outputFile = TFile::Open(outputFileName, "RECREATE"); + + // Create a clone of the tree in the new file + TTree* outputTree = inputTree->CloneTree(0); + + // Write the appropriate entries to the subfile + Long64_t start = i * entriesPerFile; + Long64_t end = (i == N - 1) ? totalEntries : start + entriesPerFile; + + for (Long64_t entry = start; entry < end; ++entry) { + inputTree->GetEntry(entry); + outputTree->Fill(); + + // Progress bar update + float progress = (float)(entry - start + 1) / (end - start) * 100; + printf("\rProcessing subfile %d: [%.2f%%]", i + 1, progress); + fflush(stdout); // Ensure immediate print + } + + printf("\n"); // Newline after progress bar completion for this subfile + + // Write and close the subfile + outputTree->Write(); + outputFile->Close(); + delete outputFile; + } + + inputFile->Close(); + delete inputFile; +} +