OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
gringHelper.cpp
Go to the documentation of this file.
1 // Includes from main_l1info.c
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <stdlib.h>
6 #include <stdbool.h>
7 #include <fcntl.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <errno.h>
11 #include <unistd.h>
12 #include <libgen.h>
13 #include <math.h>
14 #include <unistd.h>
15 
16 // Additional includes
17 #include "gringHelper.h"
18 #include "allocate2d.h"
19 #include "l2_flags.h" // needed for NAVFAIL
20 
26 
27  // Allocate memory for geobox[4][MAX_GEOBOX_CNT]
28  geobox = allocate2d_float(4, MAX_GEOBOX_CNT);
29  centerLat = (float*) malloc(MAX_GEOBOX_CNT * sizeof(float));
30 
31  // State vars
32  first_good_scan = false;
33  last_direction = 0;
34  last_lat = -999;
35  geobox_cnt = 0;
36  direction_line = -1;
37  direction_delta = 5;
38 
39  // Unpack gringConfig
40  delta_degrees_lat = gringConfig->delta_degrees_lat;
41  scan_direction = gringConfig->scan_direction;
42  direction_delta = gringConfig->direction_delta;
43 
44 }
45 
46 
48 
49  // Clean up
50  free2d_float(geobox);
51 
52 }
53 
54 bool gringHelper::valid_lat(float lat) {
55  if(lat > 90.0)
56  return false;
57  if(lat < -90.0)
58  return false;
59  return true;
60 }
61 
62 bool gringHelper::valid_lon(float lon) {
63  if(lon > 180.0)
64  return false;
65  if(lon < -180.0)
66  return false;
67  return true;
68 }
69 
70 void gringHelper::process_scan(l1str *l1rec, size_t recnum, size_t escan) {
71  bool gring_test_val;
72  static scanBounds_t *scanBounds;
73  if (scanBounds == NULL){
74  scanBounds = new scanBounds_t;
75  }
76 
77  gring_test_val = includeScanInGring(l1rec->lat,l1rec->lon,l1rec->flags,l1rec->l1file->npix,recnum,escan,scanBounds);
78  if(gring_test_val) {
79  if(geobox_cnt >= (MAX_GEOBOX_CNT - 1)) {
80  printf("Error - Max number of gring points exceeded.\n");
81  exit(EXIT_FAILURE);
82  }
83  //printf("Include last good scan %d where starting lat = %f, last direction = %d\n",(int)recnum,l1rec->lat[recnum],last_direction);
84  //printf(" scanBoundsOut: slat = %f, slon = %f, elat = %f, elon = %f\n", scanBounds->slat, scanBounds->slon, scanBounds->elat, scanBounds->elon);
85  // This scan should be included in the gring, so caller stuffs scanBoundsOut into a geobox array.
86  // Note that a geobox (borrowed from l2_generic.c) is just the endpoints (slon,slat,elon,elat) of a scan line.
87  geobox[0][geobox_cnt] = scanBounds->slon; // Starting lon of this scan
88  geobox[1][geobox_cnt] = scanBounds->slat; // Starting lat of this scan
89  geobox[2][geobox_cnt] = scanBounds->elon; // Ending lon of this scan
90  geobox[3][geobox_cnt] = scanBounds->elat; // Ending lat of this scan
91  centerLat[geobox_cnt] = scanBounds->clat; // save the center lat also
92  geobox_cnt++;
93 
94  }
95 
96 }
97 
98 
116 bool gringHelper::includeScanInGring(float *lat, float *lon, int32_t *flags, size_t num_pixels, size_t recnum, size_t escan,
117  scanBounds_t *scanBounds ) {
118 
119  int spix = 0; // start pixel
120  int cpix = -1; // center pixel
121  int epix = -1; // end pixel
122  int ip, good_spix, good_epix, good_cpix;
123  int this_direction = 0;
124 
125  // Initialize
126  spix = 0;
127  epix = num_pixels - 1;
128  cpix = num_pixels/2;
129  good_spix = -1;
130  good_epix = -1;
131  good_cpix = -1;
132 
133  // Find the good start, center, and end pixels for this scan
134  for (ip = spix; ip <= epix; ip++) {
135  if ((flags[ip] & NAVFAIL) == 0 && valid_lat(lat[ip]) && valid_lon(lon[ip])) {
136  // Store the first good pixel in good_spix
137  if (good_spix == -1) {
138  good_spix = ip;
139  }
140  // Store this good pixel in good_epix. Eventually (at or near the end), it will be the last good one.
141  good_epix = ip;
142  // Store this good pixel in cpix. Eventually (somewhere in the middle), it will be last good one at or before cpix.
143  if ((ip <= cpix) || (good_cpix == -1)) {
144  good_cpix = ip;
145  }
146  }
147  }
148 
149  // If this is a good scan, set the scan bounds (i.e. endpoints), and test to see if it should be included in the gring
150  if ((good_spix != -1) && (good_epix != -1) && (good_cpix != -1)) {
151  //printf("good_spix = %d, good_cpix = %d, good_epix = %d\n", good_spix, good_cpix, good_epix);
152  scanBounds->slat = lat[good_spix];
153  scanBounds->slon = lon[good_spix];
154  scanBounds->clat = lat[good_cpix];
155  scanBounds->clon = lon[good_cpix];
156  scanBounds->elat = lat[good_epix];
157  scanBounds->elon = lon[good_epix];
158 
159  // CONDITION 1: If this is the FIRST good scan, return scanBounds, after resetting "state information".
160  if (!first_good_scan) {
161  first_good_scan = true;
162  last_lat = lat[good_cpix];
163  direction_line = recnum;
164  //printf("includeScanInGring: First good scan returned, recnum = %d, lat[good_spix] = %f\n", (int)recnum, lat[good_spix]);
165  return true;
166  } else {
167  // This is a good scan, but not the first good one. So, we can start tracking direction; i.e. no sense in
168  // tracking direction prior to the first good scan.
169  // wait for a few lines before checking direction
170  if((recnum - direction_line) > direction_delta) {
171  direction_line = recnum;
172  if ((lat[good_cpix] - last_lat) > 0) {
173  this_direction = 1;
174  } else {
175  this_direction = -1;
176  }
177  if(last_direction == 0)
178  last_direction = this_direction;
179  }
180  }
181  // CONDITION 2: If the latitude of this scan is more than delta_degrees_lat from the last_lat, return scanBounds,
182  // after resetting "state information". Also CONDITION 1 must have already been satisfied; i.e. last_lat
183  // has a non-default value.
184  if (first_good_scan && (fabs(last_lat - lat[good_cpix]) > delta_degrees_lat) ) {
185  last_direction = this_direction;
186  last_lat = lat[good_cpix];
187  //printf("includeScanInGring: Scan returned due to delta lat, recnum = %d, lat[good_cpix] = %f\n", (int)recnum, lat[good_cpix]);
188  return true;
189  }
190  // CONDITION 3: If the satellite passes over a pole, detect the change from e.g. ascending to descending (or vice versa)
191  // and return scanBounds after resetting "state information". Also CONDITION 1 must have already been satisfied; i.e. last_lat
192  // has a non-default value.
193  if (first_good_scan && (last_direction == -this_direction) && (this_direction != 0)) {
194  last_direction = this_direction;
195  last_lat = lat[good_cpix];
196  //printf("includeScanInGring: Scan returned due to change in direction, recnum = %d, lat[good_cpix] = %f\n", (int)recnum, lat[good_cpix]);
197  return true;
198  }
199  }
200 
201  // If we get this far, this is not a scan to include in the gring. So, just return 0. However, if this is the last scan, we want to use
202  // the last GOOD scan.
203  if (recnum == escan) {
204  // If we got this far (without returning) AND this is the last scan, use the last GOOD scan (still stored in scanBounds).
205  return true;
206  } else {
207  return false;
208  }
209 }
210 
211 
212 void gringHelper::delete_extra_line() {
213 
214  if(geobox_cnt > 2) {
215  if(fabs(centerLat[geobox_cnt-1] - centerLat[geobox_cnt-2]) < delta_degrees_lat / 2) {
216  geobox_cnt--;
217  geobox[0][geobox_cnt-1] = geobox[0][geobox_cnt];
218  geobox[1][geobox_cnt-1] = geobox[1][geobox_cnt];
219  geobox[2][geobox_cnt-1] = geobox[2][geobox_cnt];
220  geobox[3][geobox_cnt-1] = geobox[3][geobox_cnt];
221  centerLat[geobox_cnt-1] = centerLat[geobox_cnt];
222  }
223  }
224 }
225 
244 void gringHelper::createGring(gring_t *gringOut) {
245  delete_extra_line();
246 
247  // Declarations for packing gring struct
248  float **geoboxOrdered;
249  size_t i,j;
250 
251  // Allocate memory for geoboxOrdered[4][MAX_GEOBOX_CNT]
252  geoboxOrdered = allocate2d_float(4, MAX_GEOBOX_CNT);
253 
254  // Order the geobox
255  orderGeobox(geoboxOrdered);
256 
257  // Create the gring from the ordered geobox
258  j = 1;
259  // Start at first slon
260  gringOut->gring_lon[0] = geoboxOrdered[0][0];
261  // Get elons, going forward
262  for (i = 0; i < geobox_cnt; i++) {
263  gringOut->gring_lon[j++] = geoboxOrdered[2][i];
264  }
265  // Get slons, going backwards
266  for (i = 0; i < geobox_cnt - 1; i++) {
267  gringOut->gring_lon[j++] = geoboxOrdered[0][geobox_cnt - 1 - i];
268  }
269  // gring latitides and sequence numbers
270  j = 1;
271  // Start at first slat
272  gringOut->gring_lat[0] = geoboxOrdered[1][0];
273  gringOut->gring_seq[0] = j;
274  // Get elats, going forward
275  for (i = 0; i < geobox_cnt; i++) {
276  gringOut->gring_seq[j] = j + 1;
277  gringOut->gring_lat[j++] = geoboxOrdered[3][i];
278  }
279  // Get slats, going backwards
280  for (i = 0; i < geobox_cnt - 1; i++) {
281  gringOut->gring_seq[j] = j + 1;
282  gringOut->gring_lat[j++] = geoboxOrdered[1][geobox_cnt - 1 - i];
283  }
284  // Verify
285  for (i = 0; i < j; i++) {
286  //printf("INFO: createGring: lat=%f lon=%f\n",gringOut->gring_lat[i],gringOut->gring_lon[i]);
287  }
288  // num_gring_pts
289  gringOut->num_gring_pts = j;
290 
291  // Clean up
292  free2d_float(geoboxOrdered);
293  //delete[] geoboxOrdered[0];
294  //delete[] geoboxOrdered;
295 
296 }
297 
314 void gringHelper::orderGeobox(float **geoboxOrdered) {
315  //printf("INFO: orderGeobox: scan_direction = %d\n", scan_direction);
316 
317  // Declarations
318  size_t scan_num,j;
319 
320 
321  // Initialize geoboxOrdered = geobox
322  for (scan_num=0; scan_num<geobox_cnt; scan_num++) {
323  for (j=0; j<4; j++) {
324  geoboxOrdered[j][scan_num] = geobox[j][scan_num];
325  }
326  }
327 
328  // For certain missions, the instrument scans to the right, so flip the endpoints
329  if (scan_direction > 0) {
330  for (scan_num=0; scan_num<geobox_cnt; scan_num++) {
331  //printf("INFO: orderGeobox: Swapping endpoints for scan %d\n",(int)scan_num);
332  // Lons
333  geoboxOrdered[0][scan_num] = geobox[2][scan_num];
334  geoboxOrdered[2][scan_num] = geobox[0][scan_num];
335  // Lats
336  geoboxOrdered[1][scan_num] = geobox[3][scan_num];
337  geoboxOrdered[3][scan_num] = geobox[1][scan_num];
338  }
339  }
340 
341 }
342 
343 
344 
346  delete_extra_line();
347  return (int)geobox_cnt;
348 
349 }
350 
351 
361 int gringHelper::get_gring_strings(std::string& gring_lon_string, std::string& gring_lat_string, std::string& gring_seq_string) {
362 
363  int num_gring_pts, gring_pt_num;
364 
365  if (geobox_cnt > 1) {
366  // Enough scans for a gring, so keep going
367  gring_t *this_gring = new gring_t;
368  createGring(this_gring);
369  // Declare arrays
370  float *gring_lat, *gring_lon;
371  size_t *gring_seq;
372  // Allocate memory for arrays
373  num_gring_pts = this_gring->num_gring_pts;
374  gring_lat = (float *)calloc(num_gring_pts,sizeof(float));
375  gring_lon = (float *)calloc(num_gring_pts,sizeof(float));
376  gring_seq = (size_t *)calloc(num_gring_pts,sizeof(size_t));
377 
378  // Unpack the gring_t struct
379  for (gring_pt_num = 0; gring_pt_num < num_gring_pts; gring_pt_num++) {
380  gring_lon[gring_pt_num] = this_gring->gring_lon[gring_pt_num];
381  gring_lat[gring_pt_num] = this_gring->gring_lat[gring_pt_num];
382  gring_seq[gring_pt_num] = this_gring->gring_seq[gring_pt_num];
383  //printf("INFO: get_gring_strings: lat=%f lon=%f\n",gring_lat[gring_pt_num],gring_lon[gring_pt_num]);
384  }
385 
386  // Convert arrays into strings and print
387  // Lon
388  xlat_floatArray2String(gring_lon_string, gring_lon, num_gring_pts);
389  // Lat
390  xlat_floatArray2String(gring_lat_string, gring_lat, num_gring_pts);
391  // Seq
392  xlat_intArray2String(gring_seq_string, gring_seq, num_gring_pts);
393 
394  // Clean up
395  delete(this_gring);
396  free(gring_lat);
397  free(gring_lon);
398  free(gring_seq);
399  // return success
400  return(SUCCESS);
401  } else {
402  // NOT enough scans for a gring, so return -1
403  return(-1);
404  }
405 
406 }
407 
408 
409 
416 void gringHelper::xlat_floatArray2String(std::string& myString, float *myArray, int array_length) {
417 
418  int j;
419  char tmp[64]; // One value of myArray, formatted like %6.2f
420 
421  myString.clear();
422  // Iterate through all but the last, adding a delimiter at the end
423  for (j=0; j<array_length; j++) {
424  if(j!=0)
425  myString.append(",");
426  sprintf(tmp, "%.5f",myArray[j]);
427  myString.append(tmp);
428  }
429 }
430 
431 
438 void gringHelper::xlat_intArray2String(std::string& myString, size_t *myArray, int array_length) {
439 
440  int j;
441  char tmp[64];
442 
443  myString.clear();
444  // Iterate through all
445  for (j=0; j<array_length; j++) {
446  if(j!=0)
447  myString.append(",");
448  sprintf(tmp, "%d",(int)myArray[j]);
449  myString.append(tmp);
450  }
451 }
#define SUCCESS
Definition: ObpgReadGrid.h:15
int j
Definition: decode_rs.h:73
#define NULL
Definition: decode_rs.h:63
size_t direction_delta
Definition: gringHelper.h:16
read l1rec
int get_geobox_cnt()
float gring_lat[2 *MAX_GEOBOX_CNT]
Definition: gringHelper.h:31
#define MAX_GEOBOX_CNT
Definition: gringHelper.h:5
float * lat
gringHelper(gringConfig_t *gringConfig)
Definition: gringHelper.cpp:25
@ string
float gring_lon[2 *MAX_GEOBOX_CNT]
Definition: gringHelper.h:32
data_t tmp
Definition: decode_rs.h:74
read recnum
void free2d_float(float **p)
Free a two-dimensional array created by allocate2d_float.
Definition: allocate2d.c:142
int num_gring_pts
Definition: gringHelper.h:34
int get_gring_strings(std::string &gring_lon_string, std::string &gring_lat_string, std::string &gring_seq_string)
Utility functions for allocating and freeing two-dimensional arrays of various types.
size_t gring_seq[2 *MAX_GEOBOX_CNT]
Definition: gringHelper.h:33
flags
Definition: DDAlgorithm.h:22
int32 spix
Definition: l1_czcs_hdf.c:21
#define fabs(a)
Definition: misc.h:93
virtual ~gringHelper()
Definition: gringHelper.cpp:47
float * lon
int32 epix
Definition: l1_czcs_hdf.c:23
float delta_degrees_lat
Definition: gringHelper.h:14
float ** allocate2d_float(size_t h, size_t w)
Allocate a two-dimensional array of type float of a given size.
Definition: allocate2d.c:125
void process_scan(l1str *l1rec, size_t recnum, size_t escan)
Definition: gringHelper.cpp:70
int i
Definition: decode_rs.h:71
int scan_direction
Definition: gringHelper.h:15