ComPWA
Common Partial-Wave-Analysis Framework
AsciiDataIO.cpp
Go to the documentation of this file.
1 // This file is part of the ComPWA framework, check
2 // Copyright (c) 2013 The ComPWA Team.
3 // https://github.com/ComPWA/ComPWA/license.txt for details.
4 
5 #include <fstream>
6 #include <sstream>
7 #include <utility>
8 
9 #include "Core/Exceptions.hpp"
10 #include "Core/Logging.hpp"
13 
14 namespace ComPWA {
15 namespace Data {
16 namespace Ascii {
17 
18 EventCollection readData(const std::string &InputFilePath,
19  long long NumberEventsToRead) {
21  std::ifstream InputStream(InputFilePath);
22  if (!InputStream.good())
23  throw ComPWA::CorruptFile("Cannot open file " + InputFilePath);
24 
26  AsciiHeader Header;
27  Header.importYAML(InputStream);
28  auto Position = InputStream.tellg();
29 
31  if (!Header.getFinalStatePIDs().size())
32  throw ComPWA::BadConfig("Input data file " + InputFilePath +
33  " misses a header with PIDs");
34 
36  bool HasWeights = false;
37  double weight, px, py, pz, e;
38  std::string Line;
39  while (std::getline(InputStream, Line)) {
40  if (std::all_of(Line.begin(), Line.end(),
41  [](char c) { return std::isspace(c); }))
42  continue;
43  std::stringstream StringStream(Line);
44  if ((StringStream >> weight) && !(StringStream >> py))
45  HasWeights = true;
46  break;
47  }
48  InputStream.seekg(Position);
49 
51  size_t NumberOfParticles = 0;
52  if (HasWeights) {
53  double weight, px, py, pz, e;
54  InputStream >> weight;
55  std::string Line;
56  while (std::getline(InputStream, Line)) {
57  if (std::all_of(Line.begin(), Line.end(),
58  [](char c) { return std::isspace(c); }))
59  continue;
60  std::stringstream StringStream(Line);
61  if (!(StringStream >> e >> px >> py >> pz))
62  break;
63  ++NumberOfParticles;
64  }
65  InputStream.seekg(Position);
66  if (Header.getFinalStatePIDs().size() != NumberOfParticles)
67  throw ComPWA::BadConfig("Number of particles in header is not same as "
68  "number of tuple lines in file \"" +
69  InputFilePath + "\"");
70  } else {
71  NumberOfParticles = Header.getFinalStatePIDs().size();
72  }
73 
75  bool IsEnergyFirst = false;
76  if (HasWeights)
77  InputStream >> weight;
78  InputStream >> e >> px >> py >> pz;
79  if (e * e - px * px - py * py - pz * pz > 0.)
80  IsEnergyFirst = true;
81  InputStream.seekg(Position);
82  if (Header.isEnergyFirst() != IsEnergyFirst)
83  throw ComPWA::BadConfig(
84  "Energy-momentum order is not same as stated in header for file \"" +
85  InputFilePath + "\"");
86 
88  EventCollection ImportedData{Header.getFinalStatePIDs()};
89 
90  weight = 1.;
91  while (InputStream.good()) {
92  if (HasWeights)
93  InputStream >> weight;
94  std::vector<FourMomentum> FourVectors;
95  FourVectors.reserve(NumberOfParticles);
96  for (size_t i = 0; i < NumberOfParticles; ++i) {
97  if (IsEnergyFirst)
98  InputStream >> e >> px >> py >> pz;
99  else
100  InputStream >> px >> py >> pz >> e;
101  FourVectors.push_back(ComPWA::FourMomentum(px, py, pz, e));
102  }
103  if (!InputStream.fail())
104  ImportedData.Events.push_back(Event{FourVectors, weight});
105  if (NumberEventsToRead > 0 &&
106  ImportedData.Events.size() == (std::size_t)NumberEventsToRead)
107  break;
108  }
109  InputStream.close();
110 
111  return ImportedData;
112 }
113 
114 void writeData(const EventCollection &DataSample,
115  const std::string &OutputFilePath, bool OverwriteFile) {
116  if (!DataSample.Events.size())
117  throw ComPWA::BadParameter("Cannot write empty event vector");
118  ComPWA::Logging log("warning");
119 
121  auto OpenMode = std::ofstream::out;
122  if (!OverwriteFile) {
123  std::ifstream InputStream(OutputFilePath);
124  auto HeaderContent = AsciiHeader::extractHeaderContent(InputStream);
125  if (HeaderContent != "") { // if there is a header, check consistency
126  AsciiHeader HeaderIn;
127  HeaderIn.importYAML(HeaderContent);
128  AsciiHeader HeaderOut(DataSample.Pids);
129  if (HeaderOut.getFinalStatePIDs() != HeaderIn.getFinalStatePIDs())
130  throw ComPWA::BadConfig("Cannot append to file \"" + OutputFilePath +
131  "\", because its PIDs are not the same as the "
132  "event list you try to write");
133  if (HeaderOut.getUnit() != HeaderIn.getUnit())
134  throw ComPWA::BadConfig("Cannot append to file \"" + OutputFilePath +
135  "\", because there is a mismatch in units");
136  if (HeaderOut.isEnergyFirst() != HeaderIn.isEnergyFirst())
137  throw ComPWA::BadConfig(
138  "Cannot append to file \"" + OutputFilePath +
139  "\", because the momentum-energy order is not the same");
140  }
141  OpenMode |= std::ofstream::app;
142  }
143 
145  std::ofstream OutputStream;
146  OutputStream.open(OutputFilePath, OpenMode);
147 
149  if (OverwriteFile) {
150  AsciiHeader HeaderOut(DataSample.Pids);
151  HeaderOut.dumpToYAML(OutputStream);
152  OutputStream << std::endl;
153  }
154 
156  for (const auto &Event : DataSample.Events) {
157  OutputStream << Event.Weight << std::endl;
158  for (const auto &FourMom : Event.FourMomenta) {
159  OutputStream << FourMom.px() << "\t";
160  OutputStream << FourMom.py() << "\t";
161  OutputStream << FourMom.pz() << "\t";
162  OutputStream << FourMom.e() << std::endl;
163  }
164  }
165 }
166 
167 } // namespace Ascii
168 } // namespace Data
169 } // namespace ComPWA
ComPWA four momentum class.
Parameter not existing.
Definition: Exceptions.hpp:62
void importYAML(const std::string &HeaderContent)
Set data members by reading a YAML-like string (including newlines).
Input data file is corrupt or incomplete.
Definition: Exceptions.hpp:86
Representation of data contained in an ASCII header.
ComPWA exceptions.
void dumpToYAML(std::ostream &os) const
Serialise data members to YAML format, embedded in XML header tags.
EventCollection readData(const std::string &InputFilePath, long long NumberEventsToRead)
Read momentum tuples from an ASCII file.
Definition: AsciiDataIO.cpp:18
std::vector< Event > Events
Definition: Event.hpp:34
const std::string & getUnit() const
Config is not complete.
Definition: Exceptions.hpp:50
const std::vector< int > getFinalStatePIDs() const
double Weight
Definition: Event.hpp:22
std::vector< FourMomentum > FourMomenta
Definition: Event.hpp:21
static std::string extractHeaderContent(std::istream &InputStream)
Extract the part that is between the XML/HTML tags <header>...</header> including newlines...
void writeData(const EventCollection &DataSample, const std::string &OutputFilePath, bool OverwriteFile)
Data structure containing all kinematic information of a physics event.
Definition: Event.hpp:20
std::vector< pid > Pids
Definition: Event.hpp:33
Logging class provides an interface for logging all over the framework.
Definition: Logging.hpp:19