15 using namespace netCDF;
16 using namespace netCDF::exceptions;
28 bool ScaledNcVar::floatingPoint() {
32 double ScaledNcVar::initFillValue() {
48 this->badValue = newValue;
56 throw out_of_range(
"Given fill value is outside the range of this variable");
58 fill =
static_cast<int8_t
>(newValue);
67 throw out_of_range(
"Given fill value is outside the range of this variable");
69 fill =
static_cast<uint8_t
>(newValue);
78 throw out_of_range(
"Given fill value is outside the range of this variable");
80 fill =
static_cast<short>(newValue);
89 newValue <= numeric_limits<uint16_t>::lowest()) {
90 throw out_of_range(
"Given fill value is outside the range of this variable");
92 fill =
static_cast<uint16_t
>(newValue);
101 throw out_of_range(
"Given fill value is outside the range of this variable");
103 fill =
static_cast<int>(newValue);
112 newValue <= numeric_limits<uint32_t>::lowest()) {
113 throw out_of_range(
"Given fill value is outside the range of this variable");
115 fill =
static_cast<uint32_t
>(newValue);
124 throw out_of_range(
"Given fill value is outside the range of this variable");
126 fill =
static_cast<float>(newValue);
133 setFill(
true, newValue);
135 this->fillValue = newValue;
140 for (
const auto &dim : dims)
141 size *= dim.getSize();
145 void ScaledNcVar::getScaleFactorsFromFile() {
147 getAtt(
"scale_factor").getValues(&scaleFactor);
148 }
catch (NcException
const &e) {
152 getAtt(
"add_offset").getValues(&addOffset);
153 }
catch (NcException
const &e) {
158 NcVar::getFillModeParameters(_, &fillValue);
159 }
catch (NcException
const &e) {
162 scaleFactorsSet =
true;
166 NcVar::getVar(dataValues);
168 if (!scaleFactorsSet)
169 getScaleFactorsFromFile();
178 NcVar::getVar(dataValues);
180 if (!scaleFactorsSet)
181 getScaleFactorsFromFile();
190 size_t sizeToGet = 1;
196 if (!scaleFactorsSet)
197 getScaleFactorsFromFile();
200 ScaledNcVar::uncompress(dataValues, sizeToGet);
202 fillToBad(dataValues, sizeToGet);
206 size_t sizeToGet = 1;
212 if (!scaleFactorsSet)
213 getScaleFactorsFromFile();
216 ScaledNcVar::uncompress(dataValues, sizeToGet);
218 fillToBad(dataValues, sizeToGet);
224 if (floatingPoint() || !scaleFactorsSet) {
225 if (fillValue != badValue) {
226 vector<double> buf(sizeToWrite);
227 badToFill(dataValues, sizeToWrite, buf);
228 NcVar::putVar(buf.data());
230 NcVar::putVar(dataValues);
236 vector<int32_t> buf(dataValues, dataValues + sizeToWrite);
237 compress(dataValues, buf, sizeToWrite);
238 NcVar::putVar(buf.data());
244 if (floatingPoint() || !scaleFactorsSet) {
245 if (fillValue != badValue) {
246 vector<double> buf(sizeToWrite);
247 badToFill(dataValues, sizeToWrite, buf);
248 NcVar::putVar(buf.data());
250 NcVar::putVar(dataValues);
256 vector<int32_t> buf(dataValues, dataValues + sizeToWrite);
257 compress(dataValues, buf, sizeToWrite);
258 NcVar::putVar(buf.data());
262 size_t sizeToWrite = 1;
267 if (floatingPoint() || !scaleFactorsSet) {
268 if (fillValue != badValue) {
269 vector<double> buf(sizeToWrite);
270 badToFill(dataValues, sizeToWrite, buf);
279 vector<int32_t> buf(dataValues, dataValues + sizeToWrite);
280 compress(dataValues, buf, sizeToWrite);
285 size_t sizeToWrite = 1;
290 if (floatingPoint() || !scaleFactorsSet) {
291 if (fillValue != badValue) {
292 vector<double> buf(sizeToWrite);
293 badToFill(dataValues, sizeToWrite, buf);
302 vector<int32_t> buf(dataValues, dataValues + sizeToWrite);
303 compress(dataValues, buf, sizeToWrite);
308 *fillValue = this->fillValue;
311 *fillValue = this->fillValue;
314 void ScaledNcVar::compress(
const double *toCompress, std::vector<int32_t> &compressed,
size_t count) {
315 compressed.resize(
count);
316 pair<double, double> thisVarRange = range();
318 for (
size_t i = 0;
i <
count;
i++) {
319 if (toCompress[
i] == badValue) {
320 compressed[
i] = fillValue;
322 double value = (toCompress[
i] - this->addOffset) / this->scaleFactor;
324 if (
value < thisVarRange.first || thisVarRange.second <
value) {
325 compressed[
i] = fillValue;
333 void ScaledNcVar::compress(
const float *toCompress, std::vector<int32_t> &compressed,
size_t count) {
334 compressed.resize(
count);
335 pair<double, double> thisVarRange = range();
337 for (
size_t i = 0;
i <
count;
i++) {
338 if (toCompress[
i] == badValue) {
339 compressed[
i] = fillValue;
341 double value = (toCompress[
i] - this->addOffset) / this->scaleFactor;
343 if (
value < thisVarRange.first || thisVarRange.second <
value) {
344 compressed[
i] = fillValue;
352 void ScaledNcVar::uncompress(
double *toUncompress,
size_t count) {
353 for (
size_t i = 0;
i <
count;
i++) {
354 if (toUncompress[
i] == fillValue)
355 toUncompress[
i] = badValue;
356 else if (scaleFactor != 1.0 || addOffset != 0.0)
357 toUncompress[
i] = (toUncompress[
i] * scaleFactor) + addOffset;
361 void ScaledNcVar::uncompress(
float *toUncompress,
size_t count) {
362 for (
size_t i = 0;
i <
count;
i++) {
363 if (toUncompress[
i] == fillValue)
364 toUncompress[
i] = badValue;
365 else if (scaleFactor != 1.0 || addOffset != 0.0)
366 toUncompress[
i] = (toUncompress[
i] * scaleFactor) + addOffset;
370 template <
typename T>
371 void ScaledNcVar::fillToBad(T *
data,
size_t count) {
372 if (fillValue != badValue) {
373 for (
size_t i = 0;
i <
count;
i++) {
374 if (
data[
i] == fillValue)
380 template <
typename T,
typename E>
381 void ScaledNcVar::badToFill(
const T *
data,
const size_t &
count, vector<E> &
out) {
383 for (
size_t i = 0;
i <
count;
i++) {
384 if (
data[
i] == badValue)
403 putAtt(
"long_name", prodInfo->description);
406 strcmp(prodInfo->units,
"dimensionless"))
407 putAtt(
"units", prodInfo->units);
409 if (prodInfo->standardName)
410 putAtt(
"standard_name", prodInfo->standardName);
415 putAtt(
"valid_min",
thisVarType, prodInfo->validMin);
418 putAtt(
"valid_max",
thisVarType, prodInfo->validMax);
423 putAtt(
"scale_factor", NC_DOUBLE, prodInfo->scaleFactor);
424 putAtt(
"add_offset", NC_DOUBLE, prodInfo->addOffset);
425 scaleFactor = prodInfo->scaleFactor;
426 addOffset = prodInfo->addOffset;
430 putAtt(
"reference", prodInfo->reference);
433 putAtt(
"comment", prodInfo->comment);
435 scaleFactorsSet =
true;
441 scaleFactorsSet =
true;
448 throw invalid_argument(
"Setting scale/offset for a float/double is not allowed\n");
451 this->scaleFactor =
scale;
454 putAtt(
"scale_factor", NC_DOUBLE,
scale);
455 putAtt(
"add_offset", NC_DOUBLE,
offset);
459 pair<double, double> ScaledNcVar::range() {
462 return pair<double, double>(NC_MIN_FLOAT, NC_MAX_FLOAT);
464 return pair<double, double>(NC_MIN_DOUBLE, NC_MAX_DOUBLE);
466 return pair<double, double>(NC_MIN_BYTE, NC_MAX_BYTE);
468 return pair<double, double>(0, NC_MAX_UBYTE);
470 return pair<double, double>(NC_MIN_SHORT, NC_MAX_SHORT);
472 return pair<double, double>(0, NC_MAX_USHORT);
474 return pair<double, double>(NC_MIN_INT, NC_MAX_INT);
476 return pair<double, double>(0, NC_MAX_UINT);
478 return pair<double, double>(1, -1);
483 if (typeStr ==
"byte")
484 return NcType::nc_BYTE;
485 else if (typeStr ==
"ubyte")
486 return NcType::nc_UBYTE;
487 else if (typeStr ==
"short")
488 return NcType::nc_SHORT;
489 else if (typeStr ==
"ushort")
490 return NcType::nc_USHORT;
491 else if (typeStr ==
"int")
492 return NcType::nc_INT;
493 else if (typeStr ==
"uint")
494 return NcType::nc_UINT;
495 else if (typeStr ==
"float")
496 return NcType::nc_FLOAT;
497 else if (typeStr ==
"double")
498 return NcType::nc_DOUBLE;
500 throw runtime_error(
"productInfoType2ncType could not lookup typeStr = " + typeStr);
501 return NcType::nc_FLOAT;
505 const std::vector<netCDF::NcDim> &dims,
int sensorID) {
510 throw runtime_error(
"newScaledNcVar could not find product = " +
name);