NASA Logo
Ocean Color Science Software

ocssw V2022
scaledNcVarTest.cpp
Go to the documentation of this file.
1 
2 #include <cassert>
3 #include <stdexcept>
4 
5 #include "scaledNcVar.hpp"
6 
7 using namespace netCDF;
8 using namespace std;
9 
10 const double TEST_VALUE = 20.1; // To be put and expected after getting
11 const double TEST_BADVALUE = -1;
12 const double TEST_SCALE = 2.0;
13 const double TEST_OFFSET = 1.0;
14 const int TEST_COMPRESS_VALUE = (TEST_VALUE - TEST_OFFSET) / TEST_SCALE; // expected raw data value
16 const int TEST_SIZE = 50;
17 
18 void testGetVar(const vector<double> &data) {
19  for (double datum : data) {
20  if (datum != TEST_VALUE) {
21  cerr << "-E- " << datum << " != " << TEST_VALUE << endl;
22  }
23  }
24 }
25 
26 int testReading() {
27  NcFile inFile("test.nc", NcFile::read);
28  NcGroup group = inFile.getGroup("testGroup");
29  vector<double> rawData(TEST_SIZE);
30 
31  // Scale and offset should have been ignored
32  vector<double> dataScaledDouble(TEST_SIZE);
33  ScaledNcVar scaledDouble = group.getVar("scaledDouble");
34  scaledDouble.getVar(dataScaledDouble.data());
35  for (double datum : dataScaledDouble) {
36  if (datum != TEST_VALUE) {
37  cerr << "-E- Scaled double: " << datum << " != " << TEST_VALUE << endl;
38  }
39  }
40 
41  // Scale and offset should NOT have been ignored, but ScaledNcVar::getVar() should undo it
42  vector<double> dataScaledShort(TEST_SIZE);
43  ScaledNcVar scaledShort = group.getVar("scaledShort");
44  scaledShort.getVar(dataScaledShort.data()); // Undo scale and offset
45  scaledShort.NcVar::getVar(rawData.data()); // Get what was actually written
46  for (double datum : dataScaledShort) {
47  if (datum != TEST_UNCOMPRESSED_VALUE) {
48  cerr << "-E- Scaled short " << datum << " != " << TEST_UNCOMPRESSED_VALUE << endl;
49  }
50  }
51  for (double datum : rawData)
52  if (datum != TEST_COMPRESS_VALUE) {
53  cerr << "-E- Scaled short raw data " << datum << " != " << TEST_COMPRESS_VALUE << endl;
54  }
55 
56  // If ScaledNcVar has a user-defined "bad value", then, when it finds a fill value in a file, it should
57  // interpret that fill value as that user-defined bad value
58  vector<double> dataBadValue(TEST_SIZE);
59  vector<double> rawDataBadValue(TEST_SIZE);
60  ScaledNcVar badValue = group.getVar("badValue");
61  badValue.assignBadValue(TEST_BADVALUE);
62  badValue.NcVar::getVar(rawDataBadValue.data()); // Raw fill value
63  badValue.getVar(dataBadValue.data()); // Fill value translated to badValue
64  for (size_t i = 0; i < dataBadValue.size(); i++) {
65  if (i % 2 == 0) {
66  if (dataBadValue[i] != TEST_BADVALUE) {
67  cerr << "-E- Bad value: " << dataBadValue[i] << " != " << TEST_BADVALUE << endl;
68  }
69  }
70  }
71  for (size_t i = 0; i < rawData.size(); i++) {
72  if (i % 2 == 0) {
73  if (rawDataBadValue[i] != BAD_FLT) {
74  cerr << "-E- Bad value: " << rawDataBadValue[i] << " != " << BAD_FLT << endl;
75  }
76  }
77  }
78 
79  // Test getting a range of data from a variable instead of the whole thing
80  vector<double> dataVectored(10);
81  ScaledNcVar vectored = group.getVar("vectored");
82  vectored.getVar({2, 0}, {1, 10}, dataVectored.data());
83  for (double value : dataVectored)
84  if (value != TEST_VALUE)
85  cerr << "-E- Vectored: " << value << " != " << TEST_VALUE << endl;
86 
87  return EXIT_SUCCESS;
88 }
89 
90 int testWriting() {
91  int status = EXIT_SUCCESS;
92  vector<double> pretendDataDouble(10);
93 
94  for (size_t i = 0; i < 10; i++) {
95  pretendDataDouble[i] = i + 1;
96  }
97 
98  NcFile outFile("test.nc", NcFile::replace);
99  auto dimX = outFile.addDim("x", 10);
100  auto dimY = outFile.addDim("y", 5);
101  NcGroup testGroup = outFile.addGroup("testGroup");
102  vector<double> doubleData(TEST_SIZE, TEST_VALUE);
103  vector<double> smokeArray(TEST_SIZE, .012);
104  smokeArray[1] = BAD_FLT;
105  vector<double> compressable(TEST_SIZE, TEST_COMPRESS_VALUE);
106  vector<double> dataWithBadValue(TEST_SIZE, TEST_VALUE);
107  for (size_t i = 0; i < dataWithBadValue.size(); i++) {
108  if (i % 2 == 0)
109  dataWithBadValue[i] = TEST_BADVALUE;
110  }
111 
112  // Should ignore scale/offset
113  ScaledNcVar scaledDouble = testGroup.addVar("scaledDouble", ncDouble, {dimY, dimX});
114  try {
115  scaledDouble.setScaleFactors(TEST_SCALE, TEST_OFFSET);
116  } catch (const invalid_argument &e) {
117  cout << "Caught exception - " << e.what() << endl;
118  }
119  scaledDouble.putVar(doubleData.data());
120 
121  // Should NOT ignore scale/offset
122  ScaledNcVar scaledShort = testGroup.addVar("scaledShort", ncShort, {dimY, dimX});
123  scaledShort.setScaleFactors(TEST_SCALE, TEST_OFFSET, 1);
124  scaledShort.putVar(doubleData.data());
125 
126  // Populating from product.xml
127  ScaledNcVar ndvi = newScaledNcVar(testGroup, "ndvi", {dimY, dimX});
128  ndvi.putVar(doubleData.data());
129 
130  // Also populating from product.xml, this product has a scale and offset. Should NOT ignore scale/offset
131  ScaledNcVar smoke = newScaledNcVar(testGroup, "smoke", {dimY, dimX});
132  smoke.putVar(smokeArray.data());
133 
134  // Putting a variable in specified spots (like a line out of a whole file)
135  ScaledNcVar vectored = testGroup.addVar("vectored", ncDouble, {dimY, dimX});
136  vectored.putVar({2, 0}, {1, 10}, doubleData.data());
137 
138  // When a ScaledNcVar finds a user-defined "bad value", it should write the assigned (or default) fill
139  // value instead
140  ScaledNcVar badValue = testGroup.addVar("badValue", ncDouble, {dimY, dimX});
141  badValue.assignFillValue(BAD_FLT);
142  badValue.assignBadValue(TEST_BADVALUE);
143  badValue.putVar(dataWithBadValue.data());
144 
145  // Expect an exception if a fill value that isn't representable is passed to assignFillValue
146  ScaledNcVar outOfRange = testGroup.addVar("outOfRange", ncByte, {dimY, dimX});
147  try {
148  outOfRange.assignFillValue(257);
149  } catch (const out_of_range &e) {
150  cout << "Caught exception - " << e.what() << endl;
151  }
152 
153  outFile.close();
154 
155  return status;
156 }
157 
158 int main() {
159  return testWriting() + testReading(); // Nonzero if any fail
160 }
int32 value
Definition: Granule.c:1235
const int TEST_COMPRESS_VALUE
#define EXIT_SUCCESS
Definition: GEO_basic.h:72
const double TEST_VALUE
int status
Definition: l1_czcs_hdf.c:32
int testReading()
ScaledNcVar newScaledNcVar(const netCDF::NcGroup &group, const std::string &name, const std::vector< netCDF::NcDim > &dims, int sensorID)
Create a ScaledNcVar using the product.xml for definition.
void getVar(float *dataValues)
Takes in a pointer whose memory will be modified. Assumes values found there are integers and perform...
void assignFillValue(double newValue)
Reassign the fill value.
Definition: scaledNcVar.cpp:51
void testGetVar(const vector< double > &data)
const int TEST_SIZE
void setScaleFactors(double scale, double offset, double fillValue=BAD_FLT)
Populate scale factor and add offset manually. Throws an invalid_argument
const double TEST_SCALE
void putVar(const float *dataValues)
put an entire variable
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
void assignBadValue(double newValue)
Reassign the value of badValue.
Definition: scaledNcVar.cpp:47
const double TEST_BADVALUE
#define BAD_FLT
Definition: jplaeriallib.h:19
const double TEST_OFFSET
int main()
const double TEST_UNCOMPRESSED_VALUE
int i
Definition: decode_rs.h:71
int testWriting()