diff --git a/corsika/detail/modules/writers/ParticleWriterParquet.inl b/corsika/detail/modules/writers/ParticleWriterParquet.inl index d4780a71380b47c3be1b387b0c9639e1b452bb14..640c1c704b783cd4bd2bcbaab2391abd5817d931 100644 --- a/corsika/detail/modules/writers/ParticleWriterParquet.inl +++ b/corsika/detail/modules/writers/ParticleWriterParquet.inl @@ -15,7 +15,6 @@ namespace corsika { inline ParticleWriterParquet::ParticleWriterParquet(bool const printZ) : output_() , showerId_(0) - , totalEnergy_(0_eV) , printZ_(printZ) {} inline void ParticleWriterParquet::startOfLibrary( @@ -59,18 +58,57 @@ namespace corsika { inline void ParticleWriterParquet::startOfShower(unsigned int const showerId) { showerId_ = showerId; - totalEnergy_ = 0_eV; + countHadrons_ = 0; countOthers_ = 0; countEM_ = 0; countMuons_ = 0; + + kineticEnergyHadrons_ = 0_eV; + kineticEnergyMuons_ = 0_eV; + kineticEnergyEM_ = 0_eV; + kineticEnergyOthers_ = 0_eV; + + totalEnergyHadrons_ = 0_eV; + totalEnergyMuons_ = 0_eV; + totalEnergyEM_ = 0_eV; + totalEnergyOthers_ = 0_eV; } - inline void ParticleWriterParquet::endOfShower(unsigned int const) {} + inline void ParticleWriterParquet::endOfShower(unsigned int const) { + summary_["shower_" + std::to_string(showerId_)]["hadron"]["count"] = countHadrons_; + summary_["shower_" + std::to_string(showerId_)]["hadron"]["kinetic_energy"] = + kineticEnergyHadrons_ / 1_GeV; + summary_["shower_" + std::to_string(showerId_)]["hadron"]["total_energy"] = + totalEnergyHadrons_ / 1_GeV; + + summary_["shower_" + std::to_string(showerId_)]["muon"]["count"] = countMuons_; + summary_["shower_" + std::to_string(showerId_)]["muon"]["kinetic_energy"] = + kineticEnergyMuons_ / 1_GeV; + summary_["shower_" + std::to_string(showerId_)]["muon"]["total_energy"] = + totalEnergyMuons_ / 1_GeV; + + summary_["shower_" + std::to_string(showerId_)]["em"]["count"] = countEM_; + summary_["shower_" + std::to_string(showerId_)]["em"]["kinetic_energy"] = + kineticEnergyEM_ / 1_GeV; + summary_["shower_" + std::to_string(showerId_)]["em"]["total_energy"] = + totalEnergyEM_ / 1_GeV; + + summary_["shower_" + std::to_string(showerId_)]["other"]["count"] = countOthers_; + summary_["shower_" + std::to_string(showerId_)]["other"]["kinetic_energy"] = + kineticEnergyOthers_ / 1_GeV; + summary_["shower_" + std::to_string(showerId_)]["other"]["total_energy"] = + totalEnergyOthers_ / 1_GeV; + } inline void ParticleWriterParquet::endOfLibrary() { output_.closeStreamer(); } - inline void ParticleWriterParquet::write(Code const pid, HEPEnergyType const energy, + inline HEPEnergyType ParticleWriterParquet::getEnergyGround() const { + return totalEnergyHadrons_ + totalEnergyMuons_ + totalEnergyEM_ + totalEnergyOthers_; + } + + inline void ParticleWriterParquet::write(Code const pid, + HEPEnergyType const kineticEnergy, LengthType const x, LengthType const y, LengthType const z, double const nx, double const ny, double const nz, @@ -78,7 +116,7 @@ namespace corsika { // write the next row - we must write `shower_` first. *(output_.getWriter()) << showerId_ << static_cast<int>(get_PDG(pid)) - << static_cast<float>(energy / 1_GeV) + << static_cast<float>(kineticEnergy / 1_GeV) << static_cast<float>(x / 1_m) << static_cast<float>(y / 1_m); if (printZ_) { *(output_.getWriter()) << static_cast<float>(z / 1_m); } @@ -86,30 +124,28 @@ namespace corsika { << static_cast<float>(nz) << static_cast<double>(t / 1_s) << static_cast<float>(weight) << parquet::EndRow; - totalEnergy_ += energy; - if (is_hadron(pid)) { ++countHadrons_; + kineticEnergyHadrons_ += kineticEnergy; + totalEnergyHadrons_ += kineticEnergy + get_mass(pid); } else if (is_muon(pid)) { ++countMuons_; + kineticEnergyMuons_ += kineticEnergy; + totalEnergyMuons_ += kineticEnergy + get_mass(pid); } else if (is_em(pid)) { ++countEM_; + kineticEnergyEM_ += kineticEnergy; + totalEnergyEM_ += kineticEnergy + get_mass(pid); } else { ++countOthers_; + kineticEnergyOthers_ += kineticEnergy; + totalEnergyOthers_ += kineticEnergy + get_mass(pid); } } /** * Return collected library-level summary for output. */ - inline YAML::Node ParticleWriterParquet::getSummary() const { - YAML::Node summary; - summary["Eground"] = totalEnergy_ / 1_GeV; - summary["hadrons"] = countHadrons_; - summary["muons"] = countMuons_; - summary["em"] = countEM_; - summary["others"] = countOthers_; - return summary; - } + inline YAML::Node ParticleWriterParquet::getSummary() const { return summary_; } } // namespace corsika diff --git a/corsika/modules/writers/ParticleWriterParquet.hpp b/corsika/modules/writers/ParticleWriterParquet.hpp index 4e15a34d6420d20fd1834139e68e74f52fde6f22..4eded3f6f5b1b88a405a419f5f0e279854950e1c 100644 --- a/corsika/modules/writers/ParticleWriterParquet.hpp +++ b/corsika/modules/writers/ParticleWriterParquet.hpp @@ -49,7 +49,7 @@ namespace corsika { /** * Write a PDG/corsika::Code particle to the file. */ - void write(Code const pid, units::si::HEPEnergyType const energy, + void write(Code const pid, units::si::HEPEnergyType const kineticEnergy, units::si::LengthType const x, units::si::LengthType const y, units::si::LengthType const z, double const nx, double const ny, double const nz, units::si::TimeType const time, const double weight); @@ -62,7 +62,7 @@ namespace corsika { /** * If plane is absorbing particles: return the total energy absorbed. */ - HEPEnergyType getEnergyGround() const { return totalEnergy_; } + HEPEnergyType getEnergyGround() const; private: ParquetStreamer output_; ///< The primary output file. @@ -73,7 +73,21 @@ namespace corsika { double countEM_ = 0; ///< count EM particles hitting plane. double countOthers_ = 0; ///< count other types of particles hitting plane - HEPEnergyType totalEnergy_; ///< energy absorbed in ground. + HEPEnergyType kineticEnergyHadrons_ = + 0_eV; ///< kinetic energy of hadrons hitting plane + HEPEnergyType kineticEnergyMuons_ = 0_eV; ///< kinetic energy of muons hitting plane + HEPEnergyType kineticEnergyEM_ = + 0_eV; ///< kinetic energy of EM particles hitting plane. + HEPEnergyType kineticEnergyOthers_ = + 0_eV; ///< kinetic energy of other types of particles hitting plane + + HEPEnergyType totalEnergyHadrons_ = 0_eV; ///< total energy of hadrons hitting plane + HEPEnergyType totalEnergyMuons_ = 0_eV; ///< total energy of muons hitting plane + HEPEnergyType totalEnergyEM_ = 0_eV; ///< total energy of EM particles hitting plane. + HEPEnergyType totalEnergyOthers_ = + 0_eV; ///< total energy of other types of particles hitting plane + + YAML::Node summary_; bool const printZ_; ///< flag to print the z coordinate diff --git a/tests/output/testWriterObservationPlane.cpp b/tests/output/testWriterObservationPlane.cpp index 566b7b6c0410e6f4046d447215cb486f3bb623db..ff054358388245d8159ad01c88ac3c122a1c769c 100644 --- a/tests/output/testWriterObservationPlane.cpp +++ b/tests/output/testWriterObservationPlane.cpp @@ -48,23 +48,26 @@ TEST_CASE("ObservationPlaneWriterParquet") { TestWriterPlane test(true); test.startOfLibrary(file_dir); - test.startOfShower(0); - // write a few particles + test.startOfShower(0); test.checkWrite(); - test.endOfShower(0); + test.endOfLibrary(); CHECK(boost::filesystem::exists(file_dir + "/particles.parquet")); auto const summary = test.getSummary(); - CHECK(summary["Eground"].as<double>() == Approx(5)); - CHECK(summary["hadrons"].as<int>() == Approx(1)); - CHECK(summary["muons"].as<int>() == Approx(2)); - CHECK(summary["em"].as<int>() == Approx(1)); - CHECK(summary["others"].as<int>() == Approx(1)); + CHECK(summary["shower_0"]["hadron"]["count"].as<double>() == Approx(1)); + CHECK(summary["shower_0"]["muon"]["count"].as<double>() == Approx(2)); + CHECK(summary["shower_0"]["em"]["count"].as<double>() == Approx(1)); + CHECK(summary["shower_0"]["other"]["count"].as<double>() == Approx(1)); + + CHECK(summary["shower_0"]["hadron"]["kinetic_energy"].as<double>() == Approx(1)); + CHECK(summary["shower_0"]["muon"]["kinetic_energy"].as<double>() == Approx(2)); + CHECK(summary["shower_0"]["em"]["kinetic_energy"].as<double>() == Approx(1)); + CHECK(summary["shower_0"]["other"]["kinetic_energy"].as<double>() == Approx(1)); // clean things up if (boost::filesystem::exists(file_dir)) { boost::filesystem::remove_all(file_dir); } @@ -80,23 +83,65 @@ TEST_CASE("ObservationPlaneWriterParquet") { TestWriterPlane test(false); // do not print the z-coord test.startOfLibrary(file_dir); - test.startOfShower(0); - // write a few particles + test.startOfShower(0); test.checkWrite(); - test.endOfShower(0); + test.endOfLibrary(); CHECK(boost::filesystem::exists(file_dir + "/particles.parquet")); auto const summary = test.getSummary(); - CHECK(summary["Eground"].as<double>() == Approx(5)); - CHECK(summary["hadrons"].as<int>() == Approx(1)); - CHECK(summary["muons"].as<int>() == Approx(2)); - CHECK(summary["em"].as<int>() == Approx(1)); - CHECK(summary["others"].as<int>() == Approx(1)); + CHECK(summary["shower_0"]["hadron"]["count"].as<double>() == Approx(1)); + CHECK(summary["shower_0"]["muon"]["count"].as<double>() == Approx(2)); + CHECK(summary["shower_0"]["em"]["count"].as<double>() == Approx(1)); + CHECK(summary["shower_0"]["other"]["count"].as<double>() == Approx(1)); + + CHECK(summary["shower_0"]["hadron"]["kinetic_energy"].as<double>() == Approx(1)); + CHECK(summary["shower_0"]["muon"]["kinetic_energy"].as<double>() == Approx(2)); + CHECK(summary["shower_0"]["em"]["kinetic_energy"].as<double>() == Approx(1)); + CHECK(summary["shower_0"]["other"]["kinetic_energy"].as<double>() == Approx(1)); + + // clean things up + if (boost::filesystem::exists(file_dir)) { boost::filesystem::remove_all(file_dir); } + } + + SECTION("reset_between_showers") { + // Check that the counters are reset between showers + + std::string const file_dir = "./output_dir_obs_plane_reset"; + + // preparation + if (boost::filesystem::exists(file_dir)) { boost::filesystem::remove_all(file_dir); } + boost::filesystem::create_directory(file_dir); + + TestWriterPlane test(false); // do not print the z-coord + test.startOfLibrary(file_dir); + + test.startOfShower(0); + test.checkWrite(); + test.endOfShower(0); + + test.startOfShower(1); + test.checkWrite(); + test.endOfShower(1); + + auto const summary = test.getSummary(); + + CHECK(summary["shower_0"]["hadron"]["count"].as<double>() == + summary["shower_1"]["hadron"]["count"].as<double>()); + CHECK(summary["shower_0"]["muon"]["count"].as<double>() == + summary["shower_1"]["muon"]["count"].as<double>()); + CHECK(summary["shower_0"]["em"]["count"].as<double>() == + summary["shower_1"]["em"]["count"].as<double>()); + CHECK(summary["shower_0"]["other"]["count"].as<double>() == + summary["shower_1"]["other"]["count"].as<double>()); + + CHECK(boost::filesystem::exists(file_dir + "/particles.parquet")); + + test.endOfLibrary(); // clean things up if (boost::filesystem::exists(file_dir)) { boost::filesystem::remove_all(file_dir); }