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.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 #ifdef BUILD_HISTORICAL
441  strncat(avhrrbird, xsatid2name(l1file->subsensorID) + 2, 2);
442 #endif
443  PTB(SetChrGA(ds_id, "platform", avhrrbird));
444  } else {
445  PTB(SetChrGA(ds_id, "platform", sensorId2PlatformName(l1file->sensorID)));
446  }
447  PTB(SetChrGA(ds_id, "Conventions", "CF-1.6 ACDD-1.3"));
448  PTB(SetChrGA(ds_id, "license", LICENSE));
449  PTB(SetChrGA(ds_id, "naming_authority", NAMING_AUTHORITY));
450  // create the id -
451  if (strcmp(l1_input->pversion, "Unspecified") != 0) {
452  strcpy(buf1, l1_input->pversion);
453  strcat(buf1, "/L1B/");
454  } else {
455  strcpy(buf1, "L1B/");
456  }
457  strcat(buf1, basename(l1file->name));
458  PTB(SetChrGA(ds_id, "id", buf1));
459 
460  time_t tnow;
461  time(&tnow);
462  strcpy(buf1, unix2isodate(tnow, 'G'));
463  PTB(SetChrGA(ds_id, "date_created", buf1));
464 
465  PTB(SetChrGA(ds_id, "standard_name_vocabulary", STDNAME_VOCABULARY));
466  PTB(SetChrGA(ds_id, "institution", INSTITUTION));
467  PTB(SetChrGA(ds_id, "creator_name", CREATOR_NAME));
468  PTB(SetChrGA(ds_id, "creator_email", CREATOR_EMAIL));
469  PTB(SetChrGA(ds_id, "creator_url", CREATOR_URL));
470  PTB(SetChrGA(ds_id, "project", PROJECT));
471  PTB(SetChrGA(ds_id, "publisher_name", PUBLISHER_NAME));
472  PTB(SetChrGA(ds_id, "publisher_url", PUBLISHER_URL));
473  PTB(SetChrGA(ds_id, "publisher_email", PUBLISHER_EMAIL));
474 
475  PTB(SetChrGA(ds_id, "processing_level", "L1B"));
476  PTB(SetChrGA(ds_id, "cdm_data_type", "swath"));
477  if (l1file->orbit_node_lon > -180.0 && l1file->orbit_node_lon < 180.0)
478  PTB(
479  SetF32GA(ds_id, "equatorCrossingLongitude",
480  l1file->orbit_node_lon));
481  if (l1file->orbit_number > 0)
482  PTB(SetI32GA(ds_id, "orbit_number", l1file->orbit_number));
483  if (l1file->node_crossing_time > 0) {
484  strcpy(buf1, unix2isodate(l1file->node_crossing_time, 'G'));
485  PTB(SetChrGA(ds_id, "equatorCrossingDateTime", buf1));
486  }
487 
488  PTB(SetChrGA(ds_id, "spatialResolution", l1file->spatialResolution));
489 
490  dm[0] = nctl;
491  strcpy((char *) dm_name[0], "pixel_control_points");
492  PTB(createDS(ds_id, sensorID, "cntl_pt_cols", dm, dm_name));
493  PTB(writeDS(ds_id, "cntl_pt_cols", ictl, 0, 0, 0, nctl, 0, 0));
494 
495  dm[0] = numScans;
496  strcpy((char *) dm_name[0], "number_of_lines");
497  PTB(createDS(ds_id, sensorID, "cntl_pt_rows", dm, dm_name));
498  PTB(writeDS(ds_id, "cntl_pt_rows", jctl, 0, 0, 0, numScans, 0, 0));
499 
500  // Processing Control attibutes
501  ds_id.fid = l1file->grp_id[5];
502  PTB(SetChrGA(ds_id, "software_name", "l1bgen"));
503  PTB(SetChrGA(ds_id, "software_version", soft_id));
504 
505  // Write input parameters metadata
506  ds_id.fid = l1file->grp_id[5];
507  int32_t grp_id_input_parms;
508  nc_def_grp(l1file->grp_id[5], "input_parameters", &grp_id_input_parms);
509  ds_id.fid = grp_id_input_parms;
510 
511  char *end_str;
512  char *tmp_parms = replace_ocroots(l1_input->input_parms);
513  char *token = strtok_r(tmp_parms, "\n", &end_str);
514  while (token != NULL) {
515  char *end_token;
516  char *name = strtok_r(token, "=", &end_token);
517  trimBlanks(name);
518  char *value = strtok_r(NULL, ";", &end_token);
519  trimBlanks(value);
520  if (name[0] != '#') {
521  PTB(SetChrGA(ds_id, name, value));
522  }
523  token = strtok_r(NULL, "\n", &end_str);
524  }
525  free(tmp_parms);
526 
527  }
528 
529  /* Create the scan-line SDSes */
530  char longname[64];
531  int32_t *wavelen;
532  int32_t np = numPixels;
533  int32_t nb = numBands;
534  int32_t nscan = nscans;
535 
536  /* Get sensor wavelengths */
537  if (rdsensorinfo(sensorID, evalmask, "Lambda", (void **) &wavelen) != nb) {
538  printf("-E- %s: Unable to determine sensor wavelengths\n", __FILE__);
539  exit(FATAL_ERROR);
540  }
541 
542  for (i = 0; i < nb; i++)
543  wavelength[i] = wavelen[bindx[i]];
544 
545  if (l1file->format == FT_L1BNCDF) {
546  ds_id.fid = l1file->grp_id[2];
547  strcpy((char *) dm_name[0], "number_of_lines");
548  } else {
549  strcpy((char *) dm_name[0], "Number of Scan Lines");
550  }
551  dm[0] = nscan;
552 
553  PTB(createDS(ds_id, sensorID, "year", dm, dm_name));
554  PTB(createDS(ds_id, sensorID, "day", dm, dm_name));
555  PTB(createDS(ds_id, sensorID, "msec", dm, dm_name));
556  PTB(createDS(ds_id, sensorID, "detnum", dm, dm_name));
557  PTB(createDS(ds_id, sensorID, "mside", dm, dm_name));
558  PTB(createDS(ds_id, sensorID, "slon", dm, dm_name));
559  PTB(createDS(ds_id, sensorID, "clon", dm, dm_name));
560  PTB(createDS(ds_id, sensorID, "elon", dm, dm_name));
561  PTB(createDS(ds_id, sensorID, "slat", dm, dm_name));
562  PTB(createDS(ds_id, sensorID, "clat", dm, dm_name));
563  PTB(createDS(ds_id, sensorID, "elat", dm, dm_name));
564  PTB(createDS(ds_id, sensorID, "csol_z", dm, dm_name));
565 
566  if (l1file->format == FT_L1BNCDF) {
567  ds_id.fid = l1file->grp_id[4];
568  strcpy((char *) dm_name[1], "pixels_per_line");
569  } else {
570  strcpy((char *) dm_name[1], "Pixels per Scan Line");
571  }
572  dm[1] = np;
573 
574  PTB(createDS(ds_id, sensorID, "longitude", dm, dm_name));
575  PTB(createDS(ds_id, sensorID, "latitude", dm, dm_name));
576  PTB(createDS(ds_id, sensorID, "solz", dm, dm_name));
577  PTB(createDS(ds_id, sensorID, "sola", dm, dm_name));
578  PTB(createDS(ds_id, sensorID, "senz", dm, dm_name));
579  PTB(createDS(ds_id, sensorID, "sena", dm, dm_name));
580  PTB(createDS(ds_id, sensorID, "tilt", dm, dm_name));
581 
582  if (l1file->format == FT_L1BNCDF)
583  ds_id.fid = l1file->grp_id[3];
584  for (i = 0; i < nb; i++) {
585  sprintf(rad_name, "Lt_%3d", wavelength[i]);
586  sprintf(longname, "Top of atmosphere %3d nm radiance", wavelength[i]);
587 
588  PTB(createDS(ds_id, sensorID, rad_name, dm, dm_name));
589  }
590 
591  PTB(createDS(ds_id, sensorID, "l2_flags", dm, dm_name));
592  ds_id.sid = selectDS(ds_id, "l2_flags");
593 
594  tmp_str[0] = '\0';
595  for (i = 0; i < L1_NFLAGS; i++) {
596  strcat(tmp_str, l2_flag_lname[i]);
597  flagbits[i] = pow(2, i);
598  if (i < L1_NFLAGS - 1)
599  strcat(tmp_str, " ");
600  /*
601  * Keep the old flag attribute set for HDF4 files
602  */
603  if (l1file->format == FT_L1HDF) {
604  PTB(
605  setAttr(ds_id, l2_flag_sname[i], nt_chr,
606  strlen(l2_flag_lname[i]) + 1,
607  (VOIDP) l2_flag_lname[i]));
608  }
609  }
610  PTB(setAttr(ds_id, "flag_masks", nt_i32, L1_NFLAGS, (VOIDP) flagbits));
611 
612  PTB(
613  setAttr(ds_id, "flag_meanings", nt_chr, strlen(tmp_str) + 1,
614  (VOIDP) tmp_str));
615  endaccessDS(ds_id);
616 
617  if (l1file->format == FT_L1BNCDF)
618  ds_id.fid = l1file->grp_id[0];
619  PTB(
620  writeDS(ds_id, "wavelength", Lambda, 0, 0, 0, numBands + numBandsIR,
621  0, 0));
622 
623  if (numBands > 0) {
624  PTB(writeDS(ds_id, "vcal_gain", Gain, 0, 0, 0, numBands, 0, 0));
625  PTB(writeDS(ds_id, "vcal_offset", Offset, 0, 0, 0, numBands, 0, 0));
626  PTB(writeDS(ds_id, "F0", Fobar, 0, 0, 0, numBands, 0, 0));
627  PTB(writeDS(ds_id, "k_oz", k_oz, 0, 0, 0, numBands, 0, 0));
628  PTB(writeDS(ds_id, "k_no2", k_no2, 0, 0, 0, numBands, 0, 0));
629  PTB(writeDS(ds_id, "Tau_r", Tau_r, 0, 0, 0, numBands, 0, 0));
630  }
631 
632  free(Gain);
633  free(Offset);
634  free(Fonom);
635  free(Fobar);
636  free(Tau_r);
637  free(k_oz);
638  free(k_no2);
639  free(ictl);
640  free(jctl);
641 
642  return (LIFE_IS_GOOD);
643 }
644 
645 /* -------------------------------------------------------- */
646 /* Create the SDSes for the scan-line data */
647 
648 /* -------------------------------------------------------- */
649 int writel1(filehandle *l1file, int32_t recnum, l1str *l1rec) {
650  int32_t i, j;
651  int16_t year, day;
652  double dsec;
653  unix2yds(l1rec->scantime, &year, &day, &dsec);
654  int32_t msec = (int32_t) (dsec * 1000.0);
655 
656  float *lon = (float *) l1rec->lon;
657  float *lat = (float *) l1rec->lat;
658 
659  void *pbuf;
660 
661  float *angledata[4];
662  angledata[0] = (float *) l1rec->solz;
663  angledata[1] = (float *) l1rec->senz;
664  angledata[2] = (float *) l1rec->sola;
665  angledata[3] = (float *) l1rec->sena;
666 
667  static char *anglenames[4] = {"solz", "senz", "sola", "sena"};
668  static productInfo_t *p_info[4];
669  if(!p_info[0]) {
670  for (i = 0; i < 4; i++) {
671  p_info[i] = allocateProductInfo();
672  if (!p_info[i]) {
673  printf("ERROR allocating Product Info memory for %s\n", anglenames[i]);
674  exit(EXIT_FAILURE);
675  }
676  if (!findProductInfo(anglenames[i], l1rec->l1file->sensorID, p_info[i])) {
677  printf("%s not found in XML product table\n", anglenames[i]);
678  exit(EXIT_FAILURE);
679  }
680  }
681  }
682 
683 
684  float *tilt = (float *) &(l1rec->tilt);
685  int32_t *l2_flags = (int32_t *) l1rec->flags;
686  int32_t *bindx = (int32_t *) l1file->bindx;
687 
688  static float *data = NULL;
689 
690  idDS ds_id;
691  ds_id.fid = l1file->sd_id;
692  ds_id.deflate = 0;
693  if (l1file->format == FT_L1BNCDF)
694  ds_id.fftype = DS_NCDF;
695  else
696  ds_id.fftype = DS_HDF;
697 
698  /* Write the scan-line data */
699  if (l1file->format == FT_L1BNCDF)
700  ds_id.fid = l1file->grp_id[2];
701 
702  int32_t tmpI = year;
703  PTB(writeDS(ds_id, "year", &tmpI, recnum, 0, 0, 1, 1, 1));
704  tmpI = day;
705  PTB(writeDS(ds_id, "day", &tmpI, recnum, 0, 0, 1, 1, 1));
706  PTB(writeDS(ds_id, "msec", &msec, recnum, 0, 0, 1, 1, 1));
707 
708  PTB(writeDS(ds_id, "detnum", &l1rec->detnum, recnum, 0, 0, 1, 1, 1));
709  PTB(writeDS(ds_id, "mside", &l1rec->mside, recnum, 0, 0, 1, 1, 1));
710 
711  PTB(writeDS(ds_id, "slon", &lon[0], recnum, 0, 0, 1, 1, 1));
712  PTB(writeDS(ds_id, "clon", &lon[cpix], recnum, 0, 0, 1, 1, 1));
713  PTB(writeDS(ds_id, "elon", &lon[numPixels - 1], recnum, 0, 0, 1, 1, 1));
714  PTB(writeDS(ds_id, "slat", &lat[0], recnum, 0, 0, 1, 1, 1));
715  PTB(writeDS(ds_id, "clat", &lat[cpix], recnum, 0, 0, 1, 1, 1));
716  PTB(writeDS(ds_id, "elat", &lat[numPixels - 1], recnum, 0, 0, 1, 1, 1));
717  PTB(writeDS(ds_id, "csol_z", &angledata[0][cpix], recnum, 0, 0, 1, 1, 1));
718 
719  /* Write navigation info */
720  if (l1file->format == FT_L1BNCDF)
721  ds_id.fid = l1file->grp_id[4];
722  PTB(writeDS(ds_id, "longitude", lon, recnum, 0, 0, 1, numPixels, 1));
723  PTB(writeDS(ds_id, "latitude", lat, recnum, 0, 0, 1, numPixels, 1));
724  /* Write out the angles solz, senz, sola, sena */
725  for (i = 0; i < 4; i++) {
726  pbuf = scale_sds(angledata[i], p_info[i], numPixels);
727  PTB(writeDS(ds_id, anglenames[i], pbuf, recnum, 0, 0, 1, numPixels, 1));
728  }
729 
730  PTB(writeDS(ds_id, "tilt", tilt, recnum, 0, 0, 1, 1, 1));
731 
732  /* Write the radiance data */
733  if (l1file->format == FT_L1BNCDF)
734  ds_id.fid = l1file->grp_id[3];
735  if (data == NULL) {
736  if ((data = (float *) malloc(numPixels * sizeof (float))) == NULL) {
737  fprintf(stderr, "-E- %s line %d: Memory allocation failure.\n",
738  __FILE__, __LINE__);
739  exit(FATAL_ERROR);
740  }
741  }
742 
743  for (i = 0; i < numBands; i++) {
744  sprintf(rad_name, "Lt_%3d", wavelength[i]);
745  for (j = 0; j < numPixels; j++) {
746  data[j] = (float) l1rec->Lt[j * numBands + bindx[i]] * 10.0;
747  }
748  PTB(writeDS(ds_id, rad_name, data, recnum, 0, 0, 1, numPixels, 0));
749  }
750 
751  /* Write the l2_flag data */
752  PTB(writeDS(ds_id, "l2_flags", l2_flags, recnum, 0, 0, 1, numPixels, 0));
753 
754  /* Write global attributes */
755  if (recnum == (numScans - 1)) {
756  if (l1file->format == FT_L1BNCDF)
757  ds_id.fid = l1file->sd_id;
758  scene_meta_write(ds_id);
759  }
760 
761  return (LIFE_IS_GOOD);
762 }
763 
764 /* -------------------------------------------------------- */
765 /* Finish access for the current file. */
766 
767 /* -------------------------------------------------------- */
768 void closel1_generic(filehandle *l1file) {
769  idDS ds_id;
770  ds_id.deflate = 0;
771  ds_id.fid = l1file->sd_id;
772  if (l1file->format == FT_L1BNCDF)
773  ds_id.fftype = DS_NCDF;
774  else
775  ds_id.fftype = DS_HDF;
776 
777  /* Define Vgroups */
778  if (l1file->format == FT_L1HDF)
780 
781  if (endDS(ds_id)) {
782  fprintf(stderr, "-E- %s line %d: SDend(%d) failed.\n",
783  __FILE__, __LINE__, sd_id);
784  }
785 }
786 
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:435
#define STDNAME_VOCABULARY
Definition: OutFile.h:31
#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:38
const char * sensorId2PlatformName(int sensorId)
Definition: sensorInfo.c:301
int32_t deflate
Definition: dfutils.h:32
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:33
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 L2GEN_PRODUCT_FILES in CMakeLists txt Add an entry to the output routine to call your function edit prodgen c edit function prodgen() case CAT_myprod pbuf
int32 nscan
Definition: l1_czcs_hdf.c:19
ds_format_t fftype
Definition: dfutils.h:31
#define NAMING_AUTHORITY
Definition: OutFile.h:26
int createDS(idDS ds_id, int sensorId, const char *sname, int32_t dm[3], const char dm_name[3][80])
Definition: wrapper.c:341
#define LICENSE
Definition: OutFile.h:25
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:37
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:617
char rad_name[8]
#define PUBLISHER_NAME
Definition: OutFile.h:36
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:558
#define INSTITUTION
Definition: OutFile.h:24
l1_input_t * l1_input
Definition: l1_options.c:9
#define FATAL_ERROR
Definition: swl0_parms.h:5
#define CREATOR_NAME
Definition: OutFile.h:32
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:472
char * replace_ocroots(const char *inStr)
@ DS_NCDF
Definition: dfutils.h:20
#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:323
#define basename(s)
Definition: l0chunk_modis.c:29
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
const char * xsatid2name(int xsatid)
Definition: l1_aci.c:1180
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:273
@ DS_WRITE
Definition: dfutils.h:25
int SetChrGA(idDS ds_id, const char *name, const char *value)
Definition: wrapper.c:233
#define CREATOR_URL
Definition: OutFile.h:34
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
const char * sensorId2InstrumentName(int sensorId)
Definition: sensorInfo.c:287
@ 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:35
@ 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
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:53
#define SEAWIFS
Definition: sensorDefs.h:12
int endDS(idDS ds_id)
Definition: wrapper.c:624
int16_t * tilt
Definition: l2bin.cpp:80
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:91
#define L1_NFLAGS
Definition: filehandle.h:21
int npix
Definition: get_cmp.c:28
#define HDF_FUNCTION_ERROR
Definition: passthebuck.h:7
int32_t nb
Definition: atrem_corl1.h:132