OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
fill_orb_dat.c
Go to the documentation of this file.
1 #include "l1czcs.h"
2 #include <stdlib.h>
3 #include "time_utl.h"
4 
5 typedef struct orb_struct_def {
6  int n_good; /* # of good points */
7  int flag[4]; /* data value flag: -1 - no measurement, 1 measurement */
8  double sec[4]; /* seconds attached to record */
9  double pos[4][3]; /* position [point #][x, y, or z] */
10  double vel[4][3]; /* velocity */
11  double pos_err[4]; /* position max error */
12 } orb_str;
13 
14 #define s_per_day 24 * 60 * 60
15 #define ms_per_day s_per_day * 1000
16 
17 /* function prototypes */
18 int get_orb_dat(int year, int doy, int st_msec, int en_msec, orb_str *orb);
19 int int_orb_dat(orb_str orb, int nlines, int *msec, float *orb_vec, float *pos_err);
20 
21 int rd_smmr_orb(char *sfile, int *nrec, int *syear, int *sday,
22  double **orbvec, double **time, float **pos_err);
23 
24 void asap_int2_(int32_t *nstp, double *tsap, double *asap, double *pos_erri,
25  int32_t *ngps, double *gpsec, double *vecs, float *pos_erro);
26 
27 int fill_orb_dat(l1_data_struc *l1_data, gattr_struc *gattr)
28 /*******************************************************************
29 
30  fill_orb_dat
31 
32  purpose: fill the orbit vector with Nimbus 7 data
33 
34  Returns type: int - 0 if all went well
35 
36  Parameters: (in calling order)
37  Type Name I/O Description
38  ---- ---- --- -----------
39  l1_data_struc * l1_data I level-1 data struct
40  gattr_struc * gattr I/O global attribute struct
41 
42  Modification history:
43  Programmer Date Description of change
44  ---------- ---- ---------------------
45  W. Robinson, SAIC 2 Dec 2005 Original development
46 
47  *******************************************************************/
48  {
49  int en_msec;
50  orb_str orb;
51  /*
52  * Get the orbit data for the period covered by the granule
53  */
54  en_msec = (gattr->end_day != gattr->start_day) ?
55  gattr->end_msec + ms_per_day : gattr->end_msec;
56  if (get_orb_dat(gattr->start_year, gattr->start_day, gattr->start_msec,
57  en_msec, &orb) != 0)
58  return 1;
59 
60  /*
61  * interpolate the orbit points to each line of the czcs data
62  */
63  int_orb_dat(orb, gattr->scan_lines, l1_data->msec, l1_data->orb_vec,
64  l1_data->pos_err);
65  return 0;
66 }
67 
68 int get_orb_dat(int year, int doy, int st_msec, int en_msec, orb_str *orb)
69 /*******************************************************************
70 
71  get_orb_dat
72 
73  purpose: extract orbit data needed for a czcs file
74 
75  Returns type: int - 0 if no problems
76 
77  Parameters: (in calling order)
78  Type Name I/O Description
79  ---- ---- --- -----------
80  int year I 4 digit year of data
81  int doy I day of the year
82  int st_msec I start millisec of czcs data
83  int en_msec I end millisec of czcs data,
84  relative to start day
85  orb_struc * orb O orbit data for at most 4 samples
86 
87  Note that as a CZCS granule is at most slightly longer than 2 minutes and
88  orbit info is at 1 min intervals, at most 4 samples are required to
89  interpolate a granule
90 
91  Modification history:
92  Programmer Date Description of change
93  ---------- ---- ---------------------
94  W. Robinson, SAIC 4-Nov-2005 Original development
95 
96  *******************************************************************/ {
97  char *floc, *fname;
98  int i, jd, st_min, en_min, ix_interp, ix_tim;
99  int gap_lim = 5;
100  int nrec0, nrec1, nrec2, year0, year1, year2, day0, day1, day2;
101  double *orb0, *orb1, *orb2, *tmin0, *tmin1, *tmin2;
102  float *pos_err0, *pos_err1, *pos_err2;
103 
104  /* defs needed for operation */
105  char *day_to_ofile(int day, char *floc);
106  /*
107  * initialize some items
108  */
109  for (i = 0; i < 4; i++)
110  orb->flag[i] = -1;
111  orb->n_good = 0;
112  /*
113  * read in orbit data for the year / day
114  */
115  jd = yydoy_to_jd(year, doy);
116  if ((floc = getenv("OCDATAROOT")) == NULL) {
117  printf("%s: environment variable OCDATAROOT undefined\n", __FILE__);
118  exit(1);
119  }
120  strcat(floc, "/czcs/nav/");
121 
122  fname = day_to_ofile(jd, floc);
123  if (rd_smmr_orb(fname, &nrec1, &year1, &day1, &orb1, &tmin1,
124  &pos_err1) != 0) {
125  printf(
126  "%s: Primary Nimbus 7 orbit file: %s\nwas not found but should exist\n",
127  __FILE__, fname);
128  return -1;
129  }
130  /*
131  * if no main day entries, abandon the efort
132  */
133  if (nrec1 <= 0) {
134  orb->n_good = 0;
135  return 0;
136  }
137  /*
138  * get the surrounding minute values from the start, end czcs times
139  * and handle minor (> -100 min) times, probably never happen
140  */
141  st_min = (st_msec + 6000000) / (1000 * 60) - 100;
142  en_min = ((en_msec + 59999) / 1000) / 60;
143  ix_interp = 0;
144  /*
145  * get data from previous day if needed
146  */
147  if (*(tmin1) > st_min) {
148  /*
149  * read previous day
150  */
151  fname = day_to_ofile((jd - 1), floc);
152  if (rd_smmr_orb(fname, &nrec0, &year0, &day0, &orb0, &tmin0,
153  &pos_err0) == 0) {
154  if (nrec0 > 0) {
155  if ((st_min - (*(tmin0 + nrec0 - 1) - 1440)) > gap_lim) {
156  /* we can't add this in as it is beyond interpolation limit */
157  orb->flag[ ix_interp ] = -1;
158  } else {
159  orb->flag[ ix_interp ] = 1;
160  orb->sec[ ix_interp ] = *(tmin0 + nrec0 - 1) - 1440;
161  orb->pos_err[ ix_interp ] = *(pos_err0 + nrec0 - 1);
162  for (i = 0; i < 3; i++) {
163  orb->pos[ix_interp][i] = *(orb0 + (nrec0 - 1) * 6 + i);
164  orb->vel[ix_interp][i] = *(orb0 + (nrec0 - 1) * 6 + 3 + i);
165  }
166  ix_interp++;
167  }
168  /*
169  * remove storage for the prev day
170  */
171  free(orb0);
172  free(tmin0);
173  free(pos_err0);
174  }
175  }
176  }
177  /*
178  * get back to the current day
179  * Note that we will start collecting samples starting at start min -
180  * gap_lim, but discard them if closer times are in file.
181  */
182  ix_tim = 0;
183  while ((*(tmin1 + ix_tim) < (en_min + gap_lim)) &&
184  (ix_tim < nrec1) && (ix_interp < 4)) {
185  if (*(tmin1 + ix_tim) >= st_min - gap_lim) {
186  /* discard a time found before start if a closer one exists */
187  if ((ix_interp > 0) && *(tmin1 + ix_tim) <= st_min)
188  ix_interp--;
189  orb->flag[ ix_interp ] = 1;
190  orb->sec[ ix_interp ] = *(tmin1 + ix_tim);
191  orb->pos_err[ ix_interp ] = *(pos_err1 + ix_tim);
192  for (i = 0; i < 3; i++) {
193  orb->pos[ix_interp][i] = *(orb1 + ix_tim * 6 + i);
194  orb->vel[ix_interp][i] = *(orb1 + ix_tim * 6 + 3 + i);
195  }
196  ix_interp++;
197  }
198  ix_tim++;
199  }
200  /*
201  * free storage
202  */
203  free(orb1);
204  free(tmin1);
205  free(pos_err1);
206  /*
207  * possibly, orbit information from the following day may also be needed
208  */
209  if (ix_interp < 4) {
210  if (*(tmin1 + nrec1 - 1) <= en_min) {
211  fname = day_to_ofile((jd + 1), floc);
212  if (rd_smmr_orb(fname, &nrec2, &year2, &day2, &orb2, &tmin2,
213  &pos_err2) == 0) {
214  if (nrec2 > 0) {
215  if ((*tmin2 + 1440 - en_min) <= gap_lim) {
216  ix_tim = 0;
217  while (((*(tmin2 + ix_tim) + 1440) < (en_min + gap_lim)) &&
218  (ix_tim < nrec2) && (ix_interp < 4)) {
219  if ((*(tmin2 + ix_tim) + 1440) >= st_min) {
220  orb->flag[ ix_interp ] = 1;
221  orb->sec[ ix_interp ] = *(tmin2 + ix_tim) + 1440;
222  orb->pos_err[ ix_interp ] = *(pos_err2 + ix_tim);
223  for (i = 0; i < 3; i++) {
224  orb->pos[ix_interp][i] = *(orb2 + ix_tim * 6 + i);
225  orb->vel[ix_interp][i] = *(orb2 + ix_tim * 6 + 3 + i);
226  }
227  ix_interp++;
228  }
229  ix_tim++;
230  }
231  }
232  /*
233  * free storage
234  */
235  free(orb2);
236  free(tmin2);
237  free(pos_err2);
238  }
239  }
240  }
241  }
242  orb->n_good = ix_interp;
243 
244  /*
245  * convert the orb->sec from minutes to seconds
246  */
247  for (i = 0; i < 4; i++) {
248  orb->sec[i] = orb->sec[i] * 60.;
249  }
250 
251  /*
252  * and end
253  */
254  return 0;
255 }
256 
257 int int_orb_dat(orb_str orb, int nlines, int *msec, float *orb_vec,
258  float *pos_err)
259 /*******************************************************************
260 
261  int_orb_dat
262 
263  purpose: interpolate the Nimbus 7 orbit information to each line of CZCS
264 
265  Returns type: int - 0 if all is OK
266 
267  Parameters: (in calling order)
268  Type Name I/O Description
269  ---- ---- --- -----------
270  orb_str orb I structure containing the
271  nimbus 7 orbit data available
272  at the CZCS data time range
273  int nlines I # lines of CZCS data
274  int * msec I time of each CZCS line in
275  msec
276  float * orb_vec O orbit data for each line to fill
277  float * pos_err O orbit position error estimate:
278  < 0, no orbit data available
279  0, no error or original smmr
280  orbit data
281  > 0, orbit modelled data with
282  this error estimate in m.
283  Modification history:
284  Programmer Date Description of change
285  ---------- ---- ---------------------
286  W. Robinson, SAIC 2-Dec-2005 Original development
287 
288  *******************************************************************/ {
289  int start_sec, i, j;
290  double *sec, asap[24], *lcl_orb;
291  /*
292  * at this time, use the asap_int.f routine, slightly modified to interpolate
293  */
294  /*
295  * we must adapt some inputs for asap
296  * msec to seconds
297  * and orbit position, velocity to just an orbit vector
298  */
299  start_sec = *msec / 1000 - 1;
300 
301  if ((sec = (double *) malloc(nlines * sizeof ( double))) == NULL) {
302  printf("%s: malloc failed for seconds array\n", __FILE__);
303  return 1;
304  }
305  if ((lcl_orb = (double *) malloc(nlines * 6 * sizeof ( double))) == NULL) {
306  printf("%s: malloc failed for lcl_orb array\n", __FILE__);
307  return 1;
308  }
309  for (i = 0; i < nlines; i++) {
310  *(sec + i) = (double) *(msec + i) / 1000.;
311  if (*(sec + i) < start_sec)
312  *(sec + i) = *(sec + i) + ms_per_day;
313  }
314 
315  /*
316  * with 1 or less good points, the entire czcs file is designated to
317  * not have orbit data
318  */
319  if (orb.n_good <= 1) {
320  for (i = 0; i < nlines; i++) {
321  *(pos_err + i) = -1.;
322  }
323  } else {
324  /*
325  * with good orbit to interpolate, proceed
326  * get the orbit info set up correctly for asap routine
327  */
328  for (i = 0; i < orb.n_good; i++) {
329  for (j = 0; j < 3; j++) {
330  *(asap + j + i * 6) = orb.pos[i][j];
331  *(asap + j + 3 + i * 6) = orb.vel[i][j];
332  }
333  }
334  /*
335  * call the interpolation routine
336  */
337  asap_int2_(&(orb.n_good), orb.sec, asap, orb.pos_err, &nlines,
338  sec, lcl_orb, pos_err);
339  /*
340  * place position part of orbit in orb_vec
341  */
342  for (i = 0; i < nlines; i++) {
343  for (j = 0; j < 3; j++) {
344  *(orb_vec + j + 3 * i) = *(lcl_orb + j + 6 * i);
345  }
346  }
347  }
348  /*
349  * free the seconds and local orbit
350  */
351  free(lcl_orb);
352  free(sec);
353  /*
354  * all done
355  */
356  return 0;
357 }
char * day_to_ofile(int day, char *floc)
Definition: day_to_ofile.c:5
int j
Definition: decode_rs.h:73
int32_t day
function jd(i, j, k)
Definition: jd.f:2
#define NULL
Definition: decode_rs.h:63
int yydoy_to_jd(int yy, int doy)
Definition: time_utl.c:155
double pos_err[4]
Definition: fill_orb_dat.c:11
int fill_orb_dat(l1_data_struc *l1_data, gattr_struc *gattr)
Definition: fill_orb_dat.c:27
int32 * msec
Definition: l1_czcs_hdf.c:31
int syear
Definition: l1_czcs_hdf.c:15
character(len=1000) if
Definition: names.f90:13
int sday
Definition: l1_czcs_hdf.c:15
int int_orb_dat(orb_str orb, int nlines, int *msec, float *orb_vec, float *pos_err)
Definition: fill_orb_dat.c:257
void asap_int2_(int32_t *nstp, double *tsap, double *asap, double *pos_erri, int32_t *ngps, double *gpsec, double *vecs, float *pos_erro)
#define ms_per_day
Definition: fill_orb_dat.c:15
Definition: jd.py:1
double sec[4]
Definition: fill_orb_dat.c:8
this program makes no use of any feature of the SDP Toolkit that could generate such a then geolocation is calculated at that and then aggregated up to Resolved feature request Bug by adding three new int8 SDSs for each high resolution offsets between the high resolution geolocation and a bi linear interpolation extrapolation of the positions This can be used to reconstruct the high resolution geolocation Resolved Bug by delaying cumulation of gflags until after validation of derived products Resolved Bug by setting Latitude and Longitude to the correct fill resolving to support Near Real Time because they may be unnecessary if use of entrained ephemeris and attitude data is turned resolving bug report Corrected to filter out Aqua attitude records with missing status helping resolve bug MOD_PR03 will still correctly write scan and pixel data that does not depend upon the start time
Definition: HISTORY.txt:248
double pos[4][3]
Definition: fill_orb_dat.c:9
float32 * pos_err
Definition: l1_czcs_hdf.c:35
size_t nrec1
Definition: nccmp.c:28
size_t nrec2
Definition: nccmp.c:28
int rd_smmr_orb(char *sfile, int *nrec, int *syear, int *sday, double **orbvec, double **time, float **pos_err)
Definition: rd_smmr_orb.c:7
int i
Definition: decode_rs.h:71
double vel[4][3]
Definition: fill_orb_dat.c:10
int get_orb_dat(int year, int doy, int st_msec, int en_msec, orb_str *orb)
Definition: fill_orb_dat.c:68