OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
write_l3b_meta.c
Go to the documentation of this file.
1 /*
2  * write_l3b_meta.c
3  *
4  * Created on: Jun 12, 2014
5  * Author: dshea
6  */
7 
8 #include <netcdf.h>
9 #include <meta_l3b.h>
10 #include <timeutils.h>
11 #include <sensorInfo.h>
12 #include <genutils.h>
13 
14 #include <hdf.h>
15 #include <mfhdf.h>
16 
17 
19  double timediff;
20  double days;
21  int nday;
22  char *period;
23 
24  period = (char *) malloc(SM_ATTRSZ * sizeof (char));
25 
26  timediff = meta_l3b->endTime - meta_l3b->startTime;
27  days = timediff / 86400.;
28 
29  if (days < 0.75) {
30  nday = floor(days * 24.) + 1;
31  sprintf(period, "%d-hour", nday);
32  strcpy(meta_l3b->prod_type, period);
33  } else if (days >= 0.75 && days < 1.5) {
34  strcpy(meta_l3b->prod_type, "day");
35  } else if (days >= 1.5 && days < 27.5) {
36  nday = round(days);
37  sprintf(period, "%d-day", nday);
38  strcpy(meta_l3b->prod_type, period);
39  } else if (days >= 27.5 && days < 31.5) {
40  strcpy(meta_l3b->prod_type, "month");
41  } else if (days > 31.5 && days < 32.75) {
42  // special case for rolling 32D composites
43  strcpy(meta_l3b->prod_type, "32-day");
44  } else if (days >= 32.75 && days < 364) {
45  nday = round(days / 30.);
46  sprintf(period, "%d-month", nday);
47  strcpy(meta_l3b->prod_type, period);
48  } else if (days > 364 && days < 367) {
49  strcpy(meta_l3b->prod_type, "year");
50  } else if (days >= 367) {
51  nday = round(days / 365.);
52  sprintf(period, "%d-year", nday);
53  strcpy(meta_l3b->prod_type, period);
54  }
55 
56  free(period);
57 }
58 
59 int write_l3b_meta_hdf4(int32_t sd_id, meta_l3bType *meta_l3b) {
60  /* Write Global Attributes */
61  /* ----------------------- */
62  char buf[LG_ATTRSZ];
63 
64  strcpy(buf, meta_l3b->product_name);
65  SDsetattr(sd_id, "Product Name", DFNT_CHAR, strlen(buf) + 1, buf);
66 
67  strcpy(buf, meta_l3b->sensor_name);
68  strcat(buf, " Level-3 Binned Data");
69  SDsetattr(sd_id, "Title", DFNT_CHAR, strlen(buf) + 1, buf);
70 
71  strcpy(buf, meta_l3b->sensor_name);
72  SDsetattr(sd_id, "Sensor Name", DFNT_CHAR, strlen(buf) + 1, buf);
73 
74  strcpy(buf, meta_l3b->mission);
75  SDsetattr(sd_id, "Mission", DFNT_CHAR, strlen(buf) + 1, buf);
76 
77  calculate_temporal_range(meta_l3b);
78  strcpy(buf, meta_l3b->prod_type);
79  SDsetattr(sd_id, "Product Type", DFNT_CHAR, strlen(buf) + 1, buf);
80 
81  strcpy(buf, meta_l3b->pversion);
82  SDsetattr(sd_id, "Processing Version", DFNT_CHAR, strlen(buf) + 1, buf);
83 
84  strcpy(buf, meta_l3b->soft_name);
85  SDsetattr(sd_id, "Software Name", DFNT_CHAR, strlen(buf) + 1, buf);
86 
87  strcpy(buf, meta_l3b->soft_ver);
88  SDsetattr(sd_id, "Software Version", DFNT_CHAR, strlen(buf) + 1, buf);
89 
90  SDsetattr(sd_id, "Start Orbit", DFNT_INT32, 1, &meta_l3b->start_orb);
91  SDsetattr(sd_id, "End Orbit", DFNT_INT32, 1, &meta_l3b->end_orb);
92 
93  strcpy(buf, meta_l3b->ptime);
94  SDsetattr(sd_id, "Processing Time", DFNT_CHAR, strlen(buf) + 1, buf);
95 
96  strcpy(buf, meta_l3b->proc_con);
97  SDsetattr(sd_id, "Processing Control", DFNT_CHAR, strlen(buf) + 1, buf);
98 
99  strcpy(buf, meta_l3b->input_parms);
100  SDsetattr(sd_id, "Input Parameters", DFNT_CHAR, strlen(buf) + 1, buf);
101 
102  strcpy(buf, meta_l3b->infiles);
103  SDsetattr(sd_id, "Input Files", DFNT_CHAR, strlen(buf) + 1, buf);
104 
105  strcpy(buf, meta_l3b->flag_names);
106  SDsetattr(sd_id, "L2 Flag Names", DFNT_CHAR, strlen(buf) + 1, buf);
107 
108  // if bin_syear isn't set - assume (yes, I know) the start/end year/day need to be set
109  int16_t syear, sday, eyear, eday;
110  double msec;
111  int32_t smsec, emsec;
112  unix2yds(meta_l3b->startTime, &syear, &sday, &msec);
113  smsec = (int32_t) (msec * 1000.);
114  unix2yds(meta_l3b->endTime, &eyear, &eday, &msec);
115  emsec = (int32_t) (msec * 1000.);
116 
117  // if (meta_l3b->bin_syear == 0){
118  // meta_l3b->bin_syear = syear;
119  // meta_l3b->bin_sday = sday;
120  // meta_l3b->bin_eyear = eyear;
121  // meta_l3b->bin_eday = eday;
122  // }
123  SDsetattr(sd_id, "Period Start Year", DFNT_INT16, 1, &syear);
124  SDsetattr(sd_id, "Period Start Day", DFNT_INT16, 1, &sday);
125  SDsetattr(sd_id, "Period End Year", DFNT_INT16, 1, &eyear);
126  SDsetattr(sd_id, "Period End Day", DFNT_INT16, 1, &eday);
127 
128  strcpy(buf, ydhmsf(meta_l3b->startTime, 'G'));
129  SDsetattr(sd_id, "Start Time", DFNT_CHAR, strlen(buf) + 1, buf);
130 
131  strcpy(buf, ydhmsf(meta_l3b->endTime, 'G'));
132  SDsetattr(sd_id, "End Time", DFNT_CHAR, strlen(buf) + 1, buf);
133 
134  SDsetattr(sd_id, "Start Year", DFNT_INT16, 1, &syear);
135  SDsetattr(sd_id, "Start Day", DFNT_INT16, 1, &sday);
136  SDsetattr(sd_id, "Start Millisec", DFNT_INT32, 1, &smsec);
137  SDsetattr(sd_id, "End Year", DFNT_INT16, 1, &eyear);
138  SDsetattr(sd_id, "End Day", DFNT_INT16, 1, &eday);
139  SDsetattr(sd_id, "End Millisec", DFNT_INT32, 1, &emsec);
140 
141  strcpy(buf, "degrees North");
142  SDsetattr(sd_id, "Latitude Units", DFNT_CHAR, strlen(buf) + 1, buf);
143  strcpy(buf, "degrees East");
144  SDsetattr(sd_id, "Longitude Units", DFNT_CHAR, strlen(buf) + 1, buf);
145 
146  SDsetattr(sd_id, "Northernmost Latitude", DFNT_FLOAT32, 1, &meta_l3b->north);
147  SDsetattr(sd_id, "Southernmost Latitude", DFNT_FLOAT32, 1, &meta_l3b->south);
148  SDsetattr(sd_id, "Easternmost Longitude", DFNT_FLOAT32, 1, &meta_l3b->east);
149  SDsetattr(sd_id, "Westernmost Longitude", DFNT_FLOAT32, 1, &meta_l3b->west);
150 
151  int32 tmpInt = meta_l3b->data_bins;
152  SDsetattr(sd_id, "Data Bins", DFNT_INT32, 1, &tmpInt);
153  SDsetattr(sd_id, "Percent Data Bins", DFNT_FLOAT32, 1,
154  &meta_l3b->pct_databins);
155 
156  strcpy(buf, meta_l3b->units);
157  SDsetattr(sd_id, "Units", DFNT_CHAR, strlen(buf) + 1, buf);
158  strcpy(buf, resolution2str(meta_l3b->resolution));
159  SDsetattr(sd_id, "Bin Resolution", DFNT_CHAR, strlen(buf) + 1, buf);
160 
161  return 0;
162 }
163 
164 int write_l3b_meta_netcdf4(idDS ds_id, meta_l3bType *meta_l3b, int write64bit) {
165  // Write Global Attributes
166  // -----------------------
167  char buf[LG_ATTRSZ];
168 
169  strcpy(buf, meta_l3b->product_name);
170  setAttr(ds_id, "product_name", NC_CHAR, strlen(buf) + 1, buf);
171 
172  strcpy(buf, meta_l3b->sensor);
173  strcat(buf, " Level-3 Binned Data");
174  setAttr(ds_id, "title", NC_CHAR, strlen(buf) + 1, buf);
175 
176  strcpy(buf, meta_l3b->sensor);
177  setAttr(ds_id, "instrument", NC_CHAR, strlen(buf) + 1, buf);
178 
179  strcpy(buf, meta_l3b->mission);
180  if (strcmp(meta_l3b->mission, "") != 0)
181  setAttr(ds_id, "platform", NC_CHAR, strlen(buf) + 1, buf);
182 
183  calculate_temporal_range(meta_l3b);
184  strcpy(buf, meta_l3b->prod_type);
185  setAttr(ds_id, "temporal_range", NC_CHAR, strlen(buf) + 1, buf);
186 
187  setAttr(ds_id, "start_orbit_number", NC_INT, 1, &meta_l3b->start_orb);
188  setAttr(ds_id, "end_orbit_number", NC_INT, 1, &meta_l3b->end_orb);
189 
190  strcpy(buf, meta_l3b->ptime);
191  setAttr(ds_id, "date_created", NC_CHAR, strlen(buf) + 1, buf);
192 
193  strcpy(buf, meta_l3b->pversion);
194  setAttr(ds_id, "processing_version", NC_CHAR, strlen(buf) + 1, buf);
195 
196  strcpy(buf, "satellite observations from ");
197  strncat(buf, meta_l3b->sensor,sizeof(buf) - strlen(meta_l3b->sensor) - 1);
198  if (strcmp(meta_l3b->mission, "") != 0){
199  strncat(buf, "-",sizeof(buf));
200  strncat(buf, meta_l3b->mission,sizeof(buf) - strlen(meta_l3b->mission) - 1);
201  }
202  setAttr(ds_id, "source", NC_CHAR, strlen(buf) + 1, buf);
203 
204  strcpy(buf, meta_l3b->proc_con);
205  setAttr(ds_id, "history", NC_CHAR, strlen(buf) + 1, buf);
206 
207  strcpy(buf, unix2isodate(meta_l3b->startTime, 'G'));
208  setAttr(ds_id, "time_coverage_start", NC_CHAR, strlen(buf) + 1, buf);
209 
210  strcpy(buf, unix2isodate(meta_l3b->endTime, 'G'));
211  setAttr(ds_id, "time_coverage_end", NC_CHAR, strlen(buf) + 1, buf);
212 
213  setAttr(ds_id, "northernmost_latitude", NC_FLOAT, 1,
214  (VOIDP) & meta_l3b->north);
215  setAttr(ds_id, "southernmost_latitude", NC_FLOAT, 1,
216  (VOIDP) & meta_l3b->south);
217  setAttr(ds_id, "easternmost_longitude", NC_FLOAT, 1,
218  (VOIDP) & meta_l3b->east);
219  setAttr(ds_id, "westernmost_longitude", NC_FLOAT, 1,
220  (VOIDP) & meta_l3b->west);
221  double val = (double) meta_l3b->north;
222  setAttr(ds_id, "geospatial_lat_max", NC_DOUBLE, 1, (VOIDP) & val);
223  val = (double) meta_l3b->south;
224  setAttr(ds_id, "geospatial_lat_min", NC_DOUBLE, 1, (VOIDP) & val);
225  val = (double) meta_l3b->east;
226  setAttr(ds_id, "geospatial_lon_max", NC_DOUBLE, 1, (VOIDP) & val);
227  val = (double) meta_l3b->west;
228  setAttr(ds_id, "geospatial_lon_min", NC_DOUBLE, 1, (VOIDP) & val);
229 
230  strcpy(buf, "degrees_north");
231  setAttr(ds_id, "geospatial_lat_units", NC_CHAR, strlen(buf) + 1, buf);
232 
233  strcpy(buf, "degrees_east");
234  setAttr(ds_id, "geospatial_lon_units", NC_CHAR, strlen(buf) + 1, buf);
235  const char* resString = resolution2str(meta_l3b->resolution);
236  int len = strlen(resString) + 1;
237  setAttr(ds_id, "geospatial_lat_resolution", NC_CHAR, len , (VOIDP)resString);
238  setAttr(ds_id, "geospatial_lon_resolution", NC_CHAR, len , (VOIDP)resString);
239  setAttr(ds_id, "spatialResolution", NC_CHAR, len , (VOIDP)resString);
240 
241  if(write64bit)
242  setAttr(ds_id, "data_bins", NC_INT64, 1, (VOIDP) &meta_l3b->data_bins);
243  else {
244  int tmpInt = meta_l3b->data_bins;
245  setAttr(ds_id, "data_bins", NC_INT, 1, (VOIDP) &tmpInt);
246  }
247 
248  setAttr(ds_id, "percent_data_bins", NC_FLOAT, 1,
249  (VOIDP) & meta_l3b->pct_databins);
250 
251  strcpy(buf, meta_l3b->units);
252  setAttr(ds_id, "units", NC_CHAR, strlen(buf) + 1, buf);
253 
254  strcpy(buf, meta_l3b->binning_scheme);
255  setAttr(ds_id, "binning_scheme", NC_CHAR, strlen(buf) + 1, buf);
256 
257  strcpy(buf, "Ocean Biology Processing Group (NASA/GSFC/OBPG)");
258  setAttr(ds_id, "project", NC_CHAR, strlen(buf) + 1, buf);
259 
260  strcpy(buf,
261  "NASA Goddard Space Flight Center, Ocean Ecology Laboratory, Ocean Biology Processing Group");
262  setAttr(ds_id, "institution", NC_CHAR, strlen(buf) + 1, buf);
263 
264  strcpy(buf, "CF Standard Name Table v36");
265  setAttr(ds_id, "standard_name_vocabulary", NC_CHAR, strlen(buf) + 1, buf);
266 
267  strcpy(buf, "CF-1.6 ACDD-1.3");
268  setAttr(ds_id, "Conventions", NC_CHAR, strlen(buf) + 1, buf);
269 
270  char const *naming_authority = "gov.nasa.gsfc.sci.oceandata";
271  strcpy(buf, naming_authority);
272  setAttr(ds_id, "naming_authority", NC_CHAR, strlen(buf) + 1, buf);
273  // create id
274  strcpy(buf, meta_l3b->pversion);
275  if (strcmp(meta_l3b->pversion, "Unspecified") != 0) {
276  strcpy(buf, meta_l3b->product_name);
277  strcat(buf, "/L3/");
278 
279  } else {
280  strcpy(buf, "L3/");
281  }
282  strcat(buf, meta_l3b->product_name);
283  setAttr(ds_id, "id", NC_CHAR, strlen(buf) + 1, buf);
284 
285  char const *license =
286  "https://science.nasa.gov/earth-science/earth-science-data/data-information-policy/";
287  strcpy(buf, license);
288  setAttr(ds_id, "license", NC_CHAR, strlen(buf) + 1, buf);
289 
290  strcpy(buf, "NASA/GSFC/OBPG");
291  setAttr(ds_id, "creator_name", NC_CHAR, strlen(buf) + 1, buf);
292  setAttr(ds_id, "publisher_name", NC_CHAR, strlen(buf) + 1, buf);
293 
294  strcpy(buf, "data@oceancolor.gsfc.nasa.gov");
295  setAttr(ds_id, "creator_email", NC_CHAR, strlen(buf) + 1, buf);
296  setAttr(ds_id, "publisher_email", NC_CHAR, strlen(buf) + 1, buf);
297 
298  strcpy(buf, "https://oceandata.sci.gsfc.nasa.gov");
299  setAttr(ds_id, "creator_url", NC_CHAR, strlen(buf) + 1, buf);
300  setAttr(ds_id, "publisher_url", NC_CHAR, strlen(buf) + 1, buf);
301 
302  strcpy(buf, "L3 Binned");
303  setAttr(ds_id, "processing_level", NC_CHAR, strlen(buf) + 1, buf);
304 
305  strcpy(buf, "point");
306  setAttr(ds_id, "cdm_data_type", NC_CHAR, strlen(buf) + 1, buf);
307 
308  if(meta_l3b->doi[0]) {
309  strcpy(buf, "https://dx.doi.org");
310  setAttr(ds_id, "identifier_product_doi_authority",
311  NC_CHAR, strlen(buf) + 1, buf);
312  setAttr(ds_id, "identifier_product_doi", NC_CHAR, strlen(meta_l3b->doi) + 1, meta_l3b->doi);
313  }
314 
315  if(meta_l3b->keywords[0]) {
316  strcpy(buf, "NASA Global Change Master Directory (GCMD) Science Keywords");
317  setAttr(ds_id, "keywords_vocabulary", NC_CHAR, strlen(buf) + 1, buf);
318  setAttr(ds_id, "keywords", NC_CHAR, strlen(meta_l3b->keywords) + 1, meta_l3b->keywords);
319  }
320 
321  nc_def_grp(ds_id.fid, "processing_control", &ds_id.fid);
322 
323  strcpy(buf, meta_l3b->soft_name);
324  setAttr(ds_id, "software_name", NC_CHAR, strlen(buf) + 1, buf);
325 
326  strcpy(buf, meta_l3b->soft_ver);
327  setAttr(ds_id, "software_version", NC_CHAR, strlen(buf) + 1, buf);
328 
329  strcpy(buf, meta_l3b->infiles);
330  setAttr(ds_id, "input_sources", NC_CHAR, strlen(buf) + 1, buf);
331 
332  strcpy(buf, meta_l3b->flag_names);
333  setAttr(ds_id, "l2_flag_names", NC_CHAR, strlen(buf) + 1, buf);
334 
335  nc_def_grp(ds_id.fid, "input_parameters", &ds_id.fid);
336  char *cleanInputParams = replace_ocroots(meta_l3b->input_parms);
337  char *end_str;
338  char *token = strtok_r(cleanInputParams, "\n", &end_str);
339  char tmp_buf[16384];
340  while (token != NULL) {
341  char *end_token;
342  strcpy(tmp_buf, token);
343  char *name = strtok_r(token, "=", &end_token);
344  trimBlanks(name);
345  strcpy(tmp_buf, strtok_r(NULL, "\n", &end_token));
346  trimBlanks(tmp_buf);
347  if (name[0] != '#')
348  PTB(SetChrGA(ds_id, name, tmp_buf));
349  token = strtok_r(NULL, "\n", &end_str);
350  }
351  free(cleanInputParams);
352 
353  return 0;
354 }
char * ydhmsf(double dtime, char zone)
Definition: ydhmsf.c:12
char product_name[SM_ATTRSZ]
Definition: meta_l3b.h:16
int16 eday
Definition: l1_czcs_hdf.c:17
char units[MD_ATTRSZ]
Definition: meta_l3b.h:28
char binning_scheme[SM_ATTRSZ]
Definition: meta_l3b.h:48
char infiles[LG_ATTRSZ]
Definition: meta_l3b.h:38
#define NULL
Definition: decode_rs.h:63
char mission[SM_ATTRSZ]
Definition: meta_l3b.h:21
char keywords[SM_ATTRSZ]
Definition: meta_l3b.h:55
void trimBlanks(char *str)
Definition: trimBlanks.c:10
int32_t start_orb
Definition: meta_l3b.h:42
char input_parms[LG_ATTRSZ]
Definition: meta_l3b.h:36
int write_l3b_meta_netcdf4(idDS ds_id, meta_l3bType *meta_l3b, int write64bit)
int32 * msec
Definition: l1_czcs_hdf.c:31
int16 eyear
Definition: l1_czcs_hdf.c:17
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
int syear
Definition: l1_czcs_hdf.c:15
char flag_names[SM_ATTRSZ]
Definition: meta_l3b.h:37
int32 smsec
Definition: l1_czcs_hdf.c:16
int sday
Definition: l1_czcs_hdf.c:15
char sensor[SM_ATTRSZ]
Definition: meta_l3b.h:23
double endTime
Definition: meta_l3b.h:40
char prod_type[SM_ATTRSZ]
Definition: meta_l3b.h:29
void calculate_temporal_range(meta_l3bType *meta_l3b)
int write_l3b_meta_hdf4(int32_t sd_id, meta_l3bType *meta_l3b)
double resolution
Definition: meta_l3b.h:53
void unix2yds(double usec, short *year, short *day, double *secs)
integer, parameter double
char * replace_ocroots(const char *inStr)
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT16
float north
Definition: meta_l3b.h:49
#define PTB(function)
Definition: passthebuck.h:16
float west
Definition: meta_l3b.h:52
char doi[SM_ATTRSZ]
Definition: meta_l3b.h:54
const char * resolution2str(double resolution)
Pixel resolution meters to string.
int32 emsec
Definition: l1_czcs_hdf.c:18
intn setAttr(uint8 isHDF5, int32 obj_id, const char *attr_name, int32 data_type, int32 count, VOIDP values)
Definition: put_smi.cpp:20
float south
Definition: meta_l3b.h:50
char proc_con[MD_ATTRSZ]
Definition: meta_l3b.h:35
int SetChrGA(idDS ds_id, const char *name, const char *value)
Definition: wrapper.c:236
double startTime
Definition: meta_l3b.h:39
char soft_ver[SM_ATTRSZ]
Definition: meta_l3b.h:33
int32_t fid
Definition: dfutils.h:29
char * unix2isodate(double dtime, char zone)
Definition: unix2isodate.c:10
float pct_databins
Definition: meta_l3b.h:47
Definition: dfutils.h:28
char ptime[SM_ATTRSZ]
Definition: meta_l3b.h:34
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
float east
Definition: meta_l3b.h:51
MOD_PR01 Production producing one five minute granule of output data in each run It can be configured to produce as many as three five minute granules per run Each execution with one construction record and one date file for each dataset In normal these are created by which splits them out of the hour datasets For LANCE they are created by which merges all session MODIS L0 datasets overlapping the requested time period
Definition: MOD_PR01_pr.txt:15
int64_t data_bins
Definition: meta_l3b.h:46
char sensor_name[SM_ATTRSZ]
Definition: meta_l3b.h:19
msiBandIdx val
Definition: l1c_msi.cpp:34
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
#define SM_ATTRSZ
Definition: meta_l3b.h:7
#define LG_ATTRSZ
Definition: meta_l3b.h:9
int32_t end_orb
Definition: meta_l3b.h:43
char soft_name[SM_ATTRSZ]
Definition: meta_l3b.h:32