13#include <fairlogger/Logger.h>
30 std::vector<std::string>
keys;
31 std::vector<double>
sum;
37bool readDump(
const std::string& fileName, std::vector<std::string>& meshHeader, std::vector<ScorerBlock>& blocks)
39 std::ifstream in(fileName);
44 ScorerBlock* current =
nullptr;
45 while (std::getline(in, line)) {
46 if (
line.rfind(
"# mesh name", 0) == 0) {
47 meshHeader.push_back(line);
48 }
else if (
line.rfind(
"# primitive scorer name", 0) == 0) {
49 blocks.emplace_back();
50 current = &blocks.back();
51 current->header.push_back(line);
52 }
else if (
line.rfind(
"#", 0) == 0) {
56 current->header.push_back(line);
57 }
else if (!
line.empty()) {
62 std::vector<std::string>
fields;
63 std::stringstream ss(line);
65 while (std::getline(ss, field,
',')) {
72 current->sum.push_back(std::stod(
fields[3]));
73 current->sum2.push_back(std::stod(
fields[4]));
74 current->entries.push_back(std::stol(
fields[5]));
77 return !blocks.empty();
88 namespace fs = std::filesystem;
89 const std::regex
pattern(R
"((.+)\.worker([0-9]+)\.txt)");
90 std::map<std::string, std::vector<fs::path>> filesPerMesh;
91 for (
auto&
entry : fs::directory_iterator(directory)) {
93 const auto name =
entry.path().filename().string();
95 filesPerMesh[
match[1]].push_back(
entry.path());
100 for (
auto& [mesh, files] : filesPerMesh) {
101 if (expectedWorkers > 0 &&
static_cast<int>(files.size()) != expectedWorkers) {
102 LOG(error) <<
"Found " << files.size() <<
" Geant4 scoring dumps for mesh " << mesh <<
" but expected " << expectedWorkers;
105 std::vector<std::string> meshHeader;
106 std::vector<ScorerBlock> total;
107 for (
auto& file : files) {
108 std::vector<std::string>
header;
109 std::vector<ScorerBlock> blocks;
110 if (!readDump(file.string(),
header, blocks)) {
111 LOG(error) <<
"Cannot read Geant4 scoring dump " << file;
116 total = std::move(blocks);
119 if (blocks.size() != total.size()) {
120 LOG(error) <<
"Geant4 scoring dump " << file <<
" has a different set of scorers";
123 for (
size_t b = 0;
b < blocks.size(); ++
b) {
125 LOG(error) <<
"Geant4 scoring dump " << file <<
" does not match the mesh layout of the other workers";
128 for (
size_t i = 0;
i < blocks[
b].keys.size(); ++
i) {
129 total[
b].sum[
i] += blocks[
b].sum[
i];
130 total[
b].sum2[
i] += blocks[
b].sum2[
i];
131 total[
b].entries[
i] += blocks[
b].entries[
i];
136 const auto outName = (fs::path(directory) / (mesh +
".txt")).string();
137 std::ofstream out(outName);
138 out << std::setprecision(16);
139 for (
auto& line : meshHeader) {
142 for (
auto& block : total) {
143 for (
auto& line : block.header) {
146 for (
size_t i = 0;
i < block.keys.size(); ++
i) {
147 out << block.keys[
i] <<
"," << block.sum[
i] <<
"," << block.sum2[
i] <<
"," << block.entries[
i] <<
"\n";
150 LOG(info) <<
"Merged " << files.size() <<
" Geant4 scoring dumps into " << outName;
std::vector< std::shared_ptr< arrow::Field > > fields
std::vector< std::string > header
std::vector< long > entries
std::vector< double > sum
std::vector< double > sum2
std::vector< std::string > keys
bool match(const std::vector< std::string > &queries, const char *pattern)
GLuint const GLchar * name
GLboolean GLboolean GLboolean b
std::string g4ScoringWorkerFileName(const std::string &meshName, int pid)
Name of the Geant4 scoring dump written by one simulation worker.
int mergeG4ScoringDumps(const std::string &directory, int expectedWorkers=0)
int32_t const char int32_t line
std::string to_string(gsl::span< T, Size > span)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::array< uint16_t, 5 > pattern