OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1_generic_write.c
Go to the documentation of this file.
1 /* =========================================================== */
2 /* Module l1_generic_write.c */
3 /* */
4 /* Functions to open and write a multi-sensor (generic) l1 */
5 /* file in HDF format. */
6 /* */
7 /* Written By: */
8 /* B. A. Franz, SAIC GSC, SIMBIOS Project, January 1999. */
9 /* */
10 /* Modified By: */
11 /* J. M. Gales, Futuretech, SIMBIOS Project, Sept. 1999. */
12 /* Generate standard L1B product */
13 /* Gene Eplee, SAIC GSC, SeaWiFS Project, December 2000. */
14 /* Update time correction and mirror side */
15 /* factors. */
16 /* Gene Eplee, SAIC, SeaWiFS Project, March 2004. */
17 /* Convert time correction and mirror side */
18 /* factors to simultaneous exponentials. */
19 /* J. M. Gales, Futuretech, Oct 2013. */
20 /* Add support for NETCDF4 and CF-metadata */
21 /* =========================================================== */
22 
23 #include <netcdf.h>
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <libgen.h>
28 #include <string.h>
29 #include <time.h>
30 #include <math.h>
31 
32 #include "l1.h"
33 #include "l1_aci_hdf.h"
34 
35 #include "dfutils.h"
36 #include <timeutils.h>
37 #include "mfhdf.h"
38 
39 #include "scene_meta.h"
40 
41 /* Global variables to facilitate communication
42  between some of the functions defined in this file */
43 static int32_t sd_id;
44 static int32_t numScans;
45 static int32_t numPixels;
46 static int32_t numBands;
47 static int32_t numBandsIR;
48 static int32_t spix;
49 static int32_t cpix;
50 static int32_t epix;
51 static int32_t dpix;
52 static int32_t cscan;
53 static int32_t nctl;
54 static int32_t *ictl;
55 static int32_t *jctl;
56 static int32_t sensorID;
57 static int32_t evalmask;
58 int32_t *wavelength;
59 static int32_t *Lambda, *Lambda_p;
60 char rad_name[8];
61 
62 int32_t get_ctl_pts(int32_t npix, int32_t nscans, int32_t ictl[], int32_t jctl[]) {
63  int32_t i;
64 
65  for (i = 0; i < nscans; i++)
66  jctl[i] = i + 1;
67 
68  for (i = 0; i < npix; i++)
69  ictl[i] = i + 1;
70 
71  return (npix);
72 }
73 
74 /* -------------------------------------------------------- */
75 /* Assign SDSes to Vgroups */
76 
77 /* -------------------------------------------------------- */
78 int MakeVgroupsL1(filehandle *file) {
79 
80  int32_t i;
81  int32_t h_id;
82  int32_t v_id;
83  int32_t sd_id = file->sd_id;
84 
85  /* Do we have the extra meta-data for SeaWiFS */
86  int seawifs_meta = 0;
87  if (sensorID == SEAWIFS) {
88  int32_t sds_id;
89  if (sd_select(sd_id, "scan_ell", &sds_id) == 0)
90  seawifs_meta = 1;
91  }
92 
93  h_id = Hopen(file->name, DFACC_RDWR, 0);
94  if (h_id == FAIL) {
95  fprintf(stderr, "-E- %s line %d: Hopen() failed for file, %s.\n",
96  __FILE__, __LINE__, file->name);
97  return (HDF_FUNCTION_ERROR);
98  }
99  Vstart(h_id);
100 
101  if (seawifs_meta) {
102 
103  /* Sensor Tilt */
104  DPTB(v_attach(h_id, &v_id));
105  Vsetclass(v_id, "Per File Data");
106  Vsetname(v_id, "Sensor Tilt");
107  DPTB(AddSdsToVgroup(sd_id, v_id, "ntilts"));
108  DPTB(AddSdsToVgroup(sd_id, v_id, "tilt_flags"));
109  DPTB(AddSdsToVgroup(sd_id, v_id, "tilt_ranges"));
110  Vdetach(v_id);
111 
112  }
113 
114  /* Scan-Line Attributes */
115  PTB(v_attach(h_id, &v_id));
116  Vsetclass(v_id, "Per Scan Data");
117  Vsetname(v_id, "Scan-Line Attributes");
118  PTB(AddSdsToVgroup(sd_id, v_id, "year"));
119  PTB(AddSdsToVgroup(sd_id, v_id, "day"));
120  PTB(AddSdsToVgroup(sd_id, v_id, "msec"));
121  DPTB(AddSdsToVgroup(sd_id, v_id, "slon"));
122  DPTB(AddSdsToVgroup(sd_id, v_id, "clon"));
123  DPTB(AddSdsToVgroup(sd_id, v_id, "elon"));
124  DPTB(AddSdsToVgroup(sd_id, v_id, "slat"));
125  DPTB(AddSdsToVgroup(sd_id, v_id, "clat"));
126  DPTB(AddSdsToVgroup(sd_id, v_id, "elat"));
127  DPTB(AddSdsToVgroup(sd_id, v_id, "csol_z"));
128  Vdetach(v_id);
129 
130  /* Image Data */
131  PTB(v_attach(h_id, &v_id));
132  Vsetclass(v_id, "Per Scan Data");
133  Vsetname(v_id, "Geophysical Data");
134  for (i = 0; i < numBands; i++) {
135  sprintf(rad_name, "Lt_%3d", wavelength[i]);
136  PTB(AddSdsToVgroup(sd_id, v_id, rad_name));
137  }
138  Vdetach(v_id);
139 
140  /* Navigation */
141  PTB(v_attach(h_id, &v_id));
142  Vsetclass(v_id, "Per Scan Data");
143  Vsetname(v_id, "Navigation Data");
144  PTB(AddSdsToVgroup(sd_id, v_id, "longitude"));
145  PTB(AddSdsToVgroup(sd_id, v_id, "latitude"));
146  PTB(AddSdsToVgroup(sd_id, v_id, "solz"));
147  PTB(AddSdsToVgroup(sd_id, v_id, "sola"));
148  PTB(AddSdsToVgroup(sd_id, v_id, "senz"));
149  PTB(AddSdsToVgroup(sd_id, v_id, "sena"));
150  PTB(AddSdsToVgroup(sd_id, v_id, "tilt"));
151 
152  if (seawifs_meta) {
153  DPTB(AddSdsToVgroup(sd_id, v_id, "orb_vec"));
154  DPTB(AddSdsToVgroup(sd_id, v_id, "sun_ref"));
155  DPTB(AddSdsToVgroup(sd_id, v_id, "att_ang"));
156  DPTB(AddSdsToVgroup(sd_id, v_id, "sen_mat"));
157  DPTB(AddSdsToVgroup(sd_id, v_id, "scan_ell"));
158  DPTB(AddSdsToVgroup(sd_id, v_id, "nflag"));
159  }
160  Vdetach(v_id);
161 
162  Vend(h_id);
163 
164  if (Hclose(h_id) != SUCCEED) {
165  fprintf(stderr, "-E- %s line %d: Hclose(%d) failed for file, %s .\n",
166  __FILE__, __LINE__, h_id, file->name);
167  return (HDF_FUNCTION_ERROR);
168  }
169  return (LIFE_IS_GOOD);
170 }
171 
172 /* -------------------------------------------------------- */
173 /* Open an HDF file and store global attributes in it. */
174 
175 /* -------------------------------------------------------- */
176 int openl1_write(filehandle *l1file) {
177  char *name = l1file->name;
178  int32_t nbands = (int32_t) l1file->nbands;
179  int32_t npix = (int32_t) l1file->npix;
180  int32_t nscans = (int32_t) l1file->nscan;
181  int32_t sensorID = (int32_t) l1file->sensorID;
182  int32_t *bindx = (int32_t *) l1file->bindx;
183  char avhrrbird[10];
184 
185  char buf1[1024];
186  char tmp_str[2048];
187  char title[255];
188  char soft_id[200]; /* software version info */
189  char* bandNumberStr;
190  char* totalBandNumberStr;
191  float *Gain;
192  float *Offset;
193  float *Fonom;
194  float *Fobar, *Fobar_p;
195  float *Tau_r, *Tau_r_p;
196  float *k_oz, *k_oz_p;
197  float *k_no2, *k_no2_p;
198 
199  int i, n;
200  static int firstCall = 1;
201  int32_t dm[3];
202  const char dm_name[3][80];
203  int flagbits[32];
204 
205  /* set globals */
206  numScans = nscans;
207  numPixels = npix;
208  numBands = nbands;
209  numBandsIR = l1file->nbandsir;
210  spix = l1file->spix + 1;
211  cpix = numPixels / 2;
212  epix = l1file->epix + 1;
213  dpix = l1_input->dpixl;
214  cscan = numScans / 2;
215  evalmask = l1_input->evalmask;
216 
217  if (firstCall == 1) {
218  if ((wavelength = (int32_t *) calloc(numBands, sizeof (int32_t))) == NULL) {
219  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
220  __FILE__, __LINE__);
221  exit(1);
222  }
223  if ((Lambda = (int32_t *) calloc((numBands + numBandsIR), sizeof (int32_t))) == NULL) {
224  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
225  __FILE__, __LINE__);
226  exit(1);
227  }
228  firstCall = 0;
229  }
230  if ((Gain = (float *) calloc(numBands, sizeof (float))) == NULL) {
231  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
232  __FILE__, __LINE__);
233  exit(1);
234  }
235  if ((Offset = (float *) calloc(numBands, sizeof (float))) == NULL) {
236  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
237  __FILE__, __LINE__);
238  exit(1);
239  }
240  if ((Fonom = (float *) calloc(numBands, sizeof (float))) == NULL) {
241  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
242  __FILE__, __LINE__);
243  exit(1);
244  }
245  if ((Fobar = (float *) calloc(numBands, sizeof (float))) == NULL) {
246  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
247  __FILE__, __LINE__);
248  exit(1);
249  }
250  if ((Tau_r = (float *) calloc(numBands, sizeof (float))) == NULL) {
251  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
252  __FILE__, __LINE__);
253  exit(1);
254  }
255  if ((k_oz = (float *) calloc(numBands, sizeof (float))) == NULL) {
256  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
257  __FILE__, __LINE__);
258  exit(1);
259  }
260  if ((k_no2 = (float *) calloc(numBands, sizeof (float))) == NULL) {
261  printf("-E- %s line %d : error allocating memory for l1_generic_write:open1_write.\n",
262  __FILE__, __LINE__);
263  exit(1);
264  }
265 
266  /* Get control-point array */
267  if ((ictl = calloc(numPixels, sizeof (int32_t))) == NULL) {
268  fprintf(stderr,
269  "-E- %s line %d: Unable to allocate control-point array.\n",
270  __FILE__, __LINE__);
271  return (MEMORY_ALLOCATION_ERROR);
272  }
273  if ((jctl = calloc(numScans, sizeof (int32_t))) == NULL) {
274  fprintf(stderr,
275  "-E- %s line %d: Unable to allocate control-point array.\n",
276  __FILE__, __LINE__);
277  return (MEMORY_ALLOCATION_ERROR);
278  }
279  nctl = get_ctl_pts(numPixels, numScans, ictl, jctl);
280 
281  /* Create the L1B file */
282  idDS ds_id;
283  int32_t nt_chr, nt_i32;
284 
285  if (l1file->format == FT_L1HDF) {
286  ds_id.fftype = DS_HDF;
287  nt_chr = DFNT_CHAR;
288  nt_i32 = DFNT_INT32;
289  } else if (l1file->format == FT_L1BNCDF) {
290  ds_id.fftype = DS_NCDF;
291  nt_chr = NC_CHAR;
292  nt_i32 = NC_INT;
293  }
294 
295  // Make sure startDS stores ds_id.fftype
296  ds_id = startDS(name, ds_id.fftype, DS_WRITE, 0);
297  l1file->sd_id = ds_id.fid;
298  if (l1file->sd_id == FAIL) {
299  fprintf(stderr, "-E- %s line %d: Could not create L1B file, %s .\n",
300  __FILE__, __LINE__, name);
301  return (HDF_FUNCTION_ERROR);
302  }
303 
304  totalBandNumberStr = "total band number";
305  bandNumberStr = "band number";
306 
307  /* Get sensor-specific attributes */
308  if ((n = rdsensorinfo(l1file->sensorID, l1_input->evalmask, NULL, NULL))
309  != numBands) {
310  fprintf(stderr, "-E- %s Line %d: Error reading sensor table. %d %d\n",
311  __FILE__, __LINE__, numBands, n);
312  return (-1);
313  }
314  rdsensorinfo(l1file->sensorID, l1_input->evalmask, "Lambda",
315  (void **) &Lambda_p);
316  rdsensorinfo(l1file->sensorID, l1_input->evalmask, "Fobar",
317  (void **) &Fobar_p);
318  rdsensorinfo(l1file->sensorID, l1_input->evalmask, "Tau_r",
319  (void **) &Tau_r_p);
320  rdsensorinfo(l1file->sensorID, l1_input->evalmask, "k_oz",
321  (void **) &k_oz_p);
322  rdsensorinfo(l1file->sensorID, l1_input->evalmask, "k_no2",
323  (void **) &k_no2_p);
324 
325  for (i = 0; i < numBands; i++) {
326  Lambda[i] = Lambda_p[i];
327  // multiply by 10 to put into W/m2/um, since internally all radiances are mW/cm2/um
328  Fobar[i] = Fobar_p[i] * 10.0;
329  Tau_r[i] = Tau_r_p[i];
330  k_oz[i] = k_oz_p[i];
331  k_no2[i] = k_no2_p[i];
332 
333  Gain[i] = l1_input->gain[i];
334  Offset[i] = l1_input->offset[i];
335  if (l1_input->outband_opt >= 2) {
336  get_f0_thuillier_ext(Lambda[i], BANDW, &Fonom[i]);
337  Fonom[i] *= 10.0;
338  } else {
339  Fonom[i] = Fobar[i];
340  }
341  }
342  for (i = numBands; i < numBands + numBandsIR; i++)
343  Lambda[i] = Lambda_p[i];
344 
345  if (l1file->format == FT_L1BNCDF) {
346  int dumdim;
347  totalBandNumberStr = "number_of_bands";
348  bandNumberStr = "number_of_reflective_bands";
349  if (nc_def_dim(ds_id.fid, "number_of_lines", numScans,
350  &dumdim) != NC_NOERR)
351  exit(1);
352  if (nc_def_dim(ds_id.fid, "pixels_per_line", numPixels,
353  &dumdim) != NC_NOERR)
354  exit(1);
355  if (nc_def_dim(ds_id.fid, "pixel_control_points", nctl,
356  &dumdim) != NC_NOERR)
357  exit(1);
358  if (nc_def_dim(ds_id.fid, totalBandNumberStr, numBands + numBandsIR,
359  &dumdim) != NC_NOERR)
360  exit(1);
361  if (nc_def_dim(ds_id.fid, bandNumberStr, numBands, &dumdim) != NC_NOERR)
362  exit(1);
363 
364  nc_def_grp(ds_id.fid, "sensor_band_parameters", &l1file->grp_id[0]);
365  nc_def_grp(ds_id.fid, "scan_line_attributes", &l1file->grp_id[2]);
366  nc_def_grp(ds_id.fid, "geophysical_data", &l1file->grp_id[3]);
367  nc_def_grp(ds_id.fid, "navigation_data", &l1file->grp_id[4]);
368  nc_def_grp(ds_id.fid, "processing_control", &l1file->grp_id[5]);
369  }
370 
371  /* */
372  /* Create the Sensor Band Parameters datasets */
373  /* ---------------------------------------------------------------- */
374  /* */
375  if (l1file->format == FT_L1BNCDF)
376  ds_id.fid = l1file->grp_id[0];
377 
378  dm[0] = numBands + numBandsIR;
379  strcpy((char *) dm_name[0], totalBandNumberStr);
380  PTB(createDS(ds_id, l1file->sensorID, "wavelength", dm, dm_name));
381 
382  dm[0] = numBands;
383  strcpy((char *) dm_name[0], bandNumberStr);
384 
385  if (numBands > 0) {
386  PTB(createDS(ds_id, l1file->sensorID, "vcal_gain", dm, dm_name));
387  PTB(createDS(ds_id, l1file->sensorID, "vcal_offset", dm, dm_name));
388  PTB(createDS(ds_id, l1file->sensorID, "F0", dm, dm_name));
389  PTB(createDS(ds_id, l1file->sensorID, "k_oz", dm, dm_name));
390  PTB(createDS(ds_id, l1file->sensorID, "k_no2", dm, dm_name));
391  PTB(createDS(ds_id, l1file->sensorID, "Tau_r", dm, dm_name));
392  }
393 
394  /* Write out some global attributes */
396  strcat(title, " Level-1B");
397  //strcpy(soft_id, VERSION);
398  //sprintf(soft_id, "%d.%d.%d-%s", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, GITSHA);
399 
400  if (l1file->format == FT_L1HDF) {
401  PTB(SetChrGA(ds_id, "Sensor Name", sensorId2SensorName(sensorID)));
402  PTB(SetChrGA(ds_id, "Product Name", basename(name)));
403  PTB(SetChrGA(ds_id, "Title", title));
404  PTB(SetChrGA(ds_id, "Software Name", "l1bgen"));
405  PTB(SetChrGA(ds_id, "Software Version", "2.0"));
406  PTB(SetChrGA(ds_id, "Processing Time", ydhmsf(now(), 'G')));
407  //PTB(SetChrGA(ds_id, "Processing Control", pro_control));
408  PTB(SetI32GA(ds_id, "Number of Bands", numBands));
409  PTB(SetI32GA(ds_id, "Pixels per Scan Line", numPixels));
410  PTB(SetI32GA(ds_id, "Number of Scan Lines", numScans));
411  PTB(SetI32GA(ds_id, "Start Pixel", spix));
412  PTB(SetI32GA(ds_id, "Pixel Subsampling Interval", dpix));
413  PTB(SetI32GA(ds_id, "Scene Center Scan Line", cscan));
414  PTB(SetI32GA(ds_id, "Number of Scan Control Points", numScans));
415  PTB(SetI32GA(ds_id, "Number of Pixel Control Points", nctl));
416 
417  dm[0] = nctl;
418  strcpy((char *) dm_name[0], "Number of Pixel Control Points");
419  PTB(createDS(ds_id, sensorID, "cntl_pt_cols", dm, dm_name));
420  PTB(writeDS(ds_id, "cntl_pt_cols", ictl, 0, 0, 0, nctl, 0, 0));
421 
422  dm[0] = numScans;
423  strcpy((char *) dm_name[0], "Number of Scan Lines");
424  PTB(createDS(ds_id, sensorID, "cntl_pt_rows", dm, dm_name));
425  PTB(writeDS(ds_id, "cntl_pt_rows", jctl, 0, 0, 0, numScans, 0, 0));
426 
427  } else {
428 
429  // global attr
430  ds_id.fid = l1file->sd_id;
431 
432  PTB(SetChrGA(ds_id, "product_name", basename(name)));
433  PTB(SetChrGA(ds_id, "title", title));
434  //PTB(SetChrGA(ds_id, "history", pro_control));
435 
436  PTB(SetChrGA(ds_id, "instrument", sensorId2InstrumentName(l1file->sensorID)));
437 
438  if (l1file->sensorID == AVHRR) {
439  strcpy(avhrrbird, "NOAA-");
440  strncat(avhrrbird, xsatid2name(l1file->subsensorID) + 2, 2);
441  PTB(SetChrGA(ds_id, "platform", avhrrbird));
442  } else {
443  PTB(SetChrGA(ds_id, "platform", sensorId2PlatformName(l1file->sensorID)));
444  }
445  PTB(SetChrGA(ds_id, "Conventions", "CF-1.6 ACDD-1.3"));
446  PTB(SetChrGA(ds_id, "license", LICENSE));
447  PTB(SetChrGA(ds_id, "naming_authority", NAMING_AUTHORITY));
448  // create the id -
449  if (strcmp(l1_input->pversion, "Unspecified") != 0) {
450  strcpy(buf1, l1_input->pversion);
451  strcat(buf1, "/L1B/");
452  } else {
453  strcpy(buf1, "L1B/");
454  }
455  strcat(buf1, basename(l1file->name));
456  PTB(SetChrGA(ds_id, "id", buf1));
457 
458  time_t tnow;
459  time(&tnow);
460  strcpy(buf1, unix2isodate(tnow, 'G'));
461  PTB(SetChrGA(ds_id, "date_created", buf1));
462 
463  PTB(SetChrGA(ds_id, "standard_name_vocabulary", STDNAME_VOCABULARY));
464  PTB(SetChrGA(ds_id, "institution", INSTITUTION));
465  PTB(SetChrGA(ds_id, "creator_name", CREATOR_NAME));
466  PTB(SetChrGA(ds_id, "creator_email", CREATOR_EMAIL));
467  PTB(SetChrGA(ds_id, "creator_url", CREATOR_URL));
468  PTB(SetChrGA(ds_id, "project", PROJECT));
469  PTB(SetChrGA(ds_id, "publisher_name", PUBLISHER_NAME));
470  PTB(SetChrGA(ds_id, "publisher_url", PUBLISHER_URL));
471  PTB(SetChrGA(ds_id, "publisher_email", PUBLISHER_EMAIL));
472 
473  PTB(SetChrGA(ds_id, "processing_level", "L1B"));
474  PTB(SetChrGA(ds_id, "cdm_data_type", "swath"));
475  if (l1file->orbit_node_lon > -180.0 && l1file->orbit_node_lon < 180.0)
476  PTB(
477  SetF32GA(ds_id, "equatorCrossingLongitude",
478  l1file->orbit_node_lon));
479  if (l1file->orbit_number > 0)
480  PTB(SetI32GA(ds_id, "orbit_number", l1file->orbit_number));
481  if (l1file->node_crossing_time > 0) {
482  strcpy(buf1, unix2isodate(l1file->node_crossing_time, 'G'));
483  PTB(SetChrGA(ds_id, "equatorCrossingDateTime", buf1));
484  }
485 
486  PTB(SetChrGA(ds_id, "spatialResolution", l1file->spatialResolution));
487 
488  dm[0] = nctl;
489  strcpy((char *) dm_name[0], "pixel_control_points");
490  PTB(createDS(ds_id, sensorID, "cntl_pt_cols", dm, dm_name));
491  PTB(writeDS(ds_id, "cntl_pt_cols", ictl, 0, 0, 0, nctl, 0, 0));
492 
493  dm[0] = numScans;
494  strcpy((char *) dm_name[0], "number_of_lines");
495  PTB(createDS(ds_id, sensorID, "cntl_pt_rows", dm, dm_name));
496  PTB(writeDS(ds_id, "cntl_pt_rows", jctl, 0, 0, 0, numScans, 0, 0));
497 
498  // Processing Control attibutes
499  ds_id.fid = l1file->grp_id[5];
500  PTB(SetChrGA(ds_id, "software_name", "l1bgen"));
501  PTB(SetChrGA(ds_id, "software_version", soft_id));
502 
503  // Write input parameters metadata
504  ds_id.fid = l1file->grp_id[5];
505  int32_t grp_id_input_parms;
506  nc_def_grp(l1file->grp_id[5], "input_parameters", &grp_id_input_parms);
507  ds_id.fid = grp_id_input_parms;
508 
509  char *end_str;
510  char *tmp_parms = replace_ocroots(l1_input->input_parms);
511  char *token = strtok_r(tmp_parms, "\n", &end_str);
512  while (token != NULL) {
513  char *end_token;
514  char *name = strtok_r(token, "=", &end_token);
515  trimBlanks(name);
516  char *value = strtok_r(NULL, ";", &end_token);
517  trimBlanks(value);
518  if (name[0] != '#') {
519  PTB(SetChrGA(ds_id, name, value));
520  }
521  token = strtok_r(NULL, "\n", &end_str);
522  }
523  free(tmp_parms);
524 
525  }
526 
527  /* Create the scan-line SDSes */
528  char longname[64];
529  int32_t *wavelen;
530  int32_t np = numPixels;
531  int32_t nb = numBands;
532  int32_t nscan = nscans;
533 
534  /* Get sensor wavelengths */
535  if (rdsensorinfo(sensorID, evalmask, "Lambda", (void **) &wavelen) != nb) {
536  printf("-E- %s: Unable to determine sensor wavelengths\n", __FILE__);
537  exit(FATAL_ERROR);
538  }
539 
540  for (i = 0; i < nb; i++)
541  wavelength[i] = wavelen[bindx[i]];
542 
543  if (l1file->format == FT_L1BNCDF) {
544  ds_id.fid = l1file->grp_id[2];
545  strcpy((char *) dm_name[0], "number_of_lines");
546  } else {
547  strcpy((char *) dm_name[0], "Number of Scan Lines");
548  }
549  dm[0] = nscan;
550 
551  PTB(createDS(ds_id, sensorID, "year", dm, dm_name));
552  PTB(createDS(ds_id, sensorID, "day", dm, dm_name));
553  PTB(createDS(ds_id, sensorID, "msec", dm, dm_name));
554  PTB(createDS(ds_id, sensorID, "detnum", dm, dm_name));
555  PTB(createDS(ds_id, sensorID, "mside", dm, dm_name));
556  PTB(createDS(ds_id, sensorID, "slon", dm, dm_name));
557  PTB(createDS(ds_id, sensorID, "clon", dm, dm_name));
558  PTB(createDS(ds_id, sensorID, "elon", dm, dm_name));
559  PTB(createDS(ds_id, sensorID, "slat", dm, dm_name));
560  PTB(createDS(ds_id, sensorID, "clat", dm, dm_name));
561  PTB(createDS(ds_id, sensorID, "elat", dm, dm_name));
562  PTB(createDS(ds_id, sensorID, "csol_z", dm, dm_name));
563 
564  if (l1file->format == FT_L1BNCDF) {
565  ds_id.fid = l1file->grp_id[4];
566  strcpy((char *) dm_name[1], "pixels_per_line");
567  } else {
568  strcpy((char *) dm_name[1], "Pixels per Scan Line");
569  }
570  dm[1] = np;
571 
572  PTB(createDS(ds_id, sensorID, "longitude", dm, dm_name));
573  PTB(createDS(ds_id, sensorID, "latitude", dm, dm_name));
574  PTB(createDS(ds_id, sensorID, "solz", dm, dm_name));
575  PTB(createDS(ds_id, sensorID, "sola", dm, dm_name));
576  PTB(createDS(ds_id, sensorID, "senz", dm, dm_name));
577  PTB(createDS(ds_id, sensorID, "sena", dm, dm_name));
578  PTB(createDS(ds_id, sensorID, "tilt", dm, dm_name));
579 
580  if (l1file->format == FT_L1BNCDF)
581  ds_id.fid = l1file->grp_id[3];
582  for (i = 0; i < nb; i++) {
583  sprintf(rad_name, "Lt_%3d", wavelength[i]);
584  sprintf(longname, "Top of atmosphere %3d nm radiance", wavelength[i]);
585 
586  PTB(createDS(ds_id, sensorID, rad_name, dm, dm_name));
587  }
588 
589  PTB(createDS(ds_id, sensorID, "l2_flags", dm, dm_name));
590  ds_id.sid = selectDS(ds_id, "l2_flags");
591 
592  tmp_str[0] = '\0';
593  for (i = 0; i < L1_NFLAGS; i++) {
594  strcat(tmp_str, l2_flag_lname[i]);
595  flagbits[i] = pow(2, i);
596  if (i < L1_NFLAGS - 1)
597  strcat(tmp_str, " ");
598  /*
599  * Keep the old flag attribute set for HDF4 files
600  */
601  if (l1file->format == FT_L1HDF) {
602  PTB(
603  setAttr(ds_id, l2_flag_sname[i], nt_chr,
604  strlen(l2_flag_lname[i]) + 1,
605  (VOIDP) l2_flag_lname[i]));
606  }
607  }
608  PTB(setAttr(ds_id, "flag_masks", nt_i32, L1_NFLAGS, (VOIDP) flagbits));
609 
610  PTB(
611  setAttr(ds_id, "flag_meanings", nt_chr, strlen(tmp_str) + 1,
612  (VOIDP) tmp_str));
613  endaccessDS(ds_id);
614 
615  if (l1file->format == FT_L1BNCDF)
616  ds_id.fid = l1file->grp_id[0];
617  PTB(
618  writeDS(ds_id, "wavelength", Lambda, 0, 0, 0, numBands + numBandsIR,
619  0, 0));
620 
621  if (numBands > 0) {
622  PTB(writeDS(ds_id, "vcal_gain", Gain, 0, 0, 0, numBands, 0, 0));
623  PTB(writeDS(ds_id, "vcal_offset", Offset, 0, 0, 0, numBands, 0, 0));
624  PTB(writeDS(ds_id, "F0", Fobar, 0, 0, 0, numBands, 0, 0));
625  PTB(writeDS(ds_id, "k_oz", k_oz, 0, 0, 0, numBands, 0, 0));
626  PTB(writeDS(ds_id, "k_no2", k_no2, 0, 0, 0, numBands, 0, 0));
627  PTB(writeDS(ds_id, "Tau_r", Tau_r, 0, 0, 0, numBands, 0, 0));
628  }
629 
630  free(Gain);
631  free(Offset);
632  free(Fonom);
633  free(Fobar);
634  free(Tau_r);
635  free(k_oz);
636  free(k_no2);
637  free(ictl);
638  free(jctl);
639 
640  return (LIFE_IS_GOOD);
641 }
642 
643 /* -------------------------------------------------------- */
644 /* Create the SDSes for the scan-line data */
645 
646 /* -------------------------------------------------------- */
647 int writel1(filehandle *l1file, int32_t recnum, l1str *l1rec) {
648  int32_t i, j;
649  int16_t year, day;
650  double dsec;
651  unix2yds(l1rec->scantime, &year, &day, &dsec);
652  int32_t msec = (int32_t) (dsec * 1000.0);
653 
654  float *lon = (float *) l1rec->lon;
655  float *lat = (float *) l1rec->lat;
656 
657  void *pbuf;
658 
659  float *angledata[4];
660  angledata[0] = (float *) l1rec->solz;
661  angledata[1] = (float *) l1rec->senz;
662  angledata[2] = (float *) l1rec->sola;
663  angledata[3] = (float *) l1rec->sena;
664 
665  static char *anglenames[4] = {"solz", "senz", "sola", "sena"};
666  static productInfo_t *p_info[4];
667  if(!p_info[0]) {
668  for (i = 0; i < 4; i++) {
669  p_info[i] = allocateProductInfo();
670  if (!p_info[i]) {
671  printf("ERROR allocating Product Info memory for %s\n", anglenames[i]);
672  exit(EXIT_FAILURE);
673  }
674  if (!findProductInfo(anglenames[i], l1rec->l1file->sensorID, p_info[i])) {
675  printf("%s not found in XML product table\n", anglenames[i]);
676  exit(EXIT_FAILURE);
677  }
678  }
679  }
680 
681 
682  float *tilt = (float *) &(l1rec->tilt);
683  int32_t *l2_flags = (int32_t *) l1rec->flags;
684  int32_t *bindx = (int32_t *) l1file->bindx;
685 
686  static float *data = NULL;
687 
688  idDS ds_id;
689  ds_id.fid = l1file->sd_id;
690  ds_id.deflate = 0;
691  if (l1file->format == FT_L1BNCDF)
692  ds_id.fftype = DS_NCDF;
693  else
694  ds_id.fftype = DS_HDF;
695 
696  /* Write the scan-line data */
697  if (l1file->format == FT_L1BNCDF)
698  ds_id.fid = l1file->grp_id[2];
699 
700  int32_t tmpI = year;
701  PTB(writeDS(ds_id, "year", &tmpI, recnum, 0, 0, 1, 1, 1));
702  tmpI = day;
703  PTB(writeDS(ds_id, "day", &tmpI, recnum, 0, 0, 1, 1, 1));
704  PTB(writeDS(ds_id, "msec", &msec, recnum, 0, 0, 1, 1, 1));
705 
706  PTB(writeDS(ds_id, "detnum", &l1rec->detnum, recnum, 0, 0, 1, 1, 1));
707  PTB(writeDS(ds_id, "mside", &l1rec->mside, recnum, 0, 0, 1, 1, 1));
708 
709  PTB(writeDS(ds_id, "slon", &lon[0], recnum, 0, 0, 1, 1, 1));
710  PTB(writeDS(ds_id, "clon", &lon[cpix], recnum, 0, 0, 1, 1, 1));
711  PTB(writeDS(ds_id, "elon", &lon[numPixels - 1], recnum, 0, 0, 1, 1, 1));
712  PTB(writeDS(ds_id, "slat", &lat[0], recnum, 0, 0, 1, 1, 1));
713  PTB(writeDS(ds_id, "clat", &lat[cpix], recnum, 0, 0, 1, 1, 1));
714  PTB(writeDS(ds_id, "elat", &lat[numPixels - 1], recnum, 0, 0, 1, 1, 1));
715  PTB(writeDS(ds_id, "csol_z", &angledata[0][cpix], recnum, 0, 0, 1, 1, 1));
716 
717  /* Write navigation info */
718  if (l1file->format == FT_L1BNCDF)
719  ds_id.fid = l1file->grp_id[4];
720  PTB(writeDS(ds_id, "longitude", lon, recnum, 0, 0, 1, numPixels, 1));
721  PTB(writeDS(ds_id, "latitude", lat, recnum, 0, 0, 1, numPixels, 1));
722  /* Write out the angles solz, senz, sola, sena */
723  for (i = 0; i < 4; i++) {
724  pbuf = scale_sds(angledata[i], p_info[i], numPixels);
725  PTB(writeDS(ds_id, anglenames[i], pbuf, recnum, 0, 0, 1, numPixels, 1));
726  }
727 
728  PTB(writeDS(ds_id, "tilt", tilt, recnum, 0, 0, 1, 1, 1));
729 
730  /* Write the radiance data */
731  if (l1file->format == FT_L1BNCDF)
732  ds_id.fid = l1file->grp_id[3];
733  if (data == NULL) {
734  if ((data = (float *) malloc(numPixels * sizeof (float))) == NULL) {
735  fprintf(stderr, "-E- %s line %d: Memory allocation failure.\n",
736  __FILE__, __LINE__);
737  exit(FATAL_ERROR);
738  }
739  }
740 
741  for (i = 0; i < numBands; i++) {
742  sprintf(rad_name, "Lt_%3d", wavelength[i]);
743  for (j = 0; j < numPixels; j++) {
744  data[j] = (float) l1rec->Lt[j * numBands + bindx[i]] * 10.0;
745  }
746  PTB(writeDS(ds_id, rad_name, data, recnum, 0, 0, 1, numPixels, 0));
747  }
748 
749  /* Write the l2_flag data */
750  PTB(writeDS(ds_id, "l2_flags", l2_flags, recnum, 0, 0, 1, numPixels, 0));
751 
752  /* Write global attributes */
753  if (recnum == (numScans - 1)) {
754  if (l1file->format == FT_L1BNCDF)
755  ds_id.fid = l1file->sd_id;
756  scene_meta_write(ds_id);
757  }
758 
759  return (LIFE_IS_GOOD);
760 }
761 
762 /* -------------------------------------------------------- */
763 /* Finish access for the current file. */
764 
765 /* -------------------------------------------------------- */
766 void closel1_generic(filehandle *l1file) {
767  idDS ds_id;
768  ds_id.deflate = 0;
769  ds_id.fid = l1file->sd_id;
770  if (l1file->format == FT_L1BNCDF)
771  ds_id.fftype = DS_NCDF;
772  else
773  ds_id.fftype = DS_HDF;
774 
775  /* Define Vgroups */
776  if (l1file->format == FT_L1HDF)
778 
779  if (endDS(ds_id)) {
780  fprintf(stderr, "-E- %s line %d: SDend(%d) failed.\n",
781  __FILE__, __LINE__, sd_id);
782  }
783 }
784 
char * ydhmsf(double dtime, char zone)
Definition: ydhmsf.c:12
int v_attach(int32_t h_id, int32_t *v_id)
Definition: hdf_utils.c:404
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
int SetF32GA(idDS ds_id, const char *name, float value)
int32 value
Definition: Granule.c:1235
const int bindx[3]
Definition: DbLutNetcdf.cpp:28
@ FT_L1BNCDF
Definition: filetype.h:19
int MakeVgroupsL1(filehandle *file)
int j
Definition: decode_rs.h:73
int32_t day
int sd_select(int32_t sd_id, const char *name, int32_t *sds_id)
Definition: hdf_utils.c:355
#define AVHRR
Definition: sensorDefs.h:15
int32_t * wavelength
int writel1(filehandle *l1file, int32_t recnum, l1str *l1rec)
int32_t selectDS(idDS ds_id, const char *l2_prod_names)
Definition: wrapper.c:438
#define STDNAME_VOCABULARY
Definition: OutFile.h:30
#define FAIL
Definition: ObpgReadGrid.h:18
#define NULL
Definition: decode_rs.h:63
read l1rec
void trimBlanks(char *str)
Definition: trimBlanks.c:10
#define PUBLISHER_URL
Definition: OutFile.h:37
const char * sensorId2PlatformName(int sensorId)
Definition: sensorInfo.c:226
int32_t deflate
Definition: dfutils.h:32
float * lat
int32 * msec
Definition: l1_czcs_hdf.c:31
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
void closel1_generic(filehandle *l1file)
#define CREATOR_EMAIL
Definition: OutFile.h:32
int32 nscan
Definition: l1_czcs_hdf.c:19
ds_format_t fftype
Definition: dfutils.h:31
#define NAMING_AUTHORITY
Definition: OutFile.h:25
int createDS(idDS ds_id, int sensorId, const char *sname, int32_t dm[3], const char dm_name[3][80])
Definition: wrapper.c:344
#define LICENSE
Definition: OutFile.h:24
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 PUBLISHER_EMAIL
Definition: OutFile.h:36
character(len=1000) if
Definition: names.f90:13
#define LIFE_IS_GOOD
Definition: passthebuck.h:4
#define DPTB(function)
Definition: passthebuck.h:24
int endaccessDS(idDS ds_id)
Definition: wrapper.c:627
char rad_name[8]
#define PUBLISHER_NAME
Definition: OutFile.h:35
void scene_meta_write(idDS ds_id)
Definition: scene_meta.c:241
read recnum
productInfo_t * allocateProductInfo()
idDS startDS(const char *filename, ds_format_t format, ds_access_t accessmode, int32_t deflate)
Definition: wrapper.c:561
#define INSTITUTION
Definition: OutFile.h:23
l1_input_t * l1_input
Definition: l1_options.c:9
#define FATAL_ERROR
Definition: swl0_parms.h:5
#define CREATOR_NAME
Definition: OutFile.h:31
void unix2yds(double usec, short *year, short *day, double *secs)
int writeDS(idDS ds_id, const char *name, const void *data, int32_t s0, int32_t s1, int32_t s2, int32_t e0, int32_t e1, int32_t e2)
Definition: wrapper.c:475
char * replace_ocroots(const char *inStr)
@ DS_NCDF
Definition: dfutils.h:20
const char * xsatid2name(int xsatid)
Definition: l1_aci_hdf.c:1173
#define PTB(function)
Definition: passthebuck.h:16
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
int32_t sid
Definition: dfutils.h:30
int SetI32GA(idDS ds_id, const char *name, int32_t value)
Definition: wrapper.c:326
#define basename(s)
Definition: l0chunk_modis.c:29
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
intn setAttr(uint8 isHDF5, int32 obj_id, const char *attr_name, int32 data_type, int32 count, VOIDP values)
Definition: put_smi.cpp:20
int32 dpix
Definition: l1_czcs_hdf.c:22
int32_t nbands
const char * sensorId2SensorName(int sensorId)
Definition: sensorInfo.c:198
@ DS_WRITE
Definition: dfutils.h:25
int SetChrGA(idDS ds_id, const char *name, const char *value)
Definition: wrapper.c:236
#define CREATOR_URL
Definition: OutFile.h:33
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
int32 spix
Definition: l1_czcs_hdf.c:21
void * scale_sds(float *data, productInfo_t *p, int32_t npix)
int32_t fid
Definition: dfutils.h:29
u5 which has been done in the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT production Changes from v6 which may affect scientific the sector rotation may actually occur during one of the scans earlier than the one where it is first reported As a the b1 values are about the LOCALGRANULEID metadata should have an extension NRT It is requested to identify the NRT to fill pixels affected by dead subframes with a special value Output the metadata of noisy and dead subframe Dead Subframe EV and Detector Quality Flag2 Removed the function call of Fill_Dead_Detector_SI to stop interpolating SI values for dead but also for all downstream products for science test only Changes from v5 which will affect scientific to conform to MODIS requirements Removed the Mixed option from the ScanType in the code because the L1A Scan Type is never Mixed Changed for ANSI C compliance and comments to better document the fact that when the HDF_EOS metadata is stricly the and products are off by and in the track respectively Corrected some misspelling of RCS swir_oob_sending_detector to the Reflective LUTs to enable the SWIR OOB correction detector so that if any of the sending detectors becomes noisy or non near by good detectors from the same sending band can be specified as the substitute in the new look up table Code change for adding an additional dimension of mirror side to the Band_21_b1 LUT to separate the coefficient of the two mirror sides for just like other thermal emissive so that the L1B code can calibrate Band scan to scan with mirror side dependency which leads better calibration result Changes which do not affect scientific when the EV data are not provided in this Crosstalk Correction will not be performed to the Band calibration data Changes which do not affect scientific and BB_500m in L1A Logic was added to turn off the or to spatial aggregation processes and the EV_250m_Aggr1km_RefSB and EV_500m_Aggr1km_RefSB fields were set to fill values when SDSs EV_250m and EV_500m are absent in L1A file Logic was added to skip the processing and turn off the output of the L1B QKM and HKM EV data when EV_250m and EV_500m are absent from L1A In this the new process avoids accessing and reading the and L1A EV skips and writing to the L1B and EV omits reading and subsampling SDSs from geolocation file and writing them to the L1B and omits writing metadata to L1B and EV and skips closing the L1A and L1B EV and SDSs Logic was added to turn off the L1B OBC output when the high resolution OBC SDSs are absent from L1A This is accomplished by skipping the openning the writing of metadata and the closing of the L1B OBC hdf which is Bit in the scan by scan bit QA has been changed Until now
Definition: HISTORY.txt:361
char * unix2isodate(double dtime, char zone)
Definition: unix2isodate.c:10
This should be set to the NetCDF standard name if exists for this product Create a function that computes your product edit get_myprod c add prototype to l12_proto h add get_myprod c to add_executable for l2gen and l3gen in CMakeLists txt Add an entry to the output routine to call your function edit prodgen c edit function prodgen() case CAT_myprod pbuf
const char * sensorId2InstrumentName(int sensorId)
Definition: sensorInfo.c:212
@ FT_L1HDF
Definition: filetype.h:20
#define MEMORY_ALLOCATION_ERROR
Definition: passthebuck.h:6
int32_t get_ctl_pts(int32_t npix, int32_t nscans, int32_t ictl[], int32_t jctl[])
#define PROJECT
Definition: OutFile.h:34
@ DS_HDF
Definition: dfutils.h:19
Definition: dfutils.h:28
int openl1_write(filehandle *l1file)
int AddSdsToVgroup(int32_t sd_id, int32_t v_id, const char *name)
Definition: hdf_utils.c:383
float * lon
int32 epix
Definition: l1_czcs_hdf.c:23
int32_t rdsensorinfo(int32_t, int32_t, const char *, void **)
Definition: rdsensorinfo.c:69
#define BANDW
Definition: l1.h:52
#define SEAWIFS
Definition: sensorDefs.h:12
int endDS(idDS ds_id)
Definition: wrapper.c:634
int16_t * tilt
Definition: l2bin.cpp:86
int i
Definition: decode_rs.h:71
void get_f0_thuillier_ext(int32_t wl, int32_t width, float *f0)
Definition: get_f0.c:137
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
#define HDF_FUNCTION_ERROR
Definition: passthebuck.h:7
int32_t nb
Definition: atrem_corl1.h:132