IAP GITLAB

Skip to content
Snippets Groups Projects
Commit 8bde61b4 authored by ralfulrich's avatar ralfulrich
Browse files

missing new class

parent 67c34855
No related branches found
No related tags found
1 merge request!371Additional outputs ported to new architecture
/*
* (c) Copyright 2021 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#pragma once
#include <corsika/framework/core/ParticleProperties.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/framework/utility/FindXmax.hpp>
#include <corsika/media/ShowerAxis.hpp>
#include <exception>
namespace corsika {
template <typename TOutput>
inline LongitudinalWriter<TOutput>::LongitudinalWriter(ShowerAxis const& axis,
GrammageType dX,
size_t const nBins)
: TOutput(number_profile::ProfileIndexNames)
, showerAxis_(axis)
, dX_(dX)
, nBins_(nBins) {}
template <typename TOutput>
inline void LongitudinalWriter<TOutput>::startOfLibrary(
boost::filesystem::path const& directory) {
TOutput::startOfLibrary(directory);
}
template <typename TOutput>
inline void LongitudinalWriter<TOutput>::startOfShower(unsigned int const showerId) {
TOutput::startOfShower(showerId);
// reset profile
profile_.clear();
profile_.resize(nBins_);
}
template <typename TOutput>
inline void LongitudinalWriter<TOutput>::endOfLibrary() {
TOutput::endOfLibrary();
}
template <typename TOutput>
inline void LongitudinalWriter<TOutput>::endOfShower(unsigned int const showerId) {
int iRow{0};
for (number_profile::ProfileData const& row : profile_) {
// here: write to underlying writer (e.g. parquet)
TOutput::write(showerId, iRow * dX_, row);
iRow++;
}
TOutput::endOfShower(showerId);
}
template <typename TOutput>
template <typename TTrack>
inline void LongitudinalWriter<TOutput>::write(TTrack const& track, Code const pid,
double const weight) {
GrammageType const grammageStart = showerAxis_.getProjectedX(track.getPosition(0));
GrammageType const grammageEnd = showerAxis_.getProjectedX(track.getPosition(1));
// Note: particle may go also "upward", thus, grammageEnd<grammageStart
int const binStart = std::ceil(grammageStart / dX_);
int const binEnd = std::floor(grammageEnd / dX_);
for (int bin = binStart; bin <= binEnd; ++bin) {
if (pid == Code::Photon) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::Photon)] +=
weight;
} else if (pid == Code::Positron) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::Positron)] +=
weight;
} else if (pid == Code::Electron) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::Electron)] +=
weight;
} else if (pid == Code::MuPlus) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::MuPlus)] +=
weight;
} else if (pid == Code::MuMinus) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::MuMinus)] +=
weight;
} else if (is_hadron(pid)) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::Hadron)] +=
weight;
}
if (is_charged(pid)) {
profile_[bin][static_cast<int>(number_profile::ProfileIndex::Charged)] += weight;
}
}
}
template <typename TOutput>
inline void LongitudinalWriter<TOutput>::write(GrammageType const Xstart,
GrammageType const Xend, Code const pid,
double const weight) {
double const bstart = Xstart / dX_;
double const bend = Xend / dX_;
if (abs(bstart - floor(bstart + 0.5)) > 1e-2 ||
abs(bend - floor(bend + 0.5)) > 1e-2 || abs(bend - bstart - 1) > 1e-2) {
CORSIKA_LOGGER_ERROR(TOutput::getLogger(),
"CONEX and Corsika8 dX grammage binning are not the same! "
"Xstart={} Xend={} dX={}",
Xstart / 1_g * square(1_cm), Xend / 1_g * square(1_cm),
dX_ / 1_g * square(1_cm));
throw std::runtime_error(
"CONEX and Corsika8 dX grammage binning are not the same!");
}
int const bin = int((bend + bstart) / 2);
if (pid == Code::Photon) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::Photon)] += weight;
} else if (pid == Code::Positron) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::Positron)] +=
weight;
} else if (pid == Code::Electron) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::Electron)] +=
weight;
} else if (pid == Code::MuPlus) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::MuPlus)] += weight;
} else if (pid == Code::MuMinus) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::MuMinus)] += weight;
} else if (is_hadron(pid)) {
profile_.at(bin)[static_cast<int>(number_profile::ProfileIndex::Hadron)] += weight;
}
if (is_charged(pid)) {
profile_[bin][static_cast<int>(number_profile::ProfileIndex::Charged)] += weight;
}
}
template <typename TOutput>
inline YAML::Node LongitudinalWriter<TOutput>::getConfig() const {
YAML::Node node;
node["type"] = "LongitudinalProfile";
node["units"]["grammage"] = "g/cm^2";
node["bin-size"] = dX_ / (1_g / square(1_cm));
node["nbins"] = nBins_;
return node;
}
template <typename TOutput>
inline YAML::Node LongitudinalWriter<TOutput>::getSummary() const {
YAML::Node summary;
return summary;
}
} // namespace corsika
/*
* (c) Copyright 2021 CORSIKA Project, corsika-project@lists.kit.edu
*
* This software is distributed under the terms of the GNU General Public
* Licence version 3 (GPL Version 3). See file LICENSE for a full version of
* the license.
*/
#pragma once
#include <corsika/output/BaseOutput.hpp>
#include <corsika/framework/core/ParticleProperties.hpp>
#include <corsika/framework/core/PhysicalUnits.hpp>
#include <corsika/media/ShowerAxis.hpp>
#include <corsika/modules/writers/WriterOff.hpp>
#include <corsika/modules/writers/LongitudinalProfileWriterParquet.hpp>
#include <vector>
#include <array>
/**
* @file LongitudinalWriter.hpp
*/
namespace corsika {
/**
* Local helper namespace to store number and names of particle number profile columns.
*/
namespace number_profile {
/**
* Definition of longitudinal profile columns.
*/
enum class ProfileIndex {
Charged,
Hadron,
Photon,
Electron,
Positron,
MuPlus,
MuMinus,
Entries
};
/**
* Number of columns (static).
*/
size_t constexpr NColumns = static_cast<size_t>(ProfileIndex::Entries);
/**
* Names of columns in output.
*/
static std::array<char const*, NColumns> constexpr ProfileIndexNames{
{"charged", "hadron", "photon", "electron", "positron", "muplus", "muminus"}};
/**
* Data type to store column data.
*/
typedef std::array<double, NColumns> ProfileData;
} // namespace number_profile
// clang-format-off
/**
* The LongitudinalWriter can be used to pool the particle counts of several
* longitudinal profile processes into one output file/stream.
*
* Typically several processes/modules can lead to particle counts along the shower axis
* in the shower. The LongitudianalWriter can be used in combination with the SubWriter
* class to collect all of them into a single output stream:
*
* \code {.cpp}
* # showerAxis must be a ShowerAxis object
* # the X binning can be specified.
* LongitudinalWriter profile{showerAxis, 10_g / square(1_cm), 200};
* # add to OutputManager:
* output.add("profile", profile);
* # add SubWriters, e.g. LongitudinalProfile, CONEX:
* LongitudinalProfile<SubWriter<decltype(profile)>> long{profile};
* CONEXhybrid<SubWriter<decltype(profile)>> conex{..., profile};
* ...
* \endcode
*
* The default output option is parquet format.
*
* @tparam TOutput
*/
// clang-format-on
template <typename TOutput = LongitudinalProfileWriterParquet<number_profile::NColumns>>
class LongitudinalWriter : public TOutput {
public:
/**
* Construct a new writer.
*/
LongitudinalWriter(ShowerAxis const& axis,
GrammageType dX = 10_g / square(1_cm), // profile binning
size_t const nBins = 200); // number of bins
void startOfLibrary(boost::filesystem::path const& directory) final override;
void startOfShower(unsigned int const showerId) final override;
void endOfShower(unsigned int const showerId) final override;
void endOfLibrary() final override;
/**
* Add continuous profile.
*/
template <typename TTrack>
void write(TTrack const& track, Code const pid, double const weight);
/**
* Add binned profile.
*/
void write(GrammageType const Xstart, GrammageType const Xend, Code const pid,
double const weight);
/**
* Return a summary.
*/
YAML::Node getSummary() const;
/**
* Return the configuration of this output.
*/
YAML::Node getConfig() const;
private:
ShowerAxis const& showerAxis_; ///< conversion between geometry and grammage
GrammageType dX_; ///< binning of profile.
size_t nBins_; ///< number of profile bins.
std::vector<number_profile::ProfileData> profile_; // longitudinal profile
};
} // namespace corsika
#include <corsika/detail/modules/writers/LongitudinalWriter.inl>
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