ARTS 2.5.10 (git: 2f1c442c)
nc_io.cc
Go to the documentation of this file.
1/* Copyright (C) 2012 Oliver Lemke <olemke@core-dump.info>
2
3 This program is free software; you can redistribute it and/or modify it
4 under the terms of the GNU General Public License as published by the
5 Free Software Foundation; either version 2, or (at your option) any
6 later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 USA. */
17
19// File description
21
30#include "arts.h"
31
32#ifdef ENABLE_NETCDF
33
34#include "exceptions.h"
35#include "file.h"
36#include "messages.h"
37#include "nc_io.h"
38#include "nc_io_types.h"
39
41// Default file name
43
45
53void nca_filename(String &filename, const String &varname) {
54 if ("" == filename) {
55 extern const String out_basename;
56 filename = out_basename + "." + varname + ".nc";
57 }
58}
59
61
70void nca_filename_with_index(String &filename, const Index &file_index,
71 const String &varname) {
72 if ("" == filename) {
73 extern const String out_basename;
74 ostringstream os;
75 os << out_basename << "." << varname << "." << file_index << ".nc";
76 filename = os.str();
77 } else {
78 ostringstream os;
79 os << filename << "." << file_index << ".nc";
80 filename = os.str();
81 }
82}
83
85
92template <typename T>
93void nca_read_from_file(const String &filename, T &type,
94 const Verbosity &verbosity) {
96
97 String efilename = expand_path(filename);
98
99 out2 << " Reading " << efilename << '\n';
100
101 bool fail = false;
102 String fail_msg;
103#pragma omp critical(netcdf__critical_region)
104 {
105 int ncid;
106 if (nc_open(efilename.c_str(), NC_NOWRITE, &ncid)) {
107 fail = true;
108 fail_msg = "Error opening file. Does it exists?";
109 } else {
110 try {
111 nca_read_from_file(ncid, type, verbosity);
112 } catch (const std::runtime_error &e) {
113 fail = true;
114 fail_msg = e.what();
115 }
116 nc_close(ncid);
117 }
118 }
119
120 if (fail)
121 ARTS_USER_ERROR("Error reading file: ", efilename, '\n', fail_msg);
122}
123
125
132template <typename T>
133void nca_write_to_file(const String &filename, const T &type,
134 const Verbosity &verbosity) {
136
137 String efilename = add_basedir(filename);
138
139 out2 << " Writing " << efilename << '\n';
140
141 bool fail = false;
142 String fail_msg;
143#pragma omp critical(netcdf__critical_region)
144 {
145 int ncid;
146 if (nc_create(efilename.c_str(), NC_CLOBBER | NC_NETCDF4, &ncid)) {
147 fail = true;
148 fail_msg = "Error opening file for writing.";
149 } else {
150 try {
151 nca_write_to_file(ncid, type, verbosity);
152 } catch (const std::runtime_error &e) {
153 fail = true;
154 fail_msg = e.what();
155 }
156 nc_close(ncid);
157 }
158 }
159
160 if (fail)
161 ARTS_USER_ERROR("Error writing file: ", efilename, '\n', fail_msg);
162}
163
165
173void nca_def_dim(const int ncid, const String &name, const Index nelem,
174 int *ncdim) {
175 int retval;
176 if ((retval = nc_def_dim(ncid, name.c_str(), nelem, ncdim)))
177 nca_error(retval, "nc_def_dim");
178}
179
181
191void nca_def_var(const int ncid, const String &name, const nc_type type,
192 const int ndims, const int *dims, int *varid) {
193 int retval;
194 if ((retval = nc_def_var(ncid, name.c_str(), type, ndims, dims, varid)))
195 nca_error(retval, "nc_def_var");
196}
197
199
207int nca_def_ArrayOfIndex(const int ncid, const String &name,
208 const ArrayOfIndex &a) {
209 std::array<int, 1> ncdims;
210 int varid;
211 if (a.nelem()) {
212 nca_def_dim(ncid, name + "_nelem", a.nelem(), &ncdims[0]);
213 nca_def_var(ncid, name, NC_INT, 1, &ncdims[0], &varid);
214 } else
215 varid = -1;
216
217 return varid;
218}
219
221
229int nca_def_Vector(const int ncid, const String &name, const Vector &v) {
230 std::array<int, 1> ncdims;
231 int varid;
232 if (v.nelem()) {
233 nca_def_dim(ncid, name + "_nelem", v.nelem(), &ncdims[0]);
234 nca_def_var(ncid, name, NC_DOUBLE, 1, &ncdims[0], &varid);
235 } else
236 varid = -1;
237
238 return varid;
239}
240
242
250int nca_def_Matrix(const int ncid, const String &name, const Matrix &m) {
251 std::array<int, 2> ncdims;
252 int varid;
253 if (m.nrows() && m.ncols()) {
254 nca_def_dim(ncid, name + "_nrows", m.nrows(), &ncdims[0]);
255 nca_def_dim(ncid, name + "_ncols", m.ncols(), &ncdims[1]);
256 nca_def_var(ncid, name, NC_DOUBLE, 2, &ncdims[0], &varid);
257 } else
258 varid = -1;
259
260 return varid;
261}
262
264
272int nca_def_Tensor4(const int ncid, const String &name, const Tensor4 &t) {
273 std::array<int, 4> ncdims;
274 int varid;
275 if (t.nbooks() && t.npages() && t.nrows() && t.ncols()) {
276 nca_def_dim(ncid, name + "_nbooks", t.nbooks(), &ncdims[0]);
277 nca_def_dim(ncid, name + "_npages", t.npages(), &ncdims[1]);
278 nca_def_dim(ncid, name + "_nrows", t.nrows(), &ncdims[2]);
279 nca_def_dim(ncid, name + "_ncols", t.ncols(), &ncdims[3]);
280 nca_def_var(ncid, name, NC_DOUBLE, 4, &ncdims[0], &varid);
281 } else
282 varid = -1;
283
284 return varid;
285}
286
288
296Index nca_get_dim(const int ncid, const String &name, const bool noerror) {
297 int retval, dimid;
298 size_t ndim;
299 if ((retval = nc_inq_dimid(ncid, name.c_str(), &dimid))) {
300 if (!noerror)
301 nca_error(retval, "nc_inq_ndims(" + name + ")");
302 else
303 return 0;
304 }
305 if ((retval = nc_inq_dimlen(ncid, dimid, &ndim))) {
306 if (!noerror)
307 nca_error(retval, "nc_inq_dimlen(" + name + ")");
308 else
309 return 0;
310 }
311
312 return (Index)ndim;
313}
314
316
323void nca_get_data(const int ncid, const String &name, int *data) {
324 int retval, varid;
325 if ((retval = nc_inq_varid(ncid, name.c_str(), &varid)))
326 nca_error(retval, "nc_inq_varid(" + name + ")");
327 if ((retval = nc_get_var_int(ncid, varid, data)))
328 nca_error(retval, "nc_get_var(" + name + ")");
329}
330
332
339void nca_get_data(const int ncid, const String &name, long *data) {
340 int retval, varid;
341 if ((retval = nc_inq_varid(ncid, name.c_str(), &varid)))
342 nca_error(retval, "nc_inq_varid(" + name + ")");
343 if ((retval = nc_get_var_long(ncid, varid, data)))
344 nca_error(retval, "nc_get_var(" + name + ")");
345}
346
348
355void nca_get_data(const int ncid, const String &name, long long *data) {
356 int retval, varid;
357 if ((retval = nc_inq_varid(ncid, name.c_str(), &varid)))
358 nca_error(retval, "nc_inq_varid(" + name + ")");
359 if ((retval = nc_get_var_longlong(ncid, varid, data)))
360 nca_error(retval, "nc_get_var(" + name + ")");
361}
362
364
371void nca_get_data(const int ncid, const String &name, Numeric *data) {
372 int retval, varid;
373 if ((retval = nc_inq_varid(ncid, name.c_str(), &varid)))
374 nca_error(retval, "nc_inq_varid(" + name + ")");
375 if ((retval = nc_get_var_double(ncid, varid, data)))
376 nca_error(retval, "nc_get_var(" + name + ")");
377}
378
380
387void nca_get_data(const int ncid, const String &name, size_t start,
388 size_t count, Numeric *data) {
389 int retval, varid;
390 if ((retval = nc_inq_varid(ncid, name.c_str(), &varid)))
391 nca_error(retval, "nc_inq_varid(" + name + ")");
392 if ((retval = nc_get_vara_double(ncid, varid, &start, &count, data)))
393 nca_error(retval, "nc_get_var(" + name + ")");
394}
395
397
404void nca_get_data(const int ncid, const String &name, char *data) {
405 int retval, varid;
406 if ((retval = nc_inq_varid(ncid, name.c_str(), &varid)))
407 nca_error(retval, "nc_inq_varid(" + name + ")");
408 if ((retval = nc_get_var_text(ncid, varid, data)))
409 nca_error(retval, "nc_get_var(" + name + ")");
410}
411
413
422void nca_get_data(const int ncid, const String &name, ArrayOfIndex &aoi,
423 const bool noerror) {
424 Index nelem = nca_get_dim(ncid, name + "_nelem", noerror);
425 aoi.resize(nelem);
426 if (nelem) {
427 nca_get_data(ncid, name, aoi.data());
428 }
429}
430
432
441void nca_get_data(const int ncid, const String &name,
442 ArrayOfArrayOfSpeciesTag &aast, const bool noerror) {
443 ArrayOfIndex species_count;
444 nca_get_data(ncid, name + "_count", species_count, noerror);
445 aast.resize(species_count.nelem());
446 if (species_count.nelem()) {
447 Index species_strings_nelem =
448 nca_get_dim(ncid, name + "_strings_nelem", noerror);
449 Index species_strings_length =
450 nca_get_dim(ncid, name + "_strings_length", noerror);
451 char *species_strings =
452 new char[species_strings_nelem * species_strings_length]; // FIXME: THIS SHOULD NOT USE "new"
453 if (species_count.nelem())
454 nca_get_data(ncid, name + "_strings", species_strings);
455
456 Index si = 0;
457 for (Index i = 0; i < species_count.nelem(); i++) {
458 aast[i].resize(0);
459 for (Index j = 0; j < species_count[i]; j++) {
460 aast[i].push_back(SpeciesTag(&species_strings[si]));
461 si += species_strings_length;
462 }
463 }
464
465 delete[] species_strings;
466 }
467}
468
470
479void nca_get_data(const int ncid, const String &name, Vector &v,
480 const bool noerror) {
481 Index nelem = nca_get_dim(ncid, name + "_nelem", noerror);
482 v.resize(nelem);
483 if (nelem)
484 nca_get_data(ncid, name, v.get_c_array());
485}
486
488
497void nca_get_data(const int ncid, const String &name, Matrix &m,
498 const bool noerror) {
499 Index nrows = nca_get_dim(ncid, name + "_nrows", noerror);
500 Index ncols = nca_get_dim(ncid, name + "_ncols", noerror);
501 m.resize(nrows, ncols);
502 if (nrows && ncols)
503 nca_get_data(ncid, name, m.get_c_array());
504}
505
507
516void nca_get_data(const int ncid, const String &name, Tensor4 &t,
517 const bool noerror) {
518 Index nbooks = nca_get_dim(ncid, name + "_nbooks", noerror);
519 Index npages = nca_get_dim(ncid, name + "_npages", noerror);
520 Index nrows = nca_get_dim(ncid, name + "_nrows", noerror);
521 Index ncols = nca_get_dim(ncid, name + "_ncols", noerror);
522 t.resize(nbooks, npages, nrows, ncols);
523 if (nbooks && npages && nrows && ncols)
524 nca_get_data(ncid, name, t.get_c_array());
525}
526
528
536void nca_put_var(const int ncid, const int varid, const long *ind_arr) {
537 int retval;
538 if ((retval = nc_put_var_long(ncid, varid, ind_arr)))
539 nca_error(retval, "nc_put_var");
540}
541
543
551void nca_put_var(const int ncid, const int varid, const long long *ind_arr) {
552 int retval;
553 if ((retval = nc_put_var_longlong(ncid, varid, ind_arr)))
554 nca_error(retval, "nc_put_var");
555}
556
558
566bool nca_put_var(const int ncid, const int varid, const ArrayOfIndex &a) {
567 bool fail = true;
568 if (a.nelem()) {
569 nca_put_var(ncid, varid, a.data());
570 fail = false;
571 }
572 return fail;
573}
574
576
584bool nca_put_var(const int ncid, const int varid, const Vector &v) {
585 bool fail = true;
586 if (v.nelem()) {
587 int retval;
588 if ((retval = nc_put_var_double(ncid, varid, v.get_c_array())))
589 nca_error(retval, "nc_put_var");
590 fail = false;
591 }
592 return fail;
593}
594
596
604bool nca_put_var(const int ncid, const int varid, const Matrix &m) {
605 bool fail = true;
606 if (m.nrows() && m.ncols()) {
607 int retval;
608 if ((retval = nc_put_var_double(ncid, varid, m.get_c_array())))
609 nca_error(retval, "nc_put_var");
610 fail = false;
611 }
612 return fail;
613}
614
616
624bool nca_put_var(const int ncid, const int varid, const Tensor4 &t) {
625 bool fail = true;
626 if (t.nbooks() && t.npages() && t.nrows() && t.ncols()) {
627 int retval;
628 if ((retval = nc_put_var_double(ncid, varid, t.get_c_array())))
629 nca_error(retval, "nc_put_var");
630 fail = false;
631 }
632 return fail;
633}
634
636
643void nca_error(const int e, const std::string_view s) {
644 ARTS_USER_ERROR("NetCDF error: ", s, ", ", e, "\nCheck your input file.");
645}
646
647// We can't do the instantiation at the beginning of this file, because the
648// implementation of nca_write_to_file and nca_read_from_file have to be known.
649
650#include "nc_io_instantiation.h"
651
652#endif /* ENABLE_NETCDF */
The global header file for ARTS.
Index nelem() const ARTS_NOEXCEPT
Definition: array.h:92
Numeric * get_c_array() const noexcept
Definition: matpackI.h:1157
Index nrows() const noexcept
Definition: matpackI.h:1079
Index ncols() const noexcept
Definition: matpackI.h:1080
Index ncols() const noexcept
Definition: matpackIV.h:146
Index nrows() const noexcept
Definition: matpackIV.h:145
Index nbooks() const noexcept
Definition: matpackIV.h:143
Index npages() const noexcept
Definition: matpackIV.h:144
The Matrix class.
Definition: matpackI.h:1285
void resize(Index r, Index c)
Resize function.
Definition: matpackI.cc:1011
const Numeric * get_c_array() const ARTS_NOEXCEPT
Conversion to plain C-array.
Definition: matpackIV.cc:342
The Tensor4 class.
Definition: matpackIV.h:435
void resize(Index b, Index p, Index r, Index c)
Resize function.
Definition: matpackIV.cc:1054
The Vector class.
Definition: matpackI.h:910
#define ARTS_USER_ERROR(...)
Definition: debug.h:169
The declarations of all the exception classes.
String add_basedir(const std::string_view path)
Definition: file.cc:441
String expand_path(String path)
Definition: file.cc:422
This file contains basic functions to handle ASCII files.
NUMERIC Numeric
The type to use for all floating point numbers.
Definition: matpack.h:33
INDEX Index
The type to use for all integer numbers and indices.
Definition: matpack.h:39
String out_basename
The basename for the report file and for all other output files.
Definition: messages.cc:42
Declarations having to do with the four output streams.
#define CREATE_OUT2
Definition: messages.h:205
void nca_filename_with_index(String &filename, const Index &file_index, const String &varname)
Gives the default filename, with file index, for the NetCDF formats.
Definition: nc_io.cc:70
int nca_def_Tensor4(const int ncid, const String &name, const Tensor4 &t)
Define NetCDF dimensions and variable for a Tensor4.
Definition: nc_io.cc:272
int nca_def_ArrayOfIndex(const int ncid, const String &name, const ArrayOfIndex &a)
Define NetCDF dimensions and variable for an ArrayOfIndex.
Definition: nc_io.cc:207
void nca_filename(String &filename, const String &varname)
Gives the default filename for the NetCDF formats.
Definition: nc_io.cc:53
int nca_def_Vector(const int ncid, const String &name, const Vector &v)
Define NetCDF dimensions and variable for a Vector.
Definition: nc_io.cc:229
Index nca_get_dim(const int ncid, const String &name, const bool noerror)
Read a dimension from NetCDF file.
Definition: nc_io.cc:296
void nca_def_var(const int ncid, const String &name, const nc_type type, const int ndims, const int *dims, int *varid)
Define NetCDF variable.
Definition: nc_io.cc:191
int nca_def_Matrix(const int ncid, const String &name, const Matrix &m)
Define NetCDF dimensions and variable for a Matrix.
Definition: nc_io.cc:250
void nca_error(const int e, const std::string_view s)
Throws a runtime error for the given NetCDF error code.
Definition: nc_io.cc:643
void nca_def_dim(const int ncid, const String &name, const Index nelem, int *ncdim)
Define NetCDF dimension.
Definition: nc_io.cc:173
void nca_put_var(const int ncid, const int varid, const long *ind_arr)
Write variable of type long* to NetCDF file.
Definition: nc_io.cc:536
void nca_get_data(const int ncid, const String &name, int *data)
Read variable of type int from NetCDF file.
Definition: nc_io.cc:323
void nca_write_to_file(const String &filename, const T &type, const Verbosity &verbosity)
Writes a variable to a NetCDF file.
Definition: nc_io.cc:133
void nca_read_from_file(const String &filename, T &type, const Verbosity &verbosity)
Reads a variable from a NetCDF file.
Definition: nc_io.cc:93
This file contains basic functions to handle NetCDF data files.
This file contains private function declarations and template instantiation to handle NetCDF data fil...
Species::Tag SpeciesTag
Definition: species_tags.h:100
#define v
#define a