OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
getl1rec.c
Go to the documentation of this file.
1 /* -------------------------------------------------------------------- */
2 /* getl1rec() - combines L0 data with preprocessed navigation and */
3 /* converted engineering telemetry to produce one or five */
4 /* L1 records. */
5 /* */
6 /* Synopsis: */
7 /* */
8 /* nrecs = getl1rec(file,sceneFrameNum,scene,navinp,navblk,tiltblk, */
9 /* l1rec) */
10 /* */
11 /* nrecs INT32 number of output L1 recs */
12 /* sceneFrameNum INT32 frame number relative to scene record */
13 /* scene swl0scene* pointer to scene record */
14 /* navinp input_sType* array of navigation input records */
15 /* navblk input_sType* array of processed navigation blocks */
16 /* tiltblk tilt_states_sType tilt state information */
17 /* l1rec swl1rec* array of output L1 records */
18 /* */
19 /* Description: */
20 /* */
21 /* getl1rec returns -1 if it can't read the file, otherwise it returns */
22 /* the number of output L1 records. For GAC data, nrec=5, as there are */
23 /* 5 scans in a GAC frame. All other types return nrec=1. The input */
24 /* scene record contains, among other things, the list of frame numbers */
25 /* within the L0 file which are associated with this scene. So, the */
26 /* scene record, incombination with the sceneFrameNum serve as a pointer*/
27 /* to the L0 frame of the file. The navinp array contains one record */
28 /* for each frame of the scene, but the navblk contains one record for */
29 /* each scan of the scene. So, for GAC frames the number of records in */
30 /* the navblk will be 5x the number of records in the navinp array. The */
31 /* primary purpose of this function is to coordinate the combination of */
32 /* these various input sources. */
33 /* */
34 /* Modification History: */
35 /* */
36 /* 22 Oct 1997, B. A. Franz, General Sciences Corp. */
37 /* - initial development */
38 /* */
39 /* ---------------------------------------------------------------------*/
40 
41 #include <stdio.h>
42 #include <math.h>
43 #include "swl0_proto.h"
44 
45 INT32 getl1rec(INT16 sceneFrameNum,
46  swl0scene *scene,
47  swl0ctl *l0ctl,
48  input_sType navinp[],
49  navblk_sType navblk[],
50  tilt_states_sType *tiltblk,
51  swl1rec l1rec[]) {
52  static FILE *fp = NULL;
53 
54  INT16 fileFrameNum; /* frame number relative to file start */
55  INT16 sceneScanNum; /* scan number relative to scene start */
56  INT32 fileBytePos; /* file position of desired L0 frame */
57  INT16 irec; /* output l1 record index */
58  INT16 nrecs = 1; /* number of output l1 records */
59  BYTE mnf[L0LEN]; /* raw minor frame */
60 
61  INT32 npix; /* number of pixels per scan */
62  INT32 spix; /* first pixel in LAC scan */
63  INT32 ipix; /* pixel spacing in LAC scan */
64 
65  INT32 o_inst; /* byte offset to first inst tlm block */
66  INT32 o_data; /* byte offset to first image data block */
67  INT32 o_gtdipix; /* offset to tdi pixel of image block */
68  INT32 o_startpix; /* offset to start pixel of image block */
69  INT32 o_darkpix; /* offset to first dark restore pixel */
70  INT32 o_image; /* offset to first image pixel */
71  INT32 o_stoppix; /* offset to stop pixel of image block */
72  INT32 s_data; /* size of image data block in bytes */
73  INT32 s_image; /* size of image scan in bytes */
74  INT32 s_inst; /* size of instrument telemetry block */
75 
76  static INT16 lastScanTemp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
77  static INT16 lastMirrorSide = 0;
78  static INT16 lastTdi[8] = {0, 0, 0, 0, 0, 0, 0, 0};
79 
80  INT16 scid[2];
81  INT16 mnfnum;
82  INT16 mnftype;
83  INT16 inst[44];
84  INT32 nbits;
85  INT32 nbiterrs;
86 
87  int endian = 0;
88  int i, j;
89 
90  if (endianess() == 1)
91  endian = 1;
92 
93  /* */
94  /* Define any data-type specific offset and size parameters */
95  /* */
96  if (scene->mnftype == GACTYPE) {
97  nrecs = 5;
98  spix = SPIXGAC;
99  ipix = IPIXGAC;
100  npix = NPIXGAC;
101  o_inst = O_INSTGAC;
102  o_data = O_DATAGAC;
103  s_data = S_DATAGAC;
104  } else {
105  nrecs = 1;
106  spix = SPIXLAC;
107  ipix = IPIXLAC;
108  npix = NPIXLAC;
109  o_inst = O_INSTLAC;
110  o_data = O_DATALAC;
111  s_data = S_DATALAC;
112  }
113  s_image = npix * sizeof (l1rec[0].data[0][0]) * NBANDS;
114  s_inst = sizeof (l1rec[0].inst);
115 
116 
117  /* */
118  /* Open the L0 file for reading, if it is not already opened. */
119  /* Note: this assumes only one L0 file per process. */
120  /* */
121  if (fp == NULL)
122  if ((fp = fopen(scene->l0file, "r")) == NULL) {
123  fprintf(stderr,
124  "-E- %s line %d: unable to open %s for reading\n",
125  __FILE__, __LINE__, scene->l0file);
126  return (1);
127  }
128 
129  /* */
130  /* Read minor frame from L0 file */
131  /* */
132  fileFrameNum = scene->indx[sceneFrameNum];
133  fileBytePos = sizeof (swl0hdr) + fileFrameNum * (L0LEN);
134  if (fseek(fp, fileBytePos, SEEK_SET) != 0) {
135  fprintf(stderr,
136  "-E- %s line %d: error reading %s\n",
137  __FILE__, __LINE__, scene->l0file);
138  return (1);
139  }
140  if (fread(mnf, L0LEN, 1, fp) != 1) {
141  fprintf(stderr,
142  "-E- %s line %d: error reading %s\n",
143  __FILE__, __LINE__, scene->l0file);
144  return (1);
145  }
146 
147  /* Get basic frame attributes */
148  memcpy(scid, &mnf[O_SCID], sizeof (scid));
149  if (endian)
150  swapc_bytes((char *) scid, 2, 2);
151  mnfnum = scid2mnfnum(scid);
152  mnftype = scid2mnftype(scid);
153  if (mnftype != scene->mnftype) {
154  fprintf(stderr,
155  "-E- %s line %d: frame type mismatch\n",
156  __FILE__, __LINE__);
157  return (1);
158  }
159 
160  /* */
161  /* For GAC data, there will be five l1 records generated. For */
162  /* LAC and LAC-like data, only one l1 record is generated. Load */
163  /* each output record in sequence. */
164  /* */
165  for (irec = 0; irec < nrecs; irec++) {
166 
167  /* First, clear the record so there's no confusion */
168  memset(&l1rec[irec], 0, sizeof (swl1rec));
169 
170  l1rec[irec].type = scene->mnftype;
171  l1rec[irec].npix = npix;
172 
173  /* */
174  /* Grab raw telemetry from minor frame. Note that the ttag, */
175  /* scid, and soh data are only recorded once per frame, so */
176  /* they are replicated for each GAC scan. */
177  /* */
178  memcpy(l1rec[irec].ttag, &mnf[O_TIME], sizeof (l1rec[0].ttag));
179  memcpy(l1rec[irec].scid, &mnf[O_SCID], sizeof (l1rec[0].scid));
180  memcpy(l1rec[irec].soh, &mnf[O_SOH], sizeof (l1rec[0].soh));
181  memcpy(l1rec[irec].inst, &mnf[o_inst + irec * s_inst], s_inst);
182 
183  if (endian) {
184  swapc_bytes((char *) l1rec[irec].ttag, 2, 4);
185  swapc_bytes((char *) l1rec[irec].scid, 2, 2);
186  swapc_bytes((char *) l1rec[irec].inst, 2, 44);
187  }
188 
189  /* */
190  /* Grab raw image data from minor frame. */
191  /* */
192  o_gtdipix = o_data + irec * s_data + 0;
193  o_startpix = o_data + irec * s_data + 16;
194  o_darkpix = o_data + irec * s_data + 32;
195  o_image = o_data + irec * s_data + 48;
196  o_stoppix = o_data + irec * s_data + s_data - 16;
197 
198  memcpy(l1rec[irec].startpix, &mnf[o_startpix],
199  sizeof (l1rec[0].startpix));
200  memcpy(l1rec[irec].darkpix, &mnf[o_darkpix],
201  sizeof (l1rec[0].darkpix));
202  memcpy(&l1rec[irec].data[0][0], &mnf[o_image],
203  s_image);
204  memcpy(l1rec[irec].stoppix, &mnf[o_stoppix],
205  sizeof (l1rec[0].stoppix));
206 
207  if (endian) {
208  swapc_bytes((char *) l1rec[irec].startpix, 2, 8);
209  swapc_bytes((char *) l1rec[irec].darkpix, 2, 8);
210  swapc_bytes((char *) l1rec[irec].data, 2, s_image / 2);
211  swapc_bytes((char *) l1rec[irec].stoppix, 2, 8);
212  }
213 
214  /* */
215  /* Set gain and tdi. For HRPT we just force it to nominal */
216  /* values, to avoid problems with noise. */
217  /* */
218  if (scene->type == HRPT && l0ctl->gainSetting >= 0) {
219  for (i = 0; i < NBANDS; i++) {
220  l1rec[irec].gain[i] = l0ctl->gainSetting;
221  l1rec[irec].tdi[i] = 0;
222  }
223  } else {
224  if (scene->mnftype == TDITYPE || scene->mnftype == IGCTYPE) {
225  /* Apply previous TDI setting to current scan */
226  memcpy(l1rec[irec].tdi, lastTdi, sizeof (lastTdi));
227  memcpy(lastTdi, &mnf[o_gtdipix], sizeof (lastTdi));
228  } else {
229  memcpy(l1rec[irec].tdi, &mnf[o_gtdipix], sizeof (l1rec[0].tdi));
230  }
231  if (endian)
232  swapc_bytes((char *) l1rec[irec].tdi, 2, 8);
233 
234  /* Need to separate the GAIN from the TDI */
235  for (i = 0; i < NBANDS; i++) {
236  l1rec[irec].gain[i] = l1rec[irec].tdi[i] >> 8;
237  l1rec[irec].tdi[i] = l1rec[irec].tdi[i] & (INT16) 255;
238  }
239  }
240 
241  /* */
242  /* Need to determine half-angle mirror side from start pixel. */
243  /* If the field is not all 0 or all 1, it is corrupted, so we */
244  /* assume the mirror side based on last mirror side. */
245  /* */
246  if (l1rec[irec].startpix[7] == 0)
247  l1rec[irec].side = 0;
248  else if (l1rec[irec].startpix[7] == 1023)
249  l1rec[irec].side = 1;
250  else {
251  /*
252  fprintf(stderr,
253  "-W- %s: start pix corrupted in frame %d\n",
254  __FILE__,fileFrameNum);
255  */
256  if (scene->mnftype == GACTYPE)
257  l1rec[irec].side = lastMirrorSide;
258  else
259  l1rec[irec].side = (lastMirrorSide + 1) % 2;
260  }
261  lastMirrorSide = l1rec[irec].side;
262 
263 
264  /* */
265  /* Grab converted spacecrft and instrument tlm from nav input.*/
266  /* The navigation input is passed in with 1 record per frame, */
267  /* so for GAC we will be replicating the sc_ana and sc_dis. */
268  /* */
269  memcpy(l1rec[irec].sc_ana, navinp[sceneFrameNum].sc_ana,
270  sizeof (l1rec[0].sc_ana));
271  memcpy(l1rec[irec].sc_dis, navinp[sceneFrameNum].sc_dis,
272  sizeof (l1rec[0].sc_dis));
273  memcpy(l1rec[irec].inst_ana,
274  &(navinp[sceneFrameNum].inst_ana[irec][0]),
275  sizeof (l1rec[0].inst_ana));
276  memcpy(l1rec[irec].inst_dis,
277  &(navinp[sceneFrameNum].inst_dis[irec][0]),
278  sizeof (l1rec[0].inst_dis));
279 
280 
281  /* For GAC scans beyond the first, need to add to msecs */
282  l1rec[irec].msec = (INT32) (navinp[sceneFrameNum].msec +
283  (irec * 4 * DTLAC * 1000)) % 86400000;
284 
285  /* */
286  /* The navigation block is passed in with 1 record per scan, */
287  /* so for GAC it has already been expanded. Same for tiltblk. */
288  /* */
289  sceneScanNum = sceneFrameNum * nrecs + irec;
290  memcpy(l1rec[irec].orb_vec, navblk[sceneScanNum].orb_vec,
291  sizeof (l1rec[0].orb_vec));
292  memcpy(l1rec[irec].l_vert, navblk[sceneScanNum].l_vert,
293  sizeof (l1rec[0].l_vert));
294  memcpy(l1rec[irec].sun_ref, navblk[sceneScanNum].sun_ref,
295  sizeof (l1rec[0].sun_ref));
296  memcpy(l1rec[irec].att_ang, navblk[sceneScanNum].att_ang,
297  sizeof (l1rec[0].att_ang));
298  memcpy(l1rec[irec].sen_mat, navblk[sceneScanNum].sen_mat,
299  sizeof (l1rec[0].sen_mat));
300  memcpy(l1rec[irec].scan_ell, navblk[sceneScanNum].scan_ell,
301  sizeof (l1rec[0].scan_ell));
302  memcpy(l1rec[irec].nflag, navblk[sceneScanNum].nflag,
303  sizeof (l1rec[0].nflag));
304  l1rec[irec].tilt = tiltblk->tilt[sceneScanNum];
305 
306  /* */
307  /* If the navigation quality is OK, geolocate the scanline */
308  /* and load the geolocation arrays. */
309  /* */
310  if (navblk[sceneScanNum].nflag[0] == 0) {
311  geonav_(navblk[sceneScanNum].orb_vec,
312  navblk[sceneScanNum].sen_mat,
313  navblk[sceneScanNum].scan_ell,
314  navblk[sceneScanNum].sun_ref,
315  &spix, &ipix, &npix,
316  l1rec[irec].lat,
317  l1rec[irec].lon,
318  l1rec[irec].solz,
319  l1rec[irec].sola,
320  l1rec[irec].senz,
321  l1rec[irec].sena);
322  }
323 
324  l1rec[irec].slat = MIN(l1rec[irec].lat[0], 90.0);
325  l1rec[irec].slon = MIN(l1rec[irec].lon[0], 180.0);
326  l1rec[irec].clat = MIN(l1rec[irec].lat[npix / 2], 90.0);
327  l1rec[irec].clon = MIN(l1rec[irec].lon[npix / 2], 180.0);
328  l1rec[irec].elat = MIN(l1rec[irec].lat[npix - 1], 90.0);
329  l1rec[irec].elon = MIN(l1rec[irec].lon[npix - 1], 180.0);
330  l1rec[irec].csol_z = l1rec[irec].solz[npix / 2];
331 
332 
333  /* */
334  /* Need to copy focal-plane temps from instrument telemetry, */
335  /* but not every scan has valid instrument telemetry, so in */
336  /* that case we use the nearest temperature data available. */
337  /* */
338  if (valid_instlm(mnftype, mnfnum, irec)) {
339 
340  l1rec[irec].scan_temp[0] = l1rec[irec].inst[ 7] & 255;
341  l1rec[irec].scan_temp[1] = l1rec[irec].inst[ 7] & 255;
342  l1rec[irec].scan_temp[2] = l1rec[irec].inst[ 8] & 255;
343  l1rec[irec].scan_temp[3] = l1rec[irec].inst[ 8] & 255;
344  l1rec[irec].scan_temp[4] = l1rec[irec].inst[ 9] & 255;
345  l1rec[irec].scan_temp[5] = l1rec[irec].inst[ 9] & 255;
346  l1rec[irec].scan_temp[6] = l1rec[irec].inst[10] & 255;
347  l1rec[irec].scan_temp[7] = l1rec[irec].inst[10] & 255;
348  for (i = 0; i < NBANDS; i++)
349  lastScanTemp[i] = l1rec[irec].scan_temp[i];
350 
351  /* set engineering quality flags if the inst tlm is valid.*/
352  getEngQual(l1rec[irec].inst_ana, l1rec[irec].eng_qual);
353 
354  } else {
355 
356  if ((scene->mnftype == GACTYPE) && (irec == 0)) {
357  /* */
358  /* If the first scan in a GAC frame does not have */
359  /* valid instrument telemetry, we can use the insttlm */
360  /* from the next scan to get scan temp. Otherwise, we */
361  /* can rely on the lastScanTemp array. */
362  /* */
363  memcpy(inst, &mnf[o_inst + s_inst], s_inst);
364  if (endian)
365  swapc_bytes((char *) inst, 2, 44);
366 
367 
368  l1rec[irec].scan_temp[0] = inst[ 7] & 255;
369  l1rec[irec].scan_temp[1] = inst[ 7] & 255;
370  l1rec[irec].scan_temp[2] = inst[ 8] & 255;
371  l1rec[irec].scan_temp[3] = inst[ 8] & 255;
372  l1rec[irec].scan_temp[4] = inst[ 9] & 255;
373  l1rec[irec].scan_temp[5] = inst[ 9] & 255;
374  l1rec[irec].scan_temp[6] = inst[10] & 255;
375  l1rec[irec].scan_temp[7] = inst[10] & 255;
376 
377  } else
378  /* */
379  /* In most cases, the use of the previous scan temps */
380  /* will be perfectly accurate. If, however, this is */
381  /* the first frame of a LAC-type scene, the last scan */
382  /* temp may not be set or may not apply. This issue */
383  /* is avoided if LAC-type scenes are forced to start */
384  /* on a valid instrument frame. */
385  /* */
386  for (i = 0; i < NBANDS; i++)
387  l1rec[irec].scan_temp[i] = lastScanTemp[i];
388  }
389 
390 
391  /* */
392  /* Set the scan-line flags */
393  /* 0 : # bit errors */
394  /* 3 : # bits tested */
395  /* 1 : navigation tlm quality flag */
396  /* 2 : scan number within frame (1-15) */
397  /* */
398 
399  bitError(mnf, &nbits, &nbiterrs);
400  nbits += (256 * mnf[0] + mnf[1]);
401  nbiterrs += mnf[2];
402  l1rec[irec].s_flags[0] = (BYTE) MIN(nbiterrs, 255);
403  l1rec[irec].s_flags[3] = (BYTE) MIN(nbits / 5, 255);
404 
405  l1rec[irec].s_flags[1] = scene->qual[sceneFrameNum];
406 
407  if (scene->mnftype == GACTYPE)
408  l1rec[irec].s_flags[2] = (mnfnum - 1) * 5 + irec + 1;
409  else
410  l1rec[irec].s_flags[2] = 1;
411 
412 
413  /* */
414  /* Get saturated and zero-pixel counts */
415  /* */
416  for (i = 0; i < npix; i++)
417  for (j = 0; j < NBANDS; j++) {
418  if (l1rec[irec].data[i][j] >= 1023)
419  l1rec[irec].s_satp[j]++;
420  if (l1rec[irec].data[i][j] - l1rec[irec].darkpix[j] <= 0) {
421  l1rec[irec].s_zerop[j]++;
422  }
423  }
424 
425  }
426 
427 
428  return (nrecs);
429 }
430 
431 
432 
433 
#define MIN(x, y)
Definition: rice.h:169
#define DTLAC
Definition: swl0_parms.h:47
int j
Definition: decode_rs.h:73
#define NPIXGAC
Definition: swl0_parms.h:26
INT16 getEngQual(FLOAT32 ins_ana[], BYTE eng_qual[])
Definition: instlm.c:33
#define INT32
Definition: l1_imgscale.c:3
#define SPIXGAC
Definition: swl0_parms.h:28
#define NULL
Definition: decode_rs.h:63
#define O_TIME
Definition: swl0_parms.h:33
#define S_DATALAC
Definition: swl0_parms.h:44
read l1rec
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
float * lat
int32 * msec
Definition: l1_czcs_hdf.c:31
INT16 scid2mnftype(INT16 scid[])
Definition: swl0_utils.c:20
#define O_DATALAC
Definition: swl0_parms.h:39
#define S_DATAGAC
Definition: swl0_parms.h:43
#define IPIXLAC
Definition: swl0_parms.h:29
int endianess(void)
determine endianess
Definition: endianess.c:10
#define IGCTYPE
Definition: swl0_parms.h:23
int swapc_bytes(char *in, int nbyte, int ntime)
Definition: swapc_bytes.c:4
#define O_INSTGAC
Definition: swl0_parms.h:40
unsigned char BYTE
Definition: elements.h:4
short int INT16
Definition: elements.h:5
#define HRPT
Definition: l1stat.h:35
INT16 scid2mnfnum(INT16 scid[])
Definition: swl0_utils.c:29
INT32 getl1rec(INT16 sceneFrameNum, swl0scene *scene, swl0ctl *l0ctl, input_sType navinp[], navblk_sType navblk[], tilt_states_sType *tiltblk, swl1rec l1rec[])
Definition: getl1rec.c:45
int16_t tdi[BANDS_DIMS_1A]
Definition: l1a_seawifs.c:37
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
#define GACTYPE
Definition: swl0_parms.h:19
#define BYTE
Definition: l1_imgscale.c:5
int32 spix
Definition: l1_czcs_hdf.c:21
#define L0LEN
Definition: swl0_parms.h:8
#define NPIXLAC
Definition: swl0_parms.h:25
int scan_ell(float p[3], double sm[3][3], double coef[10])
float * lon
BYTE bitError(BYTE mnf[], INT32 *totbits, INT32 *toterrs)
Definition: swl0_utils.c:441
#define O_DATAGAC
Definition: swl0_parms.h:38
float32 * att_ang
Definition: l1_czcs_hdf.c:34
#define TDITYPE
Definition: swl0_parms.h:24
#define O_SCID
Definition: swl0_parms.h:32
#define O_SOH
Definition: swl0_parms.h:34
#define O_INSTLAC
Definition: swl0_parms.h:41
int i
Definition: decode_rs.h:71
@ NBANDS
Definition: make_L3_v1.1.c:53
int npix
Definition: get_cmp.c:27
INT16 valid_instlm(INT16 mnftype, INT16 mnfnum, INT16 scanNum)
Definition: instlm.c:15
#define SPIXLAC
Definition: swl0_parms.h:27