File indexing completed on 2025-08-05 08:19:07
0001
0002
0003
0004
0005
0006 #include "output.h"
0007
0008 #include <algorithm>
0009 #include <cmath>
0010 #include <iomanip>
0011 #include <iostream>
0012
0013 #include <boost/filesystem.hpp>
0014 #include <boost/filesystem/fstream.hpp>
0015 #include <boost/program_options/variables_map.hpp>
0016
0017 #include "event.h"
0018 #include "hdf5_utils.h"
0019
0020 namespace trento {
0021
0022 namespace {
0023
0024
0025
0026 void write_stream(std::ostream& os, int width,
0027 int num, double impact_param, const Event& event) {
0028 using std::fixed;
0029 using std::setprecision;
0030 using std::setw;
0031 using std::scientific;
0032
0033
0034 os << setprecision(10)
0035 << setw(width) << num
0036 << setw(15) << fixed << impact_param
0037 << setw(5) << event.npart();
0038 if (event.with_ncoll()) os << setw(8) << event.ncoll();
0039 os << setw(18) << scientific << event.multiplicity()
0040 << fixed;
0041
0042 for (const auto& ecc : event.eccentricity())
0043 os << setw(14) << ecc.second;
0044
0045
0046
0047
0048 os << '\n';
0049 }
0050
0051 void write_text_file(const fs::path& output_dir, int width,
0052 int num, double impact_param, const Event& event, bool header) {
0053
0054
0055 std::ostringstream padded_fname{};
0056 padded_fname << std::setw(width) << std::setfill('0') << num << ".dat";
0057 fs::ofstream ofs{output_dir / padded_fname.str()};
0058
0059 if (header) {
0060
0061 ofs << std::setprecision(10)
0062 << "# event " << num << '\n'
0063 << "# b = " << impact_param << '\n'
0064 << "# npart = " << event.npart() << '\n'
0065 << "# mult = " << event.multiplicity() << '\n';
0066
0067 for (const auto& ecc : event.eccentricity())
0068 ofs << "# e" << ecc.first << " = " << ecc.second << '\n';
0069
0070 for (const auto& psi : event.participant_plane())
0071 ofs << "# psi" << psi.first << " = " << psi.second << '\n';
0072 }
0073
0074
0075
0076
0077
0078 bool is3d;
0079 if (event.density_grid().shape()[2] == 1) is3d = false;
0080 else is3d = true;
0081
0082
0083 for (const auto& slice : event.density_grid()) {
0084 for (const auto& row : slice) {
0085 for (const auto& item : row) {
0086 ofs << item << " ";
0087 }
0088 if (is3d) ofs << std::endl;
0089 }
0090 if (!is3d) ofs << std::endl;
0091 }
0092 }
0093
0094 #ifdef TRENTO_HDF5
0095
0096
0097 class HDF5Writer {
0098 public:
0099
0100 HDF5Writer(const fs::path& filename);
0101
0102
0103 void operator()(int num, double impact_param, const Event& event) const;
0104
0105 private:
0106
0107 H5::H5File file_;
0108 };
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118 template <typename T>
0119 void hdf5_add_scalar_attr(
0120 const H5::Group& group, const std::string& name, const T& value) {
0121 const auto& datatype = hdf5::type<T>();
0122 auto attr = group.createAttribute(name, datatype, H5::DataSpace{});
0123 attr.write(datatype, &value);
0124 }
0125
0126 HDF5Writer::HDF5Writer(const fs::path& filename)
0127 : file_(filename.string(), H5F_ACC_TRUNC)
0128 {}
0129
0130 void HDF5Writer::operator()(
0131 int num, double impact_param, const Event& event) const {
0132 const auto& grid1 = event.density_grid();
0133 const auto& grid2 = event.TAB_grid();
0134
0135
0136 const std::string gp_name{"/event_" + std::to_string(num)};
0137 const std::string sd_name{gp_name + "/matter_density"};
0138 const std::string tab_name{gp_name + "/Ncoll_density"};
0139
0140
0141 auto group = H5::Group(file_.createGroup(gp_name));
0142
0143 hdf5_add_scalar_attr(group, "b", impact_param);
0144 hdf5_add_scalar_attr(group, "npart", event.npart());
0145 hdf5_add_scalar_attr(group, "ncoll", event.ncoll());
0146 hdf5_add_scalar_attr(group, "mult", event.multiplicity());
0147 hdf5_add_scalar_attr(group, "dxy", event.dxy());
0148 hdf5_add_scalar_attr(group, "deta", event.deta());
0149 hdf5_add_scalar_attr(group, "Ny", grid1.shape()[0]);
0150 hdf5_add_scalar_attr(group, "Nx", grid1.shape()[1]);
0151 hdf5_add_scalar_attr(group, "Nz", grid1.shape()[2]);
0152 for (const auto& ecc : event.eccentricity())
0153 hdf5_add_scalar_attr(group, "e" + std::to_string(ecc.first), ecc.second);
0154 for (const auto& psi : event.participant_plane())
0155 hdf5_add_scalar_attr(group, "psi" + std::to_string(psi.first), psi.second);
0156
0157
0158
0159
0160 const auto& datatype1 = hdf5::type<Event::Grid3D::element>();
0161 std::array<hsize_t, Event::Grid3D::dimensionality> shape1;
0162 std::copy(grid1.shape(), grid1.shape() + shape1.size(), shape1.begin());
0163 auto dataspace1 = hdf5::make_dataspace(shape1);
0164
0165
0166 H5::DSetCreatPropList proplist1{};
0167
0168
0169
0170
0171 proplist1.setChunk(shape1.size(), shape1.data());
0172
0173 proplist1.setDeflate(4);
0174
0175
0176 auto dataset1 = file_.createDataSet(sd_name, datatype1, dataspace1, proplist1);
0177 dataset1.write(grid1.data(), datatype1);
0178
0179
0180
0181 const auto& datatype2 = hdf5::type<Event::Grid::element>();
0182 std::array<hsize_t, Event::Grid::dimensionality> shape2;
0183 std::copy(grid2.shape(), grid2.shape() + shape2.size(), shape2.begin());
0184 auto dataspace2 = hdf5::make_dataspace(shape2);
0185
0186
0187 H5::DSetCreatPropList proplist2{};
0188
0189
0190
0191
0192 proplist1.setChunk(shape2.size(), shape2.data());
0193
0194 proplist1.setDeflate(4);
0195
0196
0197 auto dataset2 = file_.createDataSet(tab_name, datatype2, dataspace2, proplist2);
0198 dataset2.write(grid2.data(), datatype2);
0199 }
0200
0201 #endif
0202
0203 }
0204
0205 Output::Output(const VarMap& var_map){
0206
0207
0208
0209 auto nevents = var_map["number-events"].as<int>();
0210 auto width = static_cast<int>(std::ceil(std::log10(nevents)));
0211
0212
0213 if (!var_map["quiet"].as<bool>()) {
0214 writers_.emplace_back(
0215 [width](int num, double impact_param, const Event& event) {
0216 write_stream(std::cout, width, num, impact_param, event);
0217 }
0218 );
0219 }
0220
0221
0222 if (var_map.count("output")) {
0223 const auto& output_path = var_map["output"].as<fs::path>();
0224 if (hdf5::filename_is_hdf5(output_path)) {
0225 #ifdef TRENTO_HDF5
0226 if (fs::exists(output_path) && !fs::is_empty(output_path))
0227 throw std::runtime_error{"file '" + output_path.string() +
0228 "' exists, will not overwrite"};
0229 writers_.emplace_back(HDF5Writer{output_path});
0230 #else
0231 throw std::runtime_error{"HDF5 output was not compiled"};
0232 #endif
0233 } else {
0234
0235
0236
0237
0238 if (fs::exists(output_path)) {
0239 if (!fs::is_empty(output_path)) {
0240 throw std::runtime_error{"output directory '" + output_path.string() +
0241 "' must be empty"};
0242 }
0243 } else {
0244 fs::create_directories(output_path);
0245 }
0246 auto header = !var_map["no-header"].as<bool>();
0247 writers_.emplace_back(
0248 [output_path, width, header](
0249 int num, double impact_param, const Event& event) {
0250 write_text_file(output_path, width, num, impact_param, event, header);
0251 }
0252 );
0253 }
0254 }
0255 }
0256
0257 }