NASA Logo
Ocean Color Science Software

ocssw V2022
acq_sfc_albedo.c
Go to the documentation of this file.
1 #include "l12_proto.h"
2 #include <string.h>
3 
4 // Sizes of the reflectance and uncertainty arrays read with acq_cth_albedo()
5 #define CTH_NWAVE 21
6 #define CTH_NMON 12
7 #define CTH_NLAT 1440
8 #define CTH_NLON 2880
9 
10 // Note that in May, 2023, we added reading of the albedo needed
11 // for doing the cloud top height calculation, init_cld_dat set up
12 // 2 more arrays and routine acq_cth_albedo() will read data for the
13 // line of pixels
14 
15 int init_cld_dat( l1str *l1rec )
16 /*******************************************************************
17 
18  init_cld_dat
19 
20  purpose: initialize the cloud structure portion of the l1rec
21 
22  Returns type: int32_t - status 0 is good
23 
24  Parameters: (in calling order)
25  Type Name I/O Description
26  ---- ---- --- -----------
27  l1str * l1rec I/O all L1 line info
28 
29  Modification history:
30  Programmer Date Description of change
31  ---------- ---- ---------------------
32  W. Robinson 3 Apr 2020 Original development
33  W. Robinson, SAIC 1 Jun 2023 set up the cth arrays: cth_alb_init,
34  cth_alb_unc_init
35 
36 *******************************************************************/ {
37  int32_t npix;
38 
39  npix = l1rec->npix;
40 
41  if( ( l1rec->cld_dat = malloc( sizeof( cld_struc ) ) ) == NULL )
42  {
43  printf( "-E- %s, %d: Failure to allocate cloud albedo data structure\n",
44  __FILE__, __LINE__ );
45  return -1;
46  }
47  if( ( ( l1rec->cld_dat->sfc_albedo_659 = (float *)
48  malloc( npix * sizeof( float ) ) ) == NULL ) ||
49  ( ( l1rec->cld_dat->sfc_albedo_858 = (float *)
50  malloc( npix * sizeof( float ) ) ) == NULL ) ||
51  ( ( l1rec->cld_dat->sfc_albedo_1240 = (float *)
52  malloc( npix * sizeof( float ) ) ) == NULL ) ||
53  ( ( l1rec->cld_dat->sfc_albedo_1640 = (float *)
54  malloc( npix * sizeof( float ) ) ) == NULL ) ||
55  ( ( l1rec->cld_dat->sfc_albedo_2130 = (float *)
56  malloc( npix * sizeof( float ) ) ) == NULL ) ||
57  ( ( l1rec->cld_dat->cth_alb_init = (float *)
58  malloc( npix * sizeof( float ) ) ) == NULL ) ||
59  ( ( l1rec->cld_dat->cth_alb_unc_init = (float *)
60  malloc( npix * sizeof( float ) ) ) == NULL ) )
61  {
62  printf( "-E- %s, %d: Failure to allocate cloud albedo data structures\n",
63  __FILE__, __LINE__ );
64  return -1;
65  }
66  return 0;
67  }
68 
69 int read_albedo( int32_t d_np, int32_t d_nl, int32_t st_lin, int32_t ix_clim,
70  int ncid, int *d_id, unsigned char ***alb_dat )
71 /*******************************************************************
72 
73  read_albedo
74 
75  purpose: get the sfc albedo read from the albedo file
76 
77  Returns type: int32_t - status 0 is good
78 
79  Parameters: (in calling order)
80  Type Name I/O Description
81  ---- ---- --- -----------
82  int32_t d_np I albedo data # pixels
83  int32_t d_nl I albedo data # lines
84  int32_t st_lin I start line to readfrom albedo
85  file
86  int32_t ix_clim I time to read -1 for no time
87  (not climatology) else time
88  index
89  int ncid I albedo file id
90  int * d_id I ids of albedo band datasets
91  unsigned char *** alb_dat O final data buffer
92 
93  Modification history:
94  Programmer Date Description of change
95  ---------- ---- ---------------------
96  W. Robinson 30 Mar 2020 Original development
97  *******************************************************************/ {
98  int32_t iwav, i_np, i_nl;
99  size_t start[] = {0,0,0}, count[] = {0,0,0};
100  int32_t ilat;
101  unsigned char *xfr_arr, **alb_lcl;
102 
103  alb_lcl = *alb_dat;
104  /* free permanent storage if needed */
105  if( alb_lcl[0] != NULL )
106  {
107  for( iwav = 0; iwav < 5; iwav++)
108  free( alb_lcl[iwav] );
109  }
110  /* allocate the transfer array and the data arrays */
111  if( ( xfr_arr = (unsigned char *) malloc( d_np * d_nl *
112  sizeof( unsigned char ) ) ) == NULL )
113  {
114  printf( "-E- %s, %d: Error allocating albedo read storage\n",
115  __FILE__, __LINE__ );
116  return -1;
117  }
118 
119  i_np = d_np + 1;
120  i_nl = d_nl + 1;
121 
122  /* get the data from the file to the albedo data array */
123  for( iwav = 0; iwav < 5; iwav++)
124  {
125  if( ( alb_lcl[iwav] = (unsigned char *)
126  malloc( i_np * i_nl * sizeof( unsigned char ) ) ) == NULL )
127  {
128  printf( "-E- %s, %d: Error allocating albedo read storage\n",
129  __FILE__, __LINE__ );
130  return -1;
131  }
132  /* Read data to the transfer array */
133  if( ix_clim < 0 )
134  {
135  /* not a climate dataset */
136  start[0] = st_lin;
137  start[1] = 0;
138  count[0] = d_nl;
139  count[1] = d_np;
140  }
141  else
142  {
143  /* climate dataset */
144  start[0] = ix_clim;
145  start[1] = st_lin;
146  start[2] = 0;
147  count[0] = 1;
148  count[1] = d_nl;
149  count[2] = d_np;
150  }
151  if( nc_get_vara_uchar( ncid, d_id[iwav], start, count, xfr_arr ) !=
152  NC_NOERR )
153  {
154  printf( "-E- %s, %d: Error reading albedo\n",
155  __FILE__, __LINE__ );
156  return -1;
157  }
158 
159  /* place it in the final data array */
160  for( ilat = 0; ilat < d_nl; ilat++ )
161  {
162  memcpy( ( alb_lcl[iwav] + ilat * i_np + 1 ),
163  ( xfr_arr + ilat * d_np ), d_np );
164  /* note that first lon will be copied from the end to get to -180 */
165  *( alb_lcl[iwav] + ilat * i_np ) =
166  *( xfr_arr + ilat * d_np + ( d_np - 1 ) );
167  }
168  /* repeat the last line - only of interest at 90 */
169  memcpy( ( alb_lcl[iwav] + ( i_nl - 1 ) * i_np ),
170  ( alb_lcl[iwav] + ( i_nl - 2 ) * i_np ), i_np );
171  }
172  free( xfr_arr );
173  return 0;
174  }
175 
177 /*******************************************************************
178 
179  acq__sfc_albedo
180 
181  purpose: retrieve the surface albedo for the scan line
182 
183  Returns type: int32_t - status 0 is good
184 
185  Parameters: (in calling order)
186  Type Name I/O Description
187  ---- ---- --- -----------
188  l1str * l1rec I/O all L1 line info
189 
190  Modification history:
191  Programmer Date Description of change
192  ---------- ---- ---------------------
193  W. Robinson 26 Mar 2020 Original development
194 
195  Note that this differs from the anc_acq... 1: only 1 file is read for the
196  data, and 2: the albedo is so large that provision is made to only read
197  in a portion of the albedo data. Also, at this time, all longitudes are
198  read to limit routine complexity.
199 
200  *******************************************************************/ {
201  static int32_t firstcall = 0, is_clim;
202  static int32_t subset_read = 0, scan_npix;
203  static float bdy_siz = 5.;
204  static float scale[5];
205  static float lat_min, lon_min, res1, res2;
206  static double lat_res, lon_res, alb_st_lat, alb_lat_rng[2] = { 900., -900. };
207  static unsigned char **alb_dat, fillv[5];
208  static int32_t ix_clim = -1, sub_nl;
209  static size_t d_np, d_nl, d_nt, i_np;
210  int32_t iwav, ipx, sub_st, good_nav, ix_lat, ix_lon;
211  int32_t n_done, ip, il;
212  float dat_sub[2][2], fin_val, sum;
213  float lat_rng[2] = { 900., -900. };
214  int16_t year, doy;
215  double sec, frac_lat, frac_lon, lat, lon;
216  char *alb_file;
217  char tit_clim[] = "MODIS/TERRA+Aqua BRDF/Albedo Gap-Filled Snow-Free 8-Day climatology";
218  char tit_daily[] = "MODIS/TERRA+Aqua BRDF/Albedo Gap-Filled Snow-Free data";
219  char str_tit[FILENAME_MAX];
220  static int ncid, d_id[5], dim_id, dim_id2;
221  nc_type att_typ;
222  char attr_buf[1024];
223  char *alb_wav_names[5] = { "Albedo_Map_0.659", "Albedo_Map_0.858",
224  "Albedo_Map_1.24", "Albedo_Map_1.64", "Albedo_Map_2.13" };
225  int nc1, nc2;
226 
227  if( firstcall == 0 )
228  {
229  firstcall = 1;
230  alb_file = input->sfc_albedo;
231  //open the file
232  if (nc_open(alb_file, 0, &ncid) != NC_NOERR) {
233  fprintf(stderr,
234  "-E- %s %d: file: %s is not netcdf, not acceptable albedo file\n",
235  __FILE__, __LINE__, alb_file);
236  return -1;
237  }
238  //read the 'title', one of 2 possibilities:
239  nc_get_att_text(ncid, NC_GLOBAL, "title", str_tit);
240  if( strncmp( str_tit, tit_daily, strlen(tit_daily) ) == 0 )
241  {
242  printf( "%s, %d: TEMP: we found the daily file: %s\n",
243  __FILE__, __LINE__, str_tit );
244  is_clim = 0;
245  }
246  else if( strncmp( str_tit, tit_clim, strlen(tit_clim) ) == 0 )
247  {
248  printf( "%s, %d: TEMP: we found the clim file: %s\n", __FILE__,
249  __LINE__, tit_clim );
250  is_clim = 1;
251  /* get the data day -> index to correct time in file */
252  unix2yds( l1rec->scantime, &year, &doy, &sec);
253  ix_clim = ( doy - 1 ) / 8; // day 1 - 8 is index 0 etc
254  printf( "-I- %s, %d: Using climate doy # %d, index: %d\n", __FILE__,
255  __LINE__, doy, ix_clim );
256  printf( "-I- From file: %s\n", alb_file );
257  }
258  else
259  {
260  printf( "-E- %s, %d: Incorrect title in albedo dataset: %s\n",
261  __FILE__, __LINE__, alb_file);
262  return -1;
263  }
264 
265  /* read the geospatial_lat_min etc to get data reolution, start */
266  if( ( nc_get_att_float(ncid, NC_GLOBAL, "geospatial_lat_min", &lat_min )
267  != NC_NOERR ) ||
268  ( nc_get_att_float(ncid, NC_GLOBAL, "geospatial_lon_min", &lon_min )
269  != NC_NOERR ) )
270  {
271  printf( "-E- %s, %d: Unable to read geolocation information for albedo file: %s\n",
272  __FILE__, __LINE__, alb_file);
273  return -1;
274  }
275 
276  /* break out the geospatial_lat_resolution, geospatial_lon_resolution
277  to have flexability for formats */
278  nc_inq_atttype( ncid, NC_GLOBAL, "geospatial_lat_resolution", &att_typ );
279  if( att_typ == NC_FLOAT ) {
280  nc1 = nc_get_att_float(ncid, NC_GLOBAL, "geospatial_lat_resolution",
281  &res1 );
282  } else {
283  nc1 = nc_get_att(ncid, NC_GLOBAL, "geospatial_lat_resolution",
284  attr_buf );
285  res1 = str2resolution(attr_buf);
286  res1 /= 111000; // as the above gives meters
287  }
288 
289  nc_inq_atttype( ncid, NC_GLOBAL, "geospatial_lon_resolution", &att_typ );
290  if( att_typ == NC_FLOAT ) {
291  nc2 = nc_get_att_float(ncid, NC_GLOBAL, "geospatial_lon_resolution",
292  &res2 );
293  } else {
294  nc1 = nc_get_att(ncid, NC_GLOBAL, "geospatial_lon_resolution",
295  attr_buf );
296  res2 = str2resolution(attr_buf);
297  res2 /= 111321; // as the above gives meters, NOTE assume km at equator!
298  }
299  if( ( nc1 != NC_NOERR ) || ( nc2 != NC_NOERR ) )
300  {
301  printf( "-E- %s, %d: Unable to read geolocation information for albedo file: %s\n",
302  __FILE__, __LINE__, alb_file);
303  return -1;
304  }
305 
306  lat_res = res1;
307  lon_res = res2;
308 
309  scan_npix = l1rec->npix;
310  // get the dimension sizes
311  if ((nc_inq_dimid(ncid, "lat", &dim_id) != NC_NOERR) ||
312  (nc_inq_dimid(ncid, "lon", &dim_id2) != NC_NOERR) )
313  {
314  printf( "-E- %s, %d: Error retrieving the lat/lon size\n",
315  __FILE__, __LINE__ );
316  return -1;
317  }
318  if ( ( nc_inq_dimlen(ncid, dim_id, &d_nl ) != NC_NOERR) ||
319  ( nc_inq_dimlen(ncid, dim_id2, &d_np ) != NC_NOERR) )
320  {
321  printf( "-E- %s, %d: Error retrieving the lat/lon size\n",
322  __FILE__, __LINE__ );
323  return -1;
324  }
325  if( is_clim == 1 )
326  {
327  if (nc_inq_dimid(ncid, "doy", &dim_id) != NC_NOERR)
328  {
329  printf( "-E- %s, %d: Error retrieving the doy size\n",
330  __FILE__, __LINE__ );
331  return -1;
332  }
333  if ( nc_inq_dimlen(ncid, dim_id, &d_nt ) != NC_NOERR)
334  {
335  printf( "-E- %s, %d: Error retrieving the doy size\n",
336  __FILE__, __LINE__ );
337  return -1;
338  }
339  }
340  i_np = d_np + 1;
341  /* allocate the 5 wavelength slots in alb_dat */
342  alb_dat = (unsigned char **) malloc( 5 * sizeof( unsigned char * ) );
343  alb_dat[0] = NULL;
344  /* if there are not too many values to read, allocate all the
345  data space here
346  */
347  subset_read = 1;
348  if( (long)d_np * (long)d_nl < 4000000 ) subset_read = 0;
349 
350  /* loop through the 5 bands */
351  for( iwav = 0; iwav < 5; iwav++ )
352  {
353 
354  /* get the data id for the band */
355  if( nc_inq_varid(ncid, alb_wav_names[iwav], ( d_id + iwav ) ) != NC_NOERR)
356  {
357  printf( "-E- %s, %d: Error retrieving the band id\n",
358  __FILE__, __LINE__ );
359  return -1;
360  }
361  /* get the fill and scale values */
362  if( ( nc_get_att_uchar( ncid, d_id[iwav], "_FillValue",
363  ( fillv + iwav ) ) != NC_NOERR ) ||
364  ( nc_get_att_float( ncid, d_id[iwav], "scale_factor",
365  ( scale + iwav ) ) != NC_NOERR ) )
366  {
367  printf( "-E- %s, %d: Error retrieving the fill or scale value\n",
368  __FILE__, __LINE__ );
369  return -1;
370  }
371  }
372  if( subset_read == 0 )
373  {
374  if( read_albedo( d_np, d_nl, 0, ix_clim, ncid, d_id, &alb_dat ) != 0 )
375  return -1;
376  }
377  alb_st_lat = -90.;
378  }
379  /* initialization is complete and all data is read in if possible */
380 
381  /* get the cld_dat structure set if needed */
382  if( l1rec->cld_dat == NULL )
383  {
384  //printf( "\n\n\n-T- %s, %d: setting up the cld_dat in l1rec again\n\n\n",
385  //__FILE__, __LINE__ );
386  // allocate the l1rec albedo struct
387  if( init_cld_dat( l1rec ) != 0 ) return -1;
388  }
389  /* in the case where only a portion of the data is read in based on the
390  latitude range, compute that range and read in that portion if needed */
391 
392  if( subset_read == 1 )
393  {
394  /* find the lat range of the scan */
395  for( ipx = 0; ipx < scan_npix; ipx++ )
396  {
397  lat = l1rec->lat[ipx];
398  if( ( lat >= -90. ) && ( lat <= 90. ) )
399  {
400  if( lat < lat_rng[0] ) lat_rng[0] = lat;
401  if( lat > lat_rng[1] ) lat_rng[1] = lat;
402  }
403  }
404  /* see if we need to read a new range */
405  if( ( alb_lat_rng[0] > lat_rng[0] ) || ( alb_lat_rng[1] < lat_rng[1] ) )
406  {
407  /* read in with added boundary */
408  alb_lat_rng[0] = lat_rng[0] - bdy_siz;
409  if( alb_lat_rng[0] < -90. )
410  alb_lat_rng[0] = -90.;
411  else{
412  // make sure the range falls on the grid points
413  sub_st = ( alb_lat_rng[0] + 90. ) / lat_res;
414  alb_lat_rng[0] = ( sub_st * lat_res ) - 90.;
415  }
416  alb_lat_rng[1] = lat_rng[1] + bdy_siz;
417  if( alb_lat_rng[1] > 90. )
418  alb_lat_rng[1] = 90.;
419  else{
420  sub_st = ( alb_lat_rng[1] + 90. ) / lat_res;
421  alb_lat_rng[1] = ( sub_st * lat_res ) - 90.;
422  }
423  alb_st_lat = alb_lat_rng[0];
424 
425  // printf( "\n\n\n-T- %s, %d: Reading the albedo data for new range:\n",
426  // __FILE__, __LINE__ );
427  printf( "Latitude: %f - %f\n\n\n",
428  alb_lat_rng[0], alb_lat_rng[1] );
429  sub_nl = ( alb_lat_rng[1] - alb_lat_rng[0] + lat_res/2. ) / lat_res;
430  sub_st = ( alb_st_lat + 90. ) / lat_res;
431  if( read_albedo( d_np, sub_nl, sub_st, ix_clim, ncid, d_id,
432  &alb_dat ) != 0 )
433  return -1;
434  }
435  }
436  /* the grid is ready, for each scan point, get the interpolated albedo */
437  for( ipx = 0; ipx < scan_npix; ipx++ )
438  {
439  fin_val = BAD_FLT;
440  lat = l1rec->lat[ipx];
441  lon = l1rec->lon[ipx];
442  good_nav = 0;
443  /* find grid box and position inside the box */
444  if( ( lat >= -90. ) && ( lat <= 90. )
445  && ( lon >= -180. ) && (lon <= 180. ) )
446  {
447  good_nav = 1;
448  frac_lat = ( lat - alb_st_lat ) / lat_res;
449  frac_lon = ( lon + 180 ) / lon_res;
450  ix_lat = (int32_t) frac_lat;
451  ix_lon = (int32_t) frac_lon;
452  frac_lat = frac_lat - (float) ix_lat; /* get remainder */
453  frac_lon = frac_lon - (float) ix_lon;
454  }
455  /* for the wavelengths, get the interpolated value */
456  for( iwav = 0; iwav < 5; iwav++ )
457  {
458  if( good_nav == 1 )
459  {
460  /* get bounding box values */
461  n_done = 0;
462  sum = 0;
463  for( ip = 0; ip < 2; ip++ )
464  {
465  for( il = 0; il < 2; il++ )
466  {
467  if( ix_lat + il >= sub_nl )
468  dat_sub[ip][il] = fillv[iwav];
469  else
470  dat_sub[ip][il] = *( alb_dat[iwav] + ( ix_lon + ip ) +
471  i_np * ( ix_lat + il ) );
472  if( dat_sub[ip][il] != fillv[iwav] )
473  {
474  sum += dat_sub[ip][il] * scale[iwav];
475  n_done++;
476  }
477  }
478  }
479  if( n_done == 0 )
480  {
481  fin_val = BAD_FLT;
482  }
483  else
484  {
485  sum /= n_done;
486  for( ip = 0; ip < 2; ip++ )
487  for( il = 0; il < 2; il++ )
488  {
489  if( dat_sub[ip][il] == fillv[iwav] )
490  dat_sub[ip][il] = sum;
491  else
492  dat_sub[ip][il] *= scale[iwav];
493  }
494  /* get the weighted average */
495  fin_val = ( 1 - frac_lon ) * ( ( dat_sub[0][0] * ( 1 - frac_lat ) ) +
496  ( dat_sub[0][1] * frac_lat ) ) +
497  frac_lon * ( ( dat_sub[1][0] * ( 1 - frac_lat ) ) +
498  ( dat_sub[1][1] * frac_lat ) );
499  }
500  }
501  /* place the final value */
502  switch( iwav )
503  {
504  case 0: l1rec->cld_dat->sfc_albedo_659[ipx] = fin_val;
505  break;
506  case 1: l1rec->cld_dat->sfc_albedo_858[ipx] = fin_val;
507  break;
508  case 2: l1rec->cld_dat->sfc_albedo_1240[ipx] = fin_val;
509  break;
510  case 3: l1rec->cld_dat->sfc_albedo_1640[ipx] = fin_val;
511  break;
512  case 4: l1rec->cld_dat->sfc_albedo_2130[ipx] = fin_val;
513  }
514  }
515  }
516  /* and finish the line */
517  return 0;
518  }
519 
521 /*******************************************************************
522 
523  acq_cth_albedo
524 
525  purpose: retrieve the surface albedo for the scan line for use to make
526  cloud top height - This does what A. Sayer did in his IDL code:
527  get data from the month of the granule and for the nearest grid point
528  to the pixel lat, lon
529 
530  Returns type: int32_t - status 0 is good
531 
532  Parameters: (in calling order)
533  Type Name I/O Description
534  ---- ---- --- -----------
535  l1str * l1rec I/O all L1 line info
536 
537  Modification history:
538  Programmer Date Description of change
539  ---------- ---- ---------------------
540  W. Robinson 31 May 2023 Original development
541 
542  *******************************************************************/ {
543  static size_t start[] = { 0,0,0,0}, count[] = { 0,0,0,0};
544  static float *alb_arr, *alb_unc_arr;
545  static int32_t firstcall = 0;
546  float *arr_ptr, talb;
547  size_t nwave, nmon, nlat, nlon, ix_clim;
548  int16_t year, mon, day, hh, mm;
549  int32_t ipix, ix, iy;
550  double sec;
551  char *alb_file, str_tit[5000];
552  char tit_clim[] = "Surface Lambertian-equivalent reflectivity (LER) observed by TROPOMI";
553  char *arr_nms[] = { "minimum_LER_clear", "uncertainty_clear" };
554  int ncid, d_id, dim_id[4];
555  int status;
556 
557  if( firstcall == 0 )
558  {
559  firstcall = 1;
560  alb_file = input->cth_albedo;
561  //open the file
562  printf( "%s, %d: I - Loading Cloud Top Height albedo file: %s\n",
563  __FILE__, __LINE__, alb_file );
564  if (nc_open(alb_file, 0, &ncid) != NC_NOERR) {
565  fprintf(stderr,
566  "-E- %s %d: file: %s is not netcdf, not acceptable cth albedo file\n",
567  __FILE__, __LINE__, alb_file);
568  return -1;
569  }
570  /* WDR quick, for the reduced TROPOMI file it has normal strings */
571  // read the 'title', and check
572  // This can't be done as the attrib is a string array so repl with 7 lines
573  status = nc_get_att_text(ncid, NC_GLOBAL, "title", str_tit);
574  //size_t varid = 0;
575  //nc_inq_attlen( ncid, NC_GLOBAL, "title", &varid);
576  //size_t attlen = 0;
577  //nc_inq_attlen(ncid, NC_GLOBAL, "title", &attlen);
578  //char **string_attr = (char**)malloc(attlen * sizeof(char*));
579  //memset(string_attr, 0, attlen * sizeof(char*));
580  //nc_get_att_string(ncid, NC_GLOBAL, "title", string_attr);
581 
582  //if( strncmp( string_attr[0], tit_clim, strlen(tit_clim) ) == 0 )
583  if( strncmp( str_tit, tit_clim, strlen(tit_clim) ) == 0 )
584  {
585  printf( "%s, %d: TEMP: we found the cth albedo clim file: %s\n",
586  __FILE__, __LINE__, tit_clim );
587  /* get the month index to correct time in file */
588  unix2ymdhms( l1rec->scantime, &year, &mon, &day, &hh, &mm, &sec);
589  ix_clim = mon - 1;
590  printf( "-I- %s, %d: Using climate month # %d, index: %ld\n", __FILE__,
591  __LINE__, mon, ix_clim );
592  printf( "-I- From file: %s\n", alb_file );
593  }
594  else
595  {
596  printf( "-E- %s, %d: Incorrect title in albedo dataset: %s\n",
597  __FILE__, __LINE__, alb_file);
598  return -1;
599  }
600 
601  // get the dim sizes - these should be as expected
602  if( ( nc_inq_dimid( ncid, "wavelength", dim_id ) != NC_NOERR) ||
603  ( nc_inq_dimid( ncid, "month", ( dim_id + 1 ) ) != NC_NOERR) ||
604  ( nc_inq_dimid( ncid, "latitude", ( dim_id + 2 ) ) != NC_NOERR) ||
605  ( nc_inq_dimid( ncid, "longitude", ( dim_id + 3 ) ) != NC_NOERR) )
606  {
607  printf( "-E- %s, %d: Error retrieving the wave, month, lat, lon size\n",
608  __FILE__, __LINE__ );
609  return -1;
610  }
611  if ( ( nc_inq_dimlen(ncid, dim_id[0], &nwave ) != NC_NOERR) ||
612  ( nc_inq_dimlen(ncid, dim_id[1], &nmon ) != NC_NOERR) ||
613  ( nc_inq_dimlen(ncid, dim_id[2], &nlat ) != NC_NOERR) ||
614  ( nc_inq_dimlen(ncid, dim_id[3], &nlon ) != NC_NOERR) )
615  {
616  printf( "-E- %s, %d: Error retrieving the wave, month, lat, lon size\n",
617  __FILE__, __LINE__ );
618  return -1;
619  }
620  // check for correct # wave, month, lat, lon
621  if( ( nwave != CTH_NWAVE ) || ( nmon != CTH_NMON ) ||
622  ( nlat != CTH_NLAT ) || ( nlon != CTH_NLON ) )
623  {
624  printf( "-E- %s, %d: cth albedo file dimension sizes, wave, month, lat, lon are not as expected\n",
625  __FILE__, __LINE__ );
626  return -1;
627  }
628  // Read the 18th wavelength, and the ix_clim month
629  // for both albedo and uncertainty
630  start[0] = ix_clim; //month
631  start[1] = 18; // wave
632  count[0] = 1;
633  count[1] = 1;
634  count[2] = CTH_NLON; // lon
635  count[3] = CTH_NLAT; // lat
636  // get the slice for that wavelength and month from the minimum_LER_clear
637  // and uncertainty_clear datasets
638  if( ( ( alb_arr = (float *) malloc( nlat * nlon * sizeof( float ) ) )
639  == NULL ) ||
640  ( ( alb_unc_arr = (float *) malloc( nlat * nlon * sizeof( float ) ) )
641  == NULL ) )
642  {
643  printf( "-E- %s, %d: Unable to allocate cth albedo storage\n",
644  __FILE__, __LINE__ );
645  return -1;
646  }
647  // get each dataset
648  for( ipix = 0; ipix < 2; ipix++ )
649  {
650  if( nc_inq_varid( ncid, arr_nms[ipix], &d_id ) != NC_NOERR )
651  {
652  printf( "-E- %s, %d: Unable to find dataset %s in cth albedo file\n",
653  __FILE__, __LINE__, arr_nms[ipix] );
654  return -1;
655  }
656  arr_ptr = ( ipix == 0 ) ? alb_arr : alb_unc_arr;
657  if( ( status = nc_get_vara_float( ncid, d_id, start, count, arr_ptr ) )
658  != NC_NOERR )
659  {
660  printf( "-E- %s, %d: Unable to read dataset %s in cth albedo file\n",
661  __FILE__, __LINE__, arr_nms[0] );
662  return -1;
663  }
664  }
665  nc_close( ncid );
666  } // end of initialization
667  /*
668  loop through the scan and find the closest value in the albedo and unc
669  */
670  for( ipix = 0; ipix < l1rec->npix; ipix++ )
671  {
672  iy = ( l1rec->lat[ipix] + 90. ) / 0.125;
673  ix = ( l1rec->lon[ipix] + 180. ) / 0.125;
674  iy = ( iy < 0 )? 0 : iy;
675  iy = ( iy > 1439 ) ? 1439 : iy;
676  ix = ( ix < 0 ) ? 0 : ix;
677  ix = ( ix > 2879 ) ? 2879 : ix;
678  // make sure albedo is < 0.99 and its unc is > 0.02
679  talb = *( alb_arr + iy + 1440 * ix );
680  l1rec->cld_dat->cth_alb_init[ipix] = ( talb > 0.99 ) ? 0.99 : talb;
681  talb = *( alb_unc_arr + iy + 1440 * ix );
682  l1rec->cld_dat->cth_alb_unc_init[ipix] = ( talb < 0.02 ) ? 0.02 : talb;
683  }
684  /* and finish the line */
685  return 0;
686  }
#define CTH_NLON
Definition: acq_sfc_albedo.c:8
int32_t day
int status
Definition: l1_czcs_hdf.c:32
int read_albedo(int32_t d_np, int32_t d_nl, int32_t st_lin, int32_t ix_clim, int ncid, int *d_id, unsigned char ***alb_dat)
#define NULL
Definition: decode_rs.h:63
read l1rec
#define CTH_NMON
Definition: acq_sfc_albedo.c:6
instr * input
void unix2yds(double usec, short *year, short *day, double *secs)
#define BAD_FLT
Definition: jplaeriallib.h:19
#define CTH_NLAT
Definition: acq_sfc_albedo.c:7
int acq_cth_albedo(l1str *l1rec)
int acq_sfc_albedo(l1str *l1rec)
void unix2ymdhms(double usec, int16_t *year, int16_t *mon, int16_t *day, int16_t *hour, int16_t *min, double *sec)
Definition: unix2ymdhms.c:8
int init_cld_dat(l1str *l1rec)
int npix
Definition: get_cmp.c:28
double str2resolution(char const *resolutionStr)
Pixel resolution string to meters.
#define CTH_NWAVE
Definition: acq_sfc_albedo.c:5
int count
Definition: decode_rs.h:79