Alexandria  2.14.1
Please provide a description of the project.
FitsReaderHelper.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012-2020 Euclid Science Ground Segment
3  *
4  * This library is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU Lesser General Public License as published by the Free
6  * Software Foundation; either version 3.0 of the License, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12  * details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
25 #include <CCfits/CCfits>
26 #include <boost/lexical_cast.hpp>
27 #include <boost/tokenizer.hpp>
29 #include "FitsReaderHelper.h"
30 
31 namespace Euclid {
32 namespace Table {
33 
34 using NdArray::NdArray;
35 
36 std::vector<std::string> autoDetectColumnNames(const CCfits::Table& table_hdu) {
37  std::vector<std::string> names {};
38  for (int i=1; i<=table_hdu.numCols(); ++i) {
39  std::string name = table_hdu.column(i).name();
40  if (name.empty()) {
41  name = "Col" + std::to_string(i);
42  }
43  names.push_back(std::move(name));
44  }
45  return names;
46 }
47 
49  if (format[0] == 'A') {
50  return typeid(std::string);
51  } else if (format[0] == 'I') {
52  return typeid(int64_t);
53  } else if (format[0] == 'F') {
54  return typeid(double);
55  } else if (format[0] == 'E') {
56  return typeid(double);
57  } else if (format[0] == 'D') {
58  return typeid(double);
59  }
60  throw Elements::Exception() << "FITS ASCII table format " << format << " is not "
61  << "yet supported";
62 }
63 
65  if (format[0] == 'L') {
66  return typeid(bool);
67  } else if (format[0] == 'B') {
68  return typeid(int32_t);
69  } else if (format[0] == 'I') {
70  return typeid(int32_t);
71  } else if (format[0] == 'J') {
72  return typeid(int32_t);
73  } else if (format[0] == 'K') {
74  return typeid(int64_t);
75  } else if (format.back() == 'A') {
76  return typeid(std::string);
77  } else if (format[0] == 'E') {
78  return typeid(float);
79  } else if (format[0] == 'D') {
80  return typeid(double);
81  } else if (shape.empty()) {
82  if (format.back() == 'B') {
83  return typeid(std::vector<int32_t>);
84  } else if (format.back() == 'I') {
85  return typeid(std::vector<int32_t>);
86  } else if (format.back() == 'J') {
87  return typeid(std::vector<int32_t>);
88  } else if (format.back() == 'K') {
89  return typeid(std::vector<int64_t>);
90  } else if (format.back() == 'E') {
91  return typeid(std::vector<float>);
92  } else if (format.back() == 'D') {
93  return typeid(std::vector<double>);
94  }
95  } else {
96  if (format.back() == 'B') {
97  return typeid(NdArray<int32_t>);
98  } else if (format.back() == 'I') {
99  return typeid(NdArray<int32_t>);
100  } else if (format.back() == 'J') {
101  return typeid(NdArray<int32_t>);
102  } else if (format.back() == 'K') {
103  return typeid(NdArray<int64_t>);
104  } else if (format.back() == 'E') {
105  return typeid(NdArray<float>);
106  } else if (format.back() == 'D') {
107  return typeid(NdArray<double>);
108  }
109  }
110  throw Elements::Exception() << "FITS binary table format " << format << " is not "
111  << "yet supported";
112 }
113 
115  std::vector<size_t> result {};
116  if (!tdim.empty() && tdim.front() == '(' && tdim.back() == ')') {
117  auto subtdim = tdim.substr(1, tdim.size() - 2);
118  boost::char_separator<char> sep{","};
119  boost::tokenizer<boost::char_separator<char>> tok{subtdim, sep};
120  for (auto& s : tok) {
121  result.push_back(boost::lexical_cast<size_t>(s));
122  }
123  // Note: the shape is in fortran order, so we need to reverse
124  std::reverse(result.begin(), result.end());
125  }
126  return result;
127 }
128 
129 std::vector<std::type_index> autoDetectColumnTypes(const CCfits::Table& table_hdu) {
131  for (int i=1; i<=table_hdu.numCols(); i++) {
132  auto& column = table_hdu.column(i);
133 
134  if (typeid(table_hdu) == typeid(CCfits::BinTable)) {
135  column.setDimen();
136  types.push_back(binaryFormatToType(column.format(), parseTDIM(column.dimen())));
137  } else {
138  types.push_back(asciiFormatToType(column.format()));
139  }
140  }
141  return types;
142 }
143 
144 std::vector<std::string> autoDetectColumnUnits(const CCfits::Table& table_hdu) {
145  std::vector<std::string> units {};
146  for (int i=1; i<=table_hdu.numCols(); ++i) {
147  units.push_back(table_hdu.column(i).unit());
148  }
149  return units;
150 }
151 
153  std::vector<std::string> descriptions {};
154  for (int i=1; i<=table_hdu.numCols(); ++i) {
155  std::string desc;
156  auto key = table_hdu.keyWord().find("TDESC" + std::to_string(i));
157  if (key != table_hdu.keyWord().end()) {
158  key->second->value(desc);
159  }
160  descriptions.push_back(desc);
161  }
162  return descriptions;
163 }
164 
165 template<typename T>
166 std::vector<Row::cell_type> convertScalarColumn(CCfits::Column& column, long first, long last) {
167  std::vector<T> data;
168  column.read(data, first, last);
170  for (auto value : data) {
171  result.push_back(value);
172  }
173  return result;
174 }
175 
176 template<typename T>
177 std::vector<Row::cell_type> convertVectorColumn(CCfits::Column& column, long first, long last) {
179  column.readArrays(data, first, last);
181  for (auto& valar : data) {
182  result.push_back(std::vector<T>(std::begin(valar),std::end(valar)));
183  }
184  return result;
185 }
186 
187 template<typename T>
188 std::vector<Row::cell_type> convertNdArrayColumn(CCfits::Column& column, long first, long last) {
190  column.readArrays(data, first, last);
191  std::vector<size_t> shape = parseTDIM(column.dimen());
192 
194  for (auto& valar : data) {
195  result.push_back(NdArray<T>(shape, std::move(std::vector<T>(std::begin(valar), std::end(valar)))));
196  }
197  return result;
198 }
199 
201  return translateColumn(column, type, 1, column.rows());
202 }
203 
204 std::vector<Row::cell_type> translateColumn(CCfits::Column& column, std::type_index type, long first, long last) {
205  if (type == typeid(bool)) {
206  return convertScalarColumn<bool>(column, first, last);
207  } if (type == typeid(int32_t)) {
208  return convertScalarColumn<int32_t>(column, first, last);
209  } if (type == typeid(int64_t)) {
210  return convertScalarColumn<int64_t>(column, first, last);
211  } if (type == typeid(float)) {
212  return convertScalarColumn<float>(column, first, last);
213  } if (type == typeid(double)) {
214  return convertScalarColumn<double>(column, first, last);
215  } if (type == typeid(std::string)) {
216  return convertScalarColumn<std::string>(column, first, last);
217  } if (type == typeid(std::vector<int32_t>)) {
218  return convertVectorColumn<int32_t>(column, first, last);
219  } if (type == typeid(std::vector<int64_t>)) {
220  return convertVectorColumn<int64_t>(column, first, last);
221  } if (type == typeid(std::vector<float>)) {
222  return convertVectorColumn<float>(column, first, last);
223  } if (type == typeid(std::vector<double>)) {
224  return convertVectorColumn<double>(column, first, last);
225  } if (type == typeid(NdArray<int32_t>)) {
226  return convertNdArrayColumn<int32_t>(column, first, last);
227  } if (type == typeid(NdArray<int64_t>)) {
228  return convertNdArrayColumn<int64_t>(column, first, last);
229  } if (type == typeid(NdArray<float>)) {
230  return convertNdArrayColumn<float>(column, first, last);
231  } if (type == typeid(NdArray<double>)) {
232  return convertNdArrayColumn<double>(column, first, last);
233  }
234  throw Elements::Exception() << "Unsupported column type " << type.name();
235 }
236 
237 }
238 } // end of namespace Euclid
Euclid::Table::binaryFormatToType
std::type_index binaryFormatToType(const std::string &format, const std::vector< size_t > &shape)
Definition: FitsReaderHelper.cpp:64
std::string
STL class.
Euclid::Table::parseTDIM
std::vector< size_t > parseTDIM(const std::string &tdim)
Definition: FitsReaderHelper.cpp:114
std::move
T move(T... args)
Euclid::Table::convertVectorColumn
std::vector< Row::cell_type > convertVectorColumn(CCfits::Column &column, long first, long last)
Definition: FitsReaderHelper.cpp:177
Euclid::Table::autoDetectColumnDescriptions
std::map< std::string, ColumnDescription > autoDetectColumnDescriptions(std::istream &in, const std::string &comment)
Reads the column descriptions of the given stream.
Definition: AsciiReaderHelper.cpp:111
Euclid::Table::translateColumn
std::vector< Row::cell_type > translateColumn(CCfits::Column &column, std::type_index type)
Returns a vector representing the given FITS table column data, converted to the requested type.
Definition: FitsReaderHelper.cpp:200
std::vector< std::string >
std::string::find
T find(T... args)
std::string::size
T size(T... args)
std::type_index::name
T name(T... args)
std::type_index
Euclid::NdArray::NdArray
Definition: NdArray.h:45
std::reverse
T reverse(T... args)
std::string::back
T back(T... args)
Euclid::Table::convertScalarColumn
std::vector< Row::cell_type > convertScalarColumn(CCfits::Column &column, long first, long last)
Definition: FitsReaderHelper.cpp:166
std::string::front
T front(T... args)
std::vector::push_back
T push_back(T... args)
Euclid::NdArray::NdArray::NdArray
NdArray(const std::vector< size_t > &shape)
Definition: NdArray.h:62
Euclid::Table::autoDetectColumnNames
std::vector< std::string > autoDetectColumnNames(std::istream &in, const std::string &comment, size_t columns_number)
Reads the column names of the given stream.
Definition: AsciiReaderHelper.cpp:178
Exception.h
std::to_string
T to_string(T... args)
Elements::Exception
Euclid::Table::autoDetectColumnUnits
std::vector< std::string > autoDetectColumnUnits(const CCfits::Table &table_hdu)
Reads the column units based on the TUNITn keyword.
Definition: FitsReaderHelper.cpp:144
std::string::substr
T substr(T... args)
std::begin
T begin(T... args)
s
constexpr double s
Euclid::Table::autoDetectColumnTypes
std::vector< std::type_index > autoDetectColumnTypes(const CCfits::Table &table_hdu)
Reads the column types of the given table HDU.
Definition: FitsReaderHelper.cpp:129
std::string::empty
T empty(T... args)
std::end
T end(T... args)
Euclid::Table::convertNdArrayColumn
std::vector< Row::cell_type > convertNdArrayColumn(CCfits::Column &column, long first, long last)
Definition: FitsReaderHelper.cpp:188
Euclid::Table::asciiFormatToType
std::type_index asciiFormatToType(const std::string &format)
Definition: FitsReaderHelper.cpp:48
Euclid
Definition: InstOrRefHolder.h:29
FitsReaderHelper.h