OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
l1_ocm2_hdf.c
Go to the documentation of this file.
1 #include "l1_ocm2_hdf.h"
2 #include "l1.h"
3 #include <mfhdf.h>
4 #include <allocate2d.h>
5 
6 static char dname[8][6] = {"L_412", "L_443", "L_490", "L_510",
7  "L_555", "L_620", "L_740", "L_865"};
8 
9 static float *data = NULL;
10 static float32 **solz = NULL;
11 static float32 **sola = NULL;
12 static float32 **senz = NULL;
13 static float32 **sena = NULL;
14 
15 
16 #define READ_GLBL_ATTR(nam,ptr) { \
17  if(SDreadattr(sd_id,SDfindattr(sd_id,(nam)),(VOIDP)(ptr))){ \
18  fprintf(stderr, \
19  "-E- %s line %d: Could not get global attribute, %s.\n", \
20  __FILE__,__LINE__,(nam)); \
21  } \
22 }
23 
24 #define READ_SDS(nam,ptr,s0,s1,s2,e0,e1,e2) { \
25  int32 start[3]; \
26  int32 edge[3]; \
27  edge[0]=(e0); edge[1]=(e1); edge[2]=(e2); \
28  start[0]=(s0); start[1]=(s1); start[2]=(s2); \
29  if(SDreaddata(SDselect(sd_id, SDnametoindex(sd_id, (nam))), \
30  start, NULL, edge, (VOIDP)(ptr)) == FAIL){ \
31  fprintf(stderr,"-E- %s line %d: Could not read SDS, %s.\n", \
32  __FILE__,__LINE__,(nam)); \
33  } \
34 }
35 
36 void interp_ocm2_geo(int32 sd_id, int32 nx, int32 ny, char *sdsname, float32 **geo) {
37  int32 sds_id;
38  int32 rank;
39  int32 dims[3];
40  int32 type;
41  int32 numattr;
42  int32 i, j, jout;
43  int32 mx, my;
44  int32 nx_ctl;
45  int32 ny_ctl;
46 
47  float32 *x_ctl, *dx_ctl;
48  float32 *y_ctl, *dy_ctl;
49  float32 *v_ctl;
50 
51  // determine size of path geometry control points
52  sds_id = SDselect(sd_id, SDnametoindex(sd_id, (sdsname)));
53  if (SDgetinfo(sds_id, NULL, &rank, dims, &type, &numattr) == -1) {
54  fprintf(stderr, "-E- %s line %d: error getting dimension info.\n",
55  __FILE__, __LINE__);
56  exit(1);
57  }
58  nx_ctl = dims[1];
59  ny_ctl = dims[0];
60 
61  // set-up interpolation grid
62  mx = nx / nx_ctl;
63  my = ny / ny_ctl;
64  x_ctl = (float32 *) calloc(nx_ctl, sizeof (float32));
65  y_ctl = (float32 *) calloc(ny_ctl, sizeof (float32));
66  for (i = 0; i < nx_ctl; i++) x_ctl[i] = (float32) i * mx + 1;
67  for (j = 0; j < ny_ctl; j++) y_ctl[j] = (float32) j * my + 1;
68 
69  // interpolate each line to full pixel
70  v_ctl = (float32 *) calloc(nx_ctl, sizeof (float32));
71  dx_ctl = (float32 *) calloc(nx_ctl, sizeof (float32));
72  for (j = 0; j < ny_ctl; j++) {
73  jout = j * my + 1;
74  READ_SDS(sdsname, v_ctl, j, 0, 0, 1, nx_ctl, 1);
75  spline(x_ctl, v_ctl, nx_ctl, 1e30, 1e30, dx_ctl);
76  for (i = 0; i < nx; i++) {
77  splint(x_ctl, v_ctl, dx_ctl, nx_ctl, (float) i, &geo[jout][i]);
78  //printf("%d %d %f\n",jout,i,geo[jout][i]);
79  }
80  }
81  free(v_ctl);
82  free(dx_ctl);
83 
84  // interpolate each line to full pixel
85  v_ctl = (float32 *) calloc(ny_ctl, sizeof (float32));
86  dy_ctl = (float32 *) calloc(ny_ctl, sizeof (float32));
87  for (i = 0; i < nx; i++) {
88  for (j = 0; j < ny_ctl; j++) {
89  jout = j * my + 1;
90  v_ctl[j] = geo[jout][i];
91  }
92  spline(y_ctl, v_ctl, ny_ctl, 1e30, 1e30, dy_ctl);
93  for (j = 0; j < ny; j++) {
94  splint(y_ctl, v_ctl, dy_ctl, ny_ctl, (float) j, &geo[j][i]);
95  }
96  }
97  free(v_ctl);
98  free(dy_ctl);
99 
100  free(x_ctl);
101  free(y_ctl);
102 }
103 
104 int openl1_ocm2_hdf(filehandle *file) {
105  int32 npix;
106  int32 nscan;
107  int32 subsamp;
108  int32 sd_id;
109 
110  /* Open the HDF input file */
111  sd_id = SDstart(file->name, DFACC_RDONLY);
112  if (sd_id == FAIL) {
113  fprintf(stderr, "-E- %s line %d: SDstart(%s, %d) failed.\n",
114  __FILE__, __LINE__, file->name, DFACC_RDONLY);
115  return (HDF_FUNCTION_ERROR);
116  }
117 
118  /* Read some of the level-1A global attributes. */
119  READ_GLBL_ATTR("Pixels per Scan Line", &npix);
120  READ_GLBL_ATTR("Number of Scan Lines", &nscan);
121  READ_GLBL_ATTR("LAC Pixel Subsampling", &subsamp);
122 
123  file->npix = npix;
124  file->nscan = nscan;
125  file->nbands = 8;
126  file->sd_id = sd_id;
127  file->sensorID = OCM2;
128  if (subsamp == 4)
129  strcpy(file->spatialResolution, "4 km");
130  else
131  strcpy(file->spatialResolution, "360 m");
132 
133  return (LIFE_IS_GOOD);
134 }
135 
136 int readl1_ocm2_hdf(filehandle *file, int32_t scan, l1str *l1rec) {
137  static int firstCall = 1;
138 
139  int32 sd_id = file->sd_id;
140  int32 npix = file->npix;
141  int32 nscan = file->nscan;
142 
143  int32 ip, ib;
144 
145  if (firstCall) {
146 
147  firstCall = 0;
148 
149  if ((data = (float *) calloc(file->npix, sizeof (float))) == NULL) {
150  printf("-E- %s line %d: Error allocating data space.\n",
151  __FILE__, __LINE__);
152  return (1);
153  }
154 
155  // allocate space for radiant path geometries
156 
157  if ((solz = allocate2d_float(nscan, npix)) == NULL) {
158  printf("-E- %s line %d: Error allocating geolocation space.\n",
159  __FILE__, __LINE__);
160  return (1);
161  }
162  if ((sola = allocate2d_float(nscan, npix)) == NULL) {
163  printf("-E- %s line %d: Error allocating geolocation space.\n",
164  __FILE__, __LINE__);
165  return (1);
166  }
167  if ((senz = allocate2d_float(nscan, npix)) == NULL) {
168  printf("-E- %s line %d: Error allocating geolocation space.\n",
169  __FILE__, __LINE__);
170  return (1);
171  }
172  if ((sena = allocate2d_float(nscan, npix)) == NULL) {
173  printf("-E- %s line %d: Error allocating geolocation space.\n",
174  __FILE__, __LINE__);
175  return (1);
176  }
177 
178 
179  printf("Interpolating radiant path geometries\n");
180  interp_ocm2_geo(sd_id, npix, nscan, "solz", solz);
181  interp_ocm2_geo(sd_id, npix, nscan, "sola", sola);
182  interp_ocm2_geo(sd_id, npix, nscan, "senz", senz);
183  interp_ocm2_geo(sd_id, npix, nscan, "sena", sena);
184  }
185 
186  int32_t year, day, msec;
187  READ_SDS("year", &year, scan, 0, 0, 1, 1, 1);
188  READ_SDS("day", &day, scan, 0, 0, 1, 1, 1);
189  READ_SDS("msec", &msec, scan, 0, 0, 1, 1, 1);
190  READ_SDS("longitude", l1rec->lon, scan, 0, 0, 1, npix, 1);
191  READ_SDS("latitude", l1rec->lat, scan, 0, 0, 1, npix, 1);
192  l1rec->scantime = yds2unix(year, day, (double) (msec / 1.e3));
193 
194  for (ip = 0; ip < npix; ip++) {
195  l1rec->solz[ip] = solz[scan][ip];
196  l1rec->sola[ip] = sola[scan][ip];
197  l1rec->senz[ip] = senz[scan][ip];
198  l1rec->sena[ip] = sena[scan][ip];
199  }
200 
201  for (ib = 0; ib < file->nbands; ib++) {
202  READ_SDS(dname[ib], data, scan, 0, 0, 1, npix, 1);
203  for (ip = 0; ip < npix; ip++) {
204  l1rec->Lt[ip * file->nbands + ib] = data[ip];
205  // if (data[ip] > 32767) l1rec->hilt[ip] = 1;
206  }
207  }
208 
209  l1rec->npix = file->npix;
210 
211  return (LIFE_IS_GOOD);
212 }
213 
214 int closel1_ocm2_hdf(filehandle *file) {
215  if (SDend(file->sd_id)) {
216  fprintf(stderr, "-E- %s line %d: SDend(%d) failed for file, %s.\n",
217  __FILE__, __LINE__, file->sd_id, file->name);
218  return (HDF_FUNCTION_ERROR);
219  }
220 
221  return (LIFE_IS_GOOD);
222 }
223 
224 
225 
226 
227 
int j
Definition: decode_rs.h:73
int32_t day
double yds2unix(int16_t year, int16_t day, double secs)
Definition: yds2unix.c:7
#define FAIL
Definition: ObpgReadGrid.h:18
#define NULL
Definition: decode_rs.h:63
void interp_ocm2_geo(int32 sd_id, int32 nx, int32 ny, char *sdsname, float32 **geo)
Definition: l1_ocm2_hdf.c:36
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 and extracts from the merged data those packets which fall within that time period Each scan of data is stored in the L1A granule that covers the start time of that scan
Definition: MOD_PR01_pr.txt:19
int readl1_ocm2_hdf(filehandle *file, int32_t scan, l1str *l1rec)
Definition: l1_ocm2_hdf.c:136
read l1rec
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
int32 * msec
Definition: l1_czcs_hdf.c:31
int32 nscan
Definition: l1_czcs_hdf.c:19
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 LIFE_IS_GOOD
Definition: passthebuck.h:4
int openl1_ocm2_hdf(filehandle *file)
Definition: l1_ocm2_hdf.c:104
int closel1_ocm2_hdf(filehandle *file)
Definition: l1_ocm2_hdf.c:214
#define READ_GLBL_ATTR(nam, ptr)
Definition: l1_ocm2_hdf.c:16
Utility functions for allocating and freeing two-dimensional arrays of various types.
no change in intended resolving MODur00064 Corrected handling of bad ephemeris attitude data
Definition: HISTORY.txt:356
#define READ_SDS(nam, ptr, s0, s1, s2, e0, e1, e2)
Definition: l1_ocm2_hdf.c:24
Extra metadata that will be written to the HDF4 file l2prod rank
subroutine splint(xa, ya, y2a, n, x, y)
float ** allocate2d_float(size_t h, size_t w)
Allocate a two-dimensional array of type float of a given size.
Definition: allocate2d.c:125
int i
Definition: decode_rs.h:71
How many dimensions is the output array Default is Not sure if anything above will work correctly strcpy(l2prod->title, "no title yet")
int npix
Definition: get_cmp.c:27
#define HDF_FUNCTION_ERROR
Definition: passthebuck.h:7
#define OCM2
Definition: sensorDefs.h:21