32 #include <BESInternalError.h>
35 #include "FONcRequestHandler.h"
36 #include "FONcArray.h"
40 #include "FONcUtils.h"
41 #include "FONcAttributes.h"
43 vector<FONcDim *> FONcArray::Dimensions;
45 const int MAX_CHUNK_SIZE = 1024;
56 FONcBaseType(), d_a(0), d_array_type(NC_NAT), d_ndims(0), d_actual_ndims(0), d_nelements(1), d_dim_ids(0),
57 d_dim_sizes(0), d_str_data(0), d_dont_use_it(false), d_chunksizes(0), d_grid_maps(0)
59 d_a =
dynamic_cast<Array *
>(b);
61 string s =
"File out netcdf, FONcArray was passed a variable that is not a DAP Array";
79 vector<FONcDim*>::iterator d = d_dims.begin();
80 while (d != d_dims.end()) {
86 vector<FONcMap*>::iterator i = d_grid_maps.begin();
87 while (i != d_grid_maps.end()) {
109 FONcBaseType::convert(embed);
112 BESDEBUG(
"fonc",
"FONcArray::convert() - converting array " << _varname << endl);
115 d_ndims = d_a->dimensions();
116 d_actual_ndims = d_ndims;
117 if (d_array_type == NC_CHAR) {
126 d_dim_ids.resize(d_ndims);
127 d_dim_sizes.resize(d_ndims);
129 Array::Dim_iter di = d_a->dim_begin();
130 Array::Dim_iter de = d_a->dim_end();
132 for (; di != de; di++) {
133 int size = d_a->dimension_size(di,
true);
134 d_dim_sizes[dimnum] = size;
138 d_chunksizes.push_back(size <= MAX_CHUNK_SIZE ? size: MAX_CHUNK_SIZE);
140 BESDEBUG(
"fonc",
"FONcArray::convert() - dim num: " << dimnum <<
", dim size: " << size <<
", chunk size: " << d_chunksizes[dimnum] << endl);
145 FONcDim *use_dim = find_dim(embed, d_a->dimension_name(di), size);
146 d_dims.push_back(use_dim);
151 if (d_array_type == NC_CHAR) {
153 int array_length = d_a->length();
155 d_str_data.reserve(array_length);
156 d_a->value(d_str_data);
159 size_t max_length = 0;
160 for (
int i = 0; i < array_length; i++) {
161 if (d_str_data[i].length() > max_length) {
162 max_length = d_str_data[i].length();
166 vector<string> empty_embed;
167 string lendim_name = _varname +
"_len";
169 FONcDim *use_dim = find_dim(empty_embed, lendim_name, max_length,
true);
171 if (use_dim->size() <
static_cast<int>(max_length)) {
172 use_dim->update_size(max_length);
175 d_dim_sizes[d_ndims - 1] = use_dim->size();
176 d_dim_ids[d_ndims - 1] = use_dim->dimid();
177 d_dims.push_back(use_dim);
186 d_chunksizes.push_back(max_length <= MAX_CHUNK_SIZE ? max_length: MAX_CHUNK_SIZE);
192 if (!
FONcGrid::InGrid && d_actual_ndims == 1 && d_a->name() == d_a->dimension_name(d_a->dim_begin())) {
194 FONcMap *map = FONcGrid::InMaps(d_a);
198 d_grid_maps.push_back(new_map);
202 d_dont_use_it =
true;
206 BESDEBUG(
"fonc",
"FONcArray::convert() - done converting array " << _varname << endl);
223 FONcArray::find_dim(vector<string> &embed,
const string &name,
int size,
bool ignore_size)
228 vector<FONcDim *>::iterator i = FONcArray::Dimensions.begin();
229 vector<FONcDim *>::iterator e = FONcArray::Dimensions.end();
230 for (; i != e && !ret_dim; i++) {
231 if (!((*i)->name().empty()) && ((*i)->name() ==
name)) {
235 else if ((*i)->size() == size) {
239 if (embed.size() > 0) {
241 return find_dim(tmp, ename, size);
243 string err =
"fileout_netcdf: dimension found with the same name, but different size";
250 FONcArray::Dimensions.push_back(ret_dim);
274 BESDEBUG(
"fonc",
"FONcArray::define() - defining array '" << _varname <<
"'" << endl);
276 if (!_defined && !d_dont_use_it) {
277 vector<FONcDim *>::iterator i = d_dims.begin();
278 vector<FONcDim *>::iterator e = d_dims.end();
280 for (; i != e; i++) {
284 d_dim_ids[dimnum] = fd->dimid();
285 BESDEBUG(
"fonc",
"FONcArray::define() - dim_id: " << fd->dimid() <<
" size:" << fd->size() << endl);
289 int stax = nc_def_var(ncid, _varname.c_str(), d_array_type, d_ndims, &d_dim_ids[0], &_varid);
290 if (stax != NC_NOERR) {
291 string err = (string)
"fileout.netcdf - Failed to define variable " + _varname;
296 BESDEBUG(
"fonc",
"FONcArray::define() Working netcdf-4 branch " << endl);
297 if (FONcRequestHandler::chunk_size == 0)
299 stax = nc_def_var_chunking(ncid, _varid, NC_CONTIGUOUS, &d_chunksizes[0]);
301 stax = nc_def_var_chunking(ncid, _varid, NC_CHUNKED, &d_chunksizes[0]);
303 if (stax != NC_NOERR) {
304 string err =
"fileout.netcdf - Failed to define chunking for variable " + _varname;
310 if (FONcRequestHandler::use_compression) {
313 int deflate_level = 4;
314 stax = nc_def_var_deflate(ncid, _varid, shuffle, deflate, deflate_level);
316 if (stax != NC_NOERR) {
317 string err = (string)
"fileout.netcdf - Failed to define compression (deflate) level for variable "
332 AttrTable &attrs = d_a->get_attr_table();
333 if (d_array_type == NC_SHORT && attrs.get_size()) {
334 for (AttrTable::Attr_iter iter = attrs.attr_begin(); iter != attrs.attr_end(); iter++)
335 if (attrs.get_name(iter) ==
"_FillValue" && attrs.get_attr_type(iter) == Attr_byte)
336 (*iter)->type = Attr_int16;
339 BESDEBUG(
"fonc",
"FONcArray::define() - Adding attributes " << endl);
347 BESDEBUG(
"fonc",
"FONcArray::define() - variable " << _varname <<
" is already defined" << endl);
350 BESDEBUG(
"fonc",
"FONcArray::define() - variable " << _varname <<
" is not being used" << endl);
354 BESDEBUG(
"fonc",
"FONcArray::define() - done defining array '" << _varname <<
"'" << endl);
368 BESDEBUG(
"fonc",
"FONcArray::write() BEGIN var: " << _varname <<
"[" << d_nelements <<
"]" << endl);
371 BESDEBUG(
"fonc",
"FONcTransform::write not using variable " << _varname << endl);
378 if (d_array_type != NC_CHAR) {
379 string var_type = d_a->var()->type_name();
382 switch (d_array_type) {
384 unsigned char *data =
new unsigned char[d_nelements];
385 d_a->buf2val((
void**) &data);
386 stax = nc_put_var_uchar(ncid, _varid, data);
389 if (stax != NC_NOERR) {
390 string err =
"fileout.netcdf - Failed to create array of bytes for " + _varname;
397 short *data =
new short[d_nelements];
403 if (var_type ==
"Byte") {
405 unsigned char *orig_data =
new unsigned char[d_nelements];
406 d_a->buf2val((
void**) &orig_data);
408 for (
int d_i = 0; d_i < d_nelements; d_i++)
409 data[d_i] = orig_data[d_i];
414 d_a->buf2val((
void**) &data);
416 int stax = nc_put_var_short(ncid, _varid, data);
419 if (stax != NC_NOERR) {
420 string err = (string)
"fileout.netcdf - Failed to create array of shorts for " + _varname;
427 int *data =
new int[d_nelements];
430 if (var_type ==
"UInt16") {
431 unsigned short *orig_data =
new unsigned short[d_nelements];
432 d_a->buf2val((
void**) &orig_data);
434 for (
int d_i = 0; d_i < d_nelements; d_i++)
435 data[d_i] = orig_data[d_i];
440 d_a->buf2val((
void**) &data);
443 int stax = nc_put_var_int(ncid, _varid, data);
446 if (stax != NC_NOERR) {
447 string err = (string)
"fileout.netcdf - Failed to create array of ints for " + _varname;
454 float *data =
new float[d_nelements];
455 d_a->buf2val((
void**) &data);
456 int stax = nc_put_var_float(ncid, _varid, data);
459 if (stax != NC_NOERR) {
460 string err = (string)
"fileout.netcdf - Failed to create array of floats for " + _varname;
467 double *data =
new double[d_nelements];
468 d_a->buf2val((
void**) &data);
469 int stax = nc_put_var_double(ncid, _varid, data);
472 if (stax != NC_NOERR) {
473 string err = (string)
"fileout.netcdf - Failed to create array of doubles for " + _varname;
480 string err = (string)
"Failed to transform array of unknown type in file out netcdf";
487 size_t var_count[d_ndims];
488 size_t var_start[d_ndims];
490 for (dim = 0; dim < d_ndims; dim++) {
500 for (
int element = 0; element < d_nelements; element++) {
501 var_count[d_ndims - 1] = d_str_data[element].size() + 1;
502 var_start[d_ndims - 1] = 0;
505 int stax = nc_put_vara_text(ncid, _varid, var_start, var_count, d_str_data[element].c_str());
506 if (stax != NC_NOERR) {
507 string err = (string)
"fileout.netcdf - Failed to create array of strings for " + _varname;
512 if (element + 1 < d_nelements) {
516 var_start[dim] = var_start[dim] + 1;
517 if (var_start[dim] == d_dim_sizes[dim]) {
529 BESDEBUG(
"fonc",
"FONcArray::write() END var: " << _varname <<
"[" << d_nelements <<
"]" << endl);
551 strm << BESIndent::LMarg <<
"FONcArray::dump - (" << (
void *)
this <<
")" << endl;
553 strm << BESIndent::LMarg <<
"name = " << _varname << endl;
554 strm << BESIndent::LMarg <<
"ndims = " << d_ndims << endl;
555 strm << BESIndent::LMarg <<
"actual ndims = " << d_actual_ndims << endl;
556 strm << BESIndent::LMarg <<
"nelements = " << d_nelements << endl;
558 strm << BESIndent::LMarg <<
"dimensions:" << endl;
560 vector<FONcDim *>::const_iterator i = d_dims.begin();
561 vector<FONcDim *>::const_iterator e = d_dims.end();
562 for (; i != e; i++) {
565 BESIndent::UnIndent();
568 strm << BESIndent::LMarg <<
"dimensions: none" << endl;
570 BESIndent::UnIndent();