forked from BoostGSoC18/astronomy
-
Notifications
You must be signed in to change notification settings - Fork 16
/
ascii_table.hpp
284 lines (243 loc) · 10.2 KB
/
ascii_table.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
/*=============================================================================
Copyright 2019 Sarthak Singhal <singhalsarthak2007@gmail.com>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file License.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
#ifndef BOOST_ASTRONOMY_IO_ASCII_TABLE_HPP
#define BOOST_ASTRONOMY_IO_ASCII_TABLE_HPP
#include <valarray>
#include <fstream>
#include <cstddef>
#include <algorithm>
#include <iterator>
#include <cstdint>
#include <string>
#include <cmath>
#include <numeric>
#include <boost/astronomy/io/column.hpp>
#include <boost/astronomy/io/column_data.hpp>
#include <boost/astronomy/io/table_extension.hpp>
#include <boost/endian/conversion.hpp>
#include <boost/cstdfloat.hpp>
/**
* @file ascii_table.hpp
* @author Sarthak Singhal
* @details This file contains definition for ascii_table structure
*/
namespace boost { namespace astronomy { namespace io {
/**
* @brief Stores the header information and data of ASCII_Table extension HDU
* @details This class provides a set of methods for creating,querying, and manipulation of ASCII_table extension HDU
* For more information on Ascii_Table extension visit
* <A href="http://archive.stsci.edu/fits/users_guide/node37.html#SECTION00540000000000000000">ASCII_TABLE</A>
* @author Sarthak Singhal
*/
struct ascii_table : public table_extension
{
public:
/**
* @brief Creates a standalone ascii_table object
*/
ascii_table() {}
/**
/**
* @brief Constructs an ascii_table object from the given filestream
* @details This constructor constructs an ASCII_table object by reading the
* header information,data from the filestream and populates the field
* information that can be used for easy access to table data
* @param[in,out] file filestream set to open mode for reading
* @note After the reading the file pointer/cursor will be set to the end of logical HDU unit
*/
ascii_table(std::fstream &file) : table_extension(file)
{
set_ascii_table_info(file);
set_unit_end(file);
}
/**
* @brief Constructs an ascii_table object from the given filestream and hdu object
* @details Constructs an ascii_table object by reading the data from filestream
* and header information from hdu object passed as an argument
* @param[in,out] file filestream set to open mode for reading
* @param[in] other hdu object containing the header information of the current extension HDU
* @note After the reading the file pointer/cursor will be set to the end of logical HDU unit
*/
ascii_table(std::fstream &file, hdu const& other) : table_extension(other)
{
set_ascii_table_info(file);
set_unit_end(file);
}
/**
* @brief Constructs an ascii_table object from the given position in filestream
* @details Constructs an ascii_table object by reading the HDU information from the
* given filestream, starting at pos
* @param[in,out] file filestream set to open mode for reading
* @param[in] pos File Pointer/cursor position from where the header information is to be read
* @note After the reading the file pointer/cursor will be set to the end of logical HDU unit
*/
ascii_table(std::fstream &file, std::streampos pos) : table_extension(file, pos)
{
set_ascii_table_info(file);
set_unit_end(file);
}
/**
* @brief Populates the metadata information for all fields of ASCII_Table extension
* @details This method populates the metadata information for all fields in a table
* for easy access to the data of ASCII table extention extension
*/
void populate_column_data()
{
for (std::size_t i = 0; i < this->tfields_; i++)
{
col_metadata_[i].index(i + 1);
col_metadata_[i].TFORM(
value_of<std::string>("TFORM" + boost::lexical_cast<std::string>(i + 1))
);
col_metadata_[i].TBCOL(
value_of<std::size_t>("TBCOL" + boost::lexical_cast<std::string>(i + 1))
);
try {
col_metadata_[i].TTYPE(
value_of<std::string>("TTYPE" + boost::lexical_cast<std::string>(i + 1))
);
col_metadata_[i].comment(
value_of<std::string>(col_metadata_[i].TTYPE())
);
}
catch (std::out_of_range&) {/*Do Nothing*/ }
try {
col_metadata_[i].TUNIT(
value_of<std::string>("TUNIT" + boost::lexical_cast<std::string>(i + 1))
);
}
catch (std::out_of_range&) {/*Do Nothing*/ }
try {
col_metadata_[i].TSCAL(
value_of<double>("TSCAL" + boost::lexical_cast<std::string>(i + 1))
);
}
catch (std::out_of_range&) {/*Do Nothing*/ }
try {
col_metadata_[i].TZERO(
value_of<double>("TZERO" + boost::lexical_cast<std::string>(i + 1))
);
}
catch (std::out_of_range&) {/*Do Nothing*/ }
}
}
/**
* @brief Returns the data of ASCII table
*/
std::vector<char>& get_data() { return data_; }
/**
* @brief Returns the data of ASCII table (const version)
*/
const std::vector<char>& get_data() const { return data_; }
/**
* @brief Gets the metadata along with value(field_value) for every row of specified field
* @details This methods takes a field name as argument and returns the metadata information
* of the field along with the field value for all the rows in the table.
* @param[in] name Name of the field
* @return Returns the metadata along with value for every row of specified field
*/
std::unique_ptr<column> get_column(std::string column_name) const {
for (auto col : col_metadata_) {
if (col.TTYPE() == column_name) {
switch (get_type(col.TFORM())) {
case 'A': {
auto result = std::make_unique<column_data<std::string>>(col);
fill_column<std::string>(result->get_data(), col);
return std::move(result);
}
case 'I': {
auto result = std::make_unique<column_data<boost::int32_t>>(col);
fill_column<boost::int32_t>(result->get_data(), col);
return std::move(result);
}
case 'F': // Floating Point only hence fallthrough
case 'E': {
auto result = std::make_unique<column_data<boost::float32_t>>(col);
fill_column<boost::float32_t>(result->get_data(), col);
return std::move(result);
}
case 'D': {
auto result = std::make_unique<column_data<boost::float64_t>>(col);
fill_column<boost::float64_t>(result->get_data(), col);
return std::move(result);
}
}
}
}
return nullptr;
}
/**
* @brief Returns the field width based on the specified format
* @param[in] format Field format
* @return Returns the width of the field
*/
std::size_t column_size(std::string format) const
{
std::string form = boost::trim_copy_if(format, [](char c) -> bool {
return c == '\'' || c == ' ';
});
int decimal = static_cast<int>(form.length());
for(int i = 0; i < static_cast<int>(form.length()); i++)
{
if(form[i] == '.')
{
decimal = i;
break;
}
}
return boost::lexical_cast<std::size_t>(form.substr(1, decimal - 1));
}
/**
* @brief Gets the type of value stored in field based on the format specified
* @param[in] format Format of field
* @return Type of value stored
*/
char get_type(std::string format) const
{
std::string form = boost::trim_copy_if(format, [](char c) -> bool {
return c == '\'' || c == ' ';
});
return form[0];
}
private:
/**
* @brief Populates the container of given type with field_value for every row of specified field
* @param[in,out] column_container Container that stores the field value for every row of specified field
* @param[in] start Position where column begins for the field
* @param[in] column_size Total size of the field
* @param[in] lambda Lambda function for fetching the field data from data buffer
* @todo Why is column size present there
*/
template<typename ColDataType, typename VectorType>
void fill_column
(
std::vector<VectorType> &column_container,
const column& col_metadata
) const
{
column_container.reserve(naxis(2));
for (std::size_t i = 0; i < naxis(2); i++) {
auto starting_offset =
this->data_.begin() + i * naxis(1) + col_metadata.TBCOL();
auto ending_offset = starting_offset + column_size(col_metadata.TFORM());
std::string row_data_str(starting_offset, ending_offset + 1);
ColDataType row_data = boost::lexical_cast<ColDataType>(
boost::algorithm::trim_copy(row_data_str));
column_container.emplace_back(row_data);
}
}
/**
* @brief Initializes the current object with column metadata and table data
*/
void set_ascii_table_info(std::fstream& file)
{
populate_column_data();
std::copy_n(std::istreambuf_iterator<char>(file), naxis(1) * naxis(2),
std::back_inserter(data_));
}
};
}}} //namespace boost::astronomy::io
#endif // !BOOST_ASTRONOMY_IO_ASCII_TABLE_HPP