OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
getl0scene_nav.c
Go to the documentation of this file.
1 /* -------------------------------------------------------------------- */
2 /* getl0scene_nav() - adds coordinate info to the scene records. */
3 /* */
4 /* B. A. Franz, GSC, November 1997 */
5 /* ---------------------------------------------------------------------*/
6 
7 #include <stdio.h>
8 #include <time.h>
9 #include <math.h>
10 #include "swl0_proto.h"
11 #include <timeutils.h>
12 
15 int getGeoNav(navblk_sType *navblk,
16  INT32 spix,
17  INT32 ipix,
18  INT32 npix,
19  FLOAT32 lat[],
20  FLOAT32 lon[],
21  FLOAT32 solz[],
22  FLOAT32 sola[],
23  FLOAT32 senz[],
24  FLOAT32 sena[]);
25 
26 /* ---------------------------------------------------------------------*/
27 
28 /* ---------------------------------------------------------------------*/
30  INT32 tnode,
31  navblk_sType navblk[],
32  tilt_states_sType *tiltblk,
33  swl0scene *scene) {
34  int i, j;
35  int nbad = 0;
36  INT32 first = -1;
37  INT32 first_plus_1 = -1;
38  INT32 last = -1;
39  INT32 center = -1;
40  INT16 srec;
41  INT16 erec;
42  INT16 ascdsc;
43  char node[2][11] = {"Ascending", "Descending"};
44 
45  INT32 spix;
46  INT32 ipix;
47  INT32 npix;
48  INT32 cpix;
55 
56  FLOAT32 lastLat;
57  FLOAT32 lastLon0;
58  FLOAT32 lastLonN;
59 
60  FLOAT64 sec;
61  INT16 day;
62  INT16 year;
63 
64  BYTE navFlag[MAXFRAMES];
65 
66 
67  /* */
68  /* Set any datatype specific parameters */
69  /* */
70  if (scene->mnftype == GACTYPE) {
71  spix = SPIXGAC;
72  ipix = IPIXGAC;
73  npix = NPIXGAC;
74  } else {
75  spix = SPIXLAC;
76  ipix = IPIXLAC;
77  npix = NPIXLAC;
78  }
79  cpix = npix / 2;
80 
81 
82  /* */
83  /* Break-down time for later use */
84  /* */
85  unix2yds(scene->stime, &year, &day, &sec);
86 
87  /* */
88  /* Copy node and tilt info */
89  /* */
90  scene->node_lon = xnodel;
91  scene->node_time = yds2unix(year, day, (FLOAT64) tnode / 1000.);
92  scene->ntilts = tiltblk->ntilts;
93  memcpy(scene->tilt_flags, tiltblk->tilt_flags,
94  sizeof (scene->tilt_flags));
95  memcpy(scene->tilt_ranges, tiltblk->tilt_ranges,
96  sizeof (scene->tilt_ranges));
97 
98  /* */
99  /* Generate navigation quality index for this scene */
100  /* */
101  for (i = 0; i < scene->nscan; i++) {
102  if (getGeoNav(&navblk[i], spix, ipix, npix, lat, lon, solz, sola, senz, sena))
103  navFlag[i] = 1; /* Good nav */
104  else {
105  navFlag[i] = 0; /* Bad nav */
106  nbad++;
107  if ((scene->mnftype != LUNTYPE) && (scene->mnftype != SOLTYPE) && nbad < 10)
108  printf("-W- %s: bad navigation at scan %d\n", __FILE__, i);
109  }
110  /* */
111  /* Update nflag[0] with results of more stringent test */
112  /* */
113  if ((navblk[i].nflag[0] == 0) && (navFlag[i] == 0)) {
114  navblk[i].nflag[0] = 1;
115  navblk[i].nflag[1] = 1;
116  }
117  }
118 
119  /* */
120  /* Require at least 3 navigatable scans, else set nav vals to 0 */
121  /* Do the same for lunar and solar calibration, but return OK. */
122  /* */
123  if ((nbad > scene->nscan - 3) || (scene->mnftype == LUNTYPE)
124  || (scene->mnftype == SOLTYPE)) {
125  scene->upper_left_lon = -999.0;
126  scene->upper_left_lat = -99.0;
127  scene->upper_right_lon = -999.0;
128  scene->upper_right_lat = -99.0;
129  scene->lower_left_lon = -999.0;
130  scene->lower_left_lat = -99.0;
131  scene->lower_right_lon = -999.0;
132  scene->lower_right_lat = -99.0;
133  scene->center_lon = -999.0;
134  scene->center_lat = -99.0;
135  scene->center_solz = -999.0;
136  scene->start_center_lon = -999.0;
137  scene->start_center_lat = -99.0;
138  scene->end_center_lon = -999.0;
139  scene->end_center_lat = -99.0;
140  scene->start_center_lon = -999.0;
141  scene->northern_lat = -99.0;
142  scene->southern_lat = -99.0;
143  scene->eastern_lon = -999.0;
144  scene->western_lon = -999.0;
145 
146  strncpy(scene->start_node, node[0], 11);
147  strncpy(scene->end_node, node[0], 11);
148 
149  if (scene->type != HRPT)
150  return (0);
151  else
152  return (1);
153  }
154 
155  /* */
156  /* Find first and last scan with good navigation */
157  /* */
158  for (i = 0; i < scene->nscan; i++) {
159  if (navFlag[i]) {
160  if (first < 0)
161  first = i;
162  else if (first_plus_1 < 0)
163  first_plus_1 = i;
164  last = i;
165  }
166  }
167 
168  /* */
169  /* Find center scan with good navigation */
170  /* */
171  center = (last + first) / 2;
172  while ((center > first) && (!navFlag[center]))
173  center--;
174  scene->center_scan_line = center + 1;
175 
176 
177  /* */
178  /* Geolocate first, central, and last navigatable scans, and */
179  /* determine scene limits and ascending, descending state */
180  /* */
181 
182  scene->northern_lat = -90.0;
183  scene->southern_lat = 90.0;
184  scene->eastern_lon = 0.0;
185  scene->western_lon = 0.0;
186  lastLat = 90.0;
187 
188  for (i = 0; i < scene->nscan; i++) {
189 
190  if (navFlag[i]) {
191 
192  geonav_(navblk[i].orb_vec,
193  navblk[i].sen_mat,
194  navblk[i].scan_ell,
195  navblk[i].sun_ref,
196  &spix, &ipix, &npix,
197  lat, lon, solz, sola, senz, sena);
198 
199  /* */
200  /* Ascending or Descending ? */
201  /* */
202  if (lat[cpix] > lastLat)
203  ascdsc = 0;
204  else
205  ascdsc = 1;
206 
207  /* */
208  /* Update first, last, center info */
209  /* */
210  if (i == first) {
211  scene->upper_left_lon = lon[0];
212  scene->upper_left_lat = lat[0];
213  scene->upper_right_lon = lon[npix - 1];
214  scene->upper_right_lat = lat[npix - 1];
215  scene->start_center_lon = lon[cpix];
216  scene->start_center_lat = lat[cpix];
217 
218  } else if (i == first_plus_1) {
219  strncpy(scene->start_node, node[ascdsc], 11);
220 
221  /* now that we know which direction we are going, */
222  /* reinitialize eastermost and westermost */
223  if (ascdsc == 1) {
224  scene->western_lon = westernmost(lastLon0, lon[0]);
225  scene->eastern_lon = easternmost(lastLonN, lon[npix - 1]);
226  } else {
227  scene->western_lon = westernmost(lastLonN, lon[npix - 1]);
228  scene->eastern_lon = easternmost(lastLon0, lon[0]);
229  }
230 
231  } else if (i == center) {
232  scene->center_lon = lon[cpix];
233  scene->center_lat = lat[cpix];
234  scene->center_solz = solz[cpix];
235 
236  } else if (i == last) {
237  scene->lower_left_lon = lon[0];
238  scene->lower_left_lat = lat[0];
239  scene->lower_right_lon = lon[npix - 1];
240  scene->lower_right_lat = lat[npix - 1];
241  scene->end_center_lon = lon[cpix];
242  scene->end_center_lat = lat[cpix];
243  strncpy(scene->end_node, node[ascdsc], 11);
244  }
245 
246  /* */
247  /* Update extrema */
248  /* */
249  for (j = 0; j < npix; j++) {
250  scene->northern_lat = MAX(scene->northern_lat, lat[j]);
251  scene->southern_lat = MIN(scene->southern_lat, lat[j]);
252  }
253 
254  if (ascdsc == 1) {
255  /* Descending */
256  scene->western_lon = westernmost(scene->western_lon,
257  lon[0]);
258  scene->eastern_lon = easternmost(scene->eastern_lon,
259  lon[npix - 1]);
260  } else {
261  /*Ascending */
262  scene->western_lon = westernmost(scene->western_lon,
263  lon[npix - 1]);
264  scene->eastern_lon = easternmost(scene->eastern_lon,
265  lon[0]);
266  }
267 
268  lastLat = lat[cpix];
269  lastLon0 = lon[0];
270  lastLonN = lon[npix - 1];
271  }
272  }
273 
274 
275  /* */
276  /* Geolocate scans at start and end of each tilt period. Try to */
277  /* compensate for nav errors, but if all lines are bad, set to 0 */
278  /* */
279  for (i = 0; i < tiltblk->ntilts; i++) {
280 
281  srec = tiltblk->tilt_ranges[i][0] - 1;
282  erec = tiltblk->tilt_ranges[i][1] - 1;
283 
284  while (!navFlag[srec]) {
285  if (srec == erec) break;
286  srec++;
287  }
288 
289  while (!navFlag[erec]) {
290  if (erec == srec) break;
291  erec--;
292  }
293 
294  if (navFlag[srec]) {
295 
296  geonav_(navblk[srec].orb_vec,
297  navblk[srec].sen_mat,
298  navblk[srec].scan_ell,
299  navblk[srec].sun_ref,
300  &spix, &ipix, &npix,
301  lat, lon, solz, sola, senz, sena);
302 
303  scene->tilt_lons[i][0][0] = lon[0];
304  scene->tilt_lons[i][0][1] = lon[npix - 1];
305  scene->tilt_lats[i][0][0] = lat[0];
306  scene->tilt_lats[i][0][1] = lat[npix - 1];
307 
308  } else {
309  scene->tilt_lons[i][0][0] = 0.0;
310  scene->tilt_lons[i][0][1] = 0.0;
311  scene->tilt_lats[i][0][0] = 0.0;
312  scene->tilt_lats[i][0][1] = 0.0;
313  }
314  if (navFlag[erec]) {
315 
316  geonav_(navblk[erec].orb_vec,
317  navblk[erec].sen_mat,
318  navblk[erec].scan_ell,
319  navblk[erec].sun_ref,
320  &spix, &ipix, &npix,
321  lat, lon, solz, sola, senz, sena);
322 
323  scene->tilt_lons[i][1][0] = lon[0];
324  scene->tilt_lons[i][1][1] = lon[npix - 1];
325  scene->tilt_lats[i][1][0] = lat[0];
326  scene->tilt_lats[i][1][1] = lat[npix - 1];
327 
328  } else {
329  scene->tilt_lons[i][1][0] = 0.0;
330  scene->tilt_lons[i][1][1] = 0.0;
331  scene->tilt_lats[i][1][0] = 0.0;
332  scene->tilt_lats[i][1][1] = 0.0;
333  }
334 
335  }
336 
337  return (0);
338 }
339 
340 /* */
341 /* getGeoNav() - runs geonav and makes additional checks on */
342 /* navigation quality. Returns 1 if OK, 0 if bad. */
343 
344 /* */
345 int getGeoNav(navblk_sType *navblk,
346  INT32 spix,
347  INT32 ipix,
348  INT32 npix,
349  FLOAT32 lat[],
350  FLOAT32 lon[],
351  FLOAT32 solz[],
352  FLOAT32 sola[],
353  FLOAT32 senz[],
354  FLOAT32 sena[]) {
355  if (navblk->nflag[0] != 0)
356  return (0);
357 
358  else {
359 
360  geonav_(navblk->orb_vec,
361  navblk->sen_mat,
362  navblk->scan_ell,
363  navblk->sun_ref,
364  &spix, &ipix, &npix,
365  lat, lon, solz, sola, senz, sena);
366 
367  if (isnan(lat[0]) || lat[0] == 999.0)
368  return (0);
369 
370  if (isnan(lat[npix / 2]) || lat[npix / 2] == 999.0)
371  return (0);
372 
373  if (isnan(lat[npix - 1]) || lat[npix - 1] == 999.0)
374  return (0);
375  }
376 
377  return (1);
378 }
379 
381  if (fabs(lon1 - lon2) < 190.0)
382  return ( MIN(lon1, lon2));
383  else
384  return ( MAX(lon1, lon2));
385 }
386 
388  if (fabs(lon1 - lon2) < 190.0)
389  return ( MAX(lon1, lon2));
390  else
391  return ( MIN(lon1, lon2));
392 }
393 
394 
395 
#define MAX(A, B)
Definition: swl0_utils.h:26
#define MIN(x, y)
Definition: rice.h:169
#define SOLTYPE
Definition: swl0_parms.h:22
double FLOAT64
Definition: elements.h:8
int j
Definition: decode_rs.h:73
int32_t day
double yds2unix(int16_t year, int16_t day, double secs)
Definition: yds2unix.c:7
#define NPIXGAC
Definition: swl0_parms.h:26
#define SPIXGAC
Definition: swl0_parms.h:28
int geonav_(FLOAT32 pos[3], FLOAT32 rm[3][3], FLOAT32 coef[6], FLOAT32 sunref[3], INT32 *spix, INT32 *ipix, INT32 *npix, FLOAT32 lat[], FLOAT32 lon[], FLOAT32 solz[], FLOAT32 sola[], FLOAT32 senz[], FLOAT32 sena[])
int32_t INT32
Definition: elements.h:6
#define IPIXGAC
Definition: swl0_parms.h:30
#define MAXFRAMES
Definition: swl0_parms.h:9
float * lat
FLOAT32 easternmost(FLOAT32 lon1, FLOAT32 lon2)
#define IPIXLAC
Definition: swl0_parms.h:29
#define LUNTYPE
Definition: swl0_parms.h:21
int getGeoNav(navblk_sType *navblk, INT32 spix, INT32 ipix, INT32 npix, FLOAT32 lat[], FLOAT32 lon[], FLOAT32 solz[], FLOAT32 sola[], FLOAT32 senz[], FLOAT32 sena[])
unsigned char BYTE
Definition: elements.h:4
short int INT16
Definition: elements.h:5
FLOAT32 westernmost(FLOAT32 lon1, FLOAT32 lon2)
#define HRPT
Definition: l1stat.h:35
void unix2yds(double usec, short *year, short *day, double *secs)
float FLOAT32
Definition: elements.h:7
int getl0scene_nav(FLOAT32 xnodel, INT32 tnode, navblk_sType navblk[], tilt_states_sType *tiltblk, swl0scene *scene)
#define GACTYPE
Definition: swl0_parms.h:19
def center
Definition: sort_gring.py:68
int32 spix
Definition: l1_czcs_hdf.c:21
#define fabs(a)
Definition: misc.h:93
#define NPIXLAC
Definition: swl0_parms.h:25
int scan_ell(float p[3], double sm[3][3], double coef[10])
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second and prod_ix set to PARAM_TYPE_INT name_prefix is compared with the beginning of the product name If name_suffix is not empty the it must match the end of the product name The characters right after the prefix are read as an integer and prod_ix is set to that number strncpy(l2prod->name_prefix, "myprod", UNITLEN)
float * lon
int i
Definition: decode_rs.h:71
int npix
Definition: get_cmp.c:27
#define SPIXLAC
Definition: swl0_parms.h:27