template<typename Converter, std::enable_if_t< std::is_same_v< Converter, ToASCII >||std::is_same_v< Converter, ToBinary >, bool > = true>
class smash::OutputFormatter< Converter, >
A general-purpose formatter for output, supporting both ASCII and binary formats.
This class allows the output of particle data in a flexible and configurable manner, either in human-readable ASCII format or compact binary format. It uses a template parameter Converter to determine the desired output format, which must conform to the interface of either ToASCII or ToBinary.
New quantities can be added for output by:
- Adding their corresponding getter to the constructor, which extracts the value from a
ParticleData instance.
- Adding the proper key-value pair to the
units_ map, specifying the unit of the quantity.
- Template Parameters
-
| Converter | The desired output format. At the moment it must be either ToASCII or ToBinary. |
Definition at line 194 of file outputformatter.h.
|
| | OutputFormatter (const std::vector< std::string > &in_quantities) |
| | Creates the formatter. More...
|
| |
| std::size_t | compute_single_size (const ParticleData &sample) const |
| | Computes and returns the total size of the formatted representation of a single particle using all registered getters. More...
|
| |
| Converter::type | single_particle_data (const ParticleData &p) const |
| | Produces a line of data representing a single particle suitable for writing to an output file. More...
|
| |
| template<class Range , std::enable_if_t< std::is_same_v< Range, Particles >||std::is_same_v< Range, ParticleList >, bool > = true> |
| Converter::type | particles_data_chunk (const Range &particles) const |
| | Builds multiple particle lines for a range of particles by appending the Converter::type representation of each particle into a single buffer. More...
|
| |
| Converter::type | quantities_line () const |
| | Produces the line with quantities for the header of the output file. More...
|
| |
| Converter::type | unit_line () const |
| | Produces the line with units for the header of the output file. More...
|
| |
|
| Converter | converter_ {} |
| | Member to convert data into the correct output format. More...
|
| |
| std::vector< std::string > | quantities_ {} |
| | List of quantities to be written. More...
|
| |
| std::vector< std::function< typename Converter::type(const ParticleData &)> > | getters_ {} |
| | List of getters to extract output data from the ParticleData object. More...
|
| |
| const std::map< std::string, std::string > | units_ |
| | Map with known quantities and corresponding units. More...
|
| |
| const std::vector< std::pair< std::string, std::string > > | aliases_ |
| | Map with known quantities and corresponding units. More...
|
| |
template<typename Converter , std::enable_if_t< std::is_same_v< Converter, ToASCII >||std::is_same_v< Converter, ToBinary >, bool > = true>
Creates the formatter.
This reduces the number of literal strings flying around in the codebase, and since this is called only once per output file, in the beginning of the run, there is almost no efficiency lost compared to having fixed strings.
- Parameters
-
| [in] | in_quantities | list of quantities to be output. |
- Exceptions
-
| std::invalid_argument | if the list of quantities is empty |
| std::invalid_argument | if unknown quantities exist in the list |
| std::invalid_argument | if incompatible quantities exist in the list |
| std::invalid_argument | if there are repeated quantities |
Definition at line 209 of file outputformatter.h.
213 if (quantity ==
"t") {
214 getters_.push_back([
this](
const ParticleData& in) {
215 return this->
converter_.as_double(in.position()[0]);
217 }
else if (quantity ==
"x") {
218 getters_.push_back([
this](
const ParticleData& in) {
219 return this->
converter_.as_double(in.position()[1]);
221 }
else if (quantity ==
"y") {
222 getters_.push_back([
this](
const ParticleData& in) {
223 return this->
converter_.as_double(in.position()[2]);
225 }
else if (quantity ==
"z") {
226 getters_.push_back([
this](
const ParticleData& in) {
227 return this->
converter_.as_double(in.position()[3]);
229 }
else if (quantity ==
"mass") {
230 getters_.push_back([
this](
const ParticleData& in) {
231 return this->
converter_.as_double(in.effective_mass());
233 }
else if (quantity ==
"p0") {
234 getters_.push_back([
this](
const ParticleData& in) {
235 return this->
converter_.as_precise_double(in.momentum()[0]);
237 }
else if (quantity ==
"px") {
238 getters_.push_back([
this](
const ParticleData& in) {
239 return this->
converter_.as_precise_double(in.momentum()[1]);
241 }
else if (quantity ==
"py") {
242 getters_.push_back([
this](
const ParticleData& in) {
243 return this->
converter_.as_precise_double(in.momentum()[2]);
245 }
else if (quantity ==
"pz") {
246 getters_.push_back([
this](
const ParticleData& in) {
247 return this->
converter_.as_precise_double(in.momentum()[3]);
249 }
else if (quantity ==
"pdg") {
250 getters_.push_back([
this](
const ParticleData& in) {
251 return this->
converter_.as_integer(in.pdgcode().get_decimal());
253 }
else if (quantity ==
"ID" || quantity ==
"id") {
254 getters_.push_back([
this](
const ParticleData& in) {
257 }
else if (quantity ==
"charge") {
258 getters_.push_back([
this](
const ParticleData& in) {
259 return this->
converter_.as_integer(in.type().charge());
261 }
else if (quantity ==
"ncoll") {
262 getters_.push_back([
this](
const ParticleData& in) {
264 in.get_history().collisions_per_particle);
266 }
else if (quantity ==
"form_time") {
267 getters_.push_back([
this](
const ParticleData& in) {
268 return this->
converter_.as_double(in.formation_time());
270 }
else if (quantity ==
"xsecfac") {
271 getters_.push_back([
this](
const ParticleData& in) {
272 return this->
converter_.as_double(in.xsec_scaling_factor());
274 }
else if (quantity ==
"proc_id_origin") {
275 getters_.push_back([
this](
const ParticleData& in) {
276 return this->
converter_.as_integer(in.get_history().id_process);
278 }
else if (quantity ==
"proc_type_origin") {
279 getters_.push_back([
this](
const ParticleData& in) {
281 static_cast<int>(in.get_history().process_type));
283 }
else if (quantity ==
"time_last_coll") {
284 getters_.push_back([
this](
const ParticleData& in) {
286 in.get_history().time_last_collision);
288 }
else if (quantity ==
"pdg_mother1") {
289 getters_.push_back([
this](
const ParticleData& in) {
290 return this->
converter_.as_integer(in.get_history().p1.get_decimal());
292 }
else if (quantity ==
"pdg_mother2") {
293 getters_.push_back([
this](
const ParticleData& in) {
294 return this->
converter_.as_integer(in.get_history().p2.get_decimal());
296 }
else if (quantity ==
"baryon_number") {
297 getters_.push_back([
this](
const ParticleData& in) {
298 return this->
converter_.as_integer(in.pdgcode().baryon_number());
300 }
else if (quantity ==
"strangeness") {
301 getters_.push_back([
this](
const ParticleData& in) {
302 return this->
converter_.as_integer(in.pdgcode().strangeness());
304 }
else if (quantity ==
"spin0") {
305 getters_.push_back([
this](
const ParticleData& in) {
306 return this->
converter_.as_double(in.spin_vector()[0]);
308 }
else if (quantity ==
"spinx") {
309 getters_.push_back([
this](
const ParticleData& in) {
310 return this->
converter_.as_double(in.spin_vector()[1]);
312 }
else if (quantity ==
"spiny") {
313 getters_.push_back([
this](
const ParticleData& in) {
314 return this->
converter_.as_double(in.spin_vector()[2]);
316 }
else if (quantity ==
"spinz") {
317 getters_.push_back([
this](
const ParticleData& in) {
318 return this->
converter_.as_double(in.spin_vector()[3]);
320 }
else if (quantity ==
"0") {
321 getters_.push_back([
this]([[maybe_unused]]
const ParticleData& in) {
324 }
else if (quantity ==
"tau") {
325 getters_.push_back([
this](
const ParticleData& in) {
326 return this->
converter_.as_double(in.hyperbolic_time());
328 }
else if (quantity ==
"eta" || quantity ==
"eta_s") {
329 getters_.push_back([
this](
const ParticleData& in) {
330 return this->
converter_.as_double(in.spatial_rapidity());
332 }
else if (quantity ==
"mt") {
333 getters_.push_back([
this](
const ParticleData& in) {
334 return this->
converter_.as_double(in.transverse_mass());
336 }
else if (quantity ==
"Rap" || quantity ==
"y_rap") {
338 getters_.push_back([
this](
const ParticleData& in) {
339 return this->
converter_.as_double(in.rapidity());
341 }
else if (quantity ==
"perturbative_weight") {
342 getters_.push_back([
this](
const ParticleData& in) {
343 return this->
converter_.as_double(in.perturbative_weight());
template<typename Converter , std::enable_if_t< std::is_same_v< Converter, ToASCII >||std::is_same_v< Converter, ToBinary >, bool > = true>
Computes and returns the total size of the formatted representation of a single particle using all registered getters.
The total size consists of:
- the sum of the sizes of all field strings (from each getter),
- (n - 1) separator characters if a separator is defined, since separators appear only between fields, not after the last one,
- one end-of-line character if an end-of-line marker is defined.
- Parameters
-
| [in] | sample | A representative particle used to compute the size. |
- Returns
- Total size of the formatted representation of one particle.
Definition at line 362 of file outputformatter.h.
367 std::size_t size = 0;
368 for (
const auto& getter :
getters_) {
369 const typename Converter::type tmp = getter(sample);
373 if (Converter::separator.has_value()) {
377 if (Converter::end_of_line.has_value()) {
template<typename Converter , std::enable_if_t< std::is_same_v< Converter, ToASCII >||std::is_same_v< Converter, ToBinary >, bool > = true>
template<class Range , std::enable_if_t< std::is_same_v< Range, Particles >||std::is_same_v< Range, ParticleList >, bool > = true>
Builds multiple particle lines for a range of particles by appending the Converter::type representation of each particle into a single buffer.
The resulting buffer reflects exactly what the Converter defines( per-record separators and end-of-line markers, if any). No additional formatting is applied beyond what the Converter specifies.
- Template Parameters
-
| Range | Container type — constrained to Particles or ParticleList. |
- Parameters
-
| [in] | particles | Container of particles whose data should be formatted and added to the buffer |
- Returns
- Converter::type A buffer containing the concatenated representation of all particles in the block.
- Note
- Capacity is reserved using a size estimate based on the first element.
- See also
- append_to_buffer
- Returns
- Converter::type
Definition at line 424 of file outputformatter.h.
425 typename Converter::type chunk{};
426 if (particles.size() == 0)
431 for (
const ParticleData&
p : particles) {
template<typename Converter , std::enable_if_t< std::is_same_v< Converter, ToASCII >||std::is_same_v< Converter, ToBinary >, bool > = true>
Produces the line with quantities for the header of the output file.
Appends each quantity name to the output buffer, separating them by the separator character if it is defined in the Converter. End of line character is added last if defined.
- Returns
- Converter::type
Definition at line 446 of file outputformatter.h.
447 typename Converter::type out{};
453 if constexpr (Converter::separator) {
455 out.push_back(*Converter::separator);
458 typename Converter::type name =
converter_.as_string(string_name);
459 out.insert(out.end(), name.begin(), name.end());
461 if constexpr (Converter::end_of_line) {
462 out.push_back(*Converter::end_of_line);
template<typename Converter , std::enable_if_t< std::is_same_v< Converter, ToASCII >||std::is_same_v< Converter, ToBinary >, bool > = true>
Produces the line with units for the header of the output file.
Looks up each quantity’s unit in the units_ map and appends it to the output buffer. Each unit is separated by the separator character if defined. End of line character is added last if defined.
- Returns
- Converter::type
Definition at line 476 of file outputformatter.h.
477 typename Converter::type out{};
483 if constexpr (Converter::separator) {
485 out.push_back(*Converter::separator);
489 out.insert(out.end(), unit.begin(), unit.end());
491 if constexpr (Converter::end_of_line) {
492 out.push_back(*Converter::end_of_line);
template<typename Converter , std::enable_if_t< std::is_same_v< Converter, ToASCII >||std::is_same_v< Converter, ToBinary >, bool > = true>
Appends the Converter::type representation of a single particle to the provided buffer.
The buffer is used exactly as provided by the caller; no assumptions or modifications are made to its initial state or capacity.
- Parameters
-
| [in] | particle | Particle whose information is to be appended. |
| [out] | buffer | Destination buffer to which the converted data is appended. |
Definition at line 628 of file outputformatter.h.
630 for (std::size_t i = 0; i <
getters_.size(); ++i) {
631 if constexpr (Converter::separator) {
633 buffer.push_back(*Converter::separator);
636 buffer.insert(buffer.end(), std::make_move_iterator(data.begin()),
637 std::make_move_iterator(data.end()));
639 if constexpr (Converter::end_of_line) {
640 buffer.push_back(*Converter::end_of_line);
template<typename Converter , std::enable_if_t< std::is_same_v< Converter, ToASCII >||std::is_same_v< Converter, ToBinary >, bool > = true>
Initial value:= {
{"ID", "id"}, {"eta_s", "eta"}, {"y_rap", "Rap"}}
Map with known quantities and corresponding units.
Definition at line 571 of file outputformatter.h.