OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
main_biosmap.c
Go to the documentation of this file.
1 /* ========================================================================
2  * SWbiosmap - generates a biosphere map from a set of SeaWiFS SMI NDVI and
3  * chlor_a maps.
4  *
5  * Synopsis:
6  *
7  * SWbiosmap -l input-filename-list | (-c chlorophyll-file -n ndvi-file)
8  * [-o output-filename] [-r replacement-filename]
9  *
10  * output-filename : output map file, def="map.hdf"
11  * chlorophyll-file : name of input Chlorophyll SMI file
12  * ndvi-file-file : name of input NDVI SMI file
13  * input-filename-list : file containing list of input SMI filenames
14  * replacement-filename : name of file which this new output supercedes
15  *
16  * Description:
17  *
18  * SWbiosmap reads through a set of SeaWiFS SMI NDVI and Chlor-a files
19  * files, and outputs a merged SMI map file containing NDVI over land and
20  * Chl_a over ocean. Multiple observations of the same grid point are
21  * resolved by "last value in". The input is the name of a file which
22  * contains a <CR> separated list of NDVI and/or Chl_a SMI files. If only
23  * one Chlorophyll file and one NDVI file are to be combined, the -c and
24  * -n options can be used instead of -l. The -r option allows
25  * specification of a filename which the new output product is intended
26  * to replace.
27  *
28  * Modification history:
29  *
30  * Programmer Organization Date Description of change
31  * -------------- ------------ -------- ---------------------
32  * Bryan A. Franz GSC 09/12/97 Original development
33  *
34  * ======================================================================== */
35 
36 #include <stdio.h>
37 #include <string.h>
38 #include <time.h>
39 #include <unistd.h>
40 #include <libgen.h>
41 
42 typedef unsigned char byte;
43 #include "map.h"
44 #include "seaproto.h"
45 #include "meta_l3b.h"
46 #include "mapproto_o.h"
47 #include <timeutils.h>
48 #include "mapproto.h"
49 
50 #define VERSION "2.0"
51 #define NX 4320 /* Map grid x-dimension */
52 #define NY 2160 /* Map grid y-dimension */
53 #define FILENAMELEN 255 /* Max filename length */
54 #define MAXSTRNGLEN 255 /* Max generic string length */
55 #define MAXINFILES 50 /* Max number of input files */
56 #define NODATA8 255 /* Missing data value (byte) */
57 #define NODATA16 65535 /* Missing data value (short int) */
58 #define CMD_ARGS "o:l:r:c:n:" /* Valid commandline options */
59 
60 /* Macro definitions */
61 #define max(A,B) ((A) > (B) ? (A) : (B)) /* Returns greater of A and B */
62 #define min(A,B) ((A) < (B) ? (A) : (B)) /* Returns lesser of A and B */
63 
64 /* Function prototypes */
65 void usage(char* progname);
66 double ydmsec2jul(int16 year, int16 day, int32 msec);
67 void jul2ydmsec(double jul, int16 *year, int16 *day, int32 *msec);
68 
69 /* ------------------------------------------------------------------------ *
70  * main *
71  * ------------------------------------------------------------------------ */
72 int main(int argc, char *argv[]) {
73 
74  static char infileList[MAXINFILES][FILENAMELEN]; /* Input file list */
75  static uint8 map08[NY][NX]; /* Equiangular grid of map data */
76  static uint16 map16[NY][NX]; /* Equiangular grid of map data */
77  int32 ix; /* Longitudinal bin index */
78  int32 iy; /* Latitudinal bin index */
79  FILE *fp; /* Pointer to list file */
80  int16 nfiles = 0; /* Number of input files in infileList */
81  int16 iarg; /* Command-line argument index */
82  int16 ifile; /* Input file index */
83  double jstart = 9e7; /* Julian start time of mapped data */
84  double jstop = -9e7; /* Julian stop time of mapped data */
85  double sjul; /* Julian start time of input file */
86  double ejul; /* Julian Stop time of input file */
87  double deljul; /* Julian time difference */
88  int16 syear;
89  int16 sday;
90  int32 smsec;
91  int16 eyear;
92  int16 eday;
93  int32 emsec;
94  int32 status;
95  uint16 offset;
96 
97  /* Parameters for getopt() */
98  extern int opterr;
99  extern int optind;
100  extern char *optarg;
101  int c;
102 
103  /* Parameters for L3 map interface */
104  char outfile[FILENAMELEN] = "map.hdf";
105  char replaces[MAXSTRNGLEN] = "ORIGINAL";
106  int16 bin_syear;
107  int16 bin_sday;
108  int16 bin_eyear;
109  int16 bin_eday;
110  int16 map_syear;
111  int16 map_sday;
112  int32 map_smsec;
113  int16 map_eyear;
114  int16 map_eday;
115  int32 map_emsec;
116  float map_latrange[2] = {90., -90.};
117  float map_lonrange[2] = {-180., 180.};
118  int32 lines = NY;
119  int32 columns = NX;
120  char flag_use[MAXSTRNGLEN] = "";
121  byte eng_q_use[4] = {0, 0, 0, 0};
122  char ptime[17];
123  static char infiles[(FILENAMELEN + 1) * MAXINFILES];
124  char prod_type[MAXSTRNGLEN];
125  int32 nbins = 0;
126  char l3m_name[MAXSTRNGLEN];
127  char measure[MAXSTRNGLEN] = "mean";
128  char l3_flag_names[MAXSTRNGLEN];
129  char proc_con[MAXSTRNGLEN];
130  char proc_log[MAXSTRNGLEN];
131 
132  char precision[2];
133  void *map;
134  int32 sdfid;
135  int32 attr_index;
136  char buffer[1024];
137  char *cptr;
138  char last_prec[2];
139 
140  meta_l3bType meta_l3b;
141 
142  /* Additional parameters for l3m_read() */
143  static byte image08[NY][NX];
144  static uint16 image16[NY][NX];
145  static byte palette[3 * 256];
146  void *image;
147  meta_struct meta_l3m;
148 
149 
150  /* Log command-line sequence to process-control string */
151  strcpy(proc_con, argv[0]);
152  for (iarg = 1; iarg < argc; iarg++) {
153  strcat(proc_con, " ");
154  strcat(proc_con, argv[iarg]);
155  }
156 
157  /* Process command-line arguments */
158  while ((c = getopt(argc, argv, CMD_ARGS)) != EOF) {
159  switch (c) {
160  case 'c': /* Input chlorophyll file */
161  case 'n': /* Input NDVI file */
162  strncpy(&infileList[nfiles][0], optarg, FILENAMELEN);
163  nfiles++;
164  break;
165  case 'o': /* Output biosphere file */
166  strncpy(outfile, optarg, FILENAMELEN);
167  break;
168  case 'l': /* Input file list */
169  if ((fp = fopen(optarg, "r")) == NULL) {
170  fprintf(stderr, "%s: Error opening %s for reading.\n",
171  argv[0], optarg);
172  exit(1);
173  }
174  while (fscanf(fp, "%s", &infileList[nfiles][0]) != EOF)
175  nfiles++;
176  break;
177  case 'r': /* File to replace at DACC */
178  strncpy(replaces, optarg, FILENAMELEN);
179  break;
180  default:
181  printf("Invalid argument: %d\n", c);
182  usage(argv[0]);
183  exit(1);
184  break;
185  }
186  }
187  if (nfiles == 0) {
188  printf("No input files specified.\n");
189  usage(argv[0]);
190  exit(1);
191  }
192 
193 
194  /* Get process start time */
195  get_time(ptime);
196 
197  strcpy(precision, "B");
198  for (ifile = 0; ifile < nfiles; ifile++) {
199  sdfid = SDstart(infileList[ifile], DFACC_RDONLY);
200  if (sdfid != -1) {
201  attr_index = SDfindattr(sdfid, "Input Parameters");
202  status = SDreadattr(sdfid, attr_index, buffer);
203  cptr = strstr(buffer, "PRECISION=");
204  if (cptr != NULL) {
205  cptr += 10;
206  if (*cptr == 'I') strcpy(precision, "I");
207  if (ifile > 0 && strcmp(last_prec, precision) != 0) {
208  printf("Input files are of varying precision\n");
209  exit(2);
210  }
211  strncpy(last_prec, precision, 1);
212  }
213  }
214  }
215 
216  /* Initialize output map array to no data */
217  if (precision[0] == 'I') {
218  map = map16;
219  image = image16;
220  for (iy = 0; iy < NY; iy++)
221  for (ix = 0; ix < NX; ix++)
222  map16[iy][ix] = NODATA16;
223  } else {
224  map = map08;
225  image = image08;
226  for (iy = 0; iy < NY; iy++)
227  for (ix = 0; ix < NX; ix++)
228  map08[iy][ix] = NODATA8;
229  }
230 
231  /* */
232  /* Loop through each input file and process accordingly */
233  /* ---------------------------------------------------- */
234  /* */
235  for (ifile = 0; ifile < nfiles; ifile++) {
236 
237  printf("Processing L3 Map file: %s\n", infileList[ifile]);
238 
239  status = get_l3m(infileList[ifile],
240  &syear, &sday, &smsec,
241  &eyear, &eday, &emsec,
242  prod_type, l3m_name,
243  image, palette, &meta_l3m);
244 
245  printf("syear = %d, sday = %d, smsec = %d\n", syear, sday, smsec);
246  printf("eyear = %d, eday = %d, emsec = %d\n", eyear, eday, emsec);
247 
248  printf("name = %s\n", l3m_name);
249  if (strncmp(l3m_name, "Chlorophyll", 11) == 0)
250  offset = 0;
251  else
252  if (precision[0] == 'I') offset = 32768 - 1;
253  else offset = 128;
254 
255 
256  /* Update data time range */
257  sjul = ydmsec2jul(syear, sday, smsec);
258  ejul = ydmsec2jul(eyear, eday, emsec);
259  jstart = min(jstart, sjul);
260  jstop = max(jstop, ejul);
261 
262 
263  /*
264  * Loop through each bin of the input image. If bin has valid
265  * data, store value in merged map.
266  */
267 
268  if (precision[0] == 'I') {
269  for (iy = 0; iy < NY; iy++) {
270  for (ix = 0; ix < NX; ix++) {
271  if (image16[iy][ix] != NODATA16)
272  map16[iy][ix] = image16[iy][ix] / 2 + offset;
273 
274  }
275  }
276  } else {
277  for (iy = 0; iy < NY; iy++) {
278  for (ix = 0; ix < NX; ix++) {
279  if (image08[iy][ix] != NODATA8)
280  map08[iy][ix] = image08[iy][ix] / 2 + offset;
281 
282  }
283  }
284  }
285 
286 
287  } /* End loop over input files */
288 
289 
290  /* */
291  /* Create remaining meta data for Map file */
292  /* ---------------------------------------- */
293  /* */
294 
295  strcpy(l3m_name, "biosphere");
296  strcpy(l3_flag_names, "");
297  strcpy(flag_use, "");
298  strcpy(proc_log, "");
299 
300  jul2ydmsec(jstart, &bin_syear, &bin_sday, &smsec);
301  jul2ydmsec(jstop + 1, &bin_eyear, &bin_eday, &emsec);
302  jul2ydmsec(jstart, &map_syear, &map_sday, &map_smsec);
303  jul2ydmsec(jstop, &map_eyear, &map_eday, &map_emsec);
304 
305  /* Create file input list */
306  strcpy(infiles, basename(infileList[0]));
307  for (ifile = 0; ifile < nfiles; ifile++) {
308  strcat(infiles, ", ");
309  strcat(infiles, basename(infileList[ifile]));
310  }
311 
312  /* Compute number of filled bins */
313  if (precision[0] == 'I') {
314  for (iy = 0; iy < NY; iy++)
315  for (ix = 0; ix < NX; ix++)
316  if (map16[iy][ix] != NODATA16)
317  nbins++;
318  } else {
319  for (iy = 0; iy < NY; iy++)
320  for (ix = 0; ix < NX; ix++)
321  if (map08[iy][ix] != NODATA8)
322  nbins++;
323  }
324 
325  /* Identify product binning period */
326  deljul = jstop - jstart;
327  if (deljul <= 0.1)
328  strcpy(prod_type, "scene");
329  else if (deljul > 0.1 && deljul <= 1.0)
330  strcpy(prod_type, "day");
331  else if (deljul > 1.0 && deljul <= 8.0)
332  strcpy(prod_type, "8-day");
333  else if (deljul > 8.0 && deljul <= 16.0)
334  strcpy(prod_type, "16-day");
335  else if (deljul > 16.0 && deljul <= 31.0)
336  strcpy(prod_type, "month");
337  else if (deljul > 31.0 && deljul <= 367.0)
338  strcpy(prod_type, "year");
339  else
340  strcpy(prod_type, "multi-year");
341 
342  /* Set the L3_bin metadata block to zeros */
343  memset(&meta_l3b, '\0', sizeof (meta_l3bType));
344 
345 
346  /* */
347  /* Write output map file */
348  /* --------------------- */
349  /* */
350  printf("Writing L3 Map file: %s\n", outfile);
351  printf("syear = %d, sday = %d, smsec = %d\n", map_syear, map_sday, map_smsec);
352  printf("eyear = %d, eday = %d, emsec = %d\n", map_eyear, map_eday, map_emsec);
353  printf("Number of filled bins: %d of %d\n", nbins, NX * NY);
354 
355  /*
356  To avoid changes the calling sequence to "put_l3m", we pass
357  info about the precision through the "nbins" parameter.
358  */
359  if (precision[0] == 'I') nbins = -nbins;
360 
361  status = put_l3m(outfile, replaces,
362  bin_syear, bin_sday, bin_eyear, bin_eday,
363  map_syear, map_sday, map_smsec,
364  map_eyear, map_eday, map_emsec,
365  map_latrange, map_lonrange, lines, columns,
366  l3_flag_names, flag_use, eng_q_use, ptime, infiles,
367  prod_type, nbins, l3m_name, map, measure,
368  proc_con, proc_log, &meta_l3b);
369  if (status < 0) {
370  printf("%s: Error opening or writing %s as L3 SMI file\n",
371  argv[0], outfile);
372  exit(1);
373  }
374 
375  return 0;
376 }
377 
378 /* ------------------------------------------------------------------------- *
379  * usage - display proper calling sequence for this program *
380  * ------------------------------------------------------------------------- */
381 void usage(char *progname) {
382 
383  printf("%s %s (%s %s)\n", progname, VERSION, __DATE__, __TIME__);
384 
385  fprintf(stderr, "\nUsage: %s ", progname);
386  fprintf(stderr, "-l input-filename-list | ");
387  fprintf(stderr, "(-c chlorophyll-file -n ndvi-file)\n");
388  fprintf(stderr, " [-o output-filename] ");
389  fprintf(stderr, "[-r replacement-filename]\n");
390  fprintf(stderr, "\n output-filename : output map file, def=\"map.hdf\"\n");
391  fprintf(stderr, " input-filename-list : file containing list of "
392  "L3 SMI CHLO or NDVI filenames\n");
393  fprintf(stderr, " chlorophyll-file : input L3 SMI CHLO filename\n");
394  fprintf(stderr, " input-filename : input L3 SMI NDVI filename\n");
395  fprintf(stderr, " replacement-filename : filename which this product is intended to replace\n");
396 }
397 
398 /* ------------------------------------------------------------------------- *
399  * ydmsec2jul - converts year, day-of-year, millisecs-of-day to Julian *
400  * ------------------------------------------------------------------------- */
401 double ydmsec2jul(int16 year, int16 day, int32 msec) {
402  double jul;
403 
404  jul = (367 * year - (7 * year) / 4 + day + 1721044) + msec / 8.64e7;
405 
406  return ( jul);
407 }
408 
409 /* ------------------------------------------------------------------------- *
410  * jul2ydmsec - converts Julian to year, day-of-year, millisecs-of-day *
411  * ------------------------------------------------------------------------- */
412 void jul2ydmsec(double jul, int16 *year, int16 *day, int32 *msec) {
413  int32 days_since;
414  int32 years_since;
415 
416  /* Compute days since January 0, 1900 */
417  days_since = (int32) jul - 2415020;
418 
419  /* Compute years since 1900 */
420  years_since = 4 * days_since / 1461;
421 
422  /* Compute year, day-of-year, msecs of day */
423  *year = years_since + 1900;
424  *day = days_since - 1461 * (years_since - 1) / 4 - 365;
425  *msec = (int32) (fmod(jul, 1.0)*8.64e7);
426 }
427 
428 
integer, parameter int16
Definition: cubeio.f90:3
int16 eday
Definition: l1_czcs_hdf.c:17
#define NX
Definition: main_biosmap.c:51
int32_t day
int status
Definition: l1_czcs_hdf.c:32
#define FILENAMELEN
Definition: main_biosmap.c:53
#define NULL
Definition: decode_rs.h:63
int32 * msec
Definition: l1_czcs_hdf.c:31
int16 eyear
Definition: l1_czcs_hdf.c:17
int syear
Definition: l1_czcs_hdf.c:15
void jul2ydmsec(double jul, int16 *year, int16 *day, int32 *msec)
Definition: main_biosmap.c:412
int32 smsec
Definition: l1_czcs_hdf.c:16
#define MAXSTRNGLEN
Definition: main_biosmap.c:54
int sday
Definition: l1_czcs_hdf.c:15
void usage(char *progname)
Definition: main_biosmap.c:381
make_L3 README txt Compiling set environment variables for HDBLIB and HDFINC to the appropriate HDF4 lib and include directories make_L3_v1 c o make_L3 LIB lib a I LIB I $HDFINC L $HDFLIB lmfhdf ldf lz ljpeg lm lmalloc Running make_L3 takes input from standard so the SeaWIFS level files should be piped to the program via the command line as in to be allocated by the program to buffer the compositing The the better Ideally it should be to fit the entire global image(with all the layers) at once. Otherwise the process will be buffered on disk. -bufstep
void get_time(char *pr_time)
Definition: get_time.c:28
#define MAXINFILES
Definition: main_biosmap.c:55
int32 put_l3m(char *l3m_path, char *replaces, int16 bin_syear, int16 bin_sday, int16 bin_eyear, int16 bin_eday, int16 syear, int16 sday, int32 smsec, int16 eyear, int16 eday, int32 emsec, float32 *lat_range, float32 *lon_range, int32 lines, int32 columns, char *flag_names, char *flag_use, uint8 *eng_q_use, char *ptime, char *infiles, char *prod_type, int32 nbins, char *l3m_name, void *l3m_data, char *measure, char *proc_con, char *proc_log, meta_l3bType *meta_l3b)
Definition: put_l3m.c:135
int main(int argc, char *argv[])
Definition: main_biosmap.c:72
#define max(A, B)
Definition: main_biosmap.c:61
double ydmsec2jul(int16 year, int16 day, int32 msec)
Definition: main_biosmap.c:401
int32_t get_l3m(char *l3m_path, int16_t *syear, int16_t *sday, int32_t *smsec, int16_t *eyear, int16_t *eday, int32_t *emsec, char *prod_type, char *l3m_name, uint8_t *l3m_data, unsigned char *palette, meta_struct *meta_l3m)
Definition: get_l3m.c:72
#define min(A, B)
Definition: main_biosmap.c:62
#define basename(s)
Definition: l0chunk_modis.c:29
int32 emsec
Definition: l1_czcs_hdf.c:18
#define NY
Definition: main_biosmap.c:52
unsigned char byte
Definition: main_biosmap.c:42
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)
l2prod offset
#define NODATA8
Definition: main_biosmap.c:56
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 as required for compatibility with version of the SDP toolkit Corrected test output file names to end in per delivery and then split off a new MYD_PR03 pcf file for Aqua Added AssociatedPlatformInstrumentSensor to the inventory metadata in MOD01 mcf and MOD03 mcf Created new versions named MYD01 mcf and MYD03 where AssociatedPlatformShortName is rather than Terra The program itself has been changed to read the Satellite Instrument validate it against the input L1A and LUT and to use it determine the correct files to retrieve the ephemeris and attitude data from Changed to produce a LocalGranuleID starting with MYD03 if run on Aqua data Added the Scan Type file attribute to the Geolocation copied from the L1A and attitude_angels to radians rather than degrees The accumulation of Cumulated gflags was moved from GEO_validate_earth_location c to GEO_locate_one_scan c
Definition: HISTORY.txt:464
#define NODATA16
Definition: main_biosmap.c:57
#define CMD_ARGS
Definition: main_biosmap.c:58
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
#define VERSION
Definition: main_biosmap.c:50