25using nc_att_t = std::variant<int, unsigned, float, double, bool, std::string,
26 std::vector<int>, std::vector<unsigned>, std::vector<float>,
27 std::vector<double>, std::vector<bool>>;
46inline std::string
timestamp(
int argc,
char* argv[])
49 auto ttt = std::time(
nullptr);
50 std::ostringstream oss;
52 oss << std::put_time(std::localtime(&ttt),
"%F %T %Z");
53 for(
int i=0; i<argc; i++) oss <<
" "<<argv[i];
80 {
"git_hash", GIT_HASH},
83 {
"git_branch", GIT_BRANCH},
86 {
"compile_time", COMPILE_TIME},
93template<
class value_type>
94inline nc_type getNCDataType(){ assert(
false &&
"Type not supported!\n" );
return NC_DOUBLE; }
96inline nc_type getNCDataType<double>(){
return NC_DOUBLE;}
98inline nc_type getNCDataType<float>(){
return NC_FLOAT;}
100inline nc_type getNCDataType<int>(){
return NC_INT;}
102inline nc_type getNCDataType<unsigned>(){
return NC_UINT;}
104inline nc_type getNCDataType<bool>(){
return NC_BYTE;}
106inline nc_type getNCDataType<std::string>(){
return NC_STRING;}
108inline nc_type getNCDataType<const char*>(){
return NC_STRING;}
112template<
class S,
class T>
113void put_att(
int ncid,
int varid,
const std::tuple<S, nc_type,
114 std::vector<T>>& att)
117 std::string name_string = std::get<0>(att);
118 auto name = name_string.c_str();
119 nc_type xtype = std::get<1>(att);
120 const std::vector<T>& data = std::get<2>(att);
121 unsigned size = data.size();
124 if constexpr( std::is_same_v<T, int>)
126 err = nc_put_att_int( ncid, varid, name, xtype, size, &data[0]);
128 else if constexpr( std::is_same_v<T, unsigned>)
130 err = nc_put_att_uint( ncid, varid, name, xtype, size, &data[0]);
132 else if constexpr( std::is_same_v<T, float>)
134 err = nc_put_att_float( ncid, varid, name, xtype, size, &data[0]);
136 else if constexpr( std::is_same_v<T, double>)
138 err = nc_put_att_double( ncid, varid, name, xtype, size, &data[0]);
140 else if constexpr( std::is_same_v<T, std::string> or
141 std::is_same_v<T, const char*>)
144 throw std::runtime_error(
"Cannot write a string array attribute to NetCDF");
145 std::string tmp = data[0];
146 err = nc_put_att_text( ncid, varid, name, tmp.size(), tmp.c_str());
148 else if constexpr( std::is_same_v<T, bool>)
151 std::vector<signed char> dataB(size);
152 for(
unsigned i=0; i<size; i++)
154 err = nc_put_att_schar( ncid, varid, name, NC_BYTE, size, &dataB[0]);
158 err = nc_put_att( ncid, varid, name, xtype, size, &data[0]);
162template<
class S,
class T>
163void put_att(
int ncid,
int varid, std::tuple<S, nc_type, T> att)
165 put_att( ncid, varid, std::make_tuple( std::get<0>(att), std::get<1>(att),
166 std::vector<T>( 1, std::get<2>(att)) ));
170template<
class S,
class T>
171void put_att(
int ncid,
int varid,
const std::pair<S, T>& att)
173 put_att( ncid, varid, std::make_tuple( att.first,
174 detail::getNCDataType<T>(), std::vector<T>(1,att.second)));
177template<
class S,
class T>
178void put_att(
int ncid,
int varid,
const std::pair<S, std::vector<T>>& att)
180 put_att( ncid, varid, std::make_tuple( att.first,
181 detail::getNCDataType<T>(), att.second));
185void put_att(
int ncid,
int varid,
const std::pair<S, nc_att_t>& att)
189 std::visit( [ncid, varid, name](
auto&& arg) { put_att( ncid, varid,
190 std::make_pair( name, arg)); }, v);
194template<
class Iterable>
195void put_atts(
int ncid,
int varid,
const Iterable& atts)
197 for(
const auto& it : atts)
198 put_att( ncid, varid, it);
204std::vector<T> get_att_v(
int ncid,
int varid, std::string att)
206 auto name = att.c_str();
209 err = nc_inq_attlen( ncid, varid, name, &size);
211 err = nc_inq_atttype( ncid, varid, name, &xtype);
212 std::vector<T> data(size);
213 if ( xtype == NC_STRING or xtype == NC_CHAR)
215 std::string str( size,
'x');
216 err = nc_get_att_text( ncid, varid, name, &str[0]);
217 if constexpr ( std::is_convertible_v<std::string,T>)
220 throw std::runtime_error(
"Cannot convert NC_STRING to given type");
222 else if ( xtype == NC_INT)
224 std::vector<int> tmp( size);
225 err = nc_get_att_int( ncid, varid, name, &tmp[0]);
226 if constexpr ( std::is_convertible_v<int,T>)
227 std::copy( tmp.begin(), tmp.end(), data.begin());
229 throw std::runtime_error(
"Cannot convert NC_INT to given type");
231 else if ( xtype == NC_UINT)
233 std::vector<unsigned> tmp( size);
234 err = nc_get_att_uint( ncid, varid, name, &tmp[0]);
235 if constexpr ( std::is_convertible_v<unsigned,T>)
236 std::copy( tmp.begin(), tmp.end(), data.begin());
238 throw std::runtime_error(
"Cannot convert NC_UINT to given type");
240 else if ( xtype == NC_FLOAT)
242 std::vector<float> tmp( size);
243 err = nc_get_att_float( ncid, varid, name, &tmp[0]);
244 if constexpr ( std::is_convertible_v<float,T>)
245 std::copy( tmp.begin(), tmp.end(), data.begin());
247 throw std::runtime_error(
"Cannot convert NC_FLOAT to given type");
249 else if ( xtype == NC_DOUBLE)
251 std::vector<double> tmp( size);
252 err = nc_get_att_double( ncid, varid, name, &tmp[0]);
253 if constexpr ( std::is_convertible_v<double,T>)
254 std::copy( tmp.begin(), tmp.end(), data.begin());
256 throw std::runtime_error(
"Cannot convert NC_DOUBLE to given type");
258 else if( xtype == NC_BYTE)
260 std::vector<signed char> tmp(size);
261 err = nc_get_att_schar( ncid, varid, name, &tmp[0]);
262 if constexpr ( std::is_convertible_v<bool,T>)
263 std::copy( tmp.begin(), tmp.end(), data.begin());
265 throw std::runtime_error(
"Cannot convert NC_BYTE to given type");
270 if constexpr (std::is_same_v<T, bool>)
272 std::vector<signed char> tmp(size);
273 err = nc_get_att( ncid, varid, name, &tmp[0]);
274 std::copy( tmp.begin(), tmp.end(), data.begin());
277 err = nc_get_att( ncid, varid, name, &data[0]);
283 std::string att_name)
285 auto name = att_name.c_str();
288 err = nc_inq_attlen( ncid, varid, name, &size);
290 err = nc_inq_atttype( ncid, varid, name, &xtype);
291 if ( xtype == NC_INT and size == 1)
292 return get_att_v<int>( ncid, varid, att_name)[0];
293 else if ( xtype == NC_INT and size != 1)
294 return get_att_v<int>( ncid, varid, att_name);
295 else if ( xtype == NC_UINT and size == 1)
296 return get_att_v<unsigned>( ncid, varid, att_name)[0];
297 else if ( xtype == NC_UINT and size != 1)
298 return get_att_v<unsigned>( ncid, varid, att_name);
299 else if ( xtype == NC_FLOAT and size == 1)
300 return get_att_v<float>( ncid, varid, att_name)[0];
301 else if ( xtype == NC_FLOAT and size != 1)
302 return get_att_v<float>( ncid, varid, att_name);
303 else if ( xtype == NC_DOUBLE and size == 1)
304 return get_att_v<double>( ncid, varid, att_name)[0];
305 else if ( xtype == NC_DOUBLE and size != 1)
306 return get_att_v<double>( ncid, varid, att_name);
307 else if ( xtype == NC_BYTE and size == 1)
310 bool value = get_att_v<bool>( ncid, varid, att_name)[0];
313 else if ( xtype == NC_BYTE and size != 1)
314 return get_att_v<bool>( ncid, varid, att_name);
315 else if ( xtype == NC_STRING || xtype == NC_CHAR)
316 return get_att_v<std::string>( ncid, varid, att_name)[0];
318 throw std::runtime_error(
"Cannot convert attribute type to nc_att_t");
325void get_att_h(
int ncid,
int varid, std::string att_name, T& att)
327 att = get_att_v<T>( ncid, varid, att_name)[0];
330void get_att_h(
int ncid,
int varid, std::string att_name, std::vector<T>& att)
332 att = get_att_v<T>( ncid, varid, att_name);
334inline void get_att_h(
int ncid,
int varid, std::string att_name,
dg::file::nc_att_t& att)
336 att = get_att_t( ncid, varid, att_name);
340T get_att_as(
int ncid,
int varid, std::string att_name)
343 detail::get_att_h( ncid, varid, att_name, att);
347std::map<std::string, T> get_atts_as(
int ncid,
int varid)
351 if( varid == NC_GLOBAL)
352 err = nc_inq_natts( ncid, &number);
354 err = nc_inq_varnatts( ncid, varid, &number);
355 std::map < std::string, T> map;
356 for(
int i=0; i<number; i++)
358 char att_name[NC_MAX_NAME];
359 err = nc_inq_attname( ncid, varid, i, att_name);
360 detail::get_att_h( ncid, varid, att_name, map[att_name]);