Extension: Json and NetCDF utilities
#include "dg/file/file.h"
Loading...
Searching...
No Matches
nc_file.h
Go to the documentation of this file.
1#pragma once
2
3#include <filesystem>
4#include <functional>
5#include <list>
6#ifdef _MSC_VER
7// On windows the filesystem::path is in wchar
8// https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string
9#include <locale>
10#include <codecvt>
11#endif // _MSC_VER
12#include "../dg/blas.h"
13#include "../dg/backend/memory.h"
14#include "nc_error.h"
15#include "easy_atts.h"
16#include "easy_output.h"
17#include "easy_input.h"
18
25namespace dg
26{
27namespace file
28{
100// Developper note: The reason we need our own flag is that NC_NOWRITE and
101// NC_CLOBBER are both defined as 0x0000 in the netcdf library so we need a
102// way to distinguish them because we merge nc_open and nc_create into one
103// function
104// Developper note: 0x1, 0x2, 0x4, etc read as bit-maps 0000, 0001, 0010,
105// 0100, etc. so these are quite useful as flags
106// Developper note: the only meaningful flag we do not capture here is
107// NC_CLASSIC_MODEL which enforces the classic mode on a NetCDF-4 file: Not
108// sure what the difference is to just not use groups, user defined types,
109// multiple unlimited dimensions, or new atomic types (I'm also unsure if this
110// will force the nc_enddef nc_redef behaviour as well?)
111
127
151{
153 // ///////////////////////////// CONSTRUCTORS/DESTRUCTOR /////////
156 SerialNcFile () = default;
161 SerialNcFile(const std::filesystem::path& filename,
162 enum NcFileMode mode = nc_nowrite)
163 {
164 open( filename, mode);
165 }
172 SerialNcFile(const SerialNcFile& rhs) = delete;
174 SerialNcFile& operator =(const SerialNcFile & rhs) = delete;
175
178 SerialNcFile(SerialNcFile&& rhs) = default;
181
186 {
187 try
188 {
189 close();
190 }
191 catch (NC_Error &e)
192 {
193 std::cerr << e.what() << std::endl;
194 }
195 }
196 // /////////////////// open/close /////////
197
205 void open(const std::filesystem::path& filename,
206 enum NcFileMode mode = nc_nowrite)
207 {
208 // Like a std::fstream opening fails if file already associated
209 if( m_open)
210 throw NC_Error( 1002);
211 // TODO Test the pathing on Windows
212 NC_Error_Handle err;
213 switch (mode)
214 {
215 case nc_nowrite:
216 err = nc_open( filename.string().c_str(), NC_NETCDF4 |
217 NC_NOWRITE, &m_ncid);
218 break;
219 case nc_write:
220 err = nc_open( filename.string().c_str(), NC_NETCDF4 |
221 NC_WRITE, &m_ncid);
222 break;
223 case nc_noclobber:
224 err = nc_create( filename.string().c_str(), NC_NETCDF4 |
225 NC_NOCLOBBER, &m_ncid);
226 break;
227 case nc_clobber:
228 err = nc_create( filename.string().c_str(), NC_NETCDF4 |
229 NC_CLOBBER, &m_ncid);
230 break;
231 }
232 m_open = true;
233 m_grp = m_ncid;
234 }
237 bool is_open() const noexcept
238 {
239 // is_closed() == not is_open()
240 return m_open;
241 }
242
252 void close()
253 {
254 // when the file is closed the ncid may be assigned to a new file
255 if (m_open)
256 {
257 NC_Error_Handle err;
258 err = nc_close(m_ncid);
259 }
260
261 m_open = false;
262 m_grp = m_ncid = 0;
263 }
264
266 void sync()
267 {
268 check_open();
269 NC_Error_Handle err;
270 err = nc_sync( m_ncid);
271 }
278 int get_ncid() const noexcept{ return m_ncid;}
279
287 int get_format() const
288 {
290 int formatp;
291 err = nc_inq_format(m_ncid, &formatp);
292 return formatp;
293 }
294
295 // ///////////// Groups /////////////////
304 void def_grp( std::string name)
305 {
306 check_open();
307 int new_grp_id = 0;
308 NC_Error_Handle err;
309 err = nc_def_grp( m_grp, name.c_str(), &new_grp_id);
310 // we just forget the id => always need to ask netcdf for id
311 // Is no performance hit as cached
312 }
313
323 void def_grp_p( std::filesystem::path path)
324 {
325 check_open();
326 if( not path.has_root_path()) // it is a relative path
327 {
328 auto current = get_current_path();
329 path = (current / path);
330 }
331 int groupid = m_ncid;
332 auto rel_path = path.relative_path();
333 NC_Error_Handle err;
334 for( auto it = rel_path.begin(); it != rel_path.end(); it++)
335 {
336#ifdef _MSC_VER
337 // https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string
338 std::wstring string_to_convert = *it;
339 //setup converter
340 using convert_type = std::codecvt_utf8<wchar_t>;
341 std::wstring_convert<convert_type, wchar_t> converter;
342
343 //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
344 std::string grp = converter.to_bytes(string_to_convert);
345
346#else
347 std::string grp = *it;
348#endif // MSVC
349 int new_grpid;
350 int retval = nc_inq_ncid( groupid, grp.c_str(), &new_grpid);
351 if( retval != NC_NOERR)
352 err = nc_def_grp( groupid, grp.c_str(), &groupid);
353 else
354 groupid = new_grpid;
355 }
356 }
361 bool grp_is_defined( std::filesystem::path path) const
362 {
363 check_open();
364 std::string name = path.generic_string();
365 if( not path.has_root_path()) // it is a relative path
366 {
367 auto current = get_current_path();
368 name = (current / path ).generic_string();
369 }
370 int grpid=0;
371 int retval = nc_inq_grp_full_ncid( m_ncid, name.c_str(), &grpid);
372 return retval == NC_NOERR;
373 }
386 void set_grp( std::filesystem::path path = "")
387 {
388 check_open();
389 NC_Error_Handle err;
390 std::string name = path.generic_string();
391 if ( name == ".")
392 return;
393 if ( name == "" or name == "/")
394 {
395 m_grp = m_ncid;
396 }
397 else if ( name == "..")
398 {
399 if( m_grp == m_ncid)
400 return;
401 err = nc_inq_grp_parent( m_grp, &m_grp);
402 }
403 else
404 {
405 if( not path.has_root_path()) // it is a relative path
406 {
407 auto current = get_current_path();
408 name = (current / path ).generic_string();
409 }
410 err = nc_inq_grp_full_ncid( m_ncid, name.c_str(), &m_grp);
411 }
412 }
415 void rename_grp( std::string old_name, std::string new_name)
416 {
417 check_open();
418 NC_Error_Handle err;
419 int old_grp;
420 err = nc_inq_grp_ncid( m_grp, old_name.c_str(), &old_grp);
421 err = nc_rename_grp( old_grp, new_name.c_str());
422 }
423
425 int get_grpid() const noexcept{ return m_grp;}
426
428 std::filesystem::path get_current_path( ) const
429 {
430 check_open();
431 return get_grp_path( m_grp);
432 }
433
436 std::list<std::filesystem::path> get_grps( ) const
437 {
438 check_open();
439 auto grps = get_grps_abs(m_grp);
440 std::list<std::filesystem::path> grps_v;
441 for( auto grp : grps)
442 grps_v.push_back( grp.second);
443 return grps_v;
444
445 }
456 std::list<std::filesystem::path> get_grps_r( ) const
457 {
458 auto grps = get_grps_abs_r(m_grp);
459 std::list<std::filesystem::path> grps_v;
460 for( auto grp : grps)
461 grps_v.push_back( grp.second);
462 return grps_v;
463 }
464
465 // //////////// Dimensions ////////////////////////
479 void def_dim( std::string name, size_t size)
480 {
481 check_open();
482 NC_Error_Handle err;
483 int dim_id;
484 err = nc_def_dim( m_grp, name.c_str(), size, &dim_id);
485 }
487 void rename_dim( std::string old_name, std::string new_name)
488 {
489 check_open();
490 int dimid;
491 NC_Error_Handle err;
492 err = nc_inq_dimid( m_grp, old_name.c_str(), &dimid);
493 err = nc_rename_dim( m_grp, dimid, new_name.c_str());
494 }
502 size_t get_dim_size( std::string name) const
503 {
504 check_open();
505 NC_Error_Handle err;
506 int dimid;
507 err = nc_inq_dimid( m_grp, name.c_str(), &dimid);
508 size_t len;
509 err = nc_inq_dimlen( m_grp, dimid, &len);
510 return len;
511
512 }
513
515 std::vector<size_t> get_dims_shape( const std::vector<std::string>& dims) const
516 {
517 std::vector<size_t> shape( dims.size());
518 for( unsigned u=0; u<dims.size(); u++)
519 shape[u] = get_dim_size( dims[u]);
520 return shape;
521 }
532 std::vector<std::string> get_dims( bool include_parents = true) const
533 {
534 check_open();
535 NC_Error_Handle err;
536 // There is a correct way of getting the dimensions in a group
537 // https://github.com/Unidata/netcdf-c/issues/2873
538 int ndims;
539 err = nc_inq_dimids( m_grp, &ndims, NULL, include_parents);
540 if( ndims == 0)
541 return {};
542 std::vector<int> dimids(ndims);
543 err = nc_inq_dimids( m_grp, &ndims, &dimids[0], include_parents);
544 // Globally dimension ids are 0, 1, 2, ... in the order in which the
545 // dimensions were defined
546 std::vector<std::string> dims;
547 for ( int i = 0; i < ndims; i++)
548 {
549 char dimname [ NC_MAX_NAME+1];
550 err = nc_inq_dimname( m_grp, dimids[i], dimname);
551 if( std::find(dims.begin(), dims.end(), std::string(dimname) ) ==
552 dims.end())
553 dims.push_back(dimname);
554 }
555 return dims;
556 }
557
564 std::vector<std::string> get_unlim_dims( ) const
565 {
566 check_open();
567 int ndims;
568 NC_Error_Handle err;
569 err = nc_inq_unlimdims( m_grp, &ndims, NULL);
570 if( ndims == 0)
571 return {};
572 std::vector<int> dimids(ndims);
573 // Our tests indicate that this does not return the unlimited dimensions
574 // of the parent group even though the documentation says so...
575 err = nc_inq_unlimdims( m_grp, &ndims, &dimids[0]);
576 std::vector<std::string> dims;
577 for( int i=0; i<ndims; i++)
578 {
579 char dimname [ NC_MAX_NAME+1];
580 err = nc_inq_dimname( m_grp, dimids[i], dimname);
581 if( std::find(dims.begin(), dims.end(), std::string(dimname) ) ==
582 dims.end())
583 dims.push_back(dimname);
584 }
585 return dims;
586 }
587
590 bool dim_is_defined( std::string name) const
591 {
592 int dimid=0;
593 int retval = nc_inq_dimid( m_grp, name.c_str(), &dimid);
594 return retval == NC_NOERR;
595 }
597
604 void put_att( const std::pair<std::string, nc_att_t>& att, std::string id = "")
605 {
606 int varid = name2varid( id);
607 dg::file::detail::put_att( m_grp, varid, att);
608 }
609
619 template<class S, class T> // T cannot be nc_att_t
620 void put_att( const std::tuple<S,nc_type, T>& att, std::string id = "")
621 {
622 int varid = name2varid( id);
623 dg::file::detail::put_att( m_grp, varid, att);
624 }
639 template<class Attributes = std::map<std::string, nc_att_t> > // *it must be usable in put_att
640 void put_atts(const Attributes& atts, std::string id = "")
641 {
642 int varid = name2varid( id);
643 dg::file::detail::put_atts( m_grp, varid, atts);
644 }
645
646 // ///////////////// Attribute getters
647
659 template<class T>
660 T get_att_as(std::string att_name, std::string id = "") const
661 {
662 int varid = name2varid( id);
663 return dg::file::detail::get_att_as<T>( m_grp, varid, att_name);
664 }
665
667 template<class T>
668 std::vector<T> get_att_vec_as(std::string att_name, std::string id = "") const
669 {
670 return get_att_as<std::vector<T>>( att_name, id);
671 }
672
684 template<class T>
685 std::map<std::string, T> get_atts_as( std::string id = "") const
686 {
687 int varid = name2varid( id);
688 return dg::file::detail::get_atts_as<T>( m_grp, varid);
689 }
690
693 std::map<std::string, nc_att_t> get_atts( std::string id = "") const
694 {
695 return get_atts_as<nc_att_t>( id);
696 }
697
708 void del_att(std::string att_name, std::string id = "")
709 {
710 int varid = name2varid( id);
711 auto name = att_name.c_str();
712 NC_Error_Handle err;
713 err = nc_del_att( m_grp, varid, name);
714 }
717 bool att_is_defined(std::string att_name, std::string id = "") const
718 {
719 int varid = name2varid( id);
720 int attid;
721 int retval = nc_inq_attid( m_grp, varid, att_name.c_str(), &attid);
722 return retval == NC_NOERR;
723 }
733 void rename_att(std::string old_att_name, std::string
734 new_att_name, std::string id = "")
735 {
736 int varid = name2varid( id);
737 auto old_name = old_att_name.c_str();
738 auto new_name = new_att_name.c_str();
739 NC_Error_Handle err;
740 err = nc_rename_att( m_grp, varid, old_name, new_name);
741 }
742
743 // //////////// Variables ////////////////////////
756 template<class T, class Attributes = std::map<std::string, nc_att_t>>
757 void def_var_as( std::string name,
758 const std::vector<std::string>& dim_names,
759 const Attributes& atts = {})
760 {
761 def_var( name, detail::getNCDataType<T>(), dim_names, atts);
762 }
763
775 template<class Attributes = std::map<std::string, nc_att_t>>
776 void def_var( std::string name, nc_type xtype,
777 const std::vector<std::string>& dim_names,
778 const Attributes& atts = {})
779 {
781 std::vector<int> dimids( dim_names.size());
782 for( unsigned u=0; u<dim_names.size(); u++)
783 err = nc_inq_dimid( m_grp, dim_names[u].c_str(), &dimids[u]);
784 int varid;
785 err = nc_def_var( m_grp, name.c_str(), xtype, dim_names.size(),
786 &dimids[0], &varid);
787 put_atts( atts, name);
788 }
789
801 template<class ContainerType, std::enable_if_t< dg::is_vector_v<
802 ContainerType, SharedVectorTag>, bool > = true>
803 void put_var( std::string name, const NcHyperslab& slab,
804 const ContainerType& data)
805 {
806 int varid = name2varid( name);
808 int ndims;
809 err = nc_inq_varndims( m_grp, varid, &ndims);
810 assert( (unsigned)ndims == slab.ndim());
811 if constexpr ( dg::has_policy_v<ContainerType, dg::CudaTag>)
812 {
813 using value_type = dg::get_value_type<ContainerType>;
814 m_buffer.template set<value_type>( data.size());
815 auto& buffer = m_buffer.template get<value_type>( );
816 dg::assign ( data, buffer);
817 err = detail::put_vara_T( m_grp, varid, slab.startp(), slab.countp(),
818 buffer.data());
819 }
820 else
821 err = detail::put_vara_T( m_grp, varid, slab.startp(), slab.countp(),
822 thrust::raw_pointer_cast(data.data()));
823 }
824
836 template<class ContainerType, class Attributes = std::map<std::string, nc_att_t>,
837 std::enable_if_t< dg::is_vector_v<ContainerType, SharedVectorTag>, bool > = true>
838 void defput_var( std::string name, const std::vector<std::string>& dim_names,
839 const Attributes& atts, const NcHyperslab& slab,
840 const ContainerType& data)
841 {
842 def_var_as<dg::get_value_type<ContainerType>>( name, dim_names, atts);
843 put_var( name, slab, data);
844 }
845
857 template<class T, std::enable_if_t< dg::is_scalar_v<T>, bool> = true>
858 void put_var( std::string name, const std::vector<size_t>& start, T data)
859 {
860 int varid = name2varid( name);
862 std::vector<size_t> count( start.size(), 1);
863 err = detail::put_vara_T( m_grp, varid, &start[0], &count[0], &data);
864 }
865
884 template<class T, class Attributes = std::map<std::string, nc_att_t>>
885 void def_dimvar_as( std::string name, size_t size, const Attributes& atts)
886 {
887 def_dim( name, size);
888 def_var_as<T>( name, {name}, atts);
889 }
890
907 template<class ContainerType, class Attributes = std::map<std::string, nc_att_t>>
908 void defput_dim( std::string name,
909 const Attributes& atts,
910 const ContainerType& abscissas)
911 {
913 abscissas.size(), atts);
914 put_var( name, {abscissas}, abscissas);
915 }
916
926 template<class ContainerType, std::enable_if_t< dg::is_vector_v<
927 ContainerType, SharedVectorTag>, bool > = true>
928 void get_var( std::string name, const NcHyperslab& slab,
929 ContainerType& data) const
930 {
931 int varid = name2varid( name);
933 int ndims;
934 err = nc_inq_varndims( m_grp, varid, &ndims);
935 assert( (unsigned)ndims == slab.ndim());
936 unsigned size = 1;
937 for( unsigned u=0; u<slab.ndim(); u++)
938 size *= slab.count()[u];
939 if constexpr ( dg::has_policy_v<ContainerType, dg::CudaTag>)
940 {
941 using value_type = dg::get_value_type<ContainerType>;
942 m_buffer.template set<value_type>( size);
943 auto& buffer = m_buffer.template get<value_type>( );
944 err = detail::get_vara_T( m_grp, varid, slab.startp(), slab.countp(),
945 buffer.data());
946 dg::assign ( buffer, data);
947 }
948 else
949 {
950 data.resize( size);
951 err = detail::get_vara_T( m_grp, varid, slab.startp(), slab.countp(),
952 thrust::raw_pointer_cast(data.data()));
953 }
954 }
955
964 template<class T, std::enable_if_t< dg::is_scalar_v<T>, bool> = true>
965 void get_var( std::string name, const std::vector<size_t>& start, T& data) const
966 {
967 int varid = name2varid( name);
969 int ndims;
970 err = nc_inq_varndims( m_grp, varid, &ndims);
971 assert( (unsigned)ndims == start.size());
972 if( ndims == 0)
973 err = detail::get_vara_T( m_grp, varid, NULL, NULL, &data);
974 else
975 {
976 std::vector<size_t> count( start.size(), 1);
977 err = detail::get_vara_T( m_grp, varid, &start[0], &count[0], &data);
978 }
979 }
980
990 template<class ContainerType, std::enable_if_t< dg::is_vector_v<
991 ContainerType, SharedVectorTag>, bool > = true>
992 ContainerType get_var_as( std::string name, const NcHyperslab& slab) const
993 {
994 ContainerType data;
995 get_var( name, slab, data);
996 return data;
997 }
1004 template<class ContainerType, std::enable_if_t< dg::is_vector_v<
1005 ContainerType, SharedVectorTag>, bool > = true>
1006 ContainerType get_var_as( std::string name) const
1007 {
1008 // ! Does not work for MPI !
1009 return get_var_as<ContainerType>( name, {*this, name});
1010 }
1011
1021 template<class T, std::enable_if_t< dg::is_scalar_v<T>, bool> = true>
1022 T get_var_as( std::string name, const std::vector<size_t>& start = {}) const
1023 {
1024 T var;
1025 get_var( name, start, var);
1026 return var;
1027 }
1028
1031 bool var_is_defined( std::string name) const
1032 {
1033 check_open();
1034 int varid=0;
1035 int retval = nc_inq_varid( m_grp, name.c_str(), &varid);
1036 return retval == NC_NOERR;
1037 }
1038
1041 nc_type get_var_type(std::string name) const
1042 {
1043 int varid = name2varid( name);
1044 int xtype;
1046 err = nc_inq_vartype( m_grp, varid, &xtype);
1047 return xtype;
1048 }
1056 std::vector<std::string> get_var_dims(std::string name) const
1057 {
1058 int varid = name2varid( name);
1060
1061 int ndims;
1062 err = nc_inq_varndims( m_grp, varid, &ndims);
1063 if( ndims == 0)
1064 return {};
1065 std::vector<int> dimids(ndims);
1066 err = nc_inq_vardimid( m_grp, varid, &dimids[0]);
1067
1068 std::vector<std::string> dims(ndims);
1069 for( int i=0; i<ndims; i++)
1070 {
1071 char dimname [ NC_MAX_NAME+1];
1072 err = nc_inq_dimname( m_grp, dimids[i], dimname);
1073 dims[i] = dimname;
1074 }
1075 return dims;
1076 }
1077
1087 std::list<std::string> get_var_names() const
1088 {
1089 check_open();
1090 return get_var_names_private( m_grp);
1091 }
1092
1093 private:
1094 int name2varid( std::string id) const
1095 {
1096 // Variable ids are persistent once created
1097 // Attribute ids can change if one deletes attributes
1098 // This is fast even for lots variables (1000 vars take <ms)
1099 check_open();
1100 NC_Error_Handle err;
1101 int varid;
1102 if ( id == "")
1103 varid = NC_GLOBAL;
1104 else
1105 {
1106 err = nc_inq_varid( m_grp, id.c_str(), &varid);
1107 }
1108 return varid;
1109
1110 }
1111 // Absolute current path
1112 std::filesystem::path get_grp_path( int ncid ) const
1113 {
1114 size_t len;
1115 NC_Error_Handle err;
1116 err = nc_inq_grpname_full( ncid, &len, NULL);
1117 std::string current( len, 'x');
1118 err = nc_inq_grpname_full( ncid, &len, &current[0]);
1119 return current;
1120 }
1121 // Absolute paths of subgroups
1122 std::map<int, std::filesystem::path> get_grps_abs( int ncid ) const
1123 {
1124 NC_Error_Handle err;
1125 int num_grps;
1126 err = nc_inq_grps( ncid, &num_grps, NULL);
1127 if( num_grps == 0)
1128 return {};
1129 std::vector<int> group_ids( num_grps);
1130 err = nc_inq_grps( ncid, &num_grps, &group_ids[0]);
1131 std::map<int, std::filesystem::path> groups;
1132 for( int i=0; i<num_grps; i++)
1133 {
1134 size_t len;
1135 err = nc_inq_grpname_full( group_ids[i], &len, NULL);
1136 std::string name( len, 'z');
1137 err = nc_inq_grpname_full( group_ids[i], &len, &name[0]);
1138 groups[group_ids[i]] = name;
1139 }
1140 return groups;
1141 }
1142 std::map<int, std::filesystem::path> get_grps_abs_r( int ncid) const
1143 {
1144 auto grps = get_grps_abs(ncid);
1145 for( auto grp : grps)
1146 {
1147 auto subgrps = get_grps_abs_r( grp.first);
1148 grps.merge( subgrps);
1149 }
1150 return grps;
1151 }
1152 // Need a different name so mpi_file can invoke
1153 std::list<std::string> get_var_names_private(int grpid) const
1154 {
1155 std::list<std::string> vars;
1156 int num_vars = 0, num_dims;
1157 file::NC_Error_Handle err;
1158 err = nc_inq(grpid, &num_dims, &num_vars, NULL, NULL);
1159 // https://docs.unidata.ucar.edu/netcdf-c/current/reading_unknown.html
1160 for( int i=0; i<num_vars; i++)
1161 {
1162 char name[NC_MAX_NAME+1]; // 256
1163 err = nc_inq_varname( grpid, i, name);
1164 vars.push_back( name);
1165 }
1166 return vars;
1167 }
1168
1169
1170 void check_open() const
1171 {
1172 if( !m_open)
1173 throw NC_Error( 1000);
1174 }
1175
1176 bool m_open = false;
1177 int m_ncid = 0; // ncid can change by closing and re-opening a file
1178 int m_grp = 0;
1179 // the currently active group (All group ids in all open files are unique
1180 // and thus group ids can be different by opening the same file twice),
1181 // dims can be seen by all child groups
1182
1183 // Buffer for device to host transfer, and dg::assign
1184 mutable dg::detail::AnyVector<thrust::host_vector> m_buffer;
1185 // ABANDONED: Variable tracker (persists on closing and opening a different
1186 // file) The problem with trying to track is
1187 // 1) do we track every file that is opened?
1188 // 2) we cannot prevent someone from opening closing a file here and simply
1189 // opening the same file somewhere else. The info is lost or corrupted then
1190 //std::map<std::filesystem::path, std::map<std::filesystem::path, NcVarInfo>>
1191 // m_vars;
1192};
1193
1194#ifndef MPI_VERSION
1197using NcFile = SerialNcFile;
1198#endif // MPI_VERSION
1199
1200}// namespace file
1201}// namespace dg
MPINcFile NcFile
Definition nc_mpi_file.h:722
NcFileMode
Convenience NetCDF file opening/create flags.
Definition nc_file.h:121
@ nc_clobber
Call nc_create( path, NC_CLOBBER | NC_NETCDF4, ...);Create a new netCDF-4 file for read and write acc...
Definition nc_file.h:124
@ nc_nowrite
Call nc_open(path, NC_NOWRITE, ...);. Open an existing file for read-only access, fail if it does not...
Definition nc_file.h:122
@ nc_write
Call nc_open(path, NC_WRITE, ...)Open an existing (netCDF-4 file for read and write access,...
Definition nc_file.h:123
@ nc_noclobber
Call nc_create( path, NC_NOCLOBBER | NC_NETCDF4, ...); Create new netCDF-4 file for read and write ac...
Definition nc_file.h:125
Definition easy_atts.h:15
DEPRECATED Empty utitlity class that handles return values of netcdf functions and throws NC_Error(st...
Definition nc_error.h:70
Class thrown by the NC_Error_Handle.
Definition nc_error.h:20
char const * what() const noexcept
What string.
Definition nc_error.h:35
A NetCDF Hyperslab for SerialNcFile.
Definition nc_hyperslab.h:27
const size_t * countp() const
Definition nc_hyperslab.h:135
const std::vector< size_t > & count() const
Definition nc_hyperslab.h:127
const size_t * startp() const
Definition nc_hyperslab.h:133
unsigned ndim() const
Definition nc_hyperslab.h:122
Serial NetCDF-4 file.
Definition nc_file.h:151
T get_att_as(std::string att_name, std::string id="") const
Get an attribute named att_name of the group or variable id.
Definition nc_file.h:660
void sync()
Call nc_sync.
Definition nc_file.h:266
void get_var(std::string name, const std::vector< size_t > &start, T &data) const
Read scalar from position start from variable named name.
Definition nc_file.h:965
std::vector< std::string > get_var_dims(std::string name) const
Get the dimension names associated to variable name.
Definition nc_file.h:1056
ContainerType get_var_as(std::string name, const NcHyperslab &slab) const
Convenience shortcut (vector version)
Definition nc_file.h:992
void def_grp(std::string name)
Define a group named name in the current group.
Definition nc_file.h:304
void defput_var(std::string name, const std::vector< std::string > &dim_names, const Attributes &atts, const NcHyperslab &slab, const ContainerType &data)
Define and put a variable in one go.
Definition nc_file.h:838
void put_att(const std::tuple< S, nc_type, T > &att, std::string id="")
Put an individual attribute of preset type to variable id.
Definition nc_file.h:620
void put_att(const std::pair< std::string, nc_att_t > &att, std::string id="")
Put an individual attribute.
Definition nc_file.h:604
void del_att(std::string att_name, std::string id="")
Remove an attribute named att_name from variable id.
Definition nc_file.h:708
ContainerType get_var_as(std::string name) const
Convenience shortcut for get_var_as<ContainerType>( name, {*this, name});
Definition nc_file.h:1006
SerialNcFile(SerialNcFile &&rhs)=default
Swap resources between two file handles.
std::vector< size_t > get_dims_shape(const std::vector< std::string > &dims) const
Get the size of each dimension in dims.
Definition nc_file.h:515
void rename_dim(std::string old_name, std::string new_name)
Rename a dimension from old_name to new_name.
Definition nc_file.h:487
void rename_att(std::string old_att_name, std::string new_att_name, std::string id="")
Rename an attribute of the variable id.
Definition nc_file.h:733
std::list< std::filesystem::path > get_grps_r() const
Get all subgroups recursively in the current group as absolute paths.
Definition nc_file.h:456
SerialNcFile(const SerialNcFile &rhs)=delete
There can only be exactly one file handle per physical file.
bool var_is_defined(std::string name) const
Definition nc_file.h:1031
std::list< std::string > get_var_names() const
Get a list of variable names in the current group.
Definition nc_file.h:1087
void put_atts(const Attributes &atts, std::string id="")
Write a collection of attributes to a NetCDF variable or file.
Definition nc_file.h:640
nc_type get_var_type(std::string name) const
Definition nc_file.h:1041
std::map< std::string, nc_att_t > get_atts(std::string id="") const
Definition nc_file.h:693
bool is_open() const noexcept
Definition nc_file.h:237
void def_var(std::string name, nc_type xtype, const std::vector< std::string > &dim_names, const Attributes &atts={})
Define a variable with given type, dimensions and (optionally) attributes.
Definition nc_file.h:776
void def_grp_p(std::filesystem::path path)
Define a group named path and all required intermediary groups.
Definition nc_file.h:323
void defput_dim(std::string name, const Attributes &atts, const ContainerType &abscissas)
Define a dimension and define and write to a dimension variable in one go.
Definition nc_file.h:908
void set_grp(std::filesystem::path path="")
Change group to path.
Definition nc_file.h:386
std::filesystem::path get_current_path() const
Get the absolute path of the current group.
Definition nc_file.h:428
bool dim_is_defined(std::string name) const
Definition nc_file.h:590
void def_dim(std::string name, size_t size)
Define a dimension named name of size size.
Definition nc_file.h:479
void get_var(std::string name, const NcHyperslab &slab, ContainerType &data) const
Read hyperslab slab from variable named name into container data.
Definition nc_file.h:928
~SerialNcFile()
Close open nc file and release all resources.
Definition nc_file.h:185
std::vector< T > get_att_vec_as(std::string att_name, std::string id="") const
Short for get_att_as<std::vector<T>>( id, att_name);
Definition nc_file.h:668
int get_grpid() const noexcept
Get the NetCDF-C ID of the current group.
Definition nc_file.h:425
int get_format() const
Check the binary file format of the netCDF file.
Definition nc_file.h:287
SerialNcFile(const std::filesystem::path &filename, enum NcFileMode mode=nc_nowrite)
Open/Create a netCDF file.
Definition nc_file.h:161
void put_var(std::string name, const std::vector< size_t > &start, T data)
Write a single data point.
Definition nc_file.h:858
void close()
Explicitly close a file.
Definition nc_file.h:252
SerialNcFile & operator=(const SerialNcFile &rhs)=delete
There can only be exactly one file handle per physical file.
bool grp_is_defined(std::filesystem::path path) const
Check for existence of the group given by path.
Definition nc_file.h:361
bool att_is_defined(std::string att_name, std::string id="") const
Definition nc_file.h:717
T get_var_as(std::string name, const std::vector< size_t > &start={}) const
Convenience shortcut (scalar version)
Definition nc_file.h:1022
std::vector< std::string > get_unlim_dims() const
Get all visible unlimited dimension names in the current group.
Definition nc_file.h:564
void put_var(std::string name, const NcHyperslab &slab, const ContainerType &data)
Write data to a variable.
Definition nc_file.h:803
std::vector< std::string > get_dims(bool include_parents=true) const
Get all visible dimension names in the current group.
Definition nc_file.h:532
void def_dimvar_as(std::string name, size_t size, const Attributes &atts)
Define a dimension and dimension variable in one go.
Definition nc_file.h:885
int get_ncid() const noexcept
Get the ncid of the underlying NetCDF C-API.
Definition nc_file.h:278
size_t get_dim_size(std::string name) const
Get the size of the dimension named name.
Definition nc_file.h:502
void def_var_as(std::string name, const std::vector< std::string > &dim_names, const Attributes &atts={})
Define a variable with given type, dimensions and (optionally) attributes.
Definition nc_file.h:757
std::map< std::string, T > get_atts_as(std::string id="") const
Read all NetCDF attributes of a certain type.
Definition nc_file.h:685
std::list< std::filesystem::path > get_grps() const
Get all subgroups in the current group as absolute paths.
Definition nc_file.h:436
void rename_grp(std::string old_name, std::string new_name)
rename a subgroup in the current group from old_name to new_name
Definition nc_file.h:415
void open(const std::filesystem::path &filename, enum NcFileMode mode=nc_nowrite)
Open/Create a netCDF file.
Definition nc_file.h:205