OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
RsViirs.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * NAME: RsViirs.cpp
4  *
5  * DESCRIPTION: Running the program on a granule will modify the data
6  * in-place ..
7  *
8  * Based on a technique described in:
9  * Remote Sensing 2016, 8(1), 79
10  * Article Titled "Improved VIIRS and MODIS SST Imagery"
11  * By Irina Gladkova, Alexander Ignatov, Fazlul Shahriar, Yury Kihai,
12  * Don Hillger and Boris Petrenko
13  *
14  *
15  * Created on: February 17, 2019
16  * Author: Sam Anderson
17  *
18  *******************************************************************************/
19 
20 
21 #include "resam_viirs/RsViirs.h"
22 
23 #include <netcdf>
24 #include <DDOptions.h>
25 
26 using namespace std;
27 using namespace netCDF;
28 using namespace netCDF::exceptions;
29 
30 // column break points
31 short SBP[NBREAKS+1] = {
32  0, 5, 87, 170, 358, 567, 720, 850, 997, 1120, 1275, 1600
33 };
34 
35 // relative row that the pixel comes from
37  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
38  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
39  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
40  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
41  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
42  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
43  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
44  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
45  {+8, +8, +8, 0, 0, 0, 0, 0, 0, 0, 0},
46  {+8, -1, -1, +7, 0, 0, 0, 0, 0, 0, 0},
47  {-2, +7, +7, -1, +6, 0, 0, 0, 0, 0, 0},
48  {+7, -2, -2, +6, -1, +5, 0, 0, 0, 0, 0},
49  {-3, +6, +6, -2, +5, -1, +4, 0, 0, 0, 0},
50  {+6, -3, -3, +5, -2, +4, -1, +3, 0, 0, 0},
51  {-4, +5, +5, -3, +4, -2, +3, -1, +2, 0, 0},
52  {+5, -4, -4, +4, -3, +3, -2, +2, -1, +1, 0},
53 };
54 
55 // relative row that the pixel comes from
57  {-5, +4, +4, -4, +3, -3, +2, -2, +1, -1, 0},
58  {+4, -5, -5, +3, -4, +2, -3, +1, -2, 0, 0},
59  {-6, +3, +3, -5, +2, -4, +1, -3, 0, 0, 0},
60  {+3, -6, -6, +2, -5, +1, -4, 0, 0, 0, 0},
61  {-7, +2, +2, -6, +1, -5, 0, 0, 0, 0, 0},
62  {+11, -7, -7, +1, -6, 0, 0, 0, 0, 0, 0},
63  {+1, +1, +1, -7, 0, 0, 0, 0, 0, 0, 0},
64  {-9, +9, -8, 0, 0, 0, 0, 0, 0, 0, 0},
65  {+9, -9, +8, 0, 0, 0, 0, 0, 0, 0, 0},
66  {-1, -1, -1, +7, 0, 0, 0, 0, 0, 0, 0},
67  {-11, +7, +7, -1, +6, 0, 0, 0, 0, 0, 0},
68  {+7, -2, -2, +6, -1, +5, 0, 0, 0, 0, 0},
69  {-3, +6, +6, -2, +5, -1, +4, 0, 0, 0, 0},
70  {+6, -3, -3, +5, -2, +4, -1, +3, 0, 0, 0},
71  {-4, +5, +5, -3, +4, -2, +3, -1, +2, 0, 0},
72  {+5, -4, -4, +4, -3, +3, -2, +2, -1, +1, 0},
73 };
74 
75 // relative row that the pixel comes from
77  {-5, +4, +4, -4, +3, -3, +2, -2, +1, -1, 0},
78  {+4, -5, -5, +3, -4, +2, -3, +1, -2, 0, 0},
79  {-6, +3, +3, -5, +2, -4, +1, -3, 0, 0, 0},
80  {+3, -6, -6, +2, -5, +1, -4, 0, 0, 0, 0},
81  {-7, +2, +2, -6, +1, -5, 0, 0, 0, 0, 0},
82  {+2, -7, -7, +1, -6, 0, 0, 0, 0, 0, 0},
83  {-8, +1, +1, -7, 0, 0, 0, 0, 0, 0, 0},
84  {-8, -8, -8, 0, 0, 0, 0, 0, 0, 0, 0},
85  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
86  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
87  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
88  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
89  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
90  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
91  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
92  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
93 };
94 
95 
96 /**************************************************************************
97  * NAME: RsViirs()
98  *
99  * DESCRIPTION: Class Constructor
100  *
101  *************************************************************************/
102 
104 }
105 
106 RsViirs::RsViirs( int lines, int pixels ) {
107  lines_ = lines;
108  pixels_ = pixels;
109 }
110 
111 /**************************************************************************
112  * NAME: ~RsViirs()
113  *
114  * DESCRIPTION: Class Destructor
115  *
116  *************************************************************************/
117 
119 }
120 
121 /**************************************************************************
122  * NAME: process()
123  *
124  * DESCRIPTION: Processes data and produces output values for granule
125  *
126  *************************************************************************/
127 
128 int RsViirs::process() {
129  int status = DT_SUCCESS;
130 
131  string filepath_l1b = get_option(INPUT_L1B);
132  string filepath_geo = get_option(INPUT_GEO);
133 
134  if (filepath_l1b.empty() || filepath_geo.empty()) {
135  return DT_FAIL;
136  }
137 
138  NcFile* nc_io;
139  try {
140  nc_io = new NcFile(filepath_l1b, NcFile::read);
141  } catch (NcException& e) {
142  e.what();
143  cerr << "RsInput:: Failure opening VIIRS L1B input file: "
144  + filepath_l1b << endl;
145  return DT_FAIL;
146  }
147  NcDim line_dim = nc_io->getDim("number_of_lines");
148  NcDim pixel_dim = nc_io->getDim("number_of_pixels");
149 
150  lines_ = line_dim.getSize();
151  pixels_ = pixel_dim.getSize();
152  delete nc_io;
153 
154  status = generate_sort_index();
155 
156  sio* sa = new sio;
157  memset( sa, 0, sizeof(sio));
158  usio* usa = new usio;
159  memset( usa, 0, sizeof(usio));
160  fio* fa = new fio;
161  memset( fa, 0, sizeof(fio));
162 
163  try {
164  nc_io = new NcFile(filepath_geo, NcFile::write);
165  } catch (NcException& e) {
166  e.what();
167  cerr << "RsViirs:: Failure opening VIIRS Geolocation input file: "
168  + filepath_geo << endl;
169  return DT_FAIL;
170  }
171 
172  NcGroup nc_group = nc_io->getGroup("geolocation_data");
173  NcVar nc_var = nc_group.getVar("quality_flag");
174  nc_var.getVar(&sa->in[0][0]);
175  resort(sa);
176  nc_var.putVar(&sa->out[0][0]);
177  nc_var = nc_group.getVar("height");
178  nc_var.getVar(&sa->in[0][0]);
179  resort(sa);
180  nc_var.putVar(&sa->out[0][0]);
181  nc_var = nc_group.getVar("range");
182  nc_var.getVar(&sa->in[0][0]);
183  resort(sa);
184  nc_var.putVar(&sa->out[0][0]);
185  nc_var = nc_group.getVar("sensor_azimuth");
186  nc_var.getVar(&sa->in[0][0]);
187  resort(sa);
188  nc_var.putVar(&sa->out[0][0]);
189  nc_var = nc_group.getVar("sensor_zenith");
190  nc_var.getVar(&sa->in[0][0]);
191  resort(sa);
192  nc_var.putVar(&sa->out[0][0]);
193  nc_var = nc_group.getVar("solar_azimuth");
194  nc_var.getVar(&sa->in[0][0]);
195  resort(sa);
196  nc_var.putVar(&sa->out[0][0]);
197  nc_var = nc_group.getVar("solar_zenith");
198  nc_var.getVar(&sa->in[0][0]);
199  resort(sa);
200  nc_var.putVar(&sa->out[0][0]);
201  nc_var = nc_group.getVar("latitude");
202  nc_var.getVar(&fa->in[0][0]);
203  resort(fa);
204  nc_var.putVar(&fa->out[0][0]);
205  nc_var = nc_group.getVar("longitude");
206  nc_var.getVar(fa);
207  resort(fa);
208  nc_var.putVar(&fa->out[0][0]);
209  delete nc_io;
210 
211  try {
212  nc_io = new NcFile(filepath_l1b, NcFile::write);
213  } catch (NcException& e) {
214  e.what();
215  cerr << "RsViirs:: Failure opening VIIRS L1B input file: "
216  + filepath_l1b << endl;
217  return DT_FAIL;
218  }
219  nc_group = nc_io->getGroup("observation_data");
220  for (int ib = 0; ib < NMBANDS; ib++) {
221  char str[20];
222  sprintf(str, "M%02d", ib + 1);
223  nc_var = nc_group.getVar(string(str));
224  nc_var.getVar(&usa->in[0][0]);
225  resort(usa);
226  fill_the_fills(usa);
227  nc_var.putVar(&usa->out[0][0]);
228  sprintf(str, "M%02d_quality_flags", ib + 1);
229  nc_var = nc_group.getVar(string(str));
230  nc_var.getVar(&sa->in[0][0]);
231  resort(sa);
232  nc_var.putVar(&sa->out[0][0]);
233  }
234  delete nc_io;
235 
236  delete sa;
237  delete usa;
238  delete fa;
239 
240  return status;
241 }
242 
243 /**************************************************************************
244  * NAME: generate_sort_index()
245  *
246  * DESCRIPTION: Generate a image of latitude sorting indices.
247  *
248  *************************************************************************/
249 
251 
252  int ND = NDETECTORS;
253  for (int i = 0; i < NBREAKS; i++) {
254  for (int ix = SBP[i]; ix < SBP[i+1]; ix++) {
255  for (int iy = 0; iy < ND; iy++) {
256  si_[iy][ix] = iy + SORT_FIRST[iy][i];
257  si_[iy][pixels_-ix-1] = iy + SORT_FIRST[iy][i];
258  }
259  for (int iy = ND; iy < lines_ - ND; iy++) {
260  si_[iy][ix] = iy + SORT_MID[iy % ND][i];
261  si_[iy][pixels_-ix-1] = iy + SORT_MID[iy % ND][i];
262  }
263  for (int iy = lines_ - ND; iy < lines_; iy++) {
264  si_[iy][ix] = iy + SORT_LAST[iy % ND][i];
265  si_[iy][pixels_-ix-1] = iy + SORT_LAST[iy % ND][i];
266  }
267  }
268  }
269  return DT_SUCCESS;
270 }
271 
272 /**************************************************************************
273  * NAME: resort()
274  *
275  * DESCRIPTION: Returns the sorted image.
276  * Si is the image of sort indices.
277  *
278  *************************************************************************/
279 
280 int RsViirs::resort(sio* io) {
281  for (int iy = 0; iy < lines_; iy++) {
282  for (int ix = 0; ix < pixels_; ix++) {
283  io->out[iy][ix] = io->in[si_[iy][ix]][ix];
284  }
285  }
286  return DT_SUCCESS;
287 }
288 
289 int RsViirs::resort(usio* io) {
290  for (int iy = 0; iy < lines_; iy++) {
291  for (int ix = 0; ix < pixels_; ix++) {
292  io->out[iy][ix] = io->in[si_[iy][ix]][ix];
293  }
294  }
295  return DT_SUCCESS;
296 }
297 
298 int RsViirs::resort(fio* io) {
299  for (int iy = 0; iy < lines_; iy++) {
300  for (int ix = 0; ix < pixels_; ix++) {
301  io->out[iy][ix] = io->in[si_[iy][ix]][ix];
302  }
303  }
304  return DT_SUCCESS;
305 }
306 
307 /**************************************************************************
308  * NAME: fill_the_fills()
309  *
310  * DESCRIPTION: Replace fill values with average of above and below.
311  *
312  *************************************************************************/
313 
314 int RsViirs::fill_the_fills(usio* io) {
315  const unsigned short filltest = SOUB_UINT16_FILL;
316 
317  for (int iy = 1; iy < lines_ - 1; iy++) {
318  for (int ix = 0; ix < pixels_; ix++) {
319  if (io->out[iy][ix] >= filltest) {
320  if (io->out[iy - 1][ix] < filltest &&
321  io->out[iy + 1][ix] < filltest) {
322  io->out[iy][ix] = io->out[iy - 1][ix] / 2 +
323  io->out[iy + 1][ix] / 2;
324  } else if (io->out[iy - 1][ix] < filltest) {
325  io->out[iy][ix] = io->out[iy - 1][ix];
326  } else if (io->out[iy + 1][ix] < filltest) {
327  io->out[iy][ix] = io->out[iy + 1][ix];
328  }
329  }
330  }
331  }
332  for (int ix = 0; ix < pixels_; ix++) {
333  if (io->out[0][ix] >= filltest) {
334  if (io->out[1][ix] < filltest) {
335  io->out[0][ix] = io->out[1][ix];
336  }
337  }
338  }
339  for (int ix = 0; ix < pixels_; ix++) {
340  if (io->out[lines_-1][ix] >= filltest) {
341  if (io->out[lines_-2][ix] < filltest) {
342  io->out[lines_-1][ix] = io->out[lines_-2][ix];
343  }
344  }
345  }
346 
347  return DT_SUCCESS;
348 }
349 
350 int RsViirs::fill_the_fills(fio* io) {
351  const unsigned short filltest = SOUB_UINT16_FILL;
352 
353  for (int iy = 1; iy < lines_ - 1; iy++) {
354  for (int ix = 0; ix < pixels_; ix++) {
355  if (io->out[iy][ix] < filltest) {
356  if (io->out[iy - 1][ix] > filltest &&
357  io->out[iy + 1][ix] > filltest) {
358  io->out[iy][ix] = io->out[iy - 1][ix] / 2 +
359  io->out[iy + 1][ix] / 2;
360  } else if (io->out[iy - 1][ix] > filltest) {
361  io->out[iy][ix] = io->out[iy - 1][ix];
362  } else if (io->out[iy + 1][ix] > filltest) {
363  io->out[iy][ix] = io->out[iy + 1][ix];
364  }
365  }
366  }
367  }
368  for (int ix = 0; ix < pixels_; ix++) {
369  if (io->out[0][ix] < filltest) {
370  if (io->out[1][ix] > filltest) {
371  io->out[0][ix] = io->out[1][ix];
372  }
373  }
374  }
375  for (int ix = 0; ix < pixels_; ix++) {
376  if (io->out[lines_-1][ix] < filltest) {
377  if (io->out[lines_-2][ix] > filltest) {
378  io->out[lines_-1][ix] = io->out[lines_-2][ix];
379  }
380  }
381  }
382 
383  return DT_SUCCESS;
384 }
385 
RsViirs()
Definition: RsViirs.cpp:102
int resort(sio *io)
Definition: RsViirs.cpp:290
int status
Definition: l1_czcs_hdf.c:32
short out[NSCANS *NDETECTORS][NPIXELS]
Definition: RsViirs.h:77
string get_option(const string &name)
Definition: DDOptions.cpp:211
~RsViirs()
Definition: RsViirs.cpp:117
const unsigned short SOUB_UINT16_FILL
Definition: RsViirs.h:51
short SORT_LAST[NDETECTORS][NBREAKS]
Definition: RsViirs.hpp:76
short SBP[NBREAKS+1]
Definition: RsViirs.hpp:31
short SORT_MID[NDETECTORS][NBREAKS]
Definition: RsViirs.hpp:56
const string INPUT_L1B
Definition: DDOptions.cpp:40
unsigned short in[NSCANS *NDETECTORS][NPIXELS]
Definition: RsViirs.h:80
float in[NSCANS *NDETECTORS][NPIXELS]
Definition: RsViirs.h:72
const int NDETECTORS
Definition: RsViirs.h:65
float out[NSCANS *NDETECTORS][NPIXELS]
Definition: RsViirs.h:73
const string INPUT_GEO
Definition: DDOptions.cpp:41
int generate_sort_index()
Definition: RsViirs.cpp:260
Definition: RsViirs.h:79
short in[NSCANS *NDETECTORS][NPIXELS]
Definition: RsViirs.h:76
const int NMBANDS
Definition: RsViirs.h:62
int process()
Definition: RsViirs.cpp:127
short SORT_FIRST[NDETECTORS][NBREAKS]
Definition: RsViirs.hpp:36
const char * str
Definition: l1c_msi.cpp:35
const int NBREAKS
Definition: RsViirs.h:66
Definition: RsViirs.h:71
Definition: RsViirs.h:75
int fill_the_fills(usio *io)
Definition: RsViirs.cpp:333
int i
Definition: decode_rs.h:71
unsigned short out[NSCANS *NDETECTORS][NPIXELS]
Definition: RsViirs.h:81