OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
czl1merge.c
Go to the documentation of this file.
1 #include <libgen.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <sys/utsname.h>
8 
9 #include "l1czcs.h"
10 
11 #include <passthebuck.h>
12 #include <GetStationInfo.h>
13 #include <timeutils.h>
14 
15 #define MAXFILES 80
16 #define PROGRAM "czl1merge"
17 #define VERSION "1.1"
18 
19 int main(int argc, char *argv[])
20 /*******************************************************************
21 
22  czl1merge
23 
24  purpose: merge several CZCS L1 files together into 1 file
25 
26  Returns type: int - 0 if all good
27 
28  Parameters: (in calling order)
29  Type Name I/O Description
30  ---- ---- --- -----------
31  int argc I count of command line
32  args
33  char * argv[] I command line arguments
34  They are:
35  [1] input L1 list file
36  [2] merged file name or
37  just the path for it
38 
39  Modification history:
40  Programmer Date Description of change
41  ---------- ---- ---------------------
42  W. Robinson 9 Aug 2004 Original development
43 
44  *******************************************************************/ {
45  struct stat file_stat;
46  l1_data_struc l1_data; /* output L1 data storage */
47  gattr_struc gattr; /* and global attributes */
48  mstr_struc mstr; /* master storage of time and quality */
49  timqual_struc init_info; /* time, quality from candidate file */
50  int n_mstr, i, mstr_last, in_ptr, mstr_ptr, nfiles, ifil, new_start,
51  new_end, rstat, n_ctl_pt, mtch_st, olap_end, nscans, init = 1,
52  orb_st_day, num_used[MAXFILES], scans_per_file[50];
53  int32_t mmsec, imsec;
54  char infiles[MAXFILES][FILENAME_MAX]; /* list of input files */
55  short file_used[MAXFILES]; /* 1 if the input L1 was used to make output */
56  char outfile[FILENAME_MAX], outpath[FILENAME_MAX];
57  char inflist[FILENAME_MAX];
58  char seadas_vs[64], prog_version[64];
59  /*
60  * for the library functions, define here
61  */
62  int get_swf_def_meta1();
63  int gen_soft_id();
64  int get_current_time();
65 
66  for (i = 0; i < MAXFILES; i++) {
67  file_used[i] = 0;
68  num_used[i] = 0;
69  }
70  olap_end = 0;
71  n_ctl_pt = 0;
72  /*
73  * get inputs
74  */
75  if (argc == 2) {
76  strcpy(inflist, argv[1]);
77  strcpy(outpath, ".");
78  } else if (argc == 3) {
79  strcpy(inflist, argv[1]);
80  strcpy(outpath, argv[2]);
81  } else
82  usage(basename(argv[0]));
83  /*
84  * get the start times from the file list and order by start time
85  */
86  nfiles = read_file_list(inflist, (char**) infiles, 80);
87  if (nfiles <= 0) {
88  printf("-E- %s: error reading list file %s\n", argv[0], inflist);
89  exit(-1);
90  }
91 
92  /*
93  * inflist can be sorted with qsort and thus, end up
94  * in the correct order (Use strcmp).
95  */
96  qsort((char *) infiles, nfiles, sizeof ( *infiles),
97  (int (*)(const void*, const void*))strcmp);
98 
99  printf("\nordered list of input L1 CZCS files:\n");
100  printf("numb name\n");
101  for (ifil = 0; ifil < nfiles; ifil++)
102  printf("%4d %s\n", ifil, infiles[ifil]);
103  /*
104  * allocate the storage for the master list of time and quality
105  */
106  n_mstr = nfiles * 970;
107  mstr.msec = (int32_t *) malloc(n_mstr * sizeof ( int32_t));
108  mstr.exist = (short *) calloc(n_mstr, sizeof ( short));
109  mstr.qual = (short *) malloc(n_mstr * sizeof ( short));
110  mstr.ds_num = (short *) malloc(n_mstr * sizeof ( short));
111  mstr.out_scan = (int32_t *) malloc(n_mstr * sizeof ( int32_t));
112  mstr.scan = (short *) malloc(n_mstr * sizeof ( short));
113  mstr.in_msec = (int32_t *) malloc(n_mstr * sizeof ( int32_t));
114  mstr.in_exist = (short *) malloc(n_mstr * sizeof ( short));
115  mstr.in_qual = (short *) malloc(n_mstr * sizeof ( short));
116  mstr.in_scan = (short *) malloc(n_mstr * sizeof ( short));
117  /*
118  * loop through the input datasets and construct the master list
119  * of the best scans
120  */
121  mstr_last = -1;
122  orb_st_day = -1; /* start day of the orbit, to get msec in mstr good */
123 
124  for (ifil = 0; ifil < nfiles; ifil++) {
125  printf("czl1merge: processing input file %d: %s\n", ifil, infiles[ifil]);
126  new_start = -1;
127  new_end = -1;
128 
129  if ((rstat = cztimqual(infiles[ifil], &init_info, &orb_st_day)) == 0) {
130  scans_per_file[ifil] = init_info.nscan;
131  /*
132  * There is data to use from this file. if the first usable set,
133  * or new data is beyond the current data, just put into the
134  * list as the current set.
135  */
136  n_ctl_pt = init_info.n_ctl_pt;
137 
138  if ((mstr_last == -1) || (mstr.msec[mstr_last] < init_info.msec[0])) {
139  fill_mstr(&mstr_last, &mstr, &init_info, ifil, 0,
140  init_info.nscan);
141  } else {
142  /*
143  * There is some overlap. back up in the current msec to before
144  * the new data time
145  */
146  mstr_ptr = mstr_last;
147  mtch_st = 0;
148  while (mtch_st == 0) {
149  if (mstr.msec[mstr_ptr] <= init_info.msec[0])
150  mtch_st = 1;
151  else
152  mstr_ptr--;
153  }
154  printf("czl1merge: new file matches at index %d, current end at %d\n",
155  mstr_ptr, mstr_last);
156  /*
157  * now, mstr_ptr points to the overlap start. Flip through the
158  * msec in mtch and init_info to get matches (approximate in gaps)
159  */
160  olap_end = 0;
161  in_ptr = 0;
162  while (olap_end == 0) {
163  mmsec = mstr.msec[mstr_ptr];
164  imsec = init_info.msec[in_ptr];
165  if (imsec == mmsec) {
166  /*
167  * times match. place the new data in the master list in
168  * the '_in' arrays
169  */
170  if (new_start == -1)
171  new_start = mstr_ptr;
172  new_end = mstr_ptr;
173 
174  mstr.in_msec[mstr_ptr] = init_info.msec[in_ptr];
175  mstr.in_exist[mstr_ptr] = 1;
176  mstr.in_qual[mstr_ptr] = init_info.qual[in_ptr];
177  mstr.in_scan[mstr_ptr] = in_ptr;
178 
179  in_ptr++;
180  mstr_ptr++;
181  } else if ((mstr.exist[mstr_ptr] == 0) &&
182  (imsec - mmsec < 40) && (imsec - mmsec > -40)) {
183  /*
184  * incoming time matches with a rough predicted time in a gap.
185  * do as above
186  */
187  if (new_start == -1)
188  new_start = mstr_ptr;
189  new_end = mstr_ptr;
190 
191  mstr.in_msec[mstr_ptr] = init_info.msec[in_ptr];
192  mstr.in_exist[mstr_ptr] = 1;
193  mstr.in_qual[mstr_ptr] = init_info.qual[in_ptr];
194  mstr.in_scan[mstr_ptr] = in_ptr;
195 
196  in_ptr++;
197  mstr_ptr++;
198  } else if (imsec > mmsec) {
199  mstr.in_exist[mstr_ptr] = 0;
200  mstr_ptr++;
201  printf("czl1merge: gap found in new data vs current at mstr_ptr: %d\n",
202  mstr_ptr);
203  } else if (mmsec > imsec)
204  in_ptr++;
205 
206  /*
207  * set the end condition if we exhausted the current or input data
208  */
209  if ((mstr_ptr > mstr_last) || (in_ptr >= init_info.nscan))
210  olap_end = 1;
211  } /* end loop to deal with ovelap filling of mstr */
212  /*
213  * The overlap is filled. resolve the overlap
214  */
215  printf("czl1merge: resolving overlap from index %d to %d\n",
216  new_start, new_end);
217  olap_resolve(&mstr, mstr_last, new_start, new_end, ifil);
218  /*
219  * for remaining scans, if any, just fill the master array
220  */
221  if (in_ptr < init_info.nscan) {
222  fill_mstr(&mstr_last, &mstr, &init_info, ifil, in_ptr,
223  init_info.nscan);
224  }
225  }
226  } else
227  exit(-1);
228 
229  /*
230  * free the arrays under init_info
231  */
232  free(init_info.qual);
233  free(init_info.msec);
234  }
235 
236  printf("\nFinished set-up of best data to merge, Outputting data\n\n");
237 
238  if (mstr_last == -1) {
239  printf("No suitable data exists for this set of files\n");
240  exit(-1);
241  }
242  /*
243  * the best scans are described in mstr. Get the scans from the
244  * contributing files to make the output file
245  *
246  * first count the real # scans and find which files contribute
247  * note below that mstr_last is pointer to last entry, not the #
248  * of entrys, thus the <= in the for loop
249  */
250  nscans = 0;
251  for (i = 0; i <= mstr_last; i++) {
252  if (mstr.exist[i] != 0) {
253  mstr.out_scan[i] = nscans;
254  nscans++;
255  file_used[ mstr.ds_num[i] ] = 1;
256  num_used[ mstr.ds_num[i] ]++;
257  }
258  }
259  /*
260  * set storage in the data structure
261  */
262  cz_dat_alloc(nscans, n_ctl_pt, 0, &l1_data);
263 
264  /*
265  * loop through the datasets and use cz_mov_scn() to place the scan lines
266  * using mstr as guide
267  */
268  init = 1;
269  for (i = 0; i < nfiles; i++)
270  if (file_used[i] != 0) {
271  if (
272  cz_mov_scn(init, i, infiles[i], &mstr, mstr_last, nscans,
273  &gattr, &l1_data) != 0) exit(-1);
274  if (init == 1) init = 0;
275  }
276 
277  gattr.scan_lines = nscans;
278  /*
279  * update lat, lon metadata
280  */
281  cz_ll_upd(&l1_data, &gattr);
282  /*
283  * adjust the metadata to reflect the new span of data
284  */
285  cz_meta_adj(&l1_data, &gattr);
286  /*
287  * create output file name using SWl0merge methodology
288  */
289  if (stat(outpath, &file_stat) == 0 && S_ISDIR(file_stat.st_mode)) {
290  strcat(outpath, "/");
291  strcpy(outfile, basename(infiles[0]));
292  strcpy(outfile + 19, "MLAC");
293  strcat(outpath, outfile);
294  }
295 
296  strcpy(gattr.proc_ctl, argv[0]);
297  for (i = 1; i < argc; i++) {
298  strcat(gattr.proc_ctl, " ");
299  strcat(gattr.proc_ctl, argv[i]);
300  }
301 
302  strcpy(gattr.input_files, basename(infiles[0]));
303  if (nfiles > 1)
304  for (i = 1; i < nfiles; i++) {
305  strcat(gattr.input_files, " ");
306  strcat(gattr.input_files, basename(infiles[i]));
307  }
308  /*
309  * set up some attrib info
310  */
311  StationInfo stationInfo;
312  if (GetStationInfo(NULL, &stationInfo) == LIFE_IS_GOOD) {
313  strcpy(gattr.datacenter, stationInfo.data_center);
314  strcpy(gattr.stn_name, stationInfo.station_name);
315  gattr.stn_lat = stationInfo.station_latitude;
316  gattr.stn_lon = stationInfo.station_longitude;
317  }
318 
319  sprintf(prog_version, "%s %s", PROGRAM, VERSION);
320  struct utsname osname;
321  uname(&osname);
322  sprintf(gattr.soft_id, "%s, %s, %s %s", seadas_vs, prog_version, osname.sysname,
323  osname.release);
324 
325  strcpy(gattr.datatype, "MLAC");
326  get_time((char*) &gattr.process_time);
327  /*
328  * call the czcs write routine to write out the gattr and data structs
329  */
330  printf("\n Writing data to output file...\n");
331  if (czcs_l1_write(outpath, l1_data, gattr) == 0) {
332  printf("\n\nCreated output file: %s \n", outpath);
333  printf("With %d lines\n", nscans);
334  printf("\nContributions from input files:\n\n");
335  printf("seq # file name # lines # lines contributed\n");
336  for (ifil = 0; ifil < nfiles; ifil++) {
337  strcpy(outfile, basename(infiles[ifil]));
338  i = ifil + 1;
339  printf("%5d %22s %5d %5d\n", i, outfile, scans_per_file[ifil],
340  num_used[ifil]);
341  }
342  } else {
343  printf(" output file not created\n");
344  exit(-1);
345  }
346  /*
347  * close the output and end
348  */
349  exit(0);
350 }
351 
352 void usage(char *file) {
353  printf("%s %s (%s %s)\n",
354  file, VERSION, __DATE__, __TIME__);
355  printf("\nUsage: %s input-CZCS-listfile [output-file-name or dir]\n",
356  file);
357 
358  exit(-1);
359 }
int GetStationInfo(char *stationInfoFile, StationInfo *stationInfo)
int read_file_list(char *, char **, int)
void cz_ll_upd(l1_data_struc *l1_data, gattr_struc *gattr)
Definition: cz_ll_upd.c:3
#define PROGRAM
Definition: czl1merge.c:16
#define NULL
Definition: decode_rs.h:63
int czcs_l1_write(char *ofile, l1_data_struc l1_data, gattr_struc gattr)
Definition: czcs_l1_write.c:8
int cz_dat_alloc(int nscans, int n_ctl_pt, int r_mode, l1_data_struc *l1_data)
Definition: cz_dat_alloc.c:3
char * data_center
void cz_meta_adj(l1_data_struc *l1_data, gattr_struc *gattr)
Definition: cz_meta_adj.c:4
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude resolving resolving GSFcd00179 Corrected handling of fill values for[Sensor|Solar][Zenith|Azimuth] resolving MODxl01751 Changed to validate LUT version against a value retrieved from the resolving MODxl02056 Changed to calculate Solar Diffuser angles without adjustment for estimated post launch changes in the MODIS orientation relative to incidentally resolving defects MODxl01766 Also resolves MODxl01947 Changed to ignore fill values in SCI_ABNORM and SCI_STATE rather than treating them as resolving MODxl01780 Changed to use spacecraft ancillary data to recognise when the mirror encoder data is being set by side A or side B and to change calculations accordingly This removes the need for seperate LUTs for Side A and Side B data it makes the new LUTs incompatible with older versions of the and vice versa Also resolves MODxl01685 A more robust GRing algorithm is being which will create a non default GRing anytime there s even a single geolocated pixel in a granule Removed obsolete messages from seed file
Definition: HISTORY.txt:413
#define LIFE_IS_GOOD
Definition: passthebuck.h:4
int init(int32_t ipr, int32_t jpr, char *efile, char *pfile)
Definition: proj_report.c:51
int cztimqual(char *file, timqual_struc *timqual, int *orb_st_day)
Definition: cztimqual.c:3
void get_time(char *pr_time)
Definition: get_time.c:28
int cz_mov_scn(int init, int ds_num, char *file, mstr_struc *mstr, int mstr_last, int nscan_out, gattr_struc *gattr, l1_data_struc *l1_data)
Definition: cz_mov_scn.c:4
#define VERSION
Definition: czl1merge.c:17
int gen_soft_id(char *seadas_vs, char *prog_vs, char *soft_id)
void fill_mstr(int *mstr_last, mstr_struc *mstr, timqual_struc *init_info, int ds_num, int st_scan, int en_scan)
Definition: fill_mstr.c:3
#define basename(s)
Definition: l0chunk_modis.c:29
string outpath
Definition: color_dtdb.py:224
#define MAXFILES
Definition: czl1merge.c:15
int get_swf_def_meta1(char *seadas_vs, char *data_center, char *station_name, float *station_lat, float *station_lon, char *station_code)
float station_longitude
char * station_name
float station_latitude
void usage(char *file)
Definition: czl1merge.c:352
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
void olap_resolve(mstr_struc *, int, int, int, int)
Definition: olap_resolve.c:3
int main(int argc, char *argv[])
Definition: czl1merge.c:19