1 #ifndef STAN__IO__STAN_CSV_READER_HPP
2 #define STAN__IO__STAN_CSV_READER_HPP
8 #include <boost/algorithm/string.hpp>
9 #include <boost/lexical_cast.hpp>
62 Eigen::Matrix<std::string, Eigen::Dynamic, 1>
header;
85 while (in.peek() ==
'#') {
86 std::getline(in, line);
89 ss.seekg(std::ios_base::beg);
100 std::getline(ss, lhs);
102 size_t equal = lhs.find(
"=");
103 if (equal != std::string::npos) {
104 name = lhs.substr(0, equal);
106 value = lhs.substr(equal + 2, lhs.size());
107 boost::replace_first(value,
" (Default)",
"");
112 if (name.compare(
"stan_version_major") == 0) {
114 }
else if (name.compare(
"stan_version_minor") == 0) {
116 }
else if (name.compare(
"stan_version_patch") == 0) {
118 }
else if (name.compare(
"model") == 0) {
119 metadata.
model = value;
120 }
else if (name.compare(
"num_samples") == 0) {
121 metadata.
num_samples = boost::lexical_cast<
int>(value);
122 }
else if (name.compare(
"num_warmup") == 0) {
123 metadata.
num_warmup = boost::lexical_cast<
int>(value);
124 }
else if (name.compare(
"save_warmup") == 0) {
125 metadata.
save_warmup = boost::lexical_cast<
bool>(value);
126 }
else if (name.compare(
"thin") == 0) {
127 metadata.
thin = boost::lexical_cast<
int>(value);
128 }
else if (name.compare(
"chain_id") == 0) {
129 metadata.
chain_id = boost::lexical_cast<
int>(value);
130 }
else if (name.compare(
"data") == 0) {
131 metadata.
data = value;
132 }
else if (name.compare(
"init") == 0) {
133 metadata.
init = value;
134 boost::trim(metadata.
init);
135 }
else if (name.compare(
"seed") == 0) {
136 metadata.
seed = boost::lexical_cast<
unsigned int>(value);
138 }
else if (name.compare(
"append_samples") == 0) {
140 }
else if (name.compare(
"algorithm") == 0) {
142 }
else if (name.compare(
"engine") == 0) {
148 if (ss.good() ==
true)
155 static bool read_header(std::istream& in, Eigen::Matrix<std::string, Eigen::Dynamic, 1>& header) {
159 if (in.peek() !=
'l')
162 std::getline(in, line);
163 std::stringstream ss(line);
165 header.resize(std::count(line.begin(), line.end(),
',') + 1);
169 std::getline(ss, token,
',');
172 int pos = token.find(
'.');
174 token.replace(pos, 1,
"[");
175 std::replace(token.begin(), token.end(),
'.',
',');
178 header(idx++) = token;
185 std::stringstream ss;
189 if (in.peek() !=
'#' || in.good() ==
false)
192 while (in.peek() ==
'#') {
193 std::getline(in, line);
194 ss << line << std::endl;
197 ss.seekg(std::ios_base::beg);
202 std::getline(ss, line);
205 std::getline(ss, line,
'=');
210 std::getline(ss, line);
211 std::getline(ss, line);
212 std::getline(ss, line);
214 int rows = lines - 3;
215 int cols = std::count(line.begin(), line.end(),
',') + 1;
216 adaptation.
metric.resize(rows, cols);
220 std::stringstream line_ss;
226 std::getline(line_ss, token,
',');
228 adaptation.
metric(
row,
col) = boost::lexical_cast<
double>(token);
231 std::getline(ss, line);
244 std::stringstream ss;
250 if (in.peek() ==
'#' || in.good() ==
false)
255 bool comment_line = (in.peek() ==
'#');
256 bool empty_line = (in.peek() ==
'\n');
258 std::getline(in, line);
260 if (empty_line)
continue;
261 if (!line.length())
break;
265 if (line.find(
"(Warm-up)") != std::string::npos) {
267 int right = line.find(
" seconds");
268 timing.
warmup += boost::lexical_cast<
double>(line.substr(left, right - left));
269 }
else if (line.find(
"(Sampling)") != std::string::npos) {
271 int right = line.find(
" seconds");
272 timing.
sampling += boost::lexical_cast<
double>(line.substr(left, right - left));
280 int current_cols = std::count(line.begin(), line.end(),
',') + 1;
283 }
else if (cols != current_cols) {
284 std::cout <<
"Error: expected " << cols <<
" columns, but found "
285 << current_cols <<
" instead for row " << rows + 1 << std::endl;
296 ss.seekg(std::ios_base::beg);
299 samples.resize(rows, cols);
301 std::getline(ss, line);
302 std::stringstream ls(line);
304 std::getline(ls, line,
',');
307 samples(
row,
col) = boost::lexical_cast<
double>(line);
324 std::cout <<
"Warning: non-fatal error reading metadata" << std::endl;
328 std::cout <<
"Error: error reading header" << std::endl;
329 throw std::invalid_argument(
"Error with header of input file in parse");
333 std::cout <<
"Warning: non-fatal error reading adapation data" << std::endl;
340 std::cout <<
"Warning: non-fatal error reading samples" << std::endl;
static bool read_samples(std::istream &in, Eigen::MatrixXd &samples, stan_csv_timing &timing)
Eigen::Matrix< T, 1, Eigen::Dynamic > row(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &m, size_t i)
Return the specified row of the specified matrix, using start-at-1 indexing.
static bool read_adaptation(std::istream &in, stan_csv_adaptation &adaptation)
Eigen::Matrix< T, Eigen::Dynamic, 1 > col(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &m, size_t j)
Return the specified column of the specified matrix using start-at-1 indexing.
static bool read_header(std::istream &in, Eigen::Matrix< std::string, Eigen::Dynamic, 1 > &header)
stan_csv_adaptation adaptation
size_t rows(const Eigen::Matrix< T, R, C > &m)
size_t cols(const Eigen::Matrix< T, R, C > &m)
static bool read_metadata(std::istream &in, stan_csv_metadata &metadata)
Reads from a Stan output csv file.
static stan_csv parse(std::istream &in)
Parses the file.
stan_csv_metadata metadata
Eigen::Matrix< std::string, Eigen::Dynamic, 1 > header