yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis 2.1.0
Writer.cc
Go to the documentation of this file.
1// -*- C++ -*-
2//
3// This file is part of YODA -- Yet more Objects for Data Analysis
4// Copyright (C) 2008-2025 The YODA collaboration (see AUTHORS for details)
5//
6#include "YODA/WriterYODA.h"
7#include "YODA/WriterFLAT.h"
9
10#ifdef HAVE_HDF5
11#include "YODA/WriterH5.h"
12#endif
13
14#ifdef HAVE_LIBZ
15#define _XOPEN_SOURCE 700
16#include "zstr/zstr.hpp"
17#endif
18
19#include <iostream>
20#include <locale>
21#include <typeinfo>
22#include <sstream>
23#include <memory>
24using namespace std;
25
26namespace YODA {
27
28
29 Writer& mkWriter(const string& name) {
30 // Determine the format from the string (a file or file extension)
31 const size_t lastdot = name.find_last_of(".");
32 string fmt = Utils::toLower(lastdot == string::npos ? name : name.substr(lastdot+1));
33 const bool compress = (fmt == "gz"s) || (fmt == "h5"s && enableH5compression);
34 //cout << "***" << compress << endl;
35 if (compress && fmt == "gz"s) {
36 #ifndef HAVE_LIBZ
37 throw UserError("YODA was compiled without zlib support: can't write " + name);
38 #endif
39 const size_t lastbutonedot = (lastdot == string::npos) ? string::npos : name.find_last_of(".", lastdot-1);
40 fmt = Utils::toLower(lastbutonedot == string::npos ? name : name.substr(lastbutonedot+1));
41 }
42 // Create the appropriate Writer
43 Writer* w = nullptr;
44 #ifdef HAVE_HDF5
45 if (Utils::startswith(fmt, "h5")) w = &WriterH5::create();
46 #endif
47 if (Utils::startswith(fmt, "yoda")) w = &WriterYODA::create();
48 else if (Utils::startswith(fmt, "dat" )) w = &WriterFLAT::create();
49 else if (Utils::startswith(fmt, "flat")) w = &WriterFLAT::create();
50 if (!w) throw UserError("Format cannot be identified from string '" + name + "'");
51 w->useCompression(compress);
52 return *w;
53 }
54
55
56 void Writer::write(const std::string& filename, const AnalysisObject& ao) {
57 std::vector<const AnalysisObject*> vec{&ao};
58 write(filename, vec);
59 }
60
61 // Canonical writer function using H5 file
62 #ifdef HAVE_HDF5
63 void Writer::write(YODA_H5::File& file, const std::vector<const AnalysisObject*>& aos) {
64 writeAOS(file, aos);
65 }
66 #endif
67
68 // Canonical writer function using stream, including compression handling
69 void Writer::write(ostream& stream, const vector<const AnalysisObject*>& aos, int precision) {
70 std::unique_ptr<std::ostream> zos;
71 std::ostream* os = &stream;
72
73 setPrecision(precision);
74
75 // Write numbers in the "C" locale
76 std::locale prev_locale = os->getloc();
77 os->imbue(std::locale::classic());
78
79 // Wrap the stream if needed
80 if (_compress) {
81 #ifdef HAVE_LIBZ
82 // Doesn't work to always create zstr wrapper: have to only create if compressing :-/
83 // zstr::ostream zstream(stream);
84 // ostream& os = _compress ? zstream : stream;
85 os = new zstr::ostream(stream);
86 zos.reset(os);
87 #else
88 throw UserError("YODA was compiled without zlib support: can't write to a compressed stream");
89 #endif
90 }
91
92 // Write the data components
94 writeHead(*os);
95 bool first = true;
96 for (const AnalysisObject* aoptr : aos) {
97 setAOPrecision( aoptr->annotation("WriterDoublePrecision", 0) );
98 if (!first) *os << "\n"; //< blank line between items
99 writeBody(*os, aoptr);
100 first = false;
101 }
102 writeFoot(*os);
103 *os << flush;
104
105 os->imbue(prev_locale);
106 }
107
108
109 void Writer::writeBody(ostream& stream, const AnalysisObject* ao) {
110 if (!ao) throw WriteError("Attempting to write a null AnalysisObject*");
111 writeBody(stream, *ao);
112 }
113
114 void Writer::writeBody(ostream& stream, const AnalysisObject& ao) {
115 try {
116 writeAO(stream, ao);
117 }
118 catch(...) {
119 ostringstream oss;
120 oss << "Unrecognised analysis object type " << ao.type() << " in Writer::write";
121 throw Exception(oss.str());
122 }
123 }
124
125
126}
AnalysisObject is the base class for histograms and scatters.
virtual std::string type() const
Get name of the analysis object type.
Generic unspecialised YODA runtime error.
Definition Exceptions.h:20
Error for problems introduced outside YODA, to put it nicely.
Definition Exceptions.h:86
Error for file writing errors.
Definition Exceptions.h:79
static Writer & create()
Singleton creation function.
Definition WriterFLAT.cc:17
static Writer & create()
Singleton creation function.
Definition WriterH5.cc:17
static Writer & create()
Singleton creation function.
Definition WriterYODA.cc:16
Pure virtual base class for various output writers.
Definition Writer.h:31
virtual void writeHead(std::ostream &)
Write any opening boilerplate required by the format to stream.
Definition Writer.h:199
virtual void writeFoot(std::ostream &stream)
Write any closing boilerplate required by the format to stream.
Definition Writer.h:214
void useCompression(const bool compress=true)
Use libz compression?
Definition Writer.h:188
virtual void writeAO(std::ostream &stream, const AnalysisObject &ao)=0
virtual void writeBody(std::ostream &stream, const AnalysisObject *ao)
Write the body elements corresponding to AnalysisObject ao to stream.
Definition Writer.cc:109
void write(const std::string &filename, const AnalysisObject &ao)
Write out object ao to file filename.
Definition Writer.cc:56
virtual void writeAOS(YODA_H5::File &file, const vector< const AnalysisObject * > &aos)=0
void setAOPrecision(const bool needsDP=false)
Set precision of numerical quantities for current AO in this writer's output.
Definition Writer.h:181
void setPrecision(int precision)
Set precision of numerical quantities in this writer's output.
Definition Writer.h:176
Anonymous namespace to limit visibility.
static bool enableH5compression
Definition Writer.h:28
Writer & mkWriter(const std::string &format_name)
Factory function to make a writer object by format name or a filename.
Definition Writer.cc:29