OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
vset_cal.c
Go to the documentation of this file.
1 #include "viirs_sim_sdr.h"
2 /*
3  * as the hdf 4 will be hopefully temporary, just have the includes here
4  */
5 #include "hio.h"
6 
7 #include <hdf.h>
8 #include <mfhdf.h>
9 
10 /*
11  * file vset_cal.c containing
12  * vset_cal_gain for the gain information
13  * vset_cal_rvs for the RVS info
14  */
15 
16 int vset_cal_gain(char *file, vir_gain_struc *gain)
17 /*-----------------------------------------------------------------------------
18  Routine: vset_cal_gain
19 
20  Description: get the gain related coefficients for VIIRS calibration
21 
22  Returns type: int - 0 if good, else I/O error
23 
24  Arguments:
25  Type Name I/O Description
26  ---- ---- --- -----------
27  char * file I calibration file name
28  vir_gain_struc * gain O structure with quadratic gain coeffs,
29  dark count, and max Lt for the high gain
30  (to cue shifting to use of low gain)
31 
32  Modification history:
33 
34  W. Robinson, SAIC 16 Sep 2010 Original development
35 
36 ----------------------------------------------------------------------------*/ {
37  float dn_trans_pct = 0.83; /* the gain switches to low at 83% of the 4095
38  counts for the 12 bit dn (small) values */
39  float c0, c1, c2, dark, lt_max, dn, big_dn, dn_max = 4095.;
40  float min_hg_lim[MAX_BND], max_hg_lim[MAX_BND],
41  min_lg_lim[MAX_BND], max_lg_lim[MAX_BND],
42  min_dn_lg[MAX_BND], max_dn_lg[MAX_BND],
43  min_dn_hg[MAX_BND], max_dn_hg[MAX_BND],
44  min_big_dn_lg[MAX_BND], max_big_dn_lg[MAX_BND],
45  min_big_dn_hg[MAX_BND], max_big_dn_hg[MAX_BND];
46  int iham, idet, igain, ibnd, ext_gain = 0;
47  int nham = 2, ndet = 16, ngain = 2, nbnd = 11;
48  char gain_ct[] = {2, 2, 2, 2, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1};
49  /* for above, # gain states for each m band */
50  h5io_str fid;
51  /*
52  * If file is unspecified, fill general array with values from the TVAC test
53  * which are band-averaged. They are also just the c1 as c0 and c2 are 0.
54  * The file source is
55  * VIIRS_RSB_Band_Average_Gains.xlsx, other info:
56  * From NICST Murphy Chart RC_02_V3 (1-12-2010)
57  * Units are dn/(W/m^2/str/micron)
58  * SO to get the c1 value (W.../dn) we'll need to invert these
59  * and if c2 is in W^2/dn in future, we'll have to re-form the equations
60  * 11 reflective M bands, low gain followed by high gain,
61  * 0. for bands with only high gain
62  */
63  float m_gains[22] = {6.4, 4.90, 4.44, 4.76, 5.15, -1., 9.97,
64  -1., -1., -1., -1.,
65  27.26, 23.84, 27.35, 37.13, 50.97, 109.37, 84.19,
66  28.11, 41.99, 49.52, 91.49};
67 
68  /*
69  * if a file was specified, open it and get the size information
70  */
71  if (strcmp(file, "Unspecified") != 0) {
72  ext_gain = 1;
73  if (h5io_openr(file, 0, &fid) != 0) {
74  printf("%s, %d, Unable to open gain calibration file: \n%s\n",
75  __FILE__, __LINE__, file);
76  return 1;
77  }
78  if (h5io_rd_attr(&fid, "ngain", (void *) &(gain->ngain)) != 0) {
79  printf("%s, %d, Unable to read ngain attr from calibration file: \n%s\n",
80  __FILE__, __LINE__, file);
81  return 1;
82  }
83  if (h5io_rd_attr(&fid, "nham", (void *) &(gain->nham)) != 0) {
84  printf("%s, %d, Unable to read nham attr from calibration file: \n%s\n",
85  __FILE__, __LINE__, file);
86  return 1;
87  }
88  if (h5io_rd_attr(&fid, "ndet", (void *) &(gain->ndet)) != 0) {
89  printf("%s, %d, Unable to read ndet attr from calibration file: \n%s\n",
90  __FILE__, __LINE__, file);
91  return 1;
92  }
93  if (h5io_rd_attr(&fid, "nbnd", (void *) &(gain->nbnd)) != 0) {
94  printf("%s, %d, Unable to read nbnd attr from calibration file: \n%s\n",
95  __FILE__, __LINE__, file);
96  return 1;
97  }
98  if ((gain->ngain != ngain) || (gain->nham != nham) ||
99  (gain->ndet != ndet) || (gain->nbnd != nbnd)) {
100  printf("%s, %d, Unexpected gain array dimensions found in file: \n%s\n",
101  __FILE__, __LINE__, file);
102  printf(" ngain: %d, expected: %d\n", gain->ngain, ngain);
103  printf(" nham: %d, expected: %d\n", gain->nham, nham);
104  printf(" ndet: %d, expected: %d\n", gain->ndet, ndet);
105  printf(" nbnd: %d, expected: %d\n", gain->nbnd, nbnd);
106  return 1;
107  }
108  } else {
109  gain->nham = nham;
110  gain->ndet = ndet;
111  gain->ngain = ngain;
112  gain->nbnd = nbnd;
113  }
114  /*
115  * allocate space for the coefficient arrays
116  */
117  if ((gain->c0 = (float *)
118  malloc(nham * ndet * ngain * nbnd * sizeof ( float))) == NULL) {
119  printf("%s, %d: Error allocating the gain->c0\n", __FILE__, __LINE__);
120  return 1;
121  }
122  if ((gain->c1 = (float *)
123  malloc(nham * ndet * ngain * nbnd * sizeof ( float))) == NULL) {
124  printf("%s, %d: Error allocating the gain->c1\n", __FILE__, __LINE__);
125  return 1;
126  }
127  if ((gain->c2 = (float *)
128  malloc(nham * ndet * ngain * nbnd * sizeof ( float))) == NULL) {
129  printf("%s, %d: Error allocating the gain->c2\n", __FILE__, __LINE__);
130  return 1;
131  }
132  if ((gain->dark = (float *)
133  malloc(nham * ndet * ngain * nbnd * sizeof ( float))) == NULL) {
134  printf("%s, %d: Error allocating the gain->dark\n", __FILE__, __LINE__);
135  return 1;
136  }
137  /*
138  * set the min, max low and high gain limits radiances (without RVS)
139  * As the hi-lo gain transition happens at a % of dn, get that instead for h-l
140  */
141  for (ibnd = 0; ibnd < nbnd; ibnd++) {
142  min_hg_lim[ibnd] = 999.;
143  max_hg_lim[ibnd] = -999.;
144  min_lg_lim[ibnd] = 999.;
145  max_lg_lim[ibnd] = -999.;
146  min_dn_lg[ibnd] = 9999.;
147  max_dn_lg[ibnd] = -9999.;
148  min_dn_hg[ibnd] = 9999.;
149  max_dn_hg[ibnd] = -9999.;
150  min_big_dn_lg[ibnd] = 9999.;
151  max_big_dn_lg[ibnd] = -9999.;
152  min_big_dn_hg[ibnd] = 9999.;
153  max_big_dn_hg[ibnd] = -9999.;
154  }
155  dn = dn_max * dn_trans_pct;
156  /*
157  * If no gain file specified, use the internal values, else read in
158  */
159  if (ext_gain == 1) {
160  if (h5io_grab_ds(&fid, "c0", (void *) gain->c0) != 0) {
161  printf("%s, %d, Unable to read c0 dataset from calibration file: \n%s\n",
162  __FILE__, __LINE__, file);
163  return 1;
164  }
165  if (h5io_grab_ds(&fid, "c1", (void *) gain->c1) != 0) {
166  printf("%s, %d, Unable to read c1 dataset from calibration file: \n%s\n",
167  __FILE__, __LINE__, file);
168  return 1;
169  }
170  if (h5io_grab_ds(&fid, "c2", (void *) gain->c2) != 0) {
171  printf("%s, %d, Unable to read c2 dataset from calibration file: \n%s\n",
172  __FILE__, __LINE__, file);
173  return 1;
174  }
175  if (h5io_grab_ds(&fid, "dark", (void *) gain->dark) != 0) {
176  printf(
177  "%s, %d, Unable to read dark dataset from calibration file: \n%s\n",
178  __FILE__, __LINE__, file);
179  return 1;
180  }
181  } else {
182  /*
183  * fill the coefficients from the local information
184  */
185  for (iham = 0; iham < nham; iham++) {
186  for (idet = 0; idet < ndet; idet++) {
187  for (ibnd = 0; ibnd < nbnd; ibnd++) {
188  for (igain = 0; igain < ngain; igain++) {
189  if ((gain_ct[ibnd] == 1) && (igain == 0)) continue;
190  /* set c0, 1, 2, dark and gain from internal values */
191  c0 = 0.;
192  /* note the provided c1s are dn / W..., so invert to use */
193  c1 = 1. / *(m_gains + ibnd + igain * nbnd);
194  c2 = 0.;
195  dark = 250. + ibnd;
196  *(gain->c0 + ibnd + nbnd * (igain + ngain *
197  (idet + ndet * iham))) = c0;
198  *(gain->c1 + ibnd + nbnd * (igain + ngain *
199  (idet + ndet * iham))) = c1;
200  *(gain->c2 + ibnd + nbnd * (igain + ngain *
201  (idet + ndet * iham))) = c2;
202  *(gain->dark + ibnd + nbnd * (igain + ngain *
203  (idet + ndet * iham))) = dark;
204  }
205  }
206  }
207  }
208  }
209  /*
210  * for gathering the min, max of the limit radiance, compute here
211  */
212  for (iham = 0; iham < nham; iham++) {
213  for (idet = 0; idet < ndet; idet++) {
214  for (ibnd = 0; ibnd < nbnd; ibnd++) {
215  for (igain = 0; igain < ngain; igain++) {
216  if ((gain_ct[ibnd] == 1) && (igain == 0)) continue;
217  big_dn = dn + *(gain->dark + ibnd + nbnd * (igain + ngain *
218  (idet + ndet * iham)));
219  c0 = *(gain->c0 + ibnd + nbnd * (igain + ngain *
220  (idet + ndet * iham)));
221  c1 = *(gain->c1 + ibnd + nbnd * (igain + ngain *
222  (idet + ndet * iham)));
223  c2 = *(gain->c2 + ibnd + nbnd * (igain + ngain *
224  (idet + ndet * iham)));
225  lt_max = c0 + c1 * dn + c2 * dn * dn;
226  if (igain == 0) {
227  if (lt_max < min_lg_lim[ibnd]) min_lg_lim[ibnd] = lt_max;
228  if (lt_max > max_lg_lim[ibnd]) max_lg_lim[ibnd] = lt_max;
229  if (dn < min_dn_lg[ibnd]) min_dn_lg[ibnd] = dn;
230  if (dn > max_dn_lg[ibnd]) max_dn_lg[ibnd] = dn;
231  if (big_dn < min_big_dn_lg[ibnd]) min_big_dn_lg[ibnd] = big_dn;
232  if (big_dn > max_big_dn_lg[ibnd]) max_big_dn_lg[ibnd] = big_dn;
233  } else {
234  if (lt_max < min_hg_lim[ibnd]) min_hg_lim[ibnd] = lt_max;
235  if (lt_max > max_hg_lim[ibnd]) max_hg_lim[ibnd] = lt_max;
236  if (dn < min_dn_hg[ibnd]) min_dn_hg[ibnd] = dn;
237  if (dn > max_dn_hg[ibnd]) max_dn_hg[ibnd] = dn;
238  if (big_dn < min_big_dn_hg[ibnd]) min_big_dn_hg[ibnd] = big_dn;
239  if (big_dn > max_big_dn_hg[ibnd]) max_big_dn_hg[ibnd] = big_dn;
240  }
241  if (lt_max < 0) {
242  printf("%s, %d: lt_max < 0 at ham: %d, det: %d, bnd: %d, gain:%d\n",
243  __FILE__, __LINE__, iham, idet, ibnd, igain);
244  }
245  }
246  }
247  }
248  }
249  /*
250  * report the radiance, dn limits found
251  */
252  printf("\n\n%s, %d: info:\n", __FILE__, __LINE__);
253  printf("\nRadiance, dn limit min and max per band\n");
254  printf("(file: %s)\n", file);
255  if (strcmp(file, "Unspecified") == 0)
256  printf("Using the general gains from TVAC tests\n");
257  printf("For HIGH GAIN setting\n");
258  printf(
259  "\nM band Min rad Max rad Min dn Max dn Min DN Max DN\n");
260  for (ibnd = 0; ibnd < nbnd; ibnd++)
261  printf(" %3d %9.4f %9.4f %8.2f %8.2f %8.2f %8.2f\n", ibnd + 1,
262  min_hg_lim[ibnd], max_hg_lim[ibnd], min_dn_hg[ibnd], max_dn_hg[ibnd],
263  min_big_dn_hg[ibnd], max_big_dn_hg[ibnd]);
264  printf("\nFor LOW GAIN setting\n");
265  printf(
266  "\nM band Min rad Max rad Min dn Max dn Min DN Max DN\n");
267  for (ibnd = 0; ibnd < nbnd; ibnd++)
268  printf(" %3d %9.4f %9.4f %8.2f %8.2f %8.2f %8.2f\n", ibnd + 1,
269  min_lg_lim[ibnd], max_lg_lim[ibnd], min_dn_lg[ibnd], max_dn_lg[ibnd],
270  min_big_dn_lg[ibnd], max_big_dn_lg[ibnd]);
271  printf("----------------------------------------\n\n");
272  /*
273  * transfer the # gain states
274  */
275  for (ibnd = 0; ibnd < nbnd; ibnd++)
276  *(gain->gain_ct + ibnd) = gain_ct[ibnd];
277  return 0;
278 }
279 
280 int vset_cal_rvs(char *file, vir_rvs_struc *rvs)
281 /*-----------------------------------------------------------------------------
282  Routine: vset_cal_rvs
283 
284  Description: get the rvs related coefficients for VIIRS calibration
285 
286  Returns type: int - 0 if good, else I/O error
287 
288  Arguments:
289  Type Name I/O Description
290  ---- ---- --- -----------
291  char * file I RVS calibration file name up to the
292  band wavelength. individual files
293  are for each band's RVS
294  vir_rvs_struc * rvs O structure with quadratic RVS coeffs,
295  as a function of AOI on HAM
296 
297  Modification history:
298 
299  W. Robinson, SAIC 16 Sep 2010 Original development
300  W. Robinson, SAIC 7 Jan 2011 Change so that if 'Unspecified' file
301  is used, a unity RVS is used
302 
303 ----------------------------------------------------------------------------*/ {
304  int ibnd, iham, idet, bnd_lambda[16];
305  int nbnd = 11, npoly = 3, nham = 2, ndet = 1;;
306  char hfile[500];
307  float *lcl_buf;
308  hio_struct finfo;
309  /*
310  * The coefficients for RVS are for a polinomial applied to the angle of
311  * incidence on the mirror AOI: RVS = a0 + a1 * aoi + a2 * aoi^2
312  *
313  * set up array sizes
314  */
315  rvs->nham = nham;
316  rvs->ndet = ndet;
317  rvs->nbnd = nbnd;
318  /*
319  * There is a RVS for I1 at 640 nm, but for this version, I1 will be ignored.
320  */
321  if (bnd_ix_2_sen_info("Lambda", (void *) bnd_lambda) != 0) {
322  printf("%s, %d: Error in getting lambda, Exiting\n", __FILE__, __LINE__);
323  return 1;
324  }
325  /*
326  * although the hdf files could be read for the array size, as other
327  * parts are hard-coded, hard-code the size as we know for these files
328  *
329  * allocate the rvs storage
330  */
331  if ((rvs->a0 = (float *) malloc(nham * ndet * nbnd * sizeof ( float)))
332  == NULL) {
333  printf("%s, %d: Error in allocating rvs->a0\n", __FILE__, __LINE__);
334  return 1;
335  }
336  if ((rvs->a1 = (float *) malloc(nham * ndet * nbnd * sizeof ( float)))
337  == NULL) {
338  printf("%s, %d: Error in allocating rvs->a1\n", __FILE__, __LINE__);
339  return 1;
340  }
341  if ((rvs->a2 = (float *) malloc(nham * ndet * nbnd * sizeof ( float)))
342  == NULL) {
343  printf("%s, %d: Error in allocating rvs->a2\n", __FILE__, __LINE__);
344  return 1;
345  }
346  /*
347  * Print the input file
348  */
349  printf("%s, %d, RVS file input: %s\n", __FILE__, __LINE__, file);
350  /*
351  * if RVS file was unspecified, use a unit RVS
352  */
353  if (strcmp(file, "Unspecified") == 0) {
354  printf("%s, %d: Note that unit RVS will be used\n", __FILE__, __LINE__);
355  for (ibnd = 0; ibnd < nbnd; ibnd++)
356  for (iham = 0; iham < nham; iham++)
357  for (idet = 0; idet < ndet; idet++) {
358  *(rvs->a0 + ibnd + nbnd * (idet + ndet * iham)) = 1.;
359  *(rvs->a1 + ibnd + nbnd * (idet + ndet * iham)) = 0.;
360  *(rvs->a2 + ibnd + nbnd * (idet + ndet * iham)) = 0.;
361  }
362  } else {
363  /*
364  * for a rvs file specified,
365  * make a read buffer for the hdf 4 i/o of the RVS
366  */
367  if ((lcl_buf = (float *) malloc(npoly * nham * ndet * sizeof ( float)))
368  == NULL) {
369  printf("%s, %d: Error in allocating lcl read buffer\n",
370  __FILE__, __LINE__);
371  return 1;
372  }
373  /*
374  * open each hdf 4 file and read the gain
375  */
376  for (ibnd = 0; ibnd < nbnd; ibnd++) {
377  /*
378  * make file name
379  */
380  sprintf(hfile, "%s%s%d%s", file, "_", bnd_lambda[ibnd], ".hdf");
381 
382  printf("%s, %d, opening RVS file %s\n", __FILE__, __LINE__, hfile);
383  /*
384  * open file
385  */
386  if (hio_open(hfile, DFACC_RDONLY, &finfo) != 0) {
387  printf("%s, %d: Error, Unable to open the HDF file: %s\n",
388  __FILE__, __LINE__, hfile);
389  return 1;
390  }
391  /*
392  * read the rvs
393  */
394  if (hio_r_sds(finfo, "rvs", DFNT_FLOAT32, (void *) lcl_buf) != 0) {
395  printf("%s, %d: Error, Unable to read the 'rvs' SDS for HDF file: %s\n",
396  __FILE__, __LINE__, hfile);
397  return 1;
398  }
399  /*
400  * read the aoi range
401  */
402  if (hio_r_sds(finfo, "aoirange", DFNT_FLOAT32, (void *) rvs->aoi_range)
403  != 0) {
404  printf(
405  "%s, %d: Error, Unable to read the 'aoirange' SDS for HDF file: %s\n",
406  __FILE__, __LINE__, hfile);
407  return 1;
408  }
409  printf("%s, %d: Info: aoi range is: %f %f\n", __FILE__, __LINE__,
410  rvs->aoi_range[0], rvs->aoi_range[1]);
411  /*
412  * close the file
413  */
414  hio_close(finfo);
415  /*
416  * transfer the information into the rvs coeff storage
417  */
418  for (iham = 0; iham < nham; iham++) {
419  for (idet = 0; idet < ndet; idet++) {
420  *(rvs->a0 + ibnd + nbnd * (idet + ndet * iham)) =
421  *(lcl_buf + idet + ndet * (iham + nham * 0));
422  *(rvs->a1 + ibnd + nbnd * (idet + ndet * iham)) =
423  *(lcl_buf + idet + ndet * (iham + nham * 1));
424  *(rvs->a2 + ibnd + nbnd * (idet + ndet * iham)) =
425  *(lcl_buf + idet + ndet * (iham + nham * 2));
426  }
427  }
428  }
429  /*
430  * release local storage
431  */
432  free(lcl_buf);
433  }
434  return 0;
435 }
int h5io_openr(char *file, int opt, h5io_str *id)
Definition: h5io.c:4
int16 * gain
Definition: l1_czcs_hdf.c:33
int vset_cal_rvs(char *file, vir_rvs_struc *rvs)
Definition: vset_cal.c:280
#define NULL
Definition: decode_rs.h:63
#define MAX_BND
Definition: viirs_sim_sdr.h:34
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
int nbnd
Definition: get_cmp.c:29
int32 hio_close(hio_struct)
Definition: hio_close.c:3
int bnd_ix_2_sen_info(char *pname, void *pval)
int h5io_rd_attr(h5io_str *id, char *attr_name, void *data)
Definition: h5io.c:412
int32 hio_open(char *, int32, hio_struct *)
int h5io_grab_ds(h5io_str *id, char *path_name, void *data)
Definition: h5io.c:1347
HDF4 data type of the output SDS Default is DFNT_FLOAT32 Common types used DFNT_FLOAT32
int32 hio_r_sds(hio_struct, char *, int32, void *)
Definition: hio_r_sds.c:4
int vset_cal_gain(char *file, vir_gain_struc *gain)
Definition: vset_cal.c:16