yoda is hosted by Hepforge, IPPP Durham
YODA - Yet more Objects for Data Analysis  1.7.2
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-2017 The YODA collaboration (see AUTHORS for details)
5 //
6 #include "YODA/Writer.h"
7 #include "YODA/WriterYODA.h"
8 #include "YODA/WriterAIDA.h"
9 #include "YODA/WriterFLAT.h"
11 
12 #ifdef HAVE_LIBZ
13 #define _XOPEN_SOURCE 700
14 #include "zstr/zstr.hpp"
15 #endif
16 
17 #include <iostream>
18 #include <typeinfo>
19 #include <sstream>
20 using namespace std;
21 
22 namespace YODA {
23 
24 
25  Writer& mkWriter(const string& name) {
26  // Determine the format from the string (a file or file extension)
27  const size_t lastdot = name.find_last_of(".");
28  string fmt = Utils::toLower(lastdot == string::npos ? name : name.substr(lastdot+1));
29  const bool compress = (fmt == "gz");
30  //cout << "***" << compress << endl;
31  if (compress) {
32  #ifndef HAVE_LIBZ
33  throw UserError("YODA was compiled without zlib support: can't write " + name);
34  #endif
35  const size_t lastbutonedot = (lastdot == string::npos) ? string::npos : name.find_last_of(".", lastdot-1);
36  fmt = Utils::toLower(lastbutonedot == string::npos ? name : name.substr(lastbutonedot+1));
37  }
38  // Create the appropriate Writer
39  Writer* w = nullptr;
40  if (Utils::startswith(fmt, "yoda")) w = &WriterYODA::create();
41  if (Utils::startswith(fmt, "aida")) w = &WriterAIDA::create();
42  if (Utils::startswith(fmt, "dat" )) w = &WriterFLAT::create();
43  if (Utils::startswith(fmt, "flat")) w = &WriterFLAT::create();
44  if (!w) throw UserError("Format cannot be identified from string '" + name + "'");
45  w->useCompression(compress);
46  return *w;
47  }
48 
49 
50  void Writer::write(const std::string& filename, const AnalysisObject& ao) {
51  std::vector<const AnalysisObject*> vec{&ao};
52  write(filename, vec);
53  }
54 
55  // Canonical writer function, including compression handling
56  void Writer::write(ostream& stream, const vector<const AnalysisObject*>& aos) {
57  std::unique_ptr<std::ostream> zos;
58  std::ostream* os = &stream;
59 
60  // Wrap the stream if needed
61  if (_compress) {
62  #ifdef HAVE_LIBZ
63  // Doesn't work to always create zstr wrapper: have to only create if compressing :-/
64  // zstr::ostream zstream(stream);
65  // ostream& os = _compress ? zstream : stream;
66  os = new zstr::ostream(stream);
67  zos.reset(os);
68  #else
69  throw UserError("YODA was compiled without zlib support: can't write to a compressed stream");
70  #endif
71  }
72 
73  // Write the data components
75  writeHead(*os);
76  bool first = true;
77  for (const AnalysisObject* aoptr : aos) {
78  try {
79  if (!first) *os << "\n"; //< blank line between items
80  writeBody(*os, aoptr);
81  first = false;
82  } catch (const LowStatsError& ex) {
84  std::cerr << "LowStatsError in writing AnalysisObject " << aoptr->title() << ":\n" << ex.what() << "\n";
85  }
86  }
87  writeFoot(*os);
88  *os << flush;
89  }
90 
91 
92  void Writer::writeBody(ostream& stream, const AnalysisObject* ao) {
93  if (!ao) throw WriteError("Attempting to write a null AnalysisObject*");
94  writeBody(stream, *ao);
95  }
96 
97  void Writer::writeBody(ostream& stream, const AnalysisObject& ao) {
98  const string aotype = ao.type();
99  if (aotype == "Counter") {
100  writeCounter(stream, dynamic_cast<const Counter&>(ao));
101  } else if (aotype == "Histo1D") {
102  writeHisto1D(stream, dynamic_cast<const Histo1D&>(ao));
103  } else if (aotype == "Histo2D") {
104  writeHisto2D(stream, dynamic_cast<const Histo2D&>(ao));
105  } else if (aotype == "Profile1D") {
106  writeProfile1D(stream, dynamic_cast<const Profile1D&>(ao));
107  } else if (aotype == "Profile2D") {
108  writeProfile2D(stream, dynamic_cast<const Profile2D&>(ao));
109  } else if (aotype == "Scatter1D") {
110  writeScatter1D(stream, dynamic_cast<const Scatter1D&>(ao));
111  } else if (aotype == "Scatter2D") {
112  writeScatter2D(stream, dynamic_cast<const Scatter2D&>(ao));
113  } else if (aotype == "Scatter3D") {
114  writeScatter3D(stream, dynamic_cast<const Scatter3D&>(ao));
115  } else if (aotype[0] == '_') {
116  // Skip writing AO types with underscore prefixes (needed e.g. for Rivet wrappers)
117  // maybe write a comment line in the output
118  } else {
119  ostringstream oss;
120  oss << "Unrecognised analysis object type " << aotype << " in Writer::write";
121  throw Exception(oss.str());
122  }
123  }
124 
125 
126 }
void write(const std::string &filename, const AnalysisObject &ao)
Write out object ao to file filename.
Definition: IO.h:19
Generic unspecialised YODA runtime error.
Definition: Exceptions.h:20
Error for file writing errors.
Definition: Exceptions.h:93
STL namespace.
Error for problems introduced outside YODA, to put it nicely.
Definition: Exceptions.h:100
Errors relating to insufficient (effective) statistics.
Definition: Exceptions.h:72
Pure virtual base class for various output writers.
Definition: Writer.h:28
AnalysisObject is the base class for histograms and scatters.
virtual std::string type() const
Get name of the analysis object type.
Writer & mkWriter(const std::string &format_name)
Factory function to make a writer object by format name or a filename.
Definition: Writer.cc:25