IAP GITLAB

Skip to content
Snippets Groups Projects
Commit 0a3c8299 authored by Maximilian Reininghaus's avatar Maximilian Reininghaus :vulcan: Committed by Maximilian Reininghaus
Browse files

new output format for interaction histograms and simplifications with

boost 1.74
parent e70ba355
No related branches found
No related tags found
No related merge requests found
...@@ -252,11 +252,8 @@ int main(int argc, char** argv) { ...@@ -252,11 +252,8 @@ int main(int argc, char** argv) {
auto const hists = sibyllCounted.GetHistogram() + sibyllNucCounted.GetHistogram() + auto const hists = sibyllCounted.GetHistogram() + sibyllNucCounted.GetHistogram() +
urqmdCounted.GetHistogram() + proposalCounted.GetHistogram(); urqmdCounted.GetHistogram() + proposalCounted.GetHistogram();
hists.saveLab("inthist_lab.txt"); hists.saveLab("inthist_lab.npz");
hists.saveCMS("inthist_cms.txt"); hists.saveCMS("inthist_cms.npz");
hists.saveLab("inthist_lab.txt");
hists.saveCMS("inthist_cms.txt");
longprof.save("longprof.txt"); longprof.save("longprof.txt");
......
...@@ -8,97 +8,94 @@ ...@@ -8,97 +8,94 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
namespace corsika { namespace corsika::utl {
namespace utl { /**
* This functions saves a boost::histogram into a numpy file. Only rather basic axis
/** * types are supported: regular, variable, integer, category<int>. Only "ordinary" bin
* This functions saves a boost::histogram into a numpy file. Only rather basic axis * counts (i.e. a double or int) are supported, nothing fancy like profiles.
* types are supported: regular, variable, integer, category<int>. Only "ordinary" bin *
* counts (i.e. a double or int) are supported, nothing fancy like profiles. * Note that this function makes a temporary, dense copy of the histogram, which could
* * be an issue for huge sizes (e.g. for high dimensions)
* Note that this function makes a temporary, dense copy of the histogram, which could */
* be an issue for huge sizes (e.g. for high dimensions) template <class Axes, class Storage>
*/ void save_hist(boost::histogram::histogram<Axes, Storage> const& h,
template <class Axes, class Storage> std::string const& filename) {
void save_hist(boost::histogram::histogram<Axes, Storage> const& h, int const rank = h.rank();
std::string const& filename) {
int const rank = h.rank(); std::vector<size_t> axes_dims;
axes_dims.reserve(rank);
std::vector<size_t> axes_dims;
axes_dims.reserve(rank); auto overflow = std::make_unique<bool[]>(rank);
auto underflow = std::make_unique<bool[]>(rank);
auto overflow = std::make_unique<bool[]>(rank);
auto underflow = std::make_unique<bool[]>(rank); std::vector<char> axis_types;
axis_types.reserve(rank);
std::vector<char> axis_types;
axis_types.reserve(rank); for (int i = 0; i < rank; ++i) {
auto const& ax = h.axis(i);
for (int i = 0; i < rank; ++i) { unsigned const has_underflow = (ax.options() & 0x01) ? 1 : 0;
auto const& ax = h.axis(i); unsigned const has_overflow = (ax.options() & 0x02) ? 1 : 0;
unsigned const has_underflow = (ax.options() & 0x01) ? 1 : 0;
unsigned const has_overflow = (ax.options() & 0x02) ? 1 : 0; underflow[i] = has_underflow;
overflow[i] = has_overflow;
underflow[i] = has_underflow;
overflow[i] = has_overflow; axes_dims.emplace_back(ax.size() + has_underflow + has_overflow);
axes_dims.emplace_back(ax.size() + has_underflow + has_overflow); if (ax.continuous()) {
axis_types.push_back('c');
if (ax.continuous()) { std::vector<double> ax_edges;
axis_types.push_back('c'); ax_edges.reserve(ax.size() + 1);
std::vector<double> ax_edges;
ax_edges.reserve(ax.size() + 1); for (int j = 0; j < ax.size(); ++j) { ax_edges.push_back(ax.bin(j).lower()); }
for (int j = 0; j < ax.size(); ++j) { ax_edges.push_back(ax.bin(j).lower()); } ax_edges.push_back(ax.bin(ax.size() - 1).upper());
ax_edges.push_back(ax.bin(ax.size() - 1).upper()); cnpy::npz_save(filename, std::string{"binedges_"} + std::to_string(i),
ax_edges.data(), {ax_edges.size()}, "a");
cnpy::npz_save(filename, std::string{"binedges_"} + std::to_string(i), } else {
ax_edges.data(), {ax_edges.size()}, "a"); axis_types.push_back('d');
} else { std::vector<int64_t> bins; // we assume that discrete axes have integer bins
axis_types.push_back('d'); bins.reserve(ax.size());
std::vector<int64_t> bins; // we assume that discrete axes have integer bins
bins.reserve(ax.size()); for (int j = 0; j < ax.size(); ++j) { bins.push_back(ax.bin(j).lower()); }
for (int j = 0; j < ax.size(); ++j) { bins.push_back(ax.bin(j).lower()); } cnpy::npz_save(filename, std::string{"bins_"} + std::to_string(i), bins.data(),
{bins.size()}, "a");
cnpy::npz_save(filename, std::string{"bins_"} + std::to_string(i), bins.data(),
{bins.size()}, "a");
}
cnpy::npz_save(filename, std::string{"axistypes"}, axis_types.data(),
{axis_types.size()}, "a");
cnpy::npz_save(filename, std::string{"overflow"}, overflow.get(),
{axis_types.size()}, "a");
cnpy::npz_save(filename, std::string{"underflow"}, underflow.get(),
{axis_types.size()}, "a");
} }
auto const prod_axis_size = std::accumulate(axes_dims.cbegin(), axes_dims.cend(), cnpy::npz_save(filename, std::string{"axistypes"}, axis_types.data(),
unsigned{1}, std::multiplies<>()); {axis_types.size()}, "a");
auto temp = std::make_unique<float[]>(prod_axis_size);
assert(prod_axis_size == h.size()); cnpy::npz_save(filename, std::string{"overflow"}, overflow.get(),
{axis_types.size()}, "a");
cnpy::npz_save(filename, std::string{"underflow"}, underflow.get(),
{axis_types.size()}, "a");
}
auto const prod_axis_size = std::accumulate(axes_dims.cbegin(), axes_dims.cend(),
unsigned{1}, std::multiplies<>());
auto temp = std::make_unique<float[]>(prod_axis_size);
// reduce multi-dim. to 1-dim, row-major (i.e., last axis index is contiguous in assert(prod_axis_size == h.size());
// memory) take special care of underflow bins which have -1 as index and thus need
// to be shifted by +1
for (auto&& x : indexed(h, boost::histogram::coverage::all)) { // reduce multi-dim. to 1-dim, row-major (i.e., last axis index is contiguous in
int p = 0; // memory) take special care of underflow bins which have -1 as index and thus need
// to be shifted by +1
for (int axis_index = 0; axis_index < rank; ++axis_index) { for (auto&& x : indexed(h, boost::histogram::coverage::all)) {
int const offset_underflow = (h.axis(axis_index).options() & 0x01) ? 1 : 0; int p = 0;
auto k = x.index(axis_index) + offset_underflow;
p = k + p * axes_dims.at(axis_index);
}
temp[p] = *x; for (int axis_index = 0; axis_index < rank; ++axis_index) {
int const offset_underflow = (h.axis(axis_index).options() & 0x01) ? 1 : 0;
auto k = x.index(axis_index) + offset_underflow;
p = k + p * axes_dims.at(axis_index);
} }
cnpy::npz_save(filename, "data", temp.get(), axes_dims, "a"); temp[p] = *x;
// In Python this array can directly be assigned to a histogram view if that
// histogram has its axes correspondingly: hist.view(flow=True)[:] = file['data']
} }
} // namespace utl
} // namespace corsika cnpy::npz_save(filename, "data", temp.get(), axes_dims, "a");
// In Python this array can directly be assigned to a histogram view if that
// histogram has its axes correspondingly: hist.view(flow=True)[:] = file['data']
}
} // namespace corsika::utl
...@@ -28,6 +28,7 @@ set_target_properties ( ...@@ -28,6 +28,7 @@ set_target_properties (
target_link_libraries ( target_link_libraries (
ProcessInteractionCounter ProcessInteractionCounter
CORSIKAunits CORSIKAunits
CORSIKAutilities
CORSIKAprocesssequence CORSIKAprocesssequence
CORSIKAthirdparty CORSIKAthirdparty
C8::ext::boost C8::ext::boost
......
...@@ -17,6 +17,7 @@ void InteractionHistogram::fill(particles::Code projectile_id, ...@@ -17,6 +17,7 @@ void InteractionHistogram::fill(particles::Code projectile_id,
units::si::HEPEnergyType lab_energy, units::si::HEPEnergyType lab_energy,
units::si::HEPEnergyType mass_target, int A, int Z) { units::si::HEPEnergyType mass_target, int A, int Z) {
using namespace units::si; using namespace units::si;
auto constexpr inv_eV = 1 / 1_eV;
if (projectile_id == particles::Code::Nucleus) { if (projectile_id == particles::Code::Nucleus) {
auto const sqrtS = auto const sqrtS =
sqrt(A * A * (units::constants::nucleonMass * units::constants::nucleonMass) + sqrt(A * A * (units::constants::nucleonMass * units::constants::nucleonMass) +
...@@ -24,123 +25,41 @@ void InteractionHistogram::fill(particles::Code projectile_id, ...@@ -24,123 +25,41 @@ void InteractionHistogram::fill(particles::Code projectile_id,
int32_t const pdg = 1'000'000'000l + Z * 10'000l + A * 10l; int32_t const pdg = 1'000'000'000l + Z * 10'000l + A * 10l;
if (nuclear_inthist_cms_.count(pdg) == 0) { inthist_lab_(pdg, lab_energy * inv_eV);
nuclear_inthist_lab_.emplace( inthist_cms_(pdg, sqrtS * inv_eV);
pdg,
boost::histogram::make_histogram(
boost::histogram::axis::regular<double,
boost::histogram::axis::transform::log>(
num_bins_lab, lower_edge_lab, upper_edge_lab)));
nuclear_inthist_cms_.emplace(
pdg,
boost::histogram::make_histogram(
boost::histogram::axis::regular<double,
boost::histogram::axis::transform::log>(
num_bins_cms, lower_edge_cms, upper_edge_cms)));
}
nuclear_inthist_lab_[pdg](lab_energy / 1_GeV);
nuclear_inthist_cms_[pdg](sqrtS / 1_GeV);
} else { } else {
auto const projectile_mass = particles::GetMass(projectile_id); auto const projectile_mass = particles::GetMass(projectile_id);
auto const sqrtS = sqrt(projectile_mass * projectile_mass + auto const sqrtS = sqrt(projectile_mass * projectile_mass +
mass_target * mass_target + 2 * lab_energy * mass_target); mass_target * mass_target + 2 * lab_energy * mass_target);
interaction_histogram_cms_( inthist_cms_(static_cast<int>(particles::GetPDG(projectile_id)), sqrtS * inv_eV);
static_cast<corsika::particles::CodeIntType>(projectile_id), sqrtS / 1_GeV); inthist_lab_(static_cast<int>(particles::GetPDG(projectile_id)), lab_energy * inv_eV);
interaction_histogram_lab_(
static_cast<corsika::particles::CodeIntType>(projectile_id), lab_energy / 1_GeV);
} }
} }
void InteractionHistogram::saveLab(std::string const& filename) const { void InteractionHistogram::saveLab(std::string const& filename) const {
save(interaction_histogram_lab_, nuclear_inthist_lab_, filename, "lab system"); corsika::utl::save_hist(inthist_lab_, filename);
} }
void InteractionHistogram::saveCMS(std::string const& filename) const { void InteractionHistogram::saveCMS(std::string const& filename) const {
save(interaction_histogram_lab_, nuclear_inthist_cms_, filename, corsika::utl::save_hist(inthist_cms_, filename);
"center-of-mass system");
} }
InteractionHistogram& InteractionHistogram::operator+=( InteractionHistogram& InteractionHistogram::operator+=(
InteractionHistogram const& other) { InteractionHistogram const& other) {
interaction_histogram_lab_ += other.interaction_histogram_lab_; inthist_lab_ += other.inthist_lab_;
interaction_histogram_cms_ += other.interaction_histogram_cms_; inthist_cms_ += other.inthist_cms_;
nuclear_inthist_lab_ += other.nuclear_inthist_lab_;
nuclear_inthist_cms_ += other.nuclear_inthist_cms_;
return *this; return *this;
} }
InteractionHistogram InteractionHistogram::operator+(InteractionHistogram other) const { InteractionHistogram InteractionHistogram::operator+(InteractionHistogram other) const {
other.nuclear_inthist_lab_ += nuclear_inthist_lab_; other.inthist_lab_ += inthist_lab_;
other.nuclear_inthist_cms_ += nuclear_inthist_cms_; other.inthist_cms_ += inthist_cms_;
other.interaction_histogram_lab_ += interaction_histogram_lab_;
other.interaction_histogram_cms_ += interaction_histogram_cms_;
return other; return other;
} }
void InteractionHistogram::saveHist(hist_type const& hist, std::string const& filename,
std::string const& comment) {
std::ofstream file;
file.open(filename);
saveHist(hist, file, comment);
}
void InteractionHistogram::saveHist(hist_type const& hist, std::ofstream& file,
std::string const& comment) {
auto const& energy_axis = hist.axis(1);
file << "# interaction count histogram (" << comment << ")" << std::endl
<< "# " << energy_axis.size() << " bins between " << energy_axis.bin(0).lower()
<< " and " << energy_axis.bin(energy_axis.size() - 1).upper() << " GeV"
<< std::endl;
for (particles::CodeIntType p = 0;
p < static_cast<particles::CodeIntType>(particles::Code::LastParticle); ++p) {
if (auto pdg = static_cast<particles::PDGCodeType>(
particles::GetPDG(static_cast<particles::Code>(p)));
pdg < 1'000'000'000l) {
file << "# " << static_cast<particles::Code>(p) << std::endl;
file << pdg;
for (int i = 0; i < energy_axis.size(); ++i) { file << ' ' << hist.at(p, i); }
file << std::endl;
}
}
}
void InteractionHistogram::saveHistMap(nuclear_hist_type const& histMap,
std::ofstream& file) {
file << "# nuclei" << std::endl;
for (auto const& [pdg, hist] : histMap) {
auto const num_ebins_nucl = hist.axis(0).size();
file << pdg << ' ';
for (int i = 0; i < num_ebins_nucl; ++i) { file << ' ' << hist.at(i); }
file << std::endl;
}
}
void InteractionHistogram::save(hist_type const& hist, nuclear_hist_type const& histMap,
std::string const& filename, std::string const& comment) {
std::ofstream file;
file.open(filename);
saveHist(hist, file, comment);
saveHistMap(histMap, file);
}
InteractionHistogram::InteractionHistogram() InteractionHistogram::InteractionHistogram()
: interaction_histogram_cms_{boost::histogram::make_histogram( : inthist_cms_{detail::hist_factory(num_bins_cms, lower_edge_cms, upper_edge_cms)}
boost::histogram::axis::integer<short>(0, numIds), , inthist_lab_{detail::hist_factory(num_bins_lab, lower_edge_lab, upper_edge_lab)} {}
boost::histogram::axis::regular<double, boost::histogram::axis::transform::log>(
num_bins_cms, lower_edge_cms, upper_edge_cms))}
, interaction_histogram_lab_{boost::histogram::make_histogram(
boost::histogram::axis::integer<short>(0, numIds),
boost::histogram::axis::regular<double, boost::histogram::axis::transform::log>(
num_bins_lab, lower_edge_lab, upper_edge_lab))} {}
...@@ -10,47 +10,39 @@ ...@@ -10,47 +10,39 @@
#include <corsika/particles/ParticleProperties.h> #include <corsika/particles/ParticleProperties.h>
#include <corsika/units/PhysicalUnits.h> #include <corsika/units/PhysicalUnits.h>
#include <corsika/utl/SaveBoostHistogram.hpp>
#include <boost/histogram.hpp> #include <boost/histogram.hpp>
#include <boost/histogram/ostream.hpp>
#include <fstream> #include <fstream>
#include <functional> #include <functional>
#include <map> #include <map>
#include <utility> #include <utility>
namespace corsika::process::interaction_counter { namespace corsika::process::interaction_counter {
using hist_type = decltype(boost::histogram::make_histogram( namespace detail {
std::declval<boost::histogram::axis::integer<particles::CodeIntType>>(), inline auto hist_factory(unsigned int bin_number, float e_low, float e_high) {
std::declval<boost::histogram::axis::regular< namespace bh = boost::histogram;
double, boost::histogram::axis::transform::log>>())); namespace bha = bh::axis;
using namespace units::si;
using nucl_hist_type = decltype(boost::histogram::make_histogram(
std::declval<boost::histogram::axis::regular< auto h = bh::make_histogram(
double, boost::histogram::axis::transform::log>>())); bha::category<int, bh::use_default, bha::option::growth_t>{{2212, 2112},
"projectile PDG"},
using nuclear_hist_type = std::map<int32_t, nucl_hist_type>; bha::regular<float, bha::transform::log>{bin_number, e_low, e_high,
"energy/eV"});
template <typename TKey, typename TVal> return h;
auto operator+=(std::map<TKey, TVal>& a, std::map<TKey, TVal> b) { }
a.merge(b); } // namespace detail
for (auto const& [id, hist] : b) { a[id] += hist; }
return a;
}
class InteractionHistogram { class InteractionHistogram {
static auto constexpr lower_edge_cms = 1., upper_edge_cms = 1e8; // GeV sqrt s static double constexpr lower_edge_cms = 1e3, upper_edge_cms = 1e17; // eV sqrt s
static auto constexpr lower_edge_lab = 1., upper_edge_lab = 1e12; // GeV lab static double constexpr lower_edge_lab = 1e3, upper_edge_lab = 1e21; // eV lab
static auto constexpr num_bins_lab = 120, num_bins_cms = 80; static unsigned int constexpr num_bins_lab = 18 * 10, num_bins_cms = 14 * 10;
static auto constexpr numIds =
static_cast<particles::CodeIntType>(particles::Code::LastParticle);
hist_type interaction_histogram_cms_; using hist_type =
hist_type interaction_histogram_lab_; decltype(detail::hist_factory(num_bins_lab, lower_edge_lab, upper_edge_lab));
/*! hist_type inthist_cms_, inthist_lab_;
* These maps map PDG nuclei codes to their corresponding interaction histograms
*/
nuclear_hist_type nuclear_inthist_lab_, nuclear_inthist_cms_;
public: public:
InteractionHistogram(); InteractionHistogram();
...@@ -59,17 +51,9 @@ namespace corsika::process::interaction_counter { ...@@ -59,17 +51,9 @@ namespace corsika::process::interaction_counter {
void fill(particles::Code projectile_id, units::si::HEPEnergyType lab_energy, void fill(particles::Code projectile_id, units::si::HEPEnergyType lab_energy,
units::si::HEPEnergyType mass_target, int A = 0, int Z = 0); units::si::HEPEnergyType mass_target, int A = 0, int Z = 0);
auto CMSHists() const { hist_type const& CMSHist() const { return inthist_cms_; }
return std::pair<decltype(interaction_histogram_cms_) const&,
decltype(nuclear_inthist_cms_) const&>{interaction_histogram_cms_,
nuclear_inthist_cms_};
}
auto labHists() const { hist_type const& labHist() const { return inthist_lab_; }
return std::pair<decltype(interaction_histogram_lab_) const&,
decltype(nuclear_inthist_lab_) const&>(interaction_histogram_lab_,
nuclear_inthist_lab_);
}
void saveLab(std::string const& filename) const; void saveLab(std::string const& filename) const;
...@@ -78,30 +62,6 @@ namespace corsika::process::interaction_counter { ...@@ -78,30 +62,6 @@ namespace corsika::process::interaction_counter {
InteractionHistogram& operator+=(InteractionHistogram const& other); InteractionHistogram& operator+=(InteractionHistogram const& other);
InteractionHistogram operator+(InteractionHistogram other) const; InteractionHistogram operator+(InteractionHistogram other) const;
private:
/*!
* Save a histogram into a text file. The \arg comment string is written
* into the header of the text file.
* This method is static so that you can sum the histograms of multiple
* InteractionProcesses before saving them into the same file.
*/
static void saveHist(hist_type const& hist, std::string const& filename,
std::string const& comment = "");
static void saveHist(hist_type const& hist, std::ofstream& file,
std::string const& comment = "");
static void saveHistMap(nuclear_hist_type const& histMap, std::ofstream& file);
/*!
* save both the "normal" particle histograms as well as the "nuclear" histograms
* into the same file
*/
static void save(hist_type const& hist, nuclear_hist_type const& histMap,
std::string const& filename, std::string const& comment = "");
}; };
} // namespace corsika::process::interaction_counter } // namespace corsika::process::interaction_counter
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment