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>>;
44inline std::string
timestamp(
int argc,
char* argv[])
48 auto ttt = std::time(
nullptr);
49 std::ostringstream oss;
51 oss << std::put_time(std::gmtime(&ttt),
"%FT%TZ");
52 for(
int i=0; i<argc; i++) oss <<
" "<<argv[i];
79 {
"git_hash", GIT_HASH},
82 {
"git_branch", GIT_BRANCH},
85 {
"compile_time", COMPILE_TIME},
92template<
class value_type>
93inline nc_type getNCDataType(){ assert(
false &&
"Type not supported!\n" );
return NC_DOUBLE; }
95inline nc_type getNCDataType<double>(){
return NC_DOUBLE;}
97inline nc_type getNCDataType<float>(){
return NC_FLOAT;}
99inline nc_type getNCDataType<int>(){
return NC_INT;}
101inline nc_type getNCDataType<unsigned>(){
return NC_UINT;}
103inline nc_type getNCDataType<bool>(){
return NC_BYTE;}
105inline nc_type getNCDataType<std::string>(){
return NC_STRING;}
107inline nc_type getNCDataType<const char*>(){
return NC_STRING;}
111template<
class S,
class T>
112void put_att(
int ncid,
int varid,
const std::tuple<S, nc_type,
113 std::vector<T>>& att)
116 std::string name_string = std::get<0>(att);
117 auto name = name_string.c_str();
118 nc_type xtype = std::get<1>(att);
119 const std::vector<T>& data = std::get<2>(att);
120 unsigned size = data.size();
123 if constexpr( std::is_same_v<T, int>)
125 err = nc_put_att_int( ncid, varid, name, xtype, size, &data[0]);
127 else if constexpr( std::is_same_v<T, unsigned>)
129 err = nc_put_att_uint( ncid, varid, name, xtype, size, &data[0]);
131 else if constexpr( std::is_same_v<T, float>)
133 err = nc_put_att_float( ncid, varid, name, xtype, size, &data[0]);
135 else if constexpr( std::is_same_v<T, double>)
137 err = nc_put_att_double( ncid, varid, name, xtype, size, &data[0]);
139 else if constexpr( std::is_same_v<T, std::string> or
140 std::is_same_v<T, const char*>)
143 throw std::runtime_error(
"Cannot write a string array attribute to NetCDF");
144 std::string tmp = data[0];
145 err = nc_put_att_text( ncid, varid, name, tmp.size(), tmp.c_str());
147 else if constexpr( std::is_same_v<T, bool>)
150 std::vector<signed char> dataB(size);
151 for(
unsigned i=0; i<size; i++)
153 err = nc_put_att_schar( ncid, varid, name, NC_BYTE, size, &dataB[0]);
157 err = nc_put_att( ncid, varid, name, xtype, size, &data[0]);
161template<
class S,
class T>
162void put_att(
int ncid,
int varid, std::tuple<S, nc_type, T> att)
164 put_att( ncid, varid, std::make_tuple( std::get<0>(att), std::get<1>(att),
165 std::vector<T>( 1, std::get<2>(att)) ));
169template<
class S,
class T>
170void put_att(
int ncid,
int varid,
const std::pair<S, T>& att)
172 put_att( ncid, varid, std::make_tuple( att.first,
173 detail::getNCDataType<T>(), std::vector<T>(1,att.second)));
176template<
class S,
class T>
177void put_att(
int ncid,
int varid,
const std::pair<S, std::vector<T>>& att)
179 put_att( ncid, varid, std::make_tuple( att.first,
180 detail::getNCDataType<T>(), att.second));
184void put_att(
int ncid,
int varid,
const std::pair<S, nc_att_t>& att)
188 std::visit( [ncid, varid, name](
auto&& arg) { put_att( ncid, varid,
189 std::make_pair( name, arg)); }, v);
193template<
class Iterable>
194void put_atts(
int ncid,
int varid,
const Iterable& atts)
196 for(
const auto& it : atts)
197 put_att( ncid, varid, it);
203std::vector<T> get_att_v(
int ncid,
int varid, std::string att)
205 auto name = att.c_str();
206 size_t size, str_len = 0;
208 err = nc_inq_attlen( ncid, varid, name, &size);
210 err = nc_inq_atttype( ncid, varid, name, &xtype);
211 if ( xtype == NC_STRING or xtype == NC_CHAR)
216 std::vector<T> data(size);
217 if ( xtype == NC_STRING or xtype == NC_CHAR)
219 std::string str( str_len,
'x');
220 err = nc_get_att_text( ncid, varid, name, str_len == 0 ? NULL : &str[0]);
221 if constexpr ( std::is_convertible_v<std::string,T>)
224 throw std::runtime_error(
"Cannot convert NC_STRING to given type");
226 else if ( xtype == NC_INT)
228 std::vector<int> tmp( size);
229 err = nc_get_att_int( ncid, varid, name, &tmp[0]);
230 if constexpr ( std::is_convertible_v<int,T>)
231 std::transform(tmp.begin(), tmp.end(), data.begin(), [](
int val) { return T(val);});
233 throw std::runtime_error(
"Cannot convert NC_INT to given type");
235 else if ( xtype == NC_UINT)
237 std::vector<unsigned> tmp( size);
238 err = nc_get_att_uint( ncid, varid, name, &tmp[0]);
239 if constexpr ( std::is_convertible_v<unsigned,T>)
240 std::transform(tmp.begin(), tmp.end(), data.begin(), [](
unsigned val) { return T(val);});
242 throw std::runtime_error(
"Cannot convert NC_UINT to given type");
244 else if ( xtype == NC_FLOAT)
246 std::vector<float> tmp( size);
247 err = nc_get_att_float( ncid, varid, name, &tmp[0]);
248 if constexpr ( std::is_convertible_v<float,T>)
249 std::transform(tmp.begin(), tmp.end(), data.begin(), [](
float val) { return T(val);});
251 throw std::runtime_error(
"Cannot convert NC_FLOAT to given type");
253 else if ( xtype == NC_DOUBLE)
255 std::vector<double> tmp( size);
256 err = nc_get_att_double( ncid, varid, name, &tmp[0]);
257 if constexpr ( std::is_convertible_v<double,T>)
258 std::transform(tmp.begin(), tmp.end(), data.begin(), [](
double val) { return T(val);});
260 throw std::runtime_error(
"Cannot convert NC_DOUBLE to given type");
262 else if( xtype == NC_BYTE)
264 std::vector<signed char> tmp(size);
265 err = nc_get_att_schar( ncid, varid, name, &tmp[0]);
266 if constexpr ( std::is_convertible_v<bool,T>)
267 std::transform(tmp.begin(), tmp.end(), data.begin(), [](
signed char val) { return T(val);});
269 throw std::runtime_error(
"Cannot convert NC_BYTE to given type");
274 if constexpr (std::is_same_v<T, bool>)
276 std::vector<signed char> tmp(size);
277 err = nc_get_att( ncid, varid, name, &tmp[0]);
278 std::transform(tmp.begin(), tmp.end(), data.begin(), [](
signed char val) { return T(val);});
281 err = nc_get_att( ncid, varid, name, &data[0]);
287 std::string att_name)
289 auto name = att_name.c_str();
292 err = nc_inq_attlen( ncid, varid, name, &size);
294 err = nc_inq_atttype( ncid, varid, name, &xtype);
295 if ( xtype == NC_INT and size == 1)
296 return get_att_v<int>( ncid, varid, att_name)[0];
297 else if ( xtype == NC_INT and size != 1)
298 return get_att_v<int>( ncid, varid, att_name);
299 else if ( xtype == NC_UINT and size == 1)
300 return get_att_v<unsigned>( ncid, varid, att_name)[0];
301 else if ( xtype == NC_UINT and size != 1)
302 return get_att_v<unsigned>( ncid, varid, att_name);
303 else if ( xtype == NC_FLOAT and size == 1)
304 return get_att_v<float>( ncid, varid, att_name)[0];
305 else if ( xtype == NC_FLOAT and size != 1)
306 return get_att_v<float>( ncid, varid, att_name);
307 else if ( xtype == NC_DOUBLE and size == 1)
308 return get_att_v<double>( ncid, varid, att_name)[0];
309 else if ( xtype == NC_DOUBLE and size != 1)
310 return get_att_v<double>( ncid, varid, att_name);
311 else if ( xtype == NC_BYTE and size == 1)
314 bool value = get_att_v<bool>( ncid, varid, att_name)[0];
317 else if ( xtype == NC_BYTE and size != 1)
318 return get_att_v<bool>( ncid, varid, att_name);
319 else if ( xtype == NC_STRING || xtype == NC_CHAR)
320 return get_att_v<std::string>( ncid, varid, att_name)[0];
322 throw std::runtime_error(
"Cannot convert attribute type to nc_att_t");
329void get_att_h(
int ncid,
int varid, std::string att_name, T& att)
331 att = get_att_v<T>( ncid, varid, att_name)[0];
334void get_att_h(
int ncid,
int varid, std::string att_name, std::vector<T>& att)
336 att = get_att_v<T>( ncid, varid, att_name);
338inline void get_att_h(
int ncid,
int varid, std::string att_name,
dg::file::nc_att_t& att)
340 att = get_att_t( ncid, varid, att_name);
344T get_att_as(
int ncid,
int varid, std::string att_name)
347 detail::get_att_h( ncid, varid, att_name, att);
351std::map<std::string, T> get_atts_as(
int ncid,
int varid)
355 if( varid == NC_GLOBAL)
356 err = nc_inq_natts( ncid, &number);
358 err = nc_inq_varnatts( ncid, varid, &number);
359 std::map < std::string, T> map;
360 for(
int i=0; i<number; i++)
362 char att_name[NC_MAX_NAME];
363 err = nc_inq_attname( ncid, varid, i, att_name);
364 detail::get_att_h( ncid, varid, att_name, map[att_name]);