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();
static void handle_error(int stax, const string &err, const string &file, int line)
handle any netcdf errors
A map of a DAP Grid with file out netcdf information included.
exception thrown if inernal error encountered
FONcArray(libdap::BaseType *b)
Constructor for FONcArray that takes a DAP Array.
virtual bool isNetCDF4()
Returns true if NetCDF4 features will be required.
static void add_variable_attributes(int ncid, int varid, BaseType *b)
Add the attributes for an OPeNDAP variable to the netcdf file.
virtual void write(int ncid)
Write the array out to the netcdf file.
static bool InGrid
tells whether we are converting or defining a grid.
static void add_original_name(int ncid, int varid, const string &var_name, const string &orig)
Adds an attribute for the variable if the variable name had to be modified in any way.
virtual ~FONcArray()
Destructor that cleans up the array.
static nc_type get_nc_type(BaseType *element)
translate the OPeNDAP data type to a netcdf data type
A class that represents the dimension of an array.
virtual void define(int ncid)
define the DAP Array in the netcdf file
virtual void dump(std::ostream &strm) const
dumps information about this object for debugging purposes
A DAP BaseType with file out netcdf information included.
virtual void define(int ncid)
define the DAP dimension in the netcdf file
static string gen_name(const vector< string > &embed, const string &name, string &original)
generate a new name for the embedded variable
virtual void convert(std::vector< std::string > embed)
Converts the DAP Array to a FONcArray.
virtual std::string name()
returns the name of the DAP Array
static vector< FONcMap * > Maps
global list of maps that could be shared amongst the different grids