OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1aextract_modis.c
Go to the documentation of this file.
1 /*
2  Modification history:
3  Programmer Organization Date Description of change
4  -------------- ------------ -------- ---------------------
5  Joel Gales Futuretech 08/10/03 Original Development
6 
7  */
8 
9 /*
10  Revision 0.76 2018-04-30
11  Return status 110 when cannot extract specified area.
12  Truncate area when requested beyond granule, rather than give up.
13  G. Fireman
14 
15  Revision 0.75 2017-03-03
16  Check for "empty" fields
17  This avoids writing day-only EV fields
18  G. Fireman
19 
20  Revision 0.70 2011-02-08
21  Make sure all engineering data required by L1B has been collected
22  Complete overhaul for maintainability
23  G. Fireman
24 
25  2009-10-14
26  Add values of any pre-existing pixel & scan offsets for correct geolocation
27  G. Fireman
28 
29  Revision 0.62 01/25/07
30  Remove clear page command in usage
31  J. Gales
32 
33  Revision 0.61 05/30/06
34  Emphasis Line # (not scan #) in usage.
35  J. Gales
36  */
37 
38 
39 #include <stdio.h>
40 #include <math.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include "hdf.h"
44 #include "mfhdf.h"
45 
46 #define VERSION "0.76"
47 #define BOUNDS_ERROR 110
48 
49 int main(int argc, char *argv[]) {
50  int32 i, j;
51  int32 status;
52 
53  /* pixel & scan */
54  int32 spixl, epixl, npixl;
55  int32 sscan, escan, nscan, iscan;
56  char *scan_type;
57  int32 nscan_day = 0, nscan_night = 0;
58  int32 spixl_old = 0, sscan_old = 0, nscan_old = 0;
59 
60  /* specific to input file */
61  char *infile;
62  int32 HDFfid_r;
63  int32 sd_id_r;
64  int32 sds_id_r;
65  int32 vd_id_r;
66  int32 dims_r[H4_MAX_VAR_DIMS];
67  int32 start_r[H4_MAX_VAR_DIMS];
68  int32 n_datasets_r;
69  intn emptySDS;
70 
71  /* specific to output file */
72  char *outfile;
73  int32 HDFfid_w;
74  int32 sd_id_w;
75  int32 sds_id_w;
76  int32 vd_id_w;
77  int32 dims_w[H4_MAX_VAR_DIMS];
78  int32 start_w[H4_MAX_VAR_DIMS];
79  int32 n_datasets_w;
80 
81  /* attribute-specific */
82  int32 nattrs;
83  int32 nglobal_attr;
84  static char attr_buf[2048];
85 
86  /* SDS-specific */
87  static char sds_name[H4_MAX_NC_NAME];
88  int32 sds_index;
89  int32 ndims; /* same as rank */
90  int32 dtype;
91  int32 count;
92  unsigned char *data;
93  int32 nelem;
94 
95  /* VD-specific */
96  static char vdata_name[VSNAMELENMAX];
97  int32 vd_index;
98  int32 n_vdata;
99  int32 *ref_array;
100  char fieldlist[VSFIELDMAX * FIELDNAMELENMAX];
101  int32 vdata_size, n_records, interlace_mode;
102  int32 n_fields;
103  int32 nrec_r;
104  int32 nrec_w;
105 
106  /* dimension info for expected SDSs */
107  typedef struct {
108  char name[H4_MAX_NC_NAME];
109  int32 scandim;
110  int32 scanfactor;
111  int32 pixldim;
112  int32 pixlfactor;
113  } sds_str;
114 
115  sds_str sds_list[] = {
116  {"Scan number", 0, 1, -1, -1},
117  {"Frame count array", 0, 1, -1, -1},
118  {"Scan Type", 0, 1, -1, -1},
119  {"SD start time", 0, 1, -1, -1},
120  {"SRCA start time", 0, 1, -1, -1},
121  {"BB start time", 0, 1, -1, -1},
122  {"SV start time", 0, 1, -1, -1},
123  {"EV start time", 0, 1, -1, -1},
124  {"SRCA calibration mode", 0, 1, -1, -1},
125  {"Packet scan count", 0, 1, -1, -1},
126  {"CCSDS Application Identifiers", 0, 1, -1, -1},
127  {"Packet expedited data flag", 0, 1, -1, -1},
128  {"Mirror side", 0, 1, -1, -1},
129  {"Scan quality array", 0, 1, -1, -1},
130  {"SD sector Pixel quality", 0, 1, -1, -1},
131  {"SRCA sector Pixel quality", 0, 1, -1, -1},
132  {"BB sector Pixel quality", 0, 1, -1, -1},
133  {"SV sector Pixel quality", 0, 1, -1, -1},
134  {"Earth sector Pixel quality", 0, 1, 1, 1},
135  {"SD_250m", 0, 40, -1, -1},
136  {"SD_500m", 0, 20, -1, -1},
137  {"SD_1km_day", 0, 10, -1, -1},
138  {"SD_1km_night", 0, 10, -1, -1},
139  {"SRCA_250m", 0, 40, -1, -1},
140  {"SRCA_500m", 0, 20, -1, -1},
141  {"SRCA_1km_day", 0, 10, -1, -1},
142  {"SRCA_1km_night", 0, 10, -1, -1},
143  {"BB_250m", 0, 40, -1, -1},
144  {"BB_500m", 0, 20, -1, -1},
145  {"BB_1km_day", 0, 10, -1, -1},
146  {"BB_1km_night", 0, 10, -1, -1},
147  {"SV_250m", 0, 40, -1, -1},
148  {"SV_500m", 0, 20, -1, -1},
149  {"SV_1km_day", 0, 10, -1, -1},
150  {"SV_1km_night", 0, 10, -1, -1},
151  {"EV_250m", 0, 40, 2, 4},
152  {"EV_500m", 0, 20, 2, 2},
153  {"EV_1km_day", 0, 10, 2, 1},
154  {"EV_1km_night", 0, 10, 2, 1},
155  {"fpa_aem_config", 0, 1, -1, -1},
156  {"science_state", 0, 1, -1, -1},
157  {"science_abnormal", 0, 1, -1, -1},
158  {"fpa_dcr_offset", 0, 1, -1, -1},
159  {"raw_mir_enc", 0, 1, -1, -1},
160  {"raw_vs_def", 0, 1, -1, -1},
161  {"raw_vs_act", 0, 1, -1, -1},
162  {"raw_sci_eng", 0, 1, -1, -1},
163  {"raw_hk_telem", 0, 1, -1, -1},
164  {"raw_sc_ancil", 0, 1, -1, -1},
165  {"raw_param", 0, 1, -1, -1},
166  {"raw_pv_gains", 0, 1, -1, -1},
167  };
168  n_datasets_w = sizeof (sds_list) / sizeof (sds_str);
169 
170 
171  /* ------------------------------------------------------------------------ */
172 
173  printf("This is version %s of %s (compiled on %s %s)\n",
174  VERSION, argv[0], __DATE__, __TIME__);
175 
176  /*** check usage ***/
177  if (argc != 7) {
178  printf("\nUsage: %s ", argv[0]);
179  printf("infile spixl epixl sline eline outfile"
180  "\n where:"
181  "\n\tinfile - input MODIS L1A datafile"
182  "\n\tspixl - start pixel number (1-based)"
183  "\n\tepixl - end pixel number (1-based)"
184  "\n\tsline - start line (1-based)"
185  "\n\teline - end line (1-based)"
186  "\n\toutfile - output file name");
187  printf("\n\nNote: Enter line number NOT scan number!\n");
188  exit(EXIT_FAILURE);
189  }
190 
191  /* load input parameters into local variables */
192  infile = argv[1];
193  spixl = atoi(argv[2]);
194  epixl = atoi(argv[3]);
195  sscan = atoi(argv[4]);
196  escan = atoi(argv[5]);
197  outfile = argv[6];
198 
199  printf("Input file: %s\n", infile);
200  printf("Output file: %s\n", outfile);
201 
202  /* Open HDF input file */
203  HDFfid_r = Hopen(infile, DFACC_READ, 0);
204  sd_id_r = SDstart(infile, DFACC_RDONLY);
205 
206  /* Convert from line to scan (line = 10*scan) */
207  sscan = (sscan / 10) + (1 * ((sscan % 10) != 0));
208  escan = (escan / 10) + (1 * ((escan % 10) != 0));
209 
210  if ((spixl > epixl) || (sscan > escan)) {
211  printf("\nInvalid range requested:\n");
212  npixl = epixl - spixl + 1;
213  nscan = escan - sscan + 1;
214  printf("spixl: %4d epixl: %4d npixl: %4d\n", spixl, epixl, npixl);
215  printf("sscan: %4d escan: %4d nscan: %4d\n", sscan, escan, nscan);
216  exit(BOUNDS_ERROR);
217  }
218 
219  /* retrieve any previous pixel & scan offsets */
220  if (SDfindattr(sd_id_r, "Extract Pixel Offset") != FAIL)
221  SDreadattr(sd_id_r, SDfindattr(sd_id_r, "Extract Pixel Offset"), &spixl_old);
222  if (SDfindattr(sd_id_r, "Extract Line Offset") != FAIL)
223  SDreadattr(sd_id_r, SDfindattr(sd_id_r, "Extract Line Offset"), &sscan_old);
224 
225  /* retrieve dimension info */
226  sds_id_r = SDselect(sd_id_r, SDnametoindex(sd_id_r, "EV_1km_day"));
227  status = SDgetinfo(sds_id_r, sds_name, &ndims, dims_r, &dtype, &nattrs);
228  status = SDreadattr(sd_id_r, SDfindattr(sd_id_r, "Number of Scans"), &nscan_old);
229 
230  /* To make sure that all engineering data required by L1B has been collected,
231  scan number 7 (or later) of the original L1A file must be included. */
232  if (nscan_old < 7) {
233  printf("Only %d scans in granule: not enough engineering data to continue processing.", nscan_old);
234  exit(BOUNDS_ERROR);
235  }
236  if ((sscan_old + escan) < 7) {
237  printf("Adjusting end scan to ensure inclusion of required engineering data.\n");
238  escan = 7 - sscan_old;
239  }
240 
241  /* Check requested number of pixels & scan lines */
242  if (spixl > dims_r[2]) {
243  printf("spixl: %d greater than # of pixels per scan: %d\n", spixl, dims_r[2]);
244  exit(BOUNDS_ERROR);
245  }
246  if (epixl > dims_r[2]) {
247  printf("epixl: %d greater than # of pixels per scan: %d; adjusting.\n",
248  epixl, dims_r[2]);
249  epixl = dims_r[2];
250  }
251 
252  if (sscan > nscan_old) {
253  printf("sscan: %d greater than # of scan lines: %d\n", sscan, nscan_old);
254  exit(BOUNDS_ERROR);
255  }
256  if (escan > nscan_old) {
257  printf("escan: %d greater than # of scan lines: %d; adjusting.\n",
258  escan, nscan_old);
259  escan = nscan_old;
260  }
261 
262  npixl = epixl - spixl + 1;
263  nscan = escan - sscan + 1;
264  printf("spixl: %4d epixl: %4d npixl: %4d\n", spixl, epixl, npixl);
265  printf("sscan: %4d escan: %4d nscan: %4d\n", sscan, escan, nscan);
266  printf("Actual line start (0-based): %d\n", (sscan - 1) * 10);
267 
268  /* Create output HDF file & open SDS interface */
269  HDFfid_w = Hopen(outfile, DFACC_CREATE, 0);
270  sd_id_w = SDstart(outfile, DFACC_RDWR);
271 
272  /* ------------------------------------------------------------------------ */
273  /* Write SDS subsets to output file */
274 
275  printf("\nWriting Science Data Sets...\n");
276 
277  /* Step through input datasets */
278  SDfileinfo(sd_id_r, &n_datasets_r, &nglobal_attr);
279  for (sds_index = 0; sds_index < n_datasets_r; sds_index++) {
280 
281  /* Get info for this SDS */
282  sds_id_r = SDselect(sd_id_r, sds_index);
283  status = SDgetinfo(sds_id_r, sds_name, &ndims, dims_r, &dtype, &nattrs);
284  for (j = 0; j < n_datasets_w; j++) {
285  if (strcmp(sds_list[j].name, sds_name) == 0) break;
286  }
287  if (j == n_datasets_w) {
288  printf("Unexpected input SDS: \"%s\"\n", sds_name);
289  exit(EXIT_FAILURE);
290  }
291 
292  /* Find input & output dimension parameters */
293  nelem = 1;
294  for (i = 0; i < ndims; i++) {
295  start_r[i] = 0;
296  dims_w[i] = dims_r[i];
297  if (i == sds_list[j].scandim) {
298  start_r[i] = sds_list[j].scanfactor * (sscan - 1);
299  dims_w[i] = sds_list[j].scanfactor * nscan;
300  }
301  if (i == sds_list[j].pixldim) {
302  start_r[i] = sds_list[j].pixlfactor * (spixl - 1);
303  dims_w[i] = sds_list[j].pixlfactor * npixl;
304  }
305  nelem *= dims_w[i];
306  }
307 
308  /* Print info */
309  printf("%s\n rank %d, type %d, dims", sds_name, ndims, dtype);
310  for (i = 0; i < ndims; i++) printf("[%d]", dims_r[i]);
311  printf("; extracting ");
312  for (i = 0; i < ndims; i++) printf("[%d-%d]", start_r[i], start_r[i] + dims_w[i] - 1);
313  printf("\n");
314 
315  /* Create SDS */
316  sds_id_w = SDcreate(sd_id_w, sds_name, dtype, ndims, dims_w);
317  if (sds_id_w == -1) {
318  printf("Field: %s cannot be created\n", sds_name);
319  exit(EXIT_FAILURE);
320  }
321 
322  /* Read and set SDS attributes */
323  for (i = 0; i < nattrs; i++) {
324  status = SDreadattr(sds_id_r, i, attr_buf);
325  status = SDattrinfo(sds_id_r, i, sds_name, &dtype, &count);
326  status = SDsetattr(sds_id_w, sds_name, dtype, count, attr_buf);
327  }
328 
329  /* Read and write SDS values */
330  data = calloc(nelem, DFKNTsize(dtype));
331  status = SDreaddata(sds_id_r, start_r, NULL, dims_w, data);
332  status = SDcheckempty(sds_id_r, &emptySDS);
333  if (emptySDS == 0)
334  status = SDwritedata(sds_id_w, start_w, NULL, dims_w, data);
335  if (status == -1) {
336  printf("write status: %d\n\n", status);
337  exit(EXIT_FAILURE);
338  }
339 
340  /* Count Day and Night Scans (for global attributes) */
341  if (strcmp(sds_name, "Scan Type") == 0) {
342  for (iscan = 0; iscan < nscan; iscan++) {
343  scan_type = (char *) (data + 10 * iscan);
344  /* printf("scan_type[%ld] = %s\n", iscan, scan_type); */
345  if (strcmp(scan_type, "Day") == 0) nscan_day++;
346  if (strcmp(scan_type, "Night") == 0) nscan_night++;
347  }
348  }
349 
350  free(data);
351  SDendaccess(sds_id_w);
352  SDendaccess(sds_id_r);
353  }
354 
355  /* ------------------------------------------------------------------------ */
356  /* Write Vdata to output file */
357 
358  printf("\nWriting VData...\n");
359  status = Vstart(HDFfid_r);
360  status = Vstart(HDFfid_w);
361 
362  /* Step through each lone vdata */
363  n_vdata = VSlone(HDFfid_r, NULL, 0);
364  ref_array = calloc(n_vdata, sizeof (int32));
365  n_vdata = VSlone(HDFfid_r, ref_array, n_vdata);
366  for (vd_index = 0; vd_index < n_vdata; vd_index++) {
367 
368  /* Get info for input VData */
369  vd_id_r = VSattach(HDFfid_r, ref_array[vd_index], "r");
370  status = VSinquire(vd_id_r, &n_records, &interlace_mode,
371  fieldlist, &vdata_size, vdata_name);
372 
373  /* Set info for output VData */
374  vd_id_w = VSattach(HDFfid_w, -1, "w");
375  VSsetname(vd_id_w, vdata_name);
376  VSsetinterlace(vd_id_w, interlace_mode);
377 
378  /* Define output fields */
379  n_fields = VFnfields(vd_id_r);
380  printf("%s\n n_records=%d, n_fields=%d\n", vdata_name, n_records, n_fields);
381  for (i = 0; i < n_fields; i++) {
382  VSfdefine(vd_id_w,
383  VFfieldname(vd_id_r, i),
384  VFfieldtype(vd_id_r, i),
385  VFfieldorder(vd_id_r, i));
386  }
387  status = VSsetfields(vd_id_w, fieldlist);
388 
389  /* Set pointer to read only desired scans */
390  /* (except for temperatures, which don't update often enough) */
391  status = VSsetfields(vd_id_r, fieldlist);
392  if ((n_records == nscan_old) &&
393  strcmp(vdata_name, "Telemetry Major Cycle 0 of 63") != 0) {
394  VSseek(vd_id_r, sscan - 1);
395  n_records = nscan;
396  }
397 
398  /* Read and write VData values */
399  data = calloc(n_records * VSsizeof(vd_id_r, fieldlist), 1);
400  nrec_r = VSread(vd_id_r, (unsigned char *) data, n_records, interlace_mode);
401  nrec_w = VSwrite(vd_id_w, (unsigned char *) data, n_records, interlace_mode);
402  if (nrec_r != nrec_w) {
403  printf("Write Error: %d %d %d\n", i, nrec_r, nrec_w);
404  }
405 
406  free(data);
407  VSdetach(vd_id_w);
408  VSdetach(vd_id_r);
409  }
410 
411  free(ref_array);
412  Vend(HDFfid_w);
413  Vend(HDFfid_r);
414 
415 
416  /* ------------------------------------------------------------------------ */
417  /* Write Global Attributes to output file */
418 
419  printf("\nWriting Global Attributes...\n");
420  for (i = 0; i < nglobal_attr; i++) {
421  status = SDattrinfo(sd_id_r, i, attr_buf, &dtype, &count);
422  data = calloc(count, DFKNTsize(dtype));
423  status = SDreadattr(sd_id_r, i, data);
424 
425  if (strcmp(attr_buf, "Number of Scans") == 0) memcpy(data, &nscan, 4);
426  if (strcmp(attr_buf, "Number of Day mode scans") == 0) memcpy(data, &nscan_day, 4);
427  if (strcmp(attr_buf, "Number of Night mode scans") == 0) memcpy(data, &nscan_night, 4);
428 
429  status = SDsetattr(sd_id_w, attr_buf, dtype, count, data);
430  free(data);
431  }
432 
433  /* update pixel offset & count */
434  spixl = spixl_old + spixl - 1;
435  status = SDsetattr(sd_id_w, "Extract Pixel Offset", DFNT_INT32, 1, &spixl);
436  status = SDsetattr(sd_id_w, "Extract Pixel Count", DFNT_INT32, 1, &npixl);
437 
438  /* update scan offset & count */
439  sscan = sscan_old + sscan - 1;
440  status = SDsetattr(sd_id_w, "Extract Line Offset", DFNT_INT32, 1, &sscan);
441  status = SDsetattr(sd_id_w, "Extract Line Count", DFNT_INT32, 1, &nscan);
442 
443 
444  /* ------------------------------------------------------------------------ */
445  /* Close input and output files */
446 
447  SDend(sd_id_w);
448  SDend(sd_id_r);
449  Hclose(HDFfid_w);
450  Hclose(HDFfid_r);
451 
452  return EXIT_SUCCESS;
453 }
#define EXIT_SUCCESS
Definition: GEO_basic.h:72
int j
Definition: decode_rs.h:73
int status
Definition: l1_czcs_hdf.c:32
#define FAIL
Definition: ObpgReadGrid.h:18
#define NULL
Definition: decode_rs.h:63
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_INT32
int32 nscan
Definition: l1_czcs_hdf.c:19
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
#define BOUNDS_ERROR
dtype
Definition: DDataset.hpp:31
int32_t iscan
int main(int argc, char *argv[])
int i
Definition: decode_rs.h:71
#define VERSION
int count
Definition: decode_rs.h:79