OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
put_smi.cpp
Go to the documentation of this file.
1 #include "netcdf.h" // Needs to be first to define netcdf stuff JMG
2 #include <stdlib.h>
3 #include "smi_map.h"
4 #include "meta_l3b.h"
5 #include "mapattr.h"
6 #include "smiinc.h"
7 #include "smigen_input.h"
8 #include "hdf5.h"
9 #include "hdf5utils.h"
10 #include "productInfo.h"
11 #include "sensorDefs.h"
12 #include "sensorInfo.h"
13 #include <timeutils.h>
14 #include <nc4utils.h>
15 
16 #define MAXVAL 255
17 
18 using namespace Hdf;
19 
20 intn setAttr(uint8 isHDF5, int32 obj_id, const char *attr_name, int32 data_type,
21  int32 count, VOIDP values) {
22  if (isHDF5 == 1) {
23  hid_t dtype = H5T_NATIVE_CHAR;
24  if (data_type == DFNT_CHAR && count > 1) dtype = H5T_STRING;
25  else if (data_type == DFNT_CHAR) dtype = H5T_NATIVE_CHAR;
26  else if (data_type == DFNT_UINT8) dtype = H5T_NATIVE_UCHAR;
27  else if (data_type == DFNT_INT16) dtype = H5T_NATIVE_SHORT;
28  else if (data_type == DFNT_UINT16) dtype = H5T_NATIVE_USHORT;
29  else if (data_type == DFNT_INT32) dtype = H5T_STD_I32LE;
30  else if (data_type == DFNT_UINT32) dtype = H5T_STD_U32LE;
31  else if (data_type == DFNT_FLOAT32) dtype = H5T_NATIVE_FLOAT;
32 
33  SetScalarH5A((hid_t) obj_id, attr_name, dtype, values);
34  return 0;
35  } else if (isHDF5 == 2) {
36  int dtype = NC_CHAR;
37 
38  if (data_type == DFNT_CHAR) dtype = NC_CHAR;
39  else if (data_type == DFNT_UINT8) dtype = NC_UBYTE;
40  else if (data_type == DFNT_INT16) dtype = NC_SHORT;
41  else if (data_type == DFNT_UINT16) dtype = NC_SHORT;
42  else if (data_type == DFNT_INT32) dtype = NC_INT;
43  else if (data_type == DFNT_UINT32) dtype = NC_INT;
44  else if (data_type == DFNT_FLOAT32) dtype = NC_FLOAT;
45 
46  int status = nc_put_att(obj_id, NC_GLOBAL, attr_name, dtype, count, values);
47  check_err(status, __LINE__, __FILE__);
48  } else {
49  return SDsetattr(obj_id, attr_name, data_type, count, (VOIDP) values);
50  }
51  return 0;
52 }
53 
54 
55 int32_t put_smi(char *l3m_path,
56  char *l3m_name,
57  uint8 *l3m_data,
58  int32 *dim_sizes,
59  float32 *lat_range,
60  float32 *lon_range,
61  char *measure,
62  char *scale_type,
63  float32 *si_used,
64  float32 *aminmax,
65  char *atype,
66  char *aopt,
67  char *infiles,
68  float32 *l3m_dminmax,
69  meta_l3bType *meta_l3b,
70  unsigned char *map_palette,
71  char *softid,
72  char *proc_con,
73  instr input,
74  char *precision,
75  /* float32 *si8_used,*/
76  uint8 *qual_byt,
77  uint8 isHDF5,
78  VOIDP fill_value);
79 
80 /*-----------------------------------------------------------------------------
81  Function: put_smi
82 
83  Returns: intn (status)
84  The return code is
85  FAIL (-1) If an I/O error occurs.
86  NOMATCH_ERR (-2) The routine checks l3m_name to find out for
87  which parameter the data is being written.
88  It tries to match a substring of the paramter
89  name with given l3m_name. If no match occurs
90  it returns NOMATCH_ERR (-2).
91  SUCCEED (0) If no errors occur.
92 
93  Description:
94  The function put_smi.c creates a level 3 Standard Map Image (SMI)
95  file with the file name given by l3m_path. Level 3 SMI file meta
96  data, map_palette, and data will be written. See "INTERFACE SPECIFICATIONS
97  FOR SeaWiFS OPERATIONAL PRODUCT INPUT AND OUTPUT AND SENSOR CALIBRATION
98  SOFTWARE", v3.3, dated 12th July 94, (By Fred Patt, Jim Firestone,
99  and Mike Darzi) and "SeaWiFS OPERATIONAL ARCHIVE PRODUCT
100  SPECIFICATIONS, v1.0 (Incomplete DRAFT version), dated 22 July 1994
101  (By F. Patt, J. Firestone, B. Schieber, L. Kumar, D. Ilg, and M. Darzi)
102  for details.
103 
104  Arguments: (in calling order)
105  Type Name I/O Description
106  ---- ---- --- -----------
107  char *l3m_path I directory path & file name for SMI product
108  char *l3m_name I name of the geophysical parameter to which
109  l3m_data corresponds
110  float *l3m_data I image data for parameter l3m_name
111  product
112  int32 *dim_sizes I #lines, #columns
113  float32 *lat_range I lats of the outside edges of the northernmost
114  and easternmost columns for l3mdata
115  float32 *lon_range I lons of the outside edges of the westernmost
116  and easternmost columns for l3m_data
117  char *measure I indicates whether it is mean, variance,
118  standard deviation, scenes or pixels
119  char *scale_type I whether was scaled LOG or LINEAR
120  float32 *si_used I slope & intercept used to scale data
121  char *infiles I name of input product
122  float32 *l3m_dminmax I data min/max found for L3-binned file
123  meta_l3bType *meta_l3b I meta data from input L3-binned file
124  unsigned char *map_palette I color map_palette
125  char *softid I SeaDAS software ID
126  char *proc_con I SeaDAS processing log - command line
127 
128  Notes: (see V4.2 I/O & V2.6 Product Specs for updated changes)
129 
130  Modification history:
131  Programmer Organization Date Description of change
132  -------------- ------------ -------- ---------------------
133  Lakshmi Kumar Hughes STX 12/16/93 Original development
134  Lakshmi Kumar Hughes STX 08/29/94 Revised version
135  Lakshmi Kumar Hughes STX 03/01/95 changed l3m data type to
136  float & added code to
137  scale the data to byte
138  Added some global attrs
139  Changed l3m_name "epsilon"
140  to "eps_68"
141  Karen Settle GSC 03/28/95 Generalized for SeaDAS.
142  Used meta data argument
143  for passing meta data from
144  parent, added arguments,
145  removed redundant arguments,
146  expanded maplists.h
147  include file.
148  --------------------------------------------------------------------------*/
149 int32_t put_smi(char *l3m_path, char*l3m_name, uint8 *l3m_data,
150  int32 *dim_sizes,
151  float32 *lat_range,
152  float32 *lon_range,
153  char *measure,
154  char *scale_type,
155  float32 *si_used,
156  float32 *aminmax,
157  char *atype,
158  char *aopt,
159  char *infiles,
160  float32 *l3m_dminmax,
161  meta_l3bType *meta_l3b,
162  uint8 *map_palette,
163  char *softid,
164  char *proc_con,
165  instr input,
166  char *precision,
167  /* float32 *si8_used,*/
168  uint8 *qual_byt,
169  uint8 isHDF5,
170  VOIDP fill_value
171  ) {
172  /*-----------------------------------------------------------------------*/
173  /*-----------------------------------------------------------------------*/
174 #include "smi_maplists.h"
175  int32 fid, sdfid, sdsid;
176  int32 i, rank = 2, mix, pal_ref;
177  int32 start[2] = {0, 0};
178 
179  char attr_buffer[MAXVAL];
180 
181  char *loc_path, *str, loc_measure[MAXVAL];
182  char data_center[MAXVAL];
183  float32 lat_step, lon_step, swlat, swlon;
184  hid_t h5fid, grp0;
185  int ncid, status;
186  float *lonarray;
187  float *latarray;
188 
189 
190  /*** Open/create output file in the given l3m_path */
191 
192  int32 valid_range[2] = {0, 2};
193 
194  if (isHDF5 == 1) {
195  h5fid = H5Fcreate(l3m_path, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
196  if (h5fid < 0) {
197  printf("\nError creating file %s \n", l3m_path);
198  exit(EXIT_FAILURE);
199  }
200  grp0 = H5Gopen1(h5fid, "/");
201  sdfid = h5fid;
202  } else if (isHDF5 == 2) {
203  status = nc_create(l3m_path, NC_NETCDF4, &ncid);
204  if (status != NC_NOERR) {
205  printf("\nError creating file %s \n", l3m_path);
206  exit(EXIT_FAILURE);
207  }
208  sdfid = ncid;
209  } else {
210  sdfid = SDstart(l3m_path, DFACC_CREATE);
211  fid = Hopen(l3m_path, DFACC_RDWR, 0);
212 
213  if (sdfid < 0 || fid < 0) {
214  printf("\nError creating file %s \n", l3m_path);
215  exit(EXIT_FAILURE);
216  }
217  }
218 
219  /* Get data center info */
220  strcpy(data_center, meta_l3b->data_center);
221 
222  /*-----------------------------------------------------------------------*/
223  /*** Write out global attributes */
224 
225  if ((loc_path = strrchr(l3m_path, '/')) != NULL)
226  loc_path++;
227  else
228  loc_path = l3m_path;
229 
230  // if (isHDF5 < 2) {
231  if (isHDF5 < 1) {
232  setAttr(isHDF5, sdfid, L3M_PNAME, DFNT_CHAR,
233  strlen(loc_path) + 1, (VOIDP) loc_path);
234 
235  setAttr(isHDF5, sdfid, L3M_SENSOR_NAME, DFNT_CHAR,
236  strlen(meta_l3b->sensor_name) + 1, (VOIDP) meta_l3b->sensor_name);
237 
238  setAttr(isHDF5, sdfid, L3M_SENSOR, DFNT_CHAR,
239  strlen(meta_l3b->sensor) + 1, (VOIDP) meta_l3b->sensor);
240 
241  sprintf(meta_l3b->title, "%s%s", meta_l3b->sensor_name,
242  " Level-3 Standard Mapped Image");
243  setAttr(isHDF5, sdfid, "Title", DFNT_CHAR,
244  strlen(meta_l3b->sensor_name) +
245  strlen(" Level-3 Standard Mapped Image") + 1,
246  meta_l3b->title);
247 
248  strcpy(meta_l3b->data_center, "NASA/GSFC OBPG");
249  setAttr(isHDF5, sdfid, L3M_DCENTER, DFNT_CHAR,
250  strlen(meta_l3b->data_center) + 1, meta_l3b->data_center);
251 
252  // setAttr(isHDF5, sdfid, L3M_STATION, DFNT_CHAR,
253  // strlen(meta_l3b->station) + 1, (VOIDP)meta_l3b->station);
254 
255  // ft_fld = meta_l3b->station_lat;
256  //setAttr(isHDF5, sdfid, L3M_STLAT, DFNT_FLOAT32, 1, (VOIDP)&ft_fld);
257 
258  //ft_fld = meta_l3b->station_lon;
259  //setAttr(isHDF5, sdfid, L3M_STLON, DFNT_FLOAT32, 1, (VOIDP)&ft_fld);
260 
261  setAttr(isHDF5, sdfid, L3M_MISSION, DFNT_CHAR,
262  strlen(meta_l3b->mission) + 1, (VOIDP) meta_l3b->mission);
263 
264  setAttr(isHDF5, sdfid, L3M_MSNCHAR, DFNT_CHAR,
265  strlen(meta_l3b->mission_char) + 1, (VOIDP) meta_l3b->mission_char);
266 
267  setAttr(isHDF5, sdfid, L3M_SNSCHAR, DFNT_CHAR,
268  strlen(meta_l3b->sensor_char) + 1, (VOIDP) meta_l3b->sensor_char);
269 
270  setAttr(isHDF5, sdfid, L3M_PRODTYPE, DFNT_CHAR,
271  strlen(meta_l3b->prod_type) + 1, (VOIDP) meta_l3b->prod_type);
272 
273  setAttr(isHDF5, sdfid, L3M_PVERSION, DFNT_CHAR,
274  strlen(input.pversion) + 1, (VOIDP) input.pversion);
275 
276  setAttr(isHDF5, sdfid, L3M_SOFTNM, DFNT_CHAR,
277  strlen(L3M_SOFTNM_VAL) + 1, (VOIDP) L3M_SOFTNM_VAL);
278 
279  setAttr(isHDF5, sdfid, L3M_SOFTVER, DFNT_CHAR,
280  strlen(L3M_SOFTVER_VAL) + 1, (VOIDP) L3M_SOFTVER_VAL);
281 
282 
283  get_time(meta_l3b->ptime);
284  setAttr(isHDF5, sdfid, L3M_PTIME, DFNT_CHAR,
285  strlen(meta_l3b->ptime) + 1, (VOIDP) meta_l3b->ptime);
286 
287  if ((str = strrchr(infiles, '/')) != NULL)
288  str++;
289  else
290  str = infiles;
291 
292  setAttr(isHDF5, sdfid, L3M_INFILES, DFNT_CHAR,
293  strlen(str) + 1, (VOIDP) str);
294 
295  setAttr(isHDF5, sdfid, L3M_PROCCON, DFNT_CHAR,
296  strlen(proc_con) + 1, (VOIDP) proc_con);
297 
298  setAttr(isHDF5, sdfid, L3M_INPARMS, DFNT_CHAR,
299  strlen(input.parms) + 1, (VOIDP) input.parms);
300 
301  setAttr(isHDF5, sdfid, L3M_FLAG_NAMES, DFNT_CHAR,
302  strlen(meta_l3b->flag_names) + 1, (VOIDP) meta_l3b->flag_names);
303 
305  double msec;
306  int32 smsec, emsec;
307  unix2yds(meta_l3b->startTime, &syear, &sday, &msec);
308  smsec = (int32) (msec * 1000.);
309  unix2yds(meta_l3b->endTime, &eyear, &eday, &msec);
310  emsec = (int32) (msec * 1000.);
311 
313  1, (VOIDP) & syear);
314 
316  1, (VOIDP) & sday);
317 
319  1, (VOIDP) & eyear);
320 
322  1, (VOIDP) & eday);
323 
324  strcpy(attr_buffer, ydhmsf(meta_l3b->startTime, 'G'));
325  setAttr(isHDF5, sdfid, L3M_STIME, DFNT_CHAR, strlen(attr_buffer) + 1, (VOIDP) attr_buffer);
326 
327  strcpy(attr_buffer, ydhmsf(meta_l3b->endTime, 'G'));
328  setAttr(isHDF5, sdfid, L3M_ETIME, DFNT_CHAR, strlen(attr_buffer) + 1, (VOIDP) attr_buffer);
329 
330 
331  setAttr(isHDF5, sdfid, L3M_SYEAR, DFNT_INT16, 1, (VOIDP) & syear);
332  setAttr(isHDF5, sdfid, L3M_SDAY, DFNT_INT16, 1, (VOIDP) & sday);
333  setAttr(isHDF5, sdfid, L3M_SMSEC, DFNT_INT32, 1, (VOIDP) & smsec);
334  setAttr(isHDF5, sdfid, L3M_EYEAR, DFNT_INT16, 1, (VOIDP) & eyear);
335  setAttr(isHDF5, sdfid, L3M_EDAY, DFNT_INT16, 1, (VOIDP) & eday);
336  setAttr(isHDF5, sdfid, L3M_EMSEC, DFNT_INT32, 1, (VOIDP) & emsec);
337  setAttr(isHDF5, sdfid, L3M_SORBIT, DFNT_INT32, 1, (VOIDP) & meta_l3b->start_orb);
338  setAttr(isHDF5, sdfid, L3M_EORBIT, DFNT_INT32, 1, (VOIDP) & meta_l3b->end_orb);
339  // setAttr(isHDF5, sdfid, L3M_ORBIT, DFNT_INT32, 1, (VOIDP)&meta_l3b->orbit);
340  setAttr(isHDF5, sdfid, L3M_MAPPROJ, DFNT_CHAR, strlen(L3M_MAPPROJ_VAL) + 1,
341  (VOIDP) L3M_MAPPROJ_VAL);
342  setAttr(isHDF5, sdfid, L3M_LATUNITS, DFNT_CHAR, strlen(L3M_LATUNITS_VAL) + 1,
343  (VOIDP) L3M_LATUNITS_VAL);
344  setAttr(isHDF5, sdfid, L3M_LONUNITS, DFNT_CHAR, strlen(L3M_LONUNITS_VAL) + 1,
345  (VOIDP) L3M_LONUNITS_VAL);
346 
347  /*** check validity of given latitude ranges-- 1st value should be greater
348  than the second one. If in error, output error message */
349  if (lat_range[0] <= lat_range[1]) {
350  printf("\nput_smi: Given latitude range is in error \n");
351  return FAIL;
352  }
353  setAttr(isHDF5, sdfid, L3M_NLAT, DFNT_FLOAT32, 1, (VOIDP) & lat_range[0]);
354  setAttr(isHDF5, sdfid, L3M_SLAT, DFNT_FLOAT32, 1, (VOIDP) & lat_range[1]);
355  setAttr(isHDF5, sdfid, L3M_WLON, DFNT_FLOAT32, 1, (VOIDP) & lon_range[0]);
356  setAttr(isHDF5, sdfid, L3M_ELON, DFNT_FLOAT32, 1, (VOIDP) & lon_range[1]);
357 
358  lat_step = (lat_range[0] - lat_range[1]) / dim_sizes[0];
359  setAttr(isHDF5, sdfid, L3M_LAT_STEP, DFNT_FLOAT32, 1, (VOIDP) & lat_step);
360 
361  if (lon_range[1] > lon_range[0])
362  lon_step = (lon_range[1] - lon_range[0]) / dim_sizes[1];
363  else
364  lon_step = (360 - lon_range[0] + lon_range[1]) / dim_sizes[1];
365  setAttr(isHDF5, sdfid, L3M_LON_STEP, DFNT_FLOAT32, 1, (VOIDP) & lon_step);
366 
367  swlat = (lat_range[1] + lat_step / 2.0);
368  swlon = (lon_range[0] + lon_step / 2.0);
369  setAttr(isHDF5, sdfid, L3M_SWLAT, DFNT_FLOAT32, 1, (VOIDP) & swlat);
370  setAttr(isHDF5, sdfid, L3M_SWLON, DFNT_FLOAT32, 1, (VOIDP) & swlon);
371 
372  int32 tmpInt = meta_l3b->data_bins;
373  setAttr(isHDF5, sdfid, L3M_DATABINS, DFNT_INT32, 1, (VOIDP) &tmpInt);
374  setAttr(isHDF5, sdfid, L3M_NROWS, DFNT_INT32, 1, (VOIDP) & dim_sizes[0]);
375  setAttr(isHDF5, sdfid, L3M_NCOLS, DFNT_INT32, 1, (VOIDP) & dim_sizes[1]);
376 
377  /*
378  setAttr(isHDF5, sdfid, L3M_PARAMETER,DFNT_CHAR, strlen(parmname_list[index])+1,
379  (VOIDP)parmname_list[index]);
380  */
381  setAttr(isHDF5, sdfid, L3M_PARAMETER, DFNT_CHAR, strlen(input.proddesc) + 1,
382  (VOIDP) input.proddesc);
383 
384  for (i = 0; i < (int32_t) strlen(measure); i++)
385  loc_measure[i] = measure[i];
386  loc_measure[i] = (char) NULL;
387 
388  mix = 0;
389  while ((strcmp(loc_measure, measure_list[mix]) != 0) &&
390  (mix < L3M_MEASURES)) {
391  mix++;
392  }
393  if (mix >= L3M_MEASURES) {
394  printf("\nput_smi: Error: measure - %s unrecognized\n", measure);
395  return FAIL;
396  }
397 
398  setAttr(isHDF5, sdfid, L3M_MEASURE, DFNT_CHAR, strlen(measure_list[mix]) + 1,
399  (VOIDP) measure_list[mix]);
400  /*
401  setAttr(isHDF5, sdfid, L3M_UNITS, DFNT_CHAR, strlen(unit_list[index]) + 1,
402  (VOIDP)unit_list[index]);
403  */
404  setAttr(isHDF5, sdfid, L3M_UNITS, DFNT_CHAR, strlen(input.units) + 1,
405  (VOIDP) input.units);
406 
407  if (strcmp(scale_type, "LOG") == 0) {
408  setAttr(isHDF5, sdfid, L3M_SCALING, DFNT_CHAR, strlen(L3M_LOG_SCALE) + 1,
409  (VOIDP) L3M_LOG_SCALE);
410  setAttr(isHDF5, sdfid, L3M_SC_EQN, DFNT_CHAR, strlen(L3M_LOG_EQN) + 1,
411  (VOIDP) L3M_LOG_EQN);
412  setAttr(isHDF5, sdfid, L3M_BASE, DFNT_FLOAT32, 1, (VOIDP) & base);
413  } else {
414  setAttr(isHDF5, sdfid, L3M_SCALING, DFNT_CHAR, strlen(L3M_LINEAR_SCALE) + 1,
415  (VOIDP) L3M_LINEAR_SCALE);
416  setAttr(isHDF5, sdfid, L3M_SC_EQN, DFNT_CHAR, strlen(L3M_LINEAR_EQN) + 1,
417  (VOIDP) L3M_LINEAR_EQN);
418  }
419 
420  setAttr(isHDF5, sdfid, L3M_SLOPE, DFNT_FLOAT32, 1, (VOIDP) & si_used[0]);
422  (VOIDP) & si_used[1]);
423 
424  setAttr(isHDF5, sdfid, L3M_MIN, DFNT_FLOAT32, 1, (VOIDP) & l3m_dminmax[0]);
425  setAttr(isHDF5, sdfid, L3M_MAX, DFNT_FLOAT32, 1, (VOIDP) & l3m_dminmax[1]);
426 
427  setAttr(isHDF5, sdfid, "Suggested Image Scaling Minimum", DFNT_FLOAT32, 1,
428  (VOIDP) & aminmax[0]);
429  setAttr(isHDF5, sdfid, "Suggested Image Scaling Maximum", DFNT_FLOAT32, 1,
430  (VOIDP) & aminmax[1]);
431  setAttr(isHDF5, sdfid, "Suggested Image Scaling Type", DFNT_CHAR, strlen(atype) + 1,
432  (VOIDP) atype);
433  setAttr(isHDF5, sdfid, "Suggested Image Scaling Applied", DFNT_CHAR, strlen(aopt) + 1,
434  (VOIDP) aopt);
435 
436  setAttr(isHDF5, sdfid, "_lastModified", DFNT_CHAR,
437  strlen(meta_l3b->ptime) + 1, (VOIDP) meta_l3b->ptime);
438 
439  } else {
440  // NETCDF4
441  setAttr(isHDF5, sdfid, "product_name", DFNT_CHAR,
442  strlen(loc_path) + 1, (VOIDP) loc_path);
443 
444  setAttr(isHDF5, sdfid, "instrument", DFNT_CHAR,
445  strlen(meta_l3b->sensor_name) + 1, (VOIDP) meta_l3b->sensor_name);
446 
447  sprintf(meta_l3b->title, "%s%s", meta_l3b->sensor_name,
448  " Level-3 Standard Mapped Image");
449  setAttr(isHDF5, sdfid, "title", DFNT_CHAR,
450  strlen(meta_l3b->sensor_name) +
451  strlen(" Level-3 Standard Mapped Image") + 1,
452  meta_l3b->title);
453 
454  char buf[2048];
455 
456  strcpy(buf, "Ocean Biology Processing Group (NASA/GSFC/OBPG)");
457  status = setAttr(isHDF5, sdfid, "project", DFNT_CHAR, strlen(buf) + 1, buf);
458 
459  if (strcmp(meta_l3b->mission, "") != 0)
460  setAttr(isHDF5, sdfid, "platform", DFNT_CHAR,
461  strlen(meta_l3b->mission) + 1, (VOIDP) meta_l3b->mission);
462 
463  setAttr(isHDF5, sdfid, "temporal_range", DFNT_CHAR,
464  strlen(meta_l3b->prod_type) + 1, (VOIDP) meta_l3b->prod_type);
465 
466  setAttr(isHDF5, sdfid, "processing_version", DFNT_CHAR,
467  strlen(input.pversion) + 1, (VOIDP) input.pversion);
468 
469  strcpy(meta_l3b->ptime, unix2isodate(time(NULL), 'G'));
470 
471  setAttr(isHDF5, sdfid, "date_created", DFNT_CHAR,
472  strlen(meta_l3b->ptime) + 1, (VOIDP) meta_l3b->ptime);
473 
474  setAttr(isHDF5, sdfid, "history", DFNT_CHAR,
475  strlen(proc_con) + 1, (VOIDP) proc_con);
476 
477  setAttr(isHDF5, sdfid, "l2_flag_names", DFNT_CHAR,
478  strlen(meta_l3b->flag_names) + 1, (VOIDP) meta_l3b->flag_names);
479 
480  strcpy(attr_buffer, unix2isodate(meta_l3b->startTime, 'G'));
481  setAttr(isHDF5, sdfid, "time_coverage_start", DFNT_CHAR, strlen(attr_buffer) + 1, attr_buffer);
482 
483  strcpy(attr_buffer, unix2isodate(meta_l3b->endTime, 'G'));
484  setAttr(isHDF5, sdfid, "time_coverage_end", DFNT_CHAR, strlen(attr_buffer) + 1, attr_buffer);
485 
486  setAttr(isHDF5, sdfid, "start_orbit_number", DFNT_INT32, 1, (VOIDP) & meta_l3b->start_orb);
487  setAttr(isHDF5, sdfid, "end_orbit_number", DFNT_INT32, 1, (VOIDP) & meta_l3b->end_orb);
488 
489  setAttr(isHDF5, sdfid, "map_projection", DFNT_CHAR, strlen(L3M_MAPPROJ_VAL) + 1,
490  (VOIDP) L3M_MAPPROJ_VAL);
491 
492  strcpy(attr_buffer, "degrees_north");
493  setAttr(isHDF5, sdfid, "latitude_units", DFNT_CHAR, strlen(attr_buffer) + 1,
494  (VOIDP) attr_buffer);
495 
496  strcpy(attr_buffer, "degrees_east");
497  setAttr(isHDF5, sdfid, "longitude_units", DFNT_CHAR, strlen(attr_buffer) + 1,
498  (VOIDP) attr_buffer);
499 
500  /*** check validity of given latitude ranges-- 1st value should be greater
501  than the second one. If in error, output error message */
502  if (lat_range[0] <= lat_range[1]) {
503  printf("\nput_smi: Given latitude range is in error \n");
504  return FAIL;
505  }
506 
507  setAttr(isHDF5, sdfid, "northernmost_latitude", DFNT_FLOAT32, 1, (VOIDP) & lat_range[0]);
508  setAttr(isHDF5, sdfid, "southernmost_latitude", DFNT_FLOAT32, 1, (VOIDP) & lat_range[1]);
509  setAttr(isHDF5, sdfid, "westernmost_longitude", DFNT_FLOAT32, 1, (VOIDP) & lon_range[0]);
510  setAttr(isHDF5, sdfid, "easternmost_longitude", DFNT_FLOAT32, 1, (VOIDP) & lon_range[1]);
511  setAttr(isHDF5, sdfid, "geospatial_lat_max", DFNT_FLOAT32, 1, (VOIDP) & lat_range[0]);
512  setAttr(isHDF5, sdfid, "geospatial_lat_min", DFNT_FLOAT32, 1, (VOIDP) & lat_range[1]);
513  setAttr(isHDF5, sdfid, "geospatial_lon_max", DFNT_FLOAT32, 1, (VOIDP) & lon_range[1]);
514  setAttr(isHDF5, sdfid, "geospatial_lon_min", DFNT_FLOAT32, 1, (VOIDP) & lon_range[0]);
515 
516  setAttr(isHDF5, sdfid, "grid_mapping_name", DFNT_CHAR, 18, (VOIDP) "latitude_longitude");
517 
518  lat_step = (lat_range[0] - lat_range[1]) / dim_sizes[0];
519  setAttr(isHDF5, sdfid, "latitude_step", DFNT_FLOAT32, 1, (VOIDP) & lat_step);
520 
521  if (lon_range[1] > lon_range[0])
522  lon_step = (lon_range[1] - lon_range[0]) / dim_sizes[1];
523  else
524  lon_step = (360 - lon_range[0] + lon_range[1]) / dim_sizes[1];
525  setAttr(isHDF5, sdfid, "longitude_step", DFNT_FLOAT32, 1, (VOIDP) & lon_step);
526 
527  if ((lonarray = (float *) malloc(dim_sizes[1] * sizeof (float))) == NULL) {
528  printf(
529  "-E- : Error allocating memory for lon array\n");
530  exit(EXIT_FAILURE);
531  }
532  if ((latarray = (float *) malloc(dim_sizes[0] * sizeof (float))) == NULL) {
533  printf(
534  "-E- : Error allocating memory for lat array\n");
535  exit(EXIT_FAILURE);
536  }
537  for (i = 0; i < dim_sizes[1]; i++) {
538  lonarray[i] = lon_range[0] + lon_step * i + lon_step / 2.0;
539  }
540  for (i = 0; i < dim_sizes[0]; i++) {
541  latarray[i] = lat_range[0] - lat_step * i - lat_step / 2.0;
542  }
543  swlat = (lat_range[1] + lat_step / 2.0);
544  swlon = (lon_range[0] + lon_step / 2.0);
545  setAttr(isHDF5, sdfid, "sw_point_latitude", DFNT_FLOAT32, 1, (VOIDP) & swlat);
546  setAttr(isHDF5, sdfid, "sw_point_longitude", DFNT_FLOAT32, 1, (VOIDP) & swlon);
547 
548  float geo_resolution;
549  char geospatial_units[8];
550  if (strcmp(input.resolution, "LAND") == 0) {
551  geo_resolution = 4.6;
552  strcpy(geospatial_units, "km");
553  } else if (strcmp(input.resolution, "9km") == 0) {
554  geo_resolution = 9.2;
555  strcpy(geospatial_units, "km");
556  } else if (strcmp(input.resolution, "18km") == 0) {
557  geo_resolution = 18.5;
558  strcpy(geospatial_units, "km");
559  } else if (strcmp(input.resolution, "4km") == 0) {
560  geo_resolution = 4.6;
561  strcpy(geospatial_units, "km");
562  } else if (strcmp(input.resolution, "2km") == 0) {
563  geo_resolution = 2.3;
564  strcpy(geospatial_units, "km");
565  } else if (strcmp(input.resolution, "1km") == 0) {
566  geo_resolution = 1.2;
567  strcpy(geospatial_units, "km");
568  } else if (strcmp(input.resolution, "hkm") == 0) {
569  geo_resolution = 575;
570  strcpy(geospatial_units, "m");
571  } else if (strcmp(input.resolution, "qkm") == 0) {
572  geo_resolution = 288;
573  strcpy(geospatial_units, "m");
574  } else if (strcmp(input.resolution, "36km") == 0) {
575  geo_resolution = 36;
576  strcpy(geospatial_units, "km");
577  } else if (strcmp(input.resolution, "90km") == 0) {
578  geo_resolution = 90;
579  strcpy(geospatial_units, "km");
580  } else if (strcmp(input.resolution, "1deg") == 0) {
581  geo_resolution = 1;
582  strcpy(geospatial_units, "deg");
583  } else if (strcmp(input.resolution, "hdeg") == 0) {
584  geo_resolution = 0.5;
585  strcpy(geospatial_units, "deg");
586  } else if (strcmp(input.resolution, "qdeg") == 0) {
587  geo_resolution = 0.25;
588  strcpy(geospatial_units, "deg");
589  } else if (strcmp(input.resolution, "10deg") == 0) {
590  geo_resolution = 10;
591  strcpy(geospatial_units, "deg");
592  } else if (strncmp(input.resolution, "udeg", 4) == 0) {
593  geo_resolution = (float) atof(&input.resolution[5]);
594  strcpy(geospatial_units, "deg");
595  } else if (strncmp(input.resolution, "ukm", 3) == 0) {
596  geo_resolution = (float) atof(&input.resolution[4]);
597  strcpy(geospatial_units, "km");
598  }
599 
600  setAttr(isHDF5, sdfid, "geospatial_lon_resolution", DFNT_FLOAT, 1, &geo_resolution);
601  setAttr(isHDF5, sdfid, "geospatial_lat_resolution", DFNT_FLOAT, 1, &geo_resolution);
602 
603 
604  setAttr(isHDF5, sdfid, "geospatial_lat_units", DFNT_CHAR,
605  strlen(geospatial_units) + 1, geospatial_units);
606 
607  setAttr(isHDF5, sdfid, "geospatial_lon_units", DFNT_CHAR,
608  strlen(geospatial_units) + 1, geospatial_units);
609 
610  sprintf(buf, "%3.2f %s", geo_resolution, geospatial_units);
611  setAttr(isHDF5, sdfid, "spatialResolution", DFNT_CHAR,
612  strlen(buf) + 1, buf);
613 
614  int32 tmpInt = meta_l3b->data_bins;
615  setAttr(isHDF5, sdfid, "data_bins", DFNT_INT32, 1, (VOIDP) &tmpInt);
616  setAttr(isHDF5, sdfid, "number_of_lines", DFNT_INT32, 1, (VOIDP) & dim_sizes[0]);
617  setAttr(isHDF5, sdfid, "number_of_columns", DFNT_INT32, 1, (VOIDP) & dim_sizes[1]);
618 
619  for (i = 0; i < (int32_t) strlen(measure); i++)
620  loc_measure[i] = measure[i];
621  loc_measure[i] = (char) NULL;
622 
623  mix = 0;
624  while ((strcmp(loc_measure, measure_list[mix]) != 0) &&
625  (mix < L3M_MEASURES)) {
626  mix++;
627  }
628  if (mix >= L3M_MEASURES) {
629  printf("\nput_smi: Error: measure - %s unrecognized\n", measure);
630  return FAIL;
631  }
632 
633  setAttr(isHDF5, sdfid, "measure", DFNT_CHAR, strlen(measure_list[mix]) + 1,
634  (VOIDP) measure_list[mix]);
635 
636  setAttr(isHDF5, sdfid, "data_minimum", DFNT_FLOAT32, 1, (VOIDP) & l3m_dminmax[0]);
637  setAttr(isHDF5, sdfid, "data_maximum", DFNT_FLOAT32, 1, (VOIDP) & l3m_dminmax[1]);
638 
639  setAttr(isHDF5, sdfid, "suggested_image_scaling_minimum", DFNT_FLOAT32, 1,
640  (VOIDP) & aminmax[0]);
641  setAttr(isHDF5, sdfid, "suggested_image_scaling_maximum", DFNT_FLOAT32, 1,
642  (VOIDP) & aminmax[1]);
643  setAttr(isHDF5, sdfid, "suggested_image_scaling_type", DFNT_CHAR, strlen(atype) + 1,
644  (VOIDP) atype);
645  setAttr(isHDF5, sdfid, "suggested_image_scaling_applied", DFNT_CHAR, strlen(aopt) + 1,
646  (VOIDP) aopt);
647 
648  setAttr(isHDF5, sdfid, "_lastModified", DFNT_CHAR,
649  strlen(meta_l3b->ptime) + 1, (VOIDP) meta_l3b->ptime);
650 
651  setAttr(isHDF5, sdfid, "Conventions", DFNT_CHAR, strlen("CF-1.6") + 1,
652  (VOIDP) "CF-1.6");
653 
654  setAttr(isHDF5, sdfid, "institution", DFNT_CHAR,
655  strlen("NASA Goddard Space Flight Center, Ocean Ecology Laboratory, Ocean Biology Processing Group") + 1,
656  (VOIDP) "NASA Goddard Space Flight Center, Ocean Ecology Laboratory, Ocean Biology Processing Group");
657 
658  char const *standard_name_vocabulary =
659  "NetCDF Climate and Forecast (CF) Metadata Convention";
660  strcpy(buf, standard_name_vocabulary);
661  status = setAttr(isHDF5, sdfid, "standard_name_vocabulary", DFNT_CHAR,
662  strlen(buf) + 1, buf);
663 
664  char const *Metadata_Conventions = "Unidata Dataset Discovery v1.0";
665  strcpy(buf, Metadata_Conventions);
666  status = setAttr(isHDF5, sdfid, "Metadata_Conventions", DFNT_CHAR, strlen(buf) + 1, buf);
667 
668  char const *naming_authority = "gov.nasa.gsfc.sci.oceandata";
669  strcpy(buf, naming_authority);
670  status = setAttr(isHDF5, sdfid, "naming_authority", DFNT_CHAR, strlen(buf) + 1, buf);
671  // create id
672  strcpy(buf, meta_l3b->pversion);
673  if (strcmp(meta_l3b->pversion, "Unspecified") != 0) {
674  strcpy(buf, meta_l3b->product_name);
675  strcat(buf, "/L3/");
676 
677  } else {
678  strcpy(buf, "L3/");
679  }
680  strcat(buf, meta_l3b->product_name);
681  status = setAttr(isHDF5, sdfid, "id", DFNT_CHAR, strlen(buf) + 1, buf);
682 
683  char const *license =
684  "http://science.nasa.gov/earth-science/earth-science-data/data-information-policy/";
685  strcpy(buf, license);
686  status = setAttr(isHDF5, sdfid, "license", DFNT_CHAR, strlen(buf) + 1, buf);
687 
688  strcpy(buf, "NASA/GSFC/OBPG");
689  status = setAttr(isHDF5, sdfid, "creator_name", DFNT_CHAR, strlen(buf) + 1, buf);
690  status = setAttr(isHDF5, sdfid, "publisher_name", DFNT_CHAR, strlen(buf) + 1, buf);
691 
692  strcpy(buf, "data@oceancolor.gsfc.nasa.gov");
693  status = setAttr(isHDF5, sdfid, "creator_email", DFNT_CHAR, strlen(buf) + 1, buf);
694  status = setAttr(isHDF5, sdfid, "publisher_email", DFNT_CHAR, strlen(buf) + 1, buf);
695 
696  strcpy(buf, "http://oceandata.sci.gsfc.nasa.gov");
697  status = setAttr(isHDF5, sdfid, "creator_url", DFNT_CHAR, strlen(buf) + 1, buf);
698  status = setAttr(isHDF5, sdfid, "publisher_url", DFNT_CHAR, strlen(buf) + 1, buf);
699 
700  strcpy(buf, "L3 Mapped");
701  status = setAttr(isHDF5, sdfid, "processing_level", DFNT_CHAR, strlen(buf) + 1, buf);
702 
703  strcpy(buf, "grid");
704  status = setAttr(isHDF5, sdfid, "cdm_data_type", DFNT_CHAR, strlen(buf) + 1, buf);
705 
706  strcpy(buf, "http://dx.doi.org");
707  status = setAttr(isHDF5, sdfid, "identifier_product_doi_authority", DFNT_CHAR,
708  strlen(buf) + 1, buf);
709 
710  if (strcmp(meta_l3b->sensor_name, "CZCS") == 0)
711  strcpy(buf, "10.5067/NIMBUS-7/CZCS_OC.2014.0");
712  if (strcmp(meta_l3b->sensor_name, "OCTS") == 0)
713  strcpy(buf, "10.5067/ADEOS/OCTS_OC.2014.0");
714  if (strcmp(meta_l3b->sensor_name, "SEAWIFS") == 0)
715  strcpy(buf, "10.5067/ORBVIEW-2/SEAWIFS_OC.2014.0");
716  if (strstr(meta_l3b->sensor_name, "MODIS") != NULL) {
717  if (strstr(meta_l3b->mission, "Aqua") != NULL)
718  strcpy(buf, "10.5067/AQUA/MODIS_OC.2014.0");
719  if (strstr(meta_l3b->mission, "Terra") != NULL)
720  strcpy(buf, "10.5067/TERRA/MODIS_OC.2014.0");
721  }
722 
723 
724  status = setAttr(isHDF5, sdfid, "identifier_product_doi", DFNT_CHAR,
725  strlen(buf) + 1, buf);
726 
727  char const *keyword_oc =
728  "Oceans > Ocean Chemistry > Chlorophyll; Oceans > Ocean Optics > Ocean Color";
729  char const *keyword_sst =
730  "Oceans > Ocean Temperature > Sea Surface Temperature";
731 
732  char const *keyword_salinity =
733  "SURFACE SALINITY, SALINITY, AQUARIUS, Jet Propulsion Laboratory, NASA, http://aquarius.nasa.gov/, AQUARIUS SAC-D, Aquarius Scatterometer, Aquarius Radiometer";
734 
735  if (strstr(input.prod, "sst") != NULL)
736  strcpy(buf, keyword_sst);
737  else
738  strcpy(buf, keyword_oc);
739 
740  if (strstr(input.prod, "SSS") != NULL)
741  strcpy(buf, keyword_salinity);
742 
743  status = setAttr(isHDF5, sdfid, "keywords", DFNT_CHAR, strlen(buf) + 1, buf);
744 
745  char const *keywords_vocabulary =
746  "NASA Global Change Master Directory (GCMD) Science Keywords";
747  strcpy(buf, keywords_vocabulary);
748  status = setAttr(isHDF5, sdfid, "keywords_vocabulary", DFNT_CHAR,
749  strlen(buf) + 1, buf);
750 
751  int grpid;
752  if (isHDF5 == 2)
753  nc_def_grp(sdfid, "processing_control", &grpid);
754  else
755  grpid = sdfid;
756 
757  setAttr(isHDF5, grpid, "software_name", DFNT_CHAR,
758  strlen(L3M_SOFTNM_VAL) + 1, (VOIDP) L3M_SOFTNM_VAL);
759 
760  setAttr(isHDF5, grpid, "software_version", DFNT_CHAR,
761  strlen(L3M_SOFTVER_VAL) + 1, (VOIDP) L3M_SOFTVER_VAL);
762 
763  if ((str = strrchr(infiles, '/')) != NULL)
764  str++;
765  else
766  str = infiles;
767  setAttr(isHDF5, grpid, "source", DFNT_CHAR,
768  strlen(str) + 1, (VOIDP) str);
769 
770  // setAttr(isHDF5, grpid, "l2_flag_names", DFNT_CHAR,
771  // strlen(meta_l3b->flag_names) + 1, (VOIDP)meta_l3b->flag_names);
772 
773 
774  if (isHDF5 == 2) {
775  nc_def_grp(grpid, "input_parameters", &grpid);
776  char *end_str;
777  char *token = strtok_r(input.parms, "|", &end_str);
778  char tmp_buf[2048];
779  while (token != NULL) {
780  char *end_token;
781  strcpy(tmp_buf, token);
782  char *name = strtok_r(token, "=", &end_token);
783  for (uint32_t i = 0; i < strlen(name); i++) {
784  if (name[i] == ' ') {
785  name[i] = 0;
786  break;
787  }
788  }
789  strcpy(tmp_buf, strtok_r(NULL, "|", &end_token));
790 
791  setAttr(isHDF5, grpid, name, DFNT_CHAR,
792  strlen(tmp_buf), (VOIDP) & tmp_buf[1]);
793  token = strtok_r(NULL, "|", &end_str);
794  }
795  }
796  }
797  // HDF5
798  if (isHDF5 == 1) {
799  hid_t dataset, datatype;
800  hsize_t dims[2] = {(hsize_t) dim_sizes[0], (hsize_t) dim_sizes[1]};
801  hid_t dataspace = H5Screate_simple(rank, dims, NULL);
802 
803  if (strcmp(precision, "F") == 0) {
804  datatype = H5T_NATIVE_FLOAT;
805  } else if (strcmp(precision, "I") == 0) {
806  datatype = H5T_NATIVE_USHORT;
807  } else {
808  datatype = H5T_NATIVE_UCHAR;
809  }
810 
811  if ((dataset = H5Dcreate1(grp0, SDS_NAME, datatype, dataspace,
812  H5P_DEFAULT)) < 0) {
813  printf("\nput_smi: H5Dcreate call to create %s is unsuccessful",
814  SDS_NAME);
815  return FAIL;
816  }
817 
818  sdsid = dataset;
819 
820  if ((H5Dwrite(dataset, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT,
821  (VOIDP) l3m_data)) < 0) {
822  printf("\nput_smi: H5Dwrite unsuccessful\n");
823  return FAIL;
824  }
825 
826  if (strcmp(scale_type, "LOG") == 0) {
827  setAttr(isHDF5, sdsid, L3M_SCALING, DFNT_CHAR, strlen(L3M_LOG_SCALE) + 1,
828  (VOIDP) L3M_LOG_SCALE);
829  setAttr(isHDF5, sdsid, L3M_SC_EQN, DFNT_CHAR, strlen(L3M_LOG_EQN) + 1,
830  (VOIDP) L3M_LOG_EQN);
831  setAttr(isHDF5, sdsid, L3M_BASE, DFNT_FLOAT32, 1, (VOIDP) & base);
832  } else {
833  setAttr(isHDF5, sdsid, L3M_SCALING, DFNT_CHAR, strlen(L3M_LINEAR_SCALE) + 1,
834  (VOIDP) L3M_LINEAR_SCALE);
835  setAttr(isHDF5, sdsid, L3M_SC_EQN, DFNT_CHAR, strlen(L3M_LINEAR_EQN) + 1,
836  (VOIDP) L3M_LINEAR_EQN);
837  }
838 
839  setAttr(isHDF5, sdsid, L3M_SLOPE, DFNT_FLOAT32, 1, (VOIDP) & si_used[0]);
841  (VOIDP) & si_used[1]);
842 
843  setAttr(isHDF5, sdsid, "_FillValue", DFNT_FLOAT32, 1, fill_value);
844 
845  setAttr(isHDF5, sdsid, "scale_factor", DFNT_FLOAT32, 1, (VOIDP) & si_used[0]);
846  setAttr(isHDF5, sdsid, "add_offset", DFNT_FLOAT32, 1,
847  (VOIDP) & si_used[1]);
848 
849  H5Sclose(dataspace);
850  H5Dclose(dataset);
851 
852  // write map_palette
853  dims[0] = 3;
854  dims[1] = 256;
855  dataspace = H5Screate_simple(2, dims, NULL);
856  if ((dataset = H5Dcreate1(grp0, "palette", H5T_NATIVE_UCHAR, dataspace,
857  H5P_DEFAULT)) < 0) {
858  printf("\nput_smi: H5Dcreate call to create %s is unsuccessful",
859  "palette");
860  return FAIL;
861  }
862 
863  if ((H5Dwrite(dataset, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL, H5P_DEFAULT,
864  (VOIDP) map_palette)) < 0) {
865  printf("\nput_smi: H5Dwrite unsuccessful\n");
866  return FAIL;
867  }
868 
869  // close down interfaces and close file
870  H5Fclose(h5fid);
871 
872  } else if (isHDF5 == 2) {
873  // NETCDF4
874  int dimids[2];
875 
876  status = nc_def_dim(sdfid, "lat", dim_sizes[0], &dimids[0]);
877  check_err(status, __LINE__, __FILE__);
878 
879  status = nc_def_dim(sdfid, "lon", dim_sizes[1], &dimids[1]);
880  check_err(status, __LINE__, __FILE__);
881 
882  int datatype;
883  if (strcmp(precision, "F") == 0) {
884  datatype = NC_FLOAT;
885  } else if (strcmp(precision, "I") == 0) {
886  datatype = NC_USHORT;
887  } else {
888  datatype = NC_UBYTE;
889  }
890 
891  int varid;
892  /*
893  * removed geophysical_data group to make SMI files more CF compliant...
894  *
895  * status = nc_def_grp( sdfid, "geophysical_data", &grpid);
896  */
897  status = nc_def_var(sdfid, l3m_name, datatype, 2, dimids, &varid);
898  check_err(status, __LINE__, __FILE__);
899 
900  /* Set compression */
901  if (input.deflate > 0) {
902  /* First set chunking */
903  size_t chunksize[2] = {64, 64};
904  status = nc_def_var_chunking(sdfid, varid, NC_CHUNKED, chunksize);
905  check_err(status, __LINE__, __FILE__);
906  if (status != NC_NOERR) exit(1);
907 
908  /* Now we can set compression */
909  status = nc_def_var_deflate(sdfid, varid, NC_NOSHUFFLE, 1,
910  input.deflate);
911  check_err(status, __LINE__, __FILE__);
912  if (status != NC_NOERR) exit(1);
913  }
914 
915  static productInfo_t *p_info;
916  p_info = allocateProductInfo();
917 
918  int sensorId = sensorName2SensorId(meta_l3b->sensor_name);
919  if (sensorId == -1)
920  sensorId = instrumentPlatform2SensorId(meta_l3b->sensor_name, meta_l3b->mission);
921  if (sensorId == -1) {
922  printf("%s is unknown\n", meta_l3b->sensor_name);
923  exit(EXIT_FAILURE);
924 
925  }
926  if (!findProductInfo(l3m_name, sensorId, p_info)) {
927  printf("%s not found in XML product table\n", l3m_name);
928  exit(EXIT_FAILURE);
929  }
930 
931  status = nc_put_att_text(sdfid, varid, "long_name",
932  strlen(p_info->description) + 1,
933  p_info->description);
934 
935  status = nc_put_att_text(sdfid, varid, "units",
936  strlen(p_info->units) + 1,
937  p_info->units);
938 
939 
940  if (p_info->standardName != NULL) {
941  status = nc_put_att_text(sdfid, varid, "standard_name",
942  strlen(p_info->standardName) + 1,
943  p_info->standardName);
944  }
945 
946  if (datatype == NC_SHORT) {
947  short fv_i16 = (int) p_info->fillValue;
948  status = nc_put_att(sdfid, varid, "_FillValue", NC_SHORT, 1, &fv_i16);
949 
950  short int valid;
951  valid = p_info->validMin;
952  status = nc_put_att_short(sdfid, varid, "valid_min", NC_SHORT, 1,
953  &valid);
954  valid = p_info->validMax;
955  status = nc_put_att_short(sdfid, varid, "valid_max", NC_SHORT, 1,
956  &valid);
957 
958 
959  } else if (datatype == NC_INT) {
960  float fv_i = (int) p_info->fillValue;
961  status = nc_put_att(sdfid, varid, "_FillValue", NC_INT, 1, &fv_i);
962 
963  int valid;
964  valid = p_info->validMin;
965  status = nc_put_att_int(sdfid, varid, "valid_min", NC_INT, 1,
966  &valid);
967  valid = p_info->validMax;
968  status = nc_put_att_int(sdfid, varid, "valid_max", NC_INT, 1,
969  &valid);
970 
971 
972  } else if (datatype == NC_FLOAT) {
973  float fv_f32 = (float) p_info->fillValue;
974  status = nc_put_att(sdfid, varid, "_FillValue", NC_FLOAT, 1, &fv_f32);
975 
976  float valid;
977  valid = p_info->validMin;
978  status = nc_put_att_float(sdfid, varid, "valid_min", NC_FLOAT, 1,
979  &valid);
980  valid = p_info->validMax;
981  status = nc_put_att_float(sdfid, varid, "valid_max", NC_FLOAT, 1,
982  &valid);
983  }
984  check_err(status, __LINE__, __FILE__);
985 
986 
987  status = nc_put_att_text(sdfid, varid, "display_scale",
988  strlen(p_info->displayScale) + 1,
989  p_info->displayScale);
990 
991  status = nc_put_att_double(sdfid, varid, "display_min", NC_DOUBLE, 1,
992  &p_info->displayMin);
993  status = nc_put_att_double(sdfid, varid, "display_max", NC_DOUBLE, 1,
994  &p_info->displayMax);
995 
996  status = nc_put_att_float(sdfid, varid, "scale_factor", NC_FLOAT, 1,
997  &si_used[0]);
998  status = nc_put_att_float(sdfid, varid, "add_offset", NC_FLOAT, 1,
999  &si_used[1]);
1000 
1001  if (&p_info->reference[0] != 0)
1002  status = nc_put_att_text(sdfid, varid, "reference",
1003  strlen(p_info->reference) + 1,
1004  p_info->reference);
1005 
1006  if (&p_info->comment[0] != 0)
1007  status = nc_put_att_text(sdfid, varid, "comment",
1008  strlen(p_info->comment) + 1,
1009  p_info->comment);
1010 
1011  status = nc_put_var(sdfid, varid, l3m_data);
1012  check_err(status, __LINE__, __FILE__);
1013 
1014  if (qual_byt != NULL) {
1015  int qualid;
1016  char l3m_qualname[128];
1017  strcpy(l3m_qualname, "qual_");
1018  strcat(l3m_qualname, l3m_name);
1019  status = nc_def_var(sdfid, l3m_qualname, NC_BYTE, 2, dimids, &qualid);
1020  check_err(status, __LINE__, __FILE__);
1021 
1022  status = nc_put_var(sdfid, qualid, qual_byt);
1023  check_err(status, __LINE__, __FILE__);
1024  }
1025 
1026  /*
1027  * Add lon and lat vectors
1028  */
1029  //Lat
1030 
1031  status = nc_def_var(sdfid, "lat", NC_FLOAT, 1, &dimids[0], &varid);
1032  check_err(status, __LINE__, __FILE__);
1033  if (!findProductInfo("lat", sensorId, p_info)) {
1034  printf("%s not found in XML product table\n", l3m_name);
1035  exit(EXIT_FAILURE);
1036  }
1037  status = nc_put_att_text(sdfid, varid, "long_name",
1038  strlen(p_info->description) + 1,
1039  p_info->description);
1040 
1041  status = nc_put_att_text(sdfid, varid, "units",
1042  strlen(p_info->units) + 1,
1043  p_info->units);
1044 
1045 
1046  if (p_info->standardName != NULL) {
1047  status = nc_put_att_text(sdfid, varid, "standard_name",
1048  strlen(p_info->standardName) + 1,
1049  p_info->standardName);
1050  }
1051  float fv_f32 = (float) p_info->fillValue;
1052  status = nc_put_att(sdfid, varid, "_FillValue", NC_FLOAT, 1, &fv_f32);
1053  float valid;
1054  valid = p_info->validMin;
1055  status = nc_put_att_float(sdfid, varid, "valid_min", NC_FLOAT, 1,
1056  &valid);
1057  valid = p_info->validMax;
1058  status = nc_put_att_float(sdfid, varid, "valid_max", NC_FLOAT, 1,
1059  &valid);
1060  status = nc_put_var(sdfid, varid, latarray);
1061  check_err(status, __LINE__, __FILE__);
1062 
1063  //Lon
1064  status = nc_def_var(sdfid, "lon", NC_FLOAT, 1, &dimids[1], &varid);
1065  check_err(status, __LINE__, __FILE__);
1066  if (!findProductInfo("lon", sensorId, p_info)) {
1067  printf("%s not found in XML product table\n", l3m_name);
1068  exit(EXIT_FAILURE);
1069  }
1070  status = nc_put_att_text(sdfid, varid, "long_name",
1071  strlen(p_info->description) + 1,
1072  p_info->description);
1073 
1074  status = nc_put_att_text(sdfid, varid, "units",
1075  strlen(p_info->units) + 1,
1076  p_info->units);
1077 
1078 
1079  if (p_info->standardName != NULL) {
1080  status = nc_put_att_text(sdfid, varid, "standard_name",
1081  strlen(p_info->standardName) + 1,
1082  p_info->standardName);
1083  }
1084  fv_f32 = (float) p_info->fillValue;
1085  status = nc_put_att(sdfid, varid, "_FillValue", NC_FLOAT, 1, &fv_f32);
1086  valid = p_info->validMin;
1087  status = nc_put_att_float(sdfid, varid, "valid_min", NC_FLOAT, 1,
1088  &valid);
1089  valid = p_info->validMax;
1090  status = nc_put_att_float(sdfid, varid, "valid_max", NC_FLOAT, 1,
1091  &valid);
1092  status = nc_put_var(sdfid, varid, lonarray);
1093  check_err(status, __LINE__, __FILE__);
1094 
1095  free(latarray);
1096  free(lonarray);
1097 
1098  // write map_palette
1099  status = nc_def_dim(sdfid, "rgb", 3, &dimids[0]);
1100  check_err(status, __LINE__, __FILE__);
1101 
1102  status = nc_def_dim(sdfid, "eightbitcolor", 256, &dimids[1]);
1103  check_err(status, __LINE__, __FILE__);
1104 
1105  status = nc_def_var(sdfid, "palette", NC_UBYTE, 2, dimids, &varid);
1106  check_err(status, __LINE__, __FILE__);
1107 
1108  status = nc_put_var(sdfid, varid, map_palette);
1109  check_err(status, __LINE__, __FILE__);
1110  // close the file
1111  status = nc_close(sdfid);
1112  check_err(status, __LINE__, __FILE__);
1113 
1114  } else {
1115  // HDF4
1116  /*-----------------------------------------------------------------------*/
1117  /*** write SDS */
1118  if (strcmp(precision, "F") == 0) {
1119  if ((sdsid = SDcreate(sdfid, SDS_NAME, DFNT_FLOAT32, rank, dim_sizes)) < 0) {
1120  printf("\nput_smi: SDcreate call to create %s is unsuccessful",
1121  SDS_NAME);
1122  return FAIL;
1123  }
1124  setAttr(isHDF5, sdsid, "Fill", DFNT_FLOAT32, 1, fill_value);
1125  } else if (strcmp(precision, "I") == 0) {
1126  if ((sdsid = SDcreate(sdfid, SDS_NAME, DFNT_UINT16, rank, dim_sizes)) < 0) {
1127  printf("\nput_smi: SDcreate call to create %s is unsuccessful",
1128  SDS_NAME);
1129  return FAIL;
1130  }
1131  setAttr(isHDF5, sdsid, "Fill", DFNT_UINT16, 1, fill_value);
1132  } else {
1133  if ((sdsid = SDcreate(sdfid, SDS_NAME, DFNT_UINT8, rank, dim_sizes)) < 0) {
1134  printf("\nput_smi: SDcreate call to create %s is unsuccessful",
1135  SDS_NAME);
1136  return FAIL;
1137  }
1138  setAttr(isHDF5, sdsid, "Fill", DFNT_UINT8, 1, fill_value);
1139  }
1140 
1141  if ((SDwritedata(sdsid, start, NULL, dim_sizes, (VOIDP) l3m_data)) < 0) {
1142  printf("\nput_smi: SDwritedata unsuccessful\n");
1143  return FAIL;
1144  }
1145 
1146  if (strcmp(scale_type, "LOG") == 0) {
1147  setAttr(isHDF5, sdsid, L3M_SCALING, DFNT_CHAR, strlen(L3M_LOG_SCALE) + 1,
1148  (VOIDP) L3M_LOG_SCALE);
1149  setAttr(isHDF5, sdsid, L3M_SC_EQN, DFNT_CHAR, strlen(L3M_LOG_EQN) + 1,
1150  (VOIDP) L3M_LOG_EQN);
1151  setAttr(isHDF5, sdsid, L3M_BASE, DFNT_FLOAT32, 1, (VOIDP) & base);
1152  } else {
1153  setAttr(isHDF5, sdsid, L3M_SCALING, DFNT_CHAR, strlen(L3M_LINEAR_SCALE) + 1,
1154  (VOIDP) L3M_LINEAR_SCALE);
1155  setAttr(isHDF5, sdsid, L3M_SC_EQN, DFNT_CHAR, strlen(L3M_LINEAR_EQN) + 1,
1156  (VOIDP) L3M_LINEAR_EQN);
1157  }
1158 
1159  setAttr(isHDF5, sdsid, L3M_SLOPE, DFNT_FLOAT32, 1, (VOIDP) & si_used[0]);
1161  (VOIDP) & si_used[1]);
1162 
1163  SDendaccess(sdsid);
1164 
1165  if (qual_byt != NULL) {
1166  if ((sdsid = SDcreate(sdfid, "l3m_qual", DFNT_UINT8, rank, dim_sizes)) < 0) {
1167  printf("\nput_smi: SDcreate call to create %s is unsuccessful",
1168  SDS_NAME);
1169  return FAIL;
1170  }
1171 
1172  if ((SDwritedata(sdsid, start, NULL, dim_sizes, (VOIDP) qual_byt)) < 0) {
1173  printf("\nput_smi: SDwritedata unsuccessful (qual_byt)\n");
1174  return FAIL;
1175  }
1176 
1177  setAttr(isHDF5, sdsid, "valid_range", DFNT_INT32, 2, (VOIDP) & valid_range[0]);
1178 
1179  SDendaccess(sdsid);
1180  }
1181 
1182 
1183 
1184  /*-----------------------------------------------------------------------*/
1185  /* write map_palette */
1186 
1187  if ((DFPaddpal(l3m_path, (VOIDP) map_palette)) < 0) {
1188  fprintf(stderr, "put_smi: Error writing map_palette.\n");
1189  return FAIL;
1190  }
1191 
1192  if ((pal_ref = DFPlastref()) > 0) {
1193  if ((DFANputlabel(l3m_path, DFTAG_IP8, pal_ref, (char*) "palette")) < 0) {
1194  printf("\nput_smi: Error writing palette label\n");
1195  }
1196  }
1197 
1198  /*-----------------------------------------------------------------------*/
1199  /*** close down interfaces and close file */
1200  SDend(sdfid);
1201  Hclose(fid);
1202  }
1203 
1204  // free(attr_buffer);
1205  return SUCCEED;
1206 }
1207 
#define L3M_LATUNITS
Definition: mapattr.h:67
char * ydhmsf(double dtime, char zone)
Definition: ydhmsf.c:12
#define L3M_SOFTVER_VAL
Definition: smiinc.h:5
integer, parameter int16
Definition: cubeio.f90:3
#define L3M_SOFTVER
Definition: mapattr.h:35
char product_name[SM_ATTRSZ]
Definition: meta_l3b.h:16
#define L3M_PEDAY
Definition: mapattr.h:50
int16 eday
Definition: l1_czcs_hdf.c:17
uint8_t isHDF5
Definition: get_l3m.c:8
#define L3M_NLAT
Definition: mapattr.h:71
Definition: bin_io.cpp:23
#define L3M_WLON
Definition: mapattr.h:75
#define L3M_INPARMS
Definition: mapattr.h:40
#define L3M_NCOLS
Definition: mapattr.h:92
int status
Definition: l1_czcs_hdf.c:32
#define L3M_INFILES
Definition: mapattr.h:37
int instrumentPlatform2SensorId(const char *instrument, const char *platform)
Definition: sensorInfo.c:302
#define L3M_SC_EQN
Definition: mapattr.h:99
void check_err(const int stat, const int line, const char *file)
Definition: nc4utils.c:35
#define L3M_LOG_SCALE
Definition: mapattr.h:97
#define L3M_MEASURES
Definition: smiinc.h:9
#define FAIL
Definition: ObpgReadGrid.h:18
#define NULL
Definition: decode_rs.h:63
char mission[SM_ATTRSZ]
Definition: meta_l3b.h:21
#define L3M_MAX
Definition: mapattr.h:106
#define L3M_LAT_STEP
Definition: mapattr.h:79
#define L3M_SORBIT
Definition: mapattr.h:60
#define L3M_MISSION
Definition: mapattr.h:19
char sensor_char[SM_ATTRSZ]
Definition: meta_l3b.h:24
#define L3M_LON_STEP
Definition: mapattr.h:80
#define L3M_SCALING
Definition: mapattr.h:96
int32_t start_orb
Definition: meta_l3b.h:42
float32 base
Definition: maplists.h:106
#define L3M_LONUNITS
Definition: mapattr.h:69
int sensorName2SensorId(const char *name)
Definition: sensorInfo.c:268
int32 * msec
Definition: l1_czcs_hdf.c:31
#define L3M_EDAY
Definition: mapattr.h:57
int16 eyear
Definition: l1_czcs_hdf.c:17
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
#define L3M_DCENTER
Definition: mapattr.h:11
int syear
Definition: l1_czcs_hdf.c:15
#define L3M_LINEAR_SCALE
Definition: mapattr.h:98
#define L3M_MEASURE
Definition: mapattr.h:93
char flag_names[SM_ATTRSZ]
Definition: meta_l3b.h:37
int32 smsec
Definition: l1_czcs_hdf.c:16
#define L3M_PNAME
Definition: mapattr.h:8
instr * input
const char * measure_list[]
Definition: smi_maplists.h:6
int sday
Definition: l1_czcs_hdf.c:15
#define L3M_MIN
Definition: mapattr.h:105
#define L3M_SYEAR
Definition: mapattr.h:53
#define L3M_SMSEC
Definition: mapattr.h:55
char sensor[SM_ATTRSZ]
Definition: meta_l3b.h:23
#define L3M_LONUNITS_VAL
Definition: mapattr.h:70
double endTime
Definition: meta_l3b.h:40
#define L3M_SNSCHAR
Definition: mapattr.h:26
productInfo_t * allocateProductInfo()
void get_time(char *pr_time)
Definition: get_time.c:28
char prod_type[SM_ATTRSZ]
Definition: meta_l3b.h:29
#define SDS_NAME
Definition: mapattr.h:86
#define L3M_SOFTNM_VAL
Definition: smiinc.h:4
#define L3M_DATABINS
Definition: mapattr.h:90
#define L3M_NROWS
Definition: mapattr.h:91
char data_center[SM_ATTRSZ]
Definition: meta_l3b.h:20
#define L3M_PEYEAR
Definition: mapattr.h:49
#define L3M_PROCCON
Definition: mapattr.h:38
void unix2yds(double usec, short *year, short *day, double *secs)
#define L3M_SOFTNM
Definition: mapattr.h:34
#define L3M_EMSEC
Definition: mapattr.h:58
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
#define L3M_EYEAR
Definition: mapattr.h:56
but the philosophy of the MODIS L1 routines is that the output granule must be if it contains even a single packet of useable data Some of the spacecraft ancillary data in L0 datasets is available only on a cycle that repeates every seconds MOD_PR01 therefore looks backwards up to for such packets If the seconds preceeding the start of an MOD_PR01 run are covered by a different L0 dataset
Definition: MOD_PR01_pr.txt:33
char title[SM_ATTRSZ]
Definition: meta_l3b.h:17
#define L3M_LATUNITS_VAL
Definition: mapattr.h:68
#define L3M_SWLAT
Definition: mapattr.h:81
int findProductInfo(const char *productName, int sensorId, productInfo_t *info)
int32_t put_smi(char *l3m_path, char *l3m_name, uint8 *l3m_data, int32 *dim_sizes, float32 *lat_range, float32 *lon_range, char *measure, char *scale_type, float32 *si_used, float32 *aminmax, char *atype, char *aopt, char *infiles, float32 *l3m_dminmax, meta_l3bType *meta_l3b, unsigned char *map_palette, char *softid, char *proc_con, instr input, char *precision, uint8 *qual_byt, uint8 isHDF5, VOIDP fill_value)
int32 emsec
Definition: l1_czcs_hdf.c:18
#define L3M_FLAG_NAMES
Definition: mapattr.h:41
#define L3M_STIME
Definition: mapattr.h:51
const char * str
Definition: l1c_msi.cpp:35
HISTORY txt for MOD_PR01(step one of PGE01) History follows the following convention needed due to new Aqua ReprocessingActual and the expected LUT revision number from PCF Changed to use PGE version for ProductionHistory Added Archive including ProcessingEnvironment Corrected handling of bad to resovle GSFcd02514 Changed to check staged LUT revision number versus the expected LUT revision number from thereby resolving defect report MODxl02056 This change also avoids the memory access violation reported in MODur00039 Changed the way output arrays were initialized with fill values
Definition: HISTORY.txt:162
intn setAttr(uint8 isHDF5, int32 obj_id, const char *attr_name, int32 data_type, int32 count, VOIDP values)
Definition: put_smi.cpp:20
#define L3M_ETIME
Definition: mapattr.h:52
#define L3M_SLOPE
Definition: mapattr.h:103
dtype
Definition: DDataset.hpp:31
#define L3M_UNITS
Definition: mapattr.h:95
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
double startTime
Definition: meta_l3b.h:39
#define L3M_PSYEAR
Definition: mapattr.h:47
Extra metadata that will be written to the HDF4 file l2prod rank
char * unix2isodate(double dtime, char zone)
Definition: unix2isodate.c:10
char mission_char[SM_ATTRSZ]
Definition: meta_l3b.h:22
#define L3M_PARAMETER
Definition: mapattr.h:94
#define L3M_PVERSION
Definition: mapattr.h:31
#define L3M_PSDAY
Definition: mapattr.h:48
#define L3M_SDAY
Definition: mapattr.h:54
#define L3M_SENSOR
Definition: mapattr.h:23
char ptime[SM_ATTRSZ]
Definition: meta_l3b.h:34
#define L3M_SWLON
Definition: mapattr.h:82
char pversion[SM_ATTRSZ]
Definition: meta_l3b.h:30
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
#define L3M_MAPPROJ
Definition: mapattr.h:65
#define L3M_ELON
Definition: mapattr.h:77
#define L3M_BASE
Definition: mapattr.h:102
int64_t data_bins
Definition: meta_l3b.h:46
#define L3M_EORBIT
Definition: mapattr.h:61
#define L3M_MSNCHAR
Definition: mapattr.h:21
char sensor_name[SM_ATTRSZ]
Definition: meta_l3b.h:19
int i
Definition: decode_rs.h:71
#define L3M_LINEAR_EQN
Definition: mapattr.h:101
#define L3M_MAPPROJ_VAL
Definition: mapattr.h:66
#define L3M_INTERCEPT
Definition: mapattr.h:104
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int SetScalarH5A(hid_t id, const char *name, hid_t type, const void *value)
Definition: hdf5util.cpp:166
int32_t end_orb
Definition: meta_l3b.h:43
#define L3M_SLAT
Definition: mapattr.h:73
#define L3M_LOG_EQN
Definition: mapattr.h:100
#define MAXVAL
Definition: put_smi.cpp:16
#define L3M_PRODTYPE
Definition: mapattr.h:30
#define L3M_SENSOR_NAME
Definition: mapattr.h:24
int count
Definition: decode_rs.h:79
#define L3M_PTIME
Definition: mapattr.h:36