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{
101
123{
125 // ///////////////////////////// CONSTRUCTORS/DESTRUCTOR /////////
128 SerialNcFile () = default;
141 SerialNcFile(const std::filesystem::path& filename,
142 enum NcFileMode mode = nc_nowrite)
143 {
144 open( filename, mode);
145 }
152 SerialNcFile(const SerialNcFile& rhs) = delete;
154 SerialNcFile& operator =(const SerialNcFile & rhs) = delete;
155
158 SerialNcFile(SerialNcFile&& rhs) = default;
161
166 {
167 try
168 {
169 close();
170 }
171 catch (NC_Error &e)
172 {
173 std::cerr << e.what() << std::endl;
174 }
175 }
176 // /////////////////// open/close /////////
177
191 void open(const std::filesystem::path& filename,
192 enum NcFileMode mode = nc_nowrite)
193 {
194 // Like a std::fstream opening fails if file already associated
195 if( m_open)
196 throw NC_Error( 1002);
197
198 // TODO Test the pathing on Windows
199 NC_Error_Handle err;
200 switch (mode)
201 {
202 case nc_nowrite:
203 err = nc_open( filename.string().c_str(), NC_NETCDF4 |
204 NC_NOWRITE, &m_ncid);
205 break;
206 case nc_write:
207 err = nc_open( filename.string().c_str(), NC_NETCDF4 |
208 NC_WRITE, &m_ncid);
209 break;
210 case nc_noclobber:
211 err = nc_create( filename.string().c_str(), NC_NETCDF4 |
212 NC_NOCLOBBER, &m_ncid);
213 break;
214 case nc_clobber:
215 err = nc_create( filename.string().c_str(), NC_NETCDF4 |
216 NC_CLOBBER, &m_ncid);
217 break;
218 }
219 m_open = true;
220 m_grp = m_ncid;
221 }
224 bool is_open() const noexcept
225 {
226 // is_closed() == not is_open()
227 return m_open;
228 }
229
239 void close()
240 {
241 // when the file is closed the ncid may be assigned to a new file
242 if (m_open)
243 {
244 NC_Error_Handle err;
245 err = nc_close(m_ncid);
246 }
247
248 m_open = false;
249 m_grp = m_ncid = 0;
250 }
251
253 void sync()
254 {
255 check_open();
256 NC_Error_Handle err;
257 err = nc_sync( m_ncid);
258 }
265 int get_ncid() const noexcept{ return m_ncid;}
266
267 // ///////////// Groups /////////////////
276 void def_grp( std::string name)
277 {
278 check_open();
279 int new_grp_id = 0;
280 NC_Error_Handle err;
281 err = nc_def_grp( m_grp, name.c_str(), &new_grp_id);
282 // we just forget the id => always need to ask netcdf for id
283 // Is no performance hit as cached
284 }
285
295 void def_grp_p( std::filesystem::path path)
296 {
297 check_open();
298 if( not path.has_root_path()) // it is a relative path
299 {
300 auto current = get_current_path();
301 path = (current / path);
302 }
303 int groupid = m_ncid;
304 auto rel_path = path.relative_path();
305 NC_Error_Handle err;
306 for( auto it = rel_path.begin(); it != rel_path.end(); it++)
307 {
308#ifdef _MSC_VER
309 // https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string
310 std::wstring string_to_convert = *it;
311 //setup converter
312 using convert_type = std::codecvt_utf8<wchar_t>;
313 std::wstring_convert<convert_type, wchar_t> converter;
314
315 //use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
316 std::string grp = converter.to_bytes(string_to_convert);
317
318#else
319 std::string grp = *it;
320#endif // MSVC
321 int new_grpid;
322 int retval = nc_inq_ncid( groupid, grp.c_str(), &new_grpid);
323 if( retval != NC_NOERR)
324 err = nc_def_grp( groupid, grp.c_str(), &groupid);
325 else
326 groupid = new_grpid;
327 }
328 }
333 bool grp_is_defined( std::filesystem::path path) const
334 {
335 check_open();
336 std::string name = path.generic_string();
337 if( not path.has_root_path()) // it is a relative path
338 {
339 auto current = get_current_path();
340 name = (current / path ).generic_string();
341 }
342 int grpid=0;
343 int retval = nc_inq_grp_full_ncid( m_ncid, name.c_str(), &grpid);
344 return retval == NC_NOERR;
345 }
355 void set_grp( std::filesystem::path path = "")
356 {
357 check_open();
358 NC_Error_Handle err;
359 std::string name = path.generic_string();
360 if ( name == ".")
361 return;
362 if ( name == "" or name == "/")
363 {
364 m_grp = m_ncid;
365 }
366 else if ( name == "..")
367 {
368 if( m_grp == m_ncid)
369 return;
370 err = nc_inq_grp_parent( m_grp, &m_grp);
371 }
372 else
373 {
374 if( not path.has_root_path()) // it is a relative path
375 {
376 auto current = get_current_path();
377 name = (current / path ).generic_string();
378 }
379 err = nc_inq_grp_full_ncid( m_ncid, name.c_str(), &m_grp);
380 }
381 }
384 void rename_grp( std::string old_name, std::string new_name)
385 {
386 check_open();
387 NC_Error_Handle err;
388 int old_grp;
389 err = nc_inq_grp_ncid( m_grp, old_name.c_str(), &old_grp);
390 err = nc_rename_grp( old_grp, new_name.c_str());
391 }
392
394 int get_grpid() const noexcept{ return m_grp;}
395
397 std::filesystem::path get_current_path( ) const
398 {
399 check_open();
400 return get_grp_path( m_grp);
401 }
402
405 std::list<std::filesystem::path> get_grps( ) const
406 {
407 check_open();
408 auto grps = get_grps_abs(m_grp);
409 std::list<std::filesystem::path> grps_v;
410 for( auto grp : grps)
411 grps_v.push_back( grp.second);
412 return grps_v;
413
414 }
425 std::list<std::filesystem::path> get_grps_r( ) const
426 {
427 auto grps = get_grps_abs_r(m_grp);
428 std::list<std::filesystem::path> grps_v;
429 for( auto grp : grps)
430 grps_v.push_back( grp.second);
431 return grps_v;
432 }
433
434 // //////////// Dimensions ////////////////////////
448 void def_dim( std::string name, size_t size)
449 {
450 check_open();
451 NC_Error_Handle err;
452 int dim_id;
453 err = nc_def_dim( m_grp, name.c_str(), size, &dim_id);
454 }
456 void rename_dim( std::string old_name, std::string new_name)
457 {
458 check_open();
459 int dimid;
460 NC_Error_Handle err;
461 err = nc_inq_dimid( m_grp, old_name.c_str(), &dimid);
462 err = nc_rename_dim( m_grp, dimid, new_name.c_str());
463 }
471 size_t get_dim_size( std::string name) const
472 {
473 check_open();
474 NC_Error_Handle err;
475 int dimid;
476 err = nc_inq_dimid( m_grp, name.c_str(), &dimid);
477 size_t len;
478 err = nc_inq_dimlen( m_grp, dimid, &len);
479 return len;
480
481 }
482
484 std::vector<size_t> get_dims_shape( const std::vector<std::string>& dims) const
485 {
486 std::vector<size_t> shape( dims.size());
487 for( unsigned u=0; u<dims.size(); u++)
488 shape[u] = get_dim_size( dims[u]);
489 return shape;
490 }
501 std::vector<std::string> get_dims( bool include_parents = true) const
502 {
503 check_open();
504 NC_Error_Handle err;
505 // There is a correct way of getting the dimensions in a group
506 // https://github.com/Unidata/netcdf-c/issues/2873
507 int ndims;
508 err = nc_inq_dimids( m_grp, &ndims, NULL, include_parents);
509 if( ndims == 0)
510 return {};
511 std::vector<int> dimids(ndims);
512 err = nc_inq_dimids( m_grp, &ndims, &dimids[0], include_parents);
513 // Globally dimension ids are 0, 1, 2, ... in the order in which the
514 // dimensions were defined
515 std::vector<std::string> dims;
516 for ( int i = 0; i < ndims; i++)
517 {
518 char dimname [ NC_MAX_NAME+1];
519 err = nc_inq_dimname( m_grp, dimids[i], dimname);
520 if( std::find(dims.begin(), dims.end(), std::string(dimname) ) ==
521 dims.end())
522 dims.push_back(dimname);
523 }
524 return dims;
525 }
526
533 std::vector<std::string> get_unlim_dims( ) const
534 {
535 check_open();
536 int ndims;
537 NC_Error_Handle err;
538 err = nc_inq_unlimdims( m_grp, &ndims, NULL);
539 if( ndims == 0)
540 return {};
541 std::vector<int> dimids(ndims);
542 // Our tests indicate that this does not return the unlimited dimensions
543 // of the parent group even though the documentation says so...
544 err = nc_inq_unlimdims( m_grp, &ndims, &dimids[0]);
545 std::vector<std::string> dims;
546 for( int i=0; i<ndims; i++)
547 {
548 char dimname [ NC_MAX_NAME+1];
549 err = nc_inq_dimname( m_grp, dimids[i], dimname);
550 if( std::find(dims.begin(), dims.end(), std::string(dimname) ) ==
551 dims.end())
552 dims.push_back(dimname);
553 }
554 return dims;
555 }
556
559 bool dim_is_defined( std::string name) const
560 {
561 int dimid=0;
562 int retval = nc_inq_dimid( m_grp, name.c_str(), &dimid);
563 return retval == NC_NOERR;
564 }
566
573 void put_att( const std::pair<std::string, nc_att_t>& att, std::string id = "")
574 {
575 int varid = name2varid( id);
576 dg::file::detail::put_att( m_grp, varid, att);
577 }
578
588 template<class S, class T> // T cannot be nc_att_t
589 void put_att( const std::tuple<S,nc_type, T>& att, std::string id = "")
590 {
591 int varid = name2varid( id);
592 dg::file::detail::put_att( m_grp, varid, att);
593 }
608 template<class Attributes = std::map<std::string, nc_att_t> > // *it must be usable in put_att
609 void put_atts(const Attributes& atts, std::string id = "")
610 {
611 int varid = name2varid( id);
612 dg::file::detail::put_atts( m_grp, varid, atts);
613 }
614
615 // ///////////////// Attribute getters
616
628 template<class T>
629 T get_att_as(std::string att_name, std::string id = "") const
630 {
631 int varid = name2varid( id);
632 return dg::file::detail::get_att_as<T>( m_grp, varid, att_name);
633 }
634
636 template<class T>
637 std::vector<T> get_att_vec_as(std::string att_name, std::string id = "") const
638 {
639 return get_att_as<std::vector<T>>( att_name, id);
640 }
641
654 template<class T>
655 std::map<std::string, T> get_atts_as( std::string id = "") const
656 {
657 int varid = name2varid( id);
658 return dg::file::detail::get_atts_as<T>( m_grp, varid);
659 }
660
663 std::map<std::string, nc_att_t> get_atts( std::string id = "") const
664 {
665 return get_atts_as<nc_att_t>( id);
666 }
667
678 void del_att(std::string att_name, std::string id = "")
679 {
680 int varid = name2varid( id);
681 auto name = att_name.c_str();
682 NC_Error_Handle err;
683 err = nc_del_att( m_grp, varid, name);
684 }
687 bool att_is_defined(std::string att_name, std::string id = "") const
688 {
689 int varid = name2varid( id);
690 int attid;
691 int retval = nc_inq_attid( m_grp, varid, att_name.c_str(), &attid);
692 return retval == NC_NOERR;
693 }
696 void rename_att(std::string old_att_name, std::string
697 new_att_name, std::string id = "")
698 {
699 int varid = name2varid( id);
700 auto old_name = old_att_name.c_str();
701 auto new_name = new_att_name.c_str();
702 NC_Error_Handle err;
703 err = nc_rename_att( m_grp, varid, old_name, new_name);
704 }
705
706 // //////////// Variables ////////////////////////
719 template<class T, class Attributes = std::map<std::string, nc_att_t>>
720 void def_var_as( std::string name,
721 const std::vector<std::string>& dim_names,
722 const Attributes& atts = {})
723 {
724 def_var( name, detail::getNCDataType<T>(), dim_names, atts);
725 }
726
738 template<class Attributes = std::map<std::string, nc_att_t>>
739 void def_var( std::string name, nc_type xtype,
740 const std::vector<std::string>& dim_names,
741 const Attributes& atts = {})
742 {
744 std::vector<int> dimids( dim_names.size());
745 for( unsigned u=0; u<dim_names.size(); u++)
746 err = nc_inq_dimid( m_grp, dim_names[u].c_str(), &dimids[u]);
747 int varid;
748 err = nc_def_var( m_grp, name.c_str(), xtype, dim_names.size(),
749 &dimids[0], &varid);
750 put_atts( atts, name);
751 }
752
764 template<class ContainerType, std::enable_if_t< dg::is_vector_v<
765 ContainerType, SharedVectorTag>, bool > = true>
766 void put_var( std::string name, const NcHyperslab& slab,
767 const ContainerType& data)
768 {
769 int varid = name2varid( name);
771 int ndims;
772 err = nc_inq_varndims( m_grp, varid, &ndims);
773 assert( (unsigned)ndims == slab.ndim());
774 if constexpr ( dg::has_policy_v<ContainerType, dg::CudaTag>)
775 {
776 using value_type = dg::get_value_type<ContainerType>;
777 m_buffer.template set<value_type>( data.size());
778 auto& buffer = m_buffer.template get<value_type>( );
779 dg::assign ( data, buffer);
780 err = detail::put_vara_T( m_grp, varid, slab.startp(), slab.countp(),
781 buffer.data());
782 }
783 else
784 err = detail::put_vara_T( m_grp, varid, slab.startp(), slab.countp(),
785 thrust::raw_pointer_cast(data.data()));
786 }
787
799 template<class ContainerType, class Attributes = std::map<std::string, nc_att_t>,
800 std::enable_if_t< dg::is_vector_v<ContainerType, SharedVectorTag>, bool > = true>
801 void defput_var( std::string name, const std::vector<std::string>& dim_names,
802 const Attributes& atts, const NcHyperslab& slab,
803 const ContainerType& data)
804 {
805 def_var_as<dg::get_value_type<ContainerType>>( name, dim_names, atts);
806 put_var( name, slab, data);
807 }
808
820 template<class T, std::enable_if_t< dg::is_scalar_v<T>, bool> = true>
821 void put_var( std::string name, const std::vector<size_t>& start, T data)
822 {
823 int varid = name2varid( name);
825 std::vector<size_t> count( start.size(), 1);
826 err = detail::put_vara_T( m_grp, varid, &start[0], &count[0], &data);
827 }
828
847 template<class T, class Attributes = std::map<std::string, nc_att_t>>
848 void def_dimvar_as( std::string name, size_t size, const Attributes& atts)
849 {
850 def_dim( name, size);
851 def_var_as<T>( name, {name}, atts);
852 }
853
870 template<class ContainerType, class Attributes = std::map<std::string, nc_att_t>>
871 void defput_dim( std::string name,
872 const Attributes& atts,
873 const ContainerType& abscissas)
874 {
876 abscissas.size(), atts);
877 put_var( name, {abscissas}, abscissas);
878 }
879
889 template<class ContainerType, std::enable_if_t< dg::is_vector_v<
890 ContainerType, SharedVectorTag>, bool > = true>
891 void get_var( std::string name, const NcHyperslab& slab,
892 ContainerType& data) const
893 {
894 int varid = name2varid( name);
896 int ndims;
897 err = nc_inq_varndims( m_grp, varid, &ndims);
898 assert( (unsigned)ndims == slab.ndim());
899 unsigned size = 1;
900 for( unsigned u=0; u<slab.ndim(); u++)
901 size *= slab.count()[u];
902 if constexpr ( dg::has_policy_v<ContainerType, dg::CudaTag>)
903 {
904 using value_type = dg::get_value_type<ContainerType>;
905 m_buffer.template set<value_type>( size);
906 auto& buffer = m_buffer.template get<value_type>( );
907 err = detail::get_vara_T( m_grp, varid, slab.startp(), slab.countp(),
908 buffer.data());
909 dg::assign ( buffer, data);
910 }
911 else
912 {
913 data.resize( size);
914 err = detail::get_vara_T( m_grp, varid, slab.startp(), slab.countp(),
915 thrust::raw_pointer_cast(data.data()));
916 }
917 }
918
927 template<class T, std::enable_if_t< dg::is_scalar_v<T>, bool> = true>
928 void get_var( std::string name, const std::vector<size_t>& start, T& data) const
929 {
930 int varid = name2varid( name);
932 int ndims;
933 err = nc_inq_varndims( m_grp, varid, &ndims);
934 assert( (unsigned)ndims == start.size());
935 if( ndims == 0)
936 err = detail::get_vara_T( m_grp, varid, NULL, NULL, &data);
937 else
938 {
939 std::vector<size_t> count( start.size(), 1);
940 err = detail::get_vara_T( m_grp, varid, &start[0], &count[0], &data);
941 }
942 }
943
946 bool var_is_defined( std::string name) const
947 {
948 check_open();
949 int varid=0;
950 int retval = nc_inq_varid( m_grp, name.c_str(), &varid);
951 return retval == NC_NOERR;
952 }
953
956 nc_type get_var_type(std::string name) const
957 {
958 int varid = name2varid( name);
959 int xtype;
961 err = nc_inq_vartype( m_grp, varid, &xtype);
962 return xtype;
963 }
971 std::vector<std::string> get_var_dims(std::string name) const
972 {
973 int varid = name2varid( name);
975
976 int ndims;
977 err = nc_inq_varndims( m_grp, varid, &ndims);
978 if( ndims == 0)
979 return {};
980 std::vector<int> dimids(ndims);
981 err = nc_inq_vardimid( m_grp, varid, &dimids[0]);
982
983 std::vector<std::string> dims(ndims);
984 for( int i=0; i<ndims; i++)
985 {
986 char dimname [ NC_MAX_NAME+1];
987 err = nc_inq_dimname( m_grp, dimids[i], dimname);
988 dims[i] = dimname;
989 }
990 return dims;
991 }
992
1002 std::list<std::string> get_var_names() const
1003 {
1004 check_open();
1005 return get_var_names_private( m_grp);
1006 }
1007
1008 private:
1009 int name2varid( std::string id) const
1010 {
1011 // Variable ids are persistent once created
1012 // Attribute ids can change if one deletes attributes
1013 // This is fast even for lots variables (1000 vars take <ms)
1014 check_open();
1015 NC_Error_Handle err;
1016 int varid;
1017 if ( id == "")
1018 varid = NC_GLOBAL;
1019 else
1020 {
1021 err = nc_inq_varid( m_grp, id.c_str(), &varid);
1022 }
1023 return varid;
1024
1025 }
1026 // Absolute current path
1027 std::filesystem::path get_grp_path( int ncid ) const
1028 {
1029 size_t len;
1030 NC_Error_Handle err;
1031 err = nc_inq_grpname_full( ncid, &len, NULL);
1032 std::string current( len, 'x');
1033 err = nc_inq_grpname_full( ncid, &len, &current[0]);
1034 return current;
1035 }
1036 // Absolute paths of subgroups
1037 std::map<int, std::filesystem::path> get_grps_abs( int ncid ) const
1038 {
1039 NC_Error_Handle err;
1040 int num_grps;
1041 err = nc_inq_grps( ncid, &num_grps, NULL);
1042 if( num_grps == 0)
1043 return {};
1044 std::vector<int> group_ids( num_grps);
1045 err = nc_inq_grps( ncid, &num_grps, &group_ids[0]);
1046 std::map<int, std::filesystem::path> groups;
1047 for( int i=0; i<num_grps; i++)
1048 {
1049 size_t len;
1050 err = nc_inq_grpname_full( group_ids[i], &len, NULL);
1051 std::string name( len, 'z');
1052 err = nc_inq_grpname_full( group_ids[i], &len, &name[0]);
1053 groups[group_ids[i]] = name;
1054 }
1055 return groups;
1056 }
1057 std::map<int, std::filesystem::path> get_grps_abs_r( int ncid) const
1058 {
1059 auto grps = get_grps_abs(ncid);
1060 for( auto grp : grps)
1061 {
1062 auto subgrps = get_grps_abs_r( grp.first);
1063 grps.merge( subgrps);
1064 }
1065 return grps;
1066 }
1067 // Need a different name so mpi_file can invoke
1068 std::list<std::string> get_var_names_private(int grpid) const
1069 {
1070 std::list<std::string> vars;
1071 int num_vars = 0, num_dims;
1072 file::NC_Error_Handle err;
1073 err = nc_inq(grpid, &num_dims, &num_vars, NULL, NULL);
1074 // https://docs.unidata.ucar.edu/netcdf-c/current/reading_unknown.html
1075 for( int i=0; i<num_vars; i++)
1076 {
1077 char name[NC_MAX_NAME+1]; // 256
1078 err = nc_inq_varname( grpid, i, name);
1079 vars.push_back( name);
1080 }
1081 return vars;
1082 }
1083
1084
1085 void check_open() const
1086 {
1087 if( !m_open)
1088 throw NC_Error( 1000);
1089 }
1090
1091 bool m_open = false;
1092 int m_ncid = 0; // ncid can change by closing and re-opening a file
1093 int m_grp = 0;
1094 // the currently active group (All group ids in all open files are unique
1095 // and thus group ids can be different by opening the same file twice),
1096 // dims can be seen by all child groups
1097
1098 // Buffer for device to host transfer, and dg::assign
1099 mutable dg::detail::AnyVector<thrust::host_vector> m_buffer;
1100 // ABANDONED: Variable tracker (persists on closing and opening a different
1101 // file) The problem with trying to track is
1102 // 1) do we track every file that is opened?
1103 // 2) we cannot prevent someone from opening closing a file here and simply
1104 // opening the same file somewhere else. The info is lost or corrupted then
1105 //std::map<std::filesystem::path, std::map<std::filesystem::path, NcVarInfo>>
1106 // m_vars;
1107};
1108
1109#ifndef MPI_VERSION
1112using NcFile = SerialNcFile;
1113#endif // MPI_VERSION
1114
1115}// namespace file
1116}// namespace dg
MPINcFile NcFile
Definition nc_mpi_file.h:693
NcFileMode
NetCDF file format.
Definition nc_file.h:95
@ nc_clobber
NC_CLOBBER Create a new file for read and write access, overwrite if file exists.
Definition nc_file.h:98
@ nc_nowrite
NC_NOWRITE Open an existing file for read-only access, fail if it does not exist.
Definition nc_file.h:96
@ nc_write
NC_WRITE Open an existing file for read and write access, fail if it does not exist.
Definition nc_file.h:97
@ nc_noclobber
NC_NOCLOBBER Create new file for read and write access, fail if already exists.
Definition nc_file.h:99
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:134
const std::vector< size_t > & count() const
Definition nc_hyperslab.h:126
const size_t * startp() const
Definition nc_hyperslab.h:132
unsigned ndim() const
Definition nc_hyperslab.h:121
Serial NetCDF-4 file.
Definition nc_file.h:123
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:629
void sync()
Call nc_sync.
Definition nc_file.h:253
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:928
std::vector< std::string > get_var_dims(std::string name) const
Get the dimension names associated to variable name.
Definition nc_file.h:971
void def_grp(std::string name)
Definition nc_file.h:276
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:801
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:589
void put_att(const std::pair< std::string, nc_att_t > &att, std::string id="")
Put an individual attribute.
Definition nc_file.h:573
void del_att(std::string att_name, std::string id="")
Remove an attribute named att_name from variable id.
Definition nc_file.h:678
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:484
void rename_dim(std::string old_name, std::string new_name)
Rename a dimension from old_name to new_name.
Definition nc_file.h:456
void rename_att(std::string old_att_name, std::string new_att_name, std::string id="")
Definition nc_file.h:696
std::list< std::filesystem::path > get_grps_r() const
Get all subgroups recursively in the current group as absolute paths.
Definition nc_file.h:425
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:946
std::list< std::string > get_var_names() const
Get a list of variable names in the current group.
Definition nc_file.h:1002
void put_atts(const Attributes &atts, std::string id="")
Write a collection of attributes to a NetCDF variable or file.
Definition nc_file.h:609
nc_type get_var_type(std::string name) const
Definition nc_file.h:956
std::map< std::string, nc_att_t > get_atts(std::string id="") const
Definition nc_file.h:663
bool is_open() const noexcept
Definition nc_file.h:224
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:739
void def_grp_p(std::filesystem::path path)
Definition nc_file.h:295
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:871
void set_grp(std::filesystem::path path="")
Change group to path.
Definition nc_file.h:355
std::filesystem::path get_current_path() const
Get the absolute path of the current group.
Definition nc_file.h:397
bool dim_is_defined(std::string name) const
Definition nc_file.h:559
void def_dim(std::string name, size_t size)
Define a dimension named name of size size.
Definition nc_file.h:448
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:891
~SerialNcFile()
Close open nc file and release all resources.
Definition nc_file.h:165
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:637
int get_grpid() const noexcept
Get the NetCDF-C ID of the current group.
Definition nc_file.h:394
SerialNcFile(const std::filesystem::path &filename, enum NcFileMode mode=nc_nowrite)
Open/Create a netCDF file.
Definition nc_file.h:141
void put_var(std::string name, const std::vector< size_t > &start, T data)
Write a single data point.
Definition nc_file.h:821
void close()
Explicitly close a file.
Definition nc_file.h:239
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:333
bool att_is_defined(std::string att_name, std::string id="") const
Definition nc_file.h:687
std::vector< std::string > get_unlim_dims() const
Definition nc_file.h:533
void put_var(std::string name, const NcHyperslab &slab, const ContainerType &data)
Write data to a variable.
Definition nc_file.h:766
std::vector< std::string > get_dims(bool include_parents=true) const
Definition nc_file.h:501
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:848
int get_ncid() const noexcept
Get the ncid of the underlying NetCDF C-API.
Definition nc_file.h:265
size_t get_dim_size(std::string name) const
Get the size of the dimension named name.
Definition nc_file.h:471
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:720
std::map< std::string, T > get_atts_as(std::string id="") const
Read all NetCDF attributes of a certain type.
Definition nc_file.h:655
std::list< std::filesystem::path > get_grps() const
Definition nc_file.h:405
void rename_grp(std::string old_name, std::string new_name)
Definition nc_file.h:384
void open(const std::filesystem::path &filename, enum NcFileMode mode=nc_nowrite)
Definition nc_file.h:191