File indexing completed on 2025-08-05 08:19:08
0001
0002
0003
0004
0005 #include "../src/output.h"
0006
0007 #include "catch.hpp"
0008 #include "util.h"
0009
0010 #include <boost/filesystem.hpp>
0011 #include <boost/filesystem/fstream.hpp>
0012
0013 #include "../src/event.h"
0014 #include "../src/hdf5_utils.h"
0015 #include "../src/nucleus.h"
0016
0017 using namespace trento;
0018
0019 TEST_CASE( "output" ) {
0020 auto var_map = make_var_map({
0021 {"normalization", 1.},
0022 {"reduced-thickness", 0.},
0023 {"grid-max", 9.},
0024 {"grid-step", 0.3},
0025 {"fluctuation", 1.},
0026 {"cross-section", 6.4},
0027 {"nucleon-width", 0.5}
0028 });
0029
0030
0031 Event event{var_map};
0032 NucleonProfile profile{var_map};
0033
0034 auto nucleusA = Nucleus::create("Pb");
0035 auto nucleusB = Nucleus::create("Pb");
0036
0037 auto b = 4.*std::sqrt(random::canonical<>());
0038 nucleusA->sample_nucleons(+.5*b);
0039 nucleusB->sample_nucleons(-.5*b);
0040
0041 for (auto&& A : *nucleusA)
0042 for (auto&& B : *nucleusB)
0043 profile.participate(A, B);
0044
0045 event.compute(*nucleusA, *nucleusB, profile);
0046
0047 SECTION( "no output" ) {
0048 capture_stdout capture;
0049 Output output{make_var_map({{"quiet", true}, {"number-events", 1}})};
0050 output(1, b, event);
0051 CHECK( capture.stream.str().empty() );
0052 }
0053
0054 SECTION( "stdout only" ) {
0055
0056 auto first_line = [&b, &event](int nev) {
0057 capture_stdout capture;
0058 Output output{make_var_map({{"quiet", false}, {"number-events", nev}})};
0059 output(0, b, event);
0060 std::string line;
0061 std::getline(capture.stream, line);
0062 return line;
0063 };
0064
0065
0066 CHECK( first_line(1).substr(0, 1) == "0" );
0067 CHECK( first_line(10).substr(0, 1) == "0" );
0068 CHECK( first_line(11).substr(0, 2) == " 0" );
0069 CHECK( first_line(100).substr(0, 2) == " 0" );
0070 CHECK( first_line(101).substr(0, 3) == " 0" );
0071
0072
0073
0074 CHECK( first_line(1).substr(1) == first_line(1000).substr(3) );
0075
0076
0077 int num, npart;
0078 double impact, mult, e2, e3, e4, e5;
0079 char end;
0080 {
0081 capture_stdout capture;
0082 Output output{make_var_map({{"quiet", false}, {"number-events", 1}})};
0083 output(0, b, event);
0084 capture.stream >> num >> impact >> npart >> mult >> e2 >> e3 >> e4 >> e5 >> std::ws;
0085 end = capture.stream.get();
0086 }
0087
0088
0089 CHECK( num == 0 );
0090 CHECK( impact == Approx(b) );
0091 CHECK( npart == event.npart() );
0092 CHECK( mult == Approx(event.multiplicity()) );
0093 CHECK( e2 == Approx(event.eccentricity().at(2)) );
0094 CHECK( e3 == Approx(event.eccentricity().at(3)) );
0095 CHECK( e4 == Approx(event.eccentricity().at(4)) );
0096 CHECK( e5 == Approx(event.eccentricity().at(5)) );
0097
0098
0099 CHECK( end == std::char_traits<char>::eof() );
0100 }
0101
0102 SECTION( "text and stdout" ) {
0103
0104 temporary_path temp{};
0105 auto output_var_map = make_var_map({
0106 {"quiet", false},
0107 {"no-header", false},
0108 {"number-events", 50},
0109 {"output", temp.path}
0110 });
0111 Output output{output_var_map};
0112
0113
0114 CHECK( fs::exists(temp.path) );
0115
0116 {
0117
0118 capture_stdout capture;
0119 output(3, b, event);
0120 output(27, b, event);
0121 int n = 0;
0122 std::string line;
0123 while (std::getline(capture.stream, line)) { ++n; }
0124 CHECK( n == 2 );
0125 }
0126
0127
0128 CHECK( fs::exists(temp.path/"03.dat") );
0129 CHECK( fs::exists(temp.path/"27.dat") );
0130
0131 {
0132
0133 fs::ifstream ifs{temp.path/"03.dat"};
0134 std::string line;
0135
0136
0137 std::getline(ifs, line);
0138 CHECK( line == "# event 3" );
0139
0140 std::getline(ifs, line);
0141 CHECK( line.substr(0, 10) == "# b = " );
0142 CHECK( std::stod(line.substr(10)) == Approx(b) );
0143
0144 std::getline(ifs, line);
0145 CHECK( line.substr(0, 10) == "# npart = " );
0146 CHECK( std::stoi(line.substr(10)) == event.npart() );
0147
0148 std::getline(ifs, line);
0149 CHECK( line.substr(0, 10) == "# mult = " );
0150 CHECK( std::stod(line.substr(10)) == Approx(event.multiplicity()) );
0151
0152 for (const auto& ecc : event.eccentricity()) {
0153 std::getline(ifs, line);
0154 CHECK( line.substr(0, 10) == ("# e" + std::to_string(ecc.first) + " = ") );
0155 CHECK( std::stod(line.substr(10)) == Approx(ecc.second) );
0156 }
0157
0158
0159 const auto* iter = event.reduced_thickness_grid().origin();
0160 double check;
0161 bool all_correct = false;
0162 while (ifs >> check)
0163 all_correct = (check == Approx(*(iter++))) || all_correct;
0164 CHECK( all_correct );
0165
0166
0167 const auto* grid_end = event.reduced_thickness_grid().origin() +
0168 event.reduced_thickness_grid().num_elements();
0169 CHECK( iter == grid_end );
0170 }
0171
0172 {
0173
0174 fs::ifstream ifs{temp.path/"27.dat"};
0175 std::string line;
0176 std::getline(ifs, line);
0177 CHECK( line == "# event 27" );
0178 }
0179
0180
0181 CHECK_THROWS_AS( Output{output_var_map}, std::runtime_error );
0182 }
0183
0184 #ifdef TRENTO_HDF5
0185 SECTION( "hdf5 only" ) {
0186 auto nev = 10;
0187
0188
0189 temporary_path temp{".hdf5"};
0190
0191 auto output_var_map = make_var_map({
0192 {"quiet", true},
0193 {"number-events", nev},
0194 {"output", temp.path}
0195 });
0196 Output output{output_var_map};
0197
0198 for (auto n = 0; n < nev; ++n)
0199 output(n, b, event);
0200
0201 {
0202 H5::H5File file{temp.path.string(), H5F_ACC_RDONLY};
0203 CHECK( static_cast<int>(file.getNumObjs()) == nev );
0204
0205 auto name = file.getObjnameByIdx(0);
0206 CHECK( name == "event_0" );
0207
0208 auto dataset = file.openDataSet(name);
0209
0210
0211 Event::Grid grid_check{event.reduced_thickness_grid()};
0212 dataset.read(grid_check.data(), H5::PredType::NATIVE_DOUBLE);
0213
0214
0215 auto grid_correct = std::equal(
0216 grid_check.origin(),
0217 grid_check.origin() + grid_check.num_elements(),
0218 event.reduced_thickness_grid().origin(),
0219 [](const double& value_check, const double& value) {
0220 return value_check == Approx(value);
0221 }
0222 );
0223 CHECK( grid_correct );
0224
0225
0226 double double_check;
0227 int int_check;
0228
0229 dataset.openAttribute("b").read(H5::PredType::NATIVE_DOUBLE, &double_check);
0230 CHECK( double_check == Approx(b) );
0231
0232 dataset.openAttribute("npart").read(H5::PredType::NATIVE_INT, &int_check);
0233 CHECK( int_check == event.npart() );
0234
0235 dataset.openAttribute("mult").read(H5::PredType::NATIVE_DOUBLE, &double_check);
0236 CHECK( double_check == Approx(event.multiplicity()) );
0237
0238 for (const auto& ecc : event.eccentricity()) {
0239 dataset.openAttribute("e" + std::to_string(ecc.first))
0240 .read(H5::PredType::NATIVE_DOUBLE, &double_check);
0241 CHECK( double_check == Approx(ecc.second) );
0242 }
0243
0244 #if H5_VERSION_GE(1, 8, 14)
0245 CHECK( dataset.getNumAttrs() == 7 );
0246 #endif
0247 }
0248
0249
0250 CHECK_THROWS_AS( Output{output_var_map}, std::runtime_error );
0251
0252
0253 temporary_path temp2{".hdf5"};
0254 {
0255 fs::ofstream{temp2.path};
0256 }
0257
0258
0259 Output{
0260 make_var_map({
0261 {"quiet", true},
0262 {"number-events", 1},
0263 {"output", temp2.path}
0264 })
0265 }(0, b, event);
0266
0267 CHECK( fs::file_size(temp2.path) > 0);
0268 }
0269 #endif
0270 }