OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
main_vcalmerge.c
Go to the documentation of this file.
1 /* ========================================================================
2  * vcalmerge - reads original and vicarious data from L2 file or files
3  * and writes valid cross-calibration data into an HDF/netCDF4 file
4  *
5  * Synopsis:
6  *
7  * vcalmerge par=parfile
8  *
9  * Description:
10  *
11  * Modification history:
12  *
13  * Programmer Organization Date Description of change
14  * -------------- ------------ -------- ---------------------
15  * Ewa Kwiatkowska SAIC 27 August 2003 Original development
16  * Ewa Kwiatkowska SAIC 6 November 2006 getl1rec change
17  * Ewa Kwiatkowska SAIC 9 October 2007 complete redevelopment
18  * to extract xcal data
19  * from L2 files
20  *
21  * Joel Gales Futuretech 24 October 2012 Fix sensor attribute bug
22  * Joel Gales Futuretech 14 June 2013 Add support for NETCDF4
23  *
24  * Sean Bailey Futuretech 23 July 2014 Modified to use the new
25  * calfile_utils and to use
26  * the clo library
27  * ======================================================================== */
28 
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <libgen.h>
37 #include <math.h>
38 
39 #include <readL2scan.h>
40 
41 #include "l12_proto.h"
42 #include <setupflags.h>
43 #include "calfile_utils.h"
44 #include <hdf5.h>
45 
46 int16_t fileID = 0;
47 #define NOVALIDPIX 111
48 
49 float ***aots, ***nlws; //arrays to contain the values needed to avg over for inversion
50 
51 /* -------------------------------------------------------------------- *
52  * main *
53  * -------------------------------------------------------------------- */
54 int main(int argc, char *argv[]) {
55 
56  int32_t iscan = 0; /* input scan number */
57  int32_t oscan = 0; /* output scan number */
58  int32_t spix = 0; /* start pixel for subscene process */
59  int32_t epix = -1; /* end pixel for subscene process */
60  int32_t ipix;
61  int32_t dpix;
62  int32_t sscan = 0; /* start scan for subscene process */
63  int32_t escan = -1; /* end scan for subscene process */
64  int32_t dscan;
65  int32_t opix = 0; /* output pixels number */
66  int32_t npix = 0; /* Number of output pixels per scan */
67  int32_t nscan = 0; /* Number of output scans */
68  int32_t npixs = 0;
69  int32_t i, j, l, np, Ltinx, vLtinx;
70  int status;
71  static int opened = 0;
72 
73  l2_prod l2_str; /* input data for L2 calibrator */
74  filehandle l2file; /* input metadata for L2 calibrator */
75  int32_t nbands, nprods;
76  int8 *iptr;
77  idDS ds_id;
78 
79  uint32_t flagusemask;
80  uint32_t required_mask;
81 
82  calstr** calrecArray; /* calrec for each pixel in a scan */
83  static int sensorID;
84  int nvars1d = 2;
85  char vars1Dnames[nvars1d][32]; // floating point one dimensional data to include in output - lon, lat
86 
87  char l2_flags[1000];
88 
89  if (argc == 1) {
90  l2gen_usage("vcalmerge");
91  return 0;
92  }
93 
94  want_verbose = 0;
95 
96  setvbuf(stdout, NULL, _IOLBF, 0);
97  setvbuf(stderr, NULL, _IOLBF, 0);
98 
99  /* Initialize file handles */
100  cdata_();
103 
104  /* Parse input parameters */
105  if (msl12_input(argc, argv, "vcalmerge", &l2file) != 0) {
106  printf("-E- %s: Error parsing input parameters.\n", argv[0]);
107  exit(EXIT_FAILURE);
108  }
109 
110  if (input->ifile[0][0] == '\0') {
111  printf("-E- %s: No L2 file provided, exiting...\n", argv[0]);
112  exit(EXIT_FAILURE);
113  }
114 
115  if (access(input->ifile[0], F_OK) || access(input->ifile[0], R_OK)) {
116  printf("-E- %s: Input file '%s' does not exist or cannot open.\n",
117  argv[0], input->ifile[0]);
118  exit(EXIT_FAILURE);
119  }
120 
121  printf("\n");
122 
123  /*
124  * If output exists, check sensorID
125  *
126  */
127  int existingSensorID;
128  sensorID = l2file.sensorID;
129 
130  /* Save old HDF5 error handler */
131  H5E_auto_t old_func;
132  void *old_client_data;
133  H5Eget_auto(H5E_DEFAULT, &old_func, &old_client_data);
134 
135  /* Turn off error handling */
136  H5Eset_auto(H5E_DEFAULT, NULL, NULL);
137 
138  if (Hishdf(input->ofile[0]) == TRUE || H5Fis_hdf5(input->ofile[0]) == TRUE) {
139  ds_id = openDS(input->ofile[0]);
140  status = readAttr(ds_id, "sensorID", &existingSensorID);
141  if (status) {
142  printf("-E- %s: Problem reading output file: %s\n", argv[0], input->ofile[0]);
143  exit(EXIT_FAILURE);
144  }
145  endDS(ds_id);
146  if (sensorID != existingSensorID) {
147  printf("-E- %s: Mixing L2 data from different sensors, %s and %s.\n",
148  argv[0], sensorId2SensorName(sensorID), sensorId2SensorName(existingSensorID));
149  exit(EXIT_FAILURE);
150  }
151 
152  }
153  /* Restore previous HDF5 error handler */
154  H5Eset_auto(H5E_DEFAULT, old_func, old_client_data);
155  l2_str.nrec = 0;
156  if (openL2(input->ifile[0], 0x0, &l2_str)) {
157  printf("-E- %s: Error reading L2 data %s.\n", argv[0], input->ifile[0]);
158  exit(EXIT_FAILURE);
159  }
160  /*
161  * Check for required data sets: mside, detnum, pixnum
162  */
163  if (l2_str.mside == NULL) {
164  printf("-E- %s: mside is missing from the L2 data file %s.\n", argv[0],
165  l2_str.filename);
166  exit(EXIT_FAILURE);
167  }
168  if (l2_str.detnum == NULL) {
169  printf("-E- %s: detnum is missing from the L2 data file %s.\n", argv[0],
170  l2_str.filename);
171  exit(EXIT_FAILURE);
172  }
173  if (l2_str.pixnum == NULL) {
174  printf("-E- %s: pixnum is missing from the L2 data file %s.\n", argv[0],
175  l2_str.filename);
176  exit(EXIT_FAILURE);
177  }
178 
179  /*
180  * Make sure all L2 products required for the xcalibration are present
181  */
182 
183  Ltinx = -1;
184  vLtinx = -1;
185  for (j = 0; j < l2_str.nprod; j++) {
186  if (strncmp(l2_str.prodname[j], "l2_flags", 8) == 0)
187  continue;
188  if (strncmp(l2_str.prodname[j], "Lt_", 3) == 0) {
189  if (Ltinx < 0)
190  Ltinx = j;
191  }
192  if (strncmp(l2_str.prodname[j], "vLt_", 4) == 0) {
193  if (vLtinx < 0)
194  vLtinx = j;
195  }
196  }
197  if (Ltinx == -1) {
198  printf(
199  "-E- %s: Lt TOA calibration data are missing from the L2 data file %s.\n",
200  argv[0], l2_str.filename);
201  exit(EXIT_FAILURE);
202  }
203  if (vLtinx == -1) {
204  printf(
205  "-E- %s: vLt TOA calibration data are missing from the L2 data file %s.\n",
206  argv[0], l2_str.filename);
207  exit(EXIT_FAILURE);
208  }
209 
211  nprods = l2_str.nprod;
212 
213  strcpy(vars1Dnames[0], "lon");
214  strcpy(vars1Dnames[1], "lat");
215 
216  /*
217  * Set up the l2_flag masking
218  */
219  l2_flags[0] = '\0';
220  for (i = 0; i < L1_NFLAGS; i++) {
221  strcat(l2_flags, l2_flag_lname[i]);
222  if (i < L1_NFLAGS - 1)
223  strcat(l2_flags, ",\0");
224  }
225  l = strlen(l2_flags);
226  setupflags(l2_flags, input->flaguse, &flagusemask, &required_mask, &status);
227  if (status < 0) {
228  printf("-E- %s: Error setting up L2 flags.\n", argv[0]);
229  exit(EXIT_FAILURE);
230  }
231 
232  printf("\n");
233 
234  /*
235  * Open the output file. It will be created if necessary
236  */
237 
238  long runCounter = 0;
239  char outprod[L1_MAXPROD][32];
240  for (i = 0; i < nprods; i++) {
241  strcpy(outprod[i], l2_str.prodname[i]);
242  }
243 
244  printf("\n%s: Appending file: %s.\n", argv[0], input->ifile[0]);
245 
246  /* Set the end pixel if it was not set by command argument */
247  if (l1_input->epixl == -1 || l1_input->epixl > l2_str.nsamp)
248  l1_input->epixl = l2_str.nsamp;
249  if (l1_input->eline == -1 || l1_input->eline > l2_str.nrec)
250  l1_input->eline = l2_str.nrec;
251  if (l1_input->spixl < 1)
252  l1_input->spixl = 1;
253  if (l1_input->sline < 1)
254  l1_input->sline = 1;
255 
256  spix = MAX(l1_input->spixl - 1, 0);
257  epix = MIN(l1_input->epixl - 1, l2_str.nsamp - 1);
258  dpix = MAX(l1_input->dpixl, 1);
259  sscan = MAX(l1_input->sline - 1, 0);
260  escan = MIN(l1_input->eline - 1, l2_str.nrec - 1);
261  dscan = MAX(l1_input->dline, 1);
262 
263  if (sscan > escan || spix > epix) {
264  printf("-E- %s: scan and pixel limits make no sense.\n", argv[0]);
265  printf(" start scan = %d\n", sscan + 1);
266  printf(" end scan = %d\n", escan + 1);
267  printf(" start pixel = %d\n", spix + 1);
268  printf(" end pixel = %d\n", epix + 1);
269  exit(EXIT_FAILURE);
270  }
271 
272  npix = (epix - spix) / dpix + 1;
273  nscan = (escan - sscan) / dscan + 1;
274 
275  int quarterscans = floor(nscan / 4);
276 
277  if ((iptr = (int8 *) malloc(nscan * sizeof (int8))) == NULL) {
278  printf("-E- %s: Error allocating memory to the pixel index.\n",
279  argv[0]);
280  exit(EXIT_FAILURE);
281  }
282 
283  npixs = 0;
284  oscan = 0;
285  for (iscan = sscan; iscan <= escan; iscan += dscan) {
286 
287  if (readL2(&l2_str, l2_str.fileindex, iscan, vLtinx, NULL)) {
288  printf("%s: Error reading L2 data file %s at scan %d.\n", argv[0],
289  l2_str.filename, iscan);
290  continue;
291  }
292  if ((iscan % quarterscans) == 0)
293  printf("Selecting valid pixels for scan %d\n", iscan);
294 
295  opix = 0;
296  l = 0;
297  for (ipix = spix; ipix <= epix; ipix += dpix) {
298 
299  if (((l2_str.l2_flags[ipix] & flagusemask) == 0)
300  && (l2_str.l2_data[vLtinx][ipix] > 0.0)) {
301  l = 1;
302  ++npixs;
303  }
304  ++opix;
305  }
306 
307  if (opix != npix) {
308  printf(
309  "%s: Error: Incorrect number of pixels %d obtained in the scan %d.\n",
310  argv[0], opix, oscan);
311  }
312 
313  if (l)
314  iptr[oscan] = 1;
315  else
316  iptr[oscan] = 0;
317  ++oscan;
318  }
319 
320  printf("Number of valid cross-calibration pixels %d in file %s\n", npixs,
321  input->ifile[0]);
322 
323  /*
324  * if any valid pixels were found, write them to the output file
325  */
326  if (npixs > 0) {
327  opened = 1;
328  ds_id = calfile_open(input->ofile[0], sensorID, npixs, 1, nprods, nvars1d, outprod,
329  vars1Dnames, &runCounter, CROSSCAL);
330  /*
331  * Allocate calrec structure
332  */
333  if ((calrecArray = (calstr **) malloc(npixs * sizeof (calstr *)))
334  == NULL) {
335  printf(
336  "-E- : Error allocating memory for crosscal record structures\n");
337  exit(EXIT_FAILURE);
338  }
339  for (j = 0; j < npixs; j++) {
340  calrecArray[j] = alloc_calrec(1, nbands, nprods, nvars1d);
341  }
342 
343  oscan = 0;
344  for (iscan = sscan; iscan <= escan; iscan += dscan) {
345  np = 0;
346  /*
347  * Give a little progress...
348  */
349  if ((iscan % quarterscans) == 0)
350  printf("Storing pixels at scan %d\n", iscan);
351 
352  if (iptr[oscan++]) {
353  if (readL2(&l2_str, l2_str.fileindex, iscan, -1, NULL)) {
354  printf("%s: Error reading L2 data file %s at scan %d.\n",
355  argv[0], l2_str.filename, iscan);
356  continue;
357  }
358 
359  opix = 0;
360  for (ipix = spix; ipix <= epix; ipix += dpix) {
361 
362  if (((l2_str.l2_flags[ipix] & flagusemask) == 0)
363  && (l2_str.l2_data[Ltinx][ipix] > 0.0)
364  && (l2_str.l2_data[Ltinx][ipix] < 10000.)
365  && (l2_str.l2_data[vLtinx][ipix] > 0.0)) {
366 
367  calrecArray[np]->sensorID = sensorID;
368  calrecArray[np]->year = (int16) l2_str.year;
369  calrecArray[np]->day = (int16) l2_str.day;
370  calrecArray[np]->msec = (int32) l2_str.msec;
371  calrecArray[np]->iscan = (int16) iscan;
372  calrecArray[np]->mside = (int32) (l2_str.mside[iscan]);
373  calrecArray[np]->detnum = (int32) (l2_str.detnum[iscan]);
374  calrecArray[np]->pixnum = (int32) (l2_str.pixnum[ipix]);
375  calrecArray[np]->vars1D[0] = l2_str.longitude[ipix];
376  calrecArray[np]->vars1D[1] = l2_str.latitude[ipix];
377  for (j = 0; j < nbands; j++) {
378  calrecArray[np]->Lt[j][0] =
379  (float) l2_str.l2_data[Ltinx + j][ipix];
380  calrecArray[np]->vLt[j][0] =
381  (float) l2_str.l2_data[vLtinx + j][ipix];
382  }
383  // The calrec entries for the other request products are populated here
384  for (j = 0; j < nprods; j++) {
385  if (strcmp(l2_str.prodname[j], "pixnum") != 0
386  && strcmp(l2_str.prodname[j], "mside") != 0
387  && strncmp(l2_str.prodname[j], "Lt", 2) != 0
388  && strncmp(l2_str.prodname[j], "vLt", 3) != 0
389  && strcmp(l2_str.prodname[j], "detnum") != 0
390  && strcmp(l2_str.prodname[j], "l2_flags") != 0) {
391 
392  // fill up calrec data
393  calrecArray[np]->data[j][0] = l2_str.l2_data[j][ipix];
394  }
395  }
396 
397  ++np;
398  }
399 
400  ++opix;
401  }
402 
403  if (opix != npix) {
404  /*
405  * this really should never happen...
406  */
407  printf(
408  "%s: Error: Incorrect number of pixels %d obtained in the scan %d.\n",
409  argv[0], opix, oscan);
410  }
411  if (np > 0) {
412  // Write out the valid pixels for this scan
413 
414  for (j = 0; j < np; j++) {
415  calfile_write(ds_id, calrecArray[j], runCounter, 1, 1,
416  nprods, nbands, nvars1d, outprod, vars1Dnames, CROSSCAL);
417  runCounter++;
418  }
419  }
420  }
421  }
422 
423  // Free up some memory
424  for (i = 0; i < np; i++) {
425  free_calrec(calrecArray[i], nbands, nprods);
426  }
427  }
428 
429  free(iptr);
430 
431  if (opened == 1) {
432  if (calfile_close(ds_id) != 0) {
433  printf("Trouble closing file %s\n", input->ofile[0]);
434  exit(EXIT_FAILURE);
435  }
436  printf("Completed processing file %s\n", input->ifile[0]);
437  exit(SUCCESS);
438  } else {
439  printf("Completed processing file %s, but no valid pixels were found\n", input->ifile[0]);
440  exit(NOVALIDPIX);
441  }
442 
443 }
444 
#define L1_MAXPROD
Definition: filehandle.h:20
int32_t openL2(const char *fname, char *plist, l2_prod *l2_str)
Definition: readL2scan.c:296
#define MAX(A, B)
Definition: swl0_utils.h:26
integer, parameter int16
Definition: cubeio.f90:3
#define MIN(x, y)
Definition: rice.h:169
#define SUCCESS
Definition: ObpgReadGrid.h:15
int j
Definition: decode_rs.h:73
int msl12_input(int argc, char *argv[], const char *progName, filehandle *l1file)
Definition: msl12_input.c:4201
int status
Definition: l1_czcs_hdf.c:32
float *** aots
#define NOVALIDPIX
idDS openDS(const char *filename)
Definition: wrapper.c:616
int calfile_write(idDS ds_id, calstr *calrec, int recnum, int ydim, int xdim, int nprods, int nbands, int nvars1d, char l2prods[L1_MAXPROD][32], char vars1Dnames[L1_MAXPROD][32], caltype ctype)
#define NULL
Definition: decode_rs.h:63
void filehandle_init(filehandle *file)
#define TRUE
Definition: rice.h:165
void msl12_input_init()
Definition: msl12_input.c:485
int32 nscan
Definition: l1_czcs_hdf.c:19
int32_t readL2(l2_prod *l2_str, int32_t ifile, int32_t recnum, int32_t iprod, unsigned char *scan_in_rowgroup)
Definition: readL2scan.c:1250
int l2gen_usage(const char *prog)
Definition: msl12_input.c:4254
instr * input
int readAttr(idDS ds_id, const char *nam, void *data)
@ CROSSCAL
Definition: calfile_utils.h:21
int16_t fileID
void setupflags(char *flagdef, char *flaguse, uint32_t *flagusemask, uint32_t *required, int *status)
Definition: setupflags.c:5
void free_calrec(calstr *calrec, int nbands, int nprods)
void cdata_()
l1_input_t * l1_input
Definition: l1_options.c:9
int want_verbose
float *** nlws
int main(int argc, char *argv[])
calstr * alloc_calrec(int ydim, int nbands, int nprods, int nvar1d)
int32 dpix
Definition: l1_czcs_hdf.c:22
int32_t nbands
const char * sensorId2SensorName(int sensorId)
Definition: sensorInfo.c:198
int32 spix
Definition: l1_czcs_hdf.c:21
int32_t iscan
Definition: dfutils.h:28
int32 epix
Definition: l1_czcs_hdf.c:23
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
int calfile_close(idDS ds_id)
int endDS(idDS ds_id)
Definition: wrapper.c:634
idDS calfile_open(char *ofile, int sensorID, int ydim, int xdim, int nprods, int nvars1d, char l2prods[L1_MAXPROD][32], char vars1Dnames[L1_MAXPROD][32], long *numExistingRecords, caltype ctype)
Definition: calfile_utils.c:48
int i
Definition: decode_rs.h:71
int32 l2file(int32 sdfid, int32 *nsamp, int32 *nscans, char *dtype)
Definition: l2stat_chk.c:313
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int32_t sensorID[MAXNFILES]
Definition: l2bin.cpp:97
#define L1_NFLAGS
Definition: filehandle.h:21
int npix
Definition: get_cmp.c:27