OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
viirs_decal.c
Go to the documentation of this file.
1 #include "viirs_sim_sdr.h"
2 #include <math.h>
3 
4 int viirs_decal(ctl_struc *ctl, in_rec_struc *in_rec)
5 /*-----------------------------------------------------------------------------
6  Program: viirs_decal.c
7 
8  Description: convert VIIRS radiances for a scan into dn values
9  The dn can be either dark subtracted (dn) or not (DN) based on the
10  cal_dark_sub value (if 1 [default] make it dark sutract, 0 no subtract)
11 
12  Returns type: int - 0 if good
13 
14  Arguments:
15  Type Name I/O Description
16  ---- ---- --- -----------
17  ctl_struc * ctl I input controls
18  in_rec_struc * in_rec I/O controls for input record reading
19 
20  Modification history:
21 
22  W. Robinson, SAIC 16 Sep 2010 Original development
23 
24 ----------------------------------------------------------------------------*/ {
25  static int first_time = 0, rvs_note = 0;
26  static float dn_max = 4095.; /* max representable dn in 12 bits */
27  static float dn_trans_pct = 0.83; /* general % of max dn when gain
28  transition occurs, NICST memo
29  NICST_MEMO_10_012_*.doc */
30  int ilin, idet, ismp, ipix, ibnd, igain, iham, dn_sat;
31  int npix, nbnd;
32  float c0, c1, c2, a0, a1, a2, dark, lt, aoi, rvs_val, dn, big_dn;
33  float min_rvs[MAX_BND], max_rvs[MAX_BND];
34  static vir_gain_struc gain;
35  static vir_rvs_struc rvs;
36  /*
37  * set up the gain and rvs strucs from the source files
38  * only do the vis NIR (7 bands)
39  */
40  iham = in_rec->ham_side;
41  nbnd = in_rec->nbnd;
42  if (first_time == 0) {
43  if (vset_cal_gain(ctl->count_decal_gain_file, &gain) != 0)
44  return 1;
45  /*
46  * check gain struct so it satisfys the needs
47  */
48  if (gain.nham != 2) {
49  printf("%s, %d: # of HAM sides in gain struct (%d) != 2\n", __FILE__,
50  __LINE__, gain.nham);
51  printf("\tgain file: %s\n", ctl->count_decal_gain_file);
52  return 1;
53  }
54  if (gain.ndet != NDET) {
55  printf(
56  "%s, %d: # of detectors in gain struct (%d) != the VIIRS # (%d)\n",
57  __FILE__, __LINE__, gain.ndet, NDET);
58  printf("\tgain file: %s\n", ctl->count_decal_gain_file);
59  return 1;
60  }
61  if (gain.ngain != 2) {
62  printf("%s, %d: # of gain states in gain struct (%d) != 2\n", __FILE__,
63  __LINE__, gain.nham);
64  printf("\tgain file: %s\n", ctl->count_decal_gain_file);
65  return 1;
66  }
67  if (gain.nbnd < N_VNIR_BND) {
68  printf(
69  "%s, %d: # of bands in gain struct (%d) not >= # VIS / NIR bands (%d)\n",
70  __FILE__, __LINE__, gain.nbnd, N_VNIR_BND);
71  printf("\tgain file: %s\n", ctl->count_decal_gain_file);
72  return 1;
73  }
74 
75  if (vset_cal_rvs(ctl->count_decal_rvs_file, &rvs) != 0)
76  return 1;
77  /*
78  * check rvs struct so it satisfys the needs
79  */
80  if (rvs.nham != 2) {
81  printf("%s, %d: # of HAM sides in RVS struct (%d) != 2\n", __FILE__,
82  __LINE__, rvs.nham);
83  printf("\trvs file: %s\n", ctl->count_decal_rvs_file);
84  return 1;
85  }
86  if (rvs.ndet != NDET) {
87  printf(
88  "%s, %d: # of detectors in RVS struct (%d) != the VIIRS # (%d)\n",
89  __FILE__, __LINE__, rvs.ndet, NDET);
90  printf("\trvs file: %s\n", ctl->count_decal_rvs_file);
91  return 1;
92  }
93  if (rvs.nbnd < N_VNIR_BND) {
94  printf("%s, %d: # of bands in RVS struct (%d) not >= # needed # (%d)\n",
95  __FILE__, __LINE__, rvs.nbnd, nbnd);
96  printf("\trvs file: %s\n", ctl->count_decal_rvs_file);
97  return 1;
98  }
99 
100  for (ibnd = 0; ibnd < N_VNIR_BND; ibnd++) {
101  min_rvs[ibnd] = 999.;
102  max_rvs[ibnd] = -999.;
103  }
104 
105  first_time = 1;
106  }
107  /*
108  * loop through the pixels, lines, and bands to get the lt
109  */
110  npix = in_rec->npix;
111  for (ipix = 0; ipix < npix; ipix++) {
112  /* get sample */
113  ismp = ipix - in_rec->margin[1];
114 
115  /* get the aoi from the sample */
116  vir_xf_scan((float) ismp, VIR_SCAN_UASMP, VIR_SCAN_AOI, &aoi);
117  if ((rvs_note == 0) && ((ipix % 200) == 0)) {
118  float scn_ang;
119  vir_xf_scan((float) ismp, VIR_SCAN_UASMP, VIR_SCAN_ANG, &scn_ang);
120  printf("%s, %d: info, sample: %d, scan angle: %f, aoi: %f\n",
121  __FILE__, __LINE__, ipix, scn_ang, aoi);
122  }
123 
124  for (ilin = 0; ilin < in_rec->ndet_scan; ilin++) {
125  /* get the detector from the line */
126  idet = ilin - in_rec->margin[0];
127  if (idet < 0) idet = 0;
128  if (idet >= NDET) idet = NDET - 1;
129 
130  for (ibnd = 0; ibnd < N_VNIR_BND; ibnd++) {
131  /*
132  * if the lt is not flagged, get it and de-cal
133  */
134  if (*(in_rec->bnd_q[ibnd] + ipix + npix * ilin) == 0) {
135  /*
136  * Assume a high gain range and check later
137  */
138  lt = *(in_rec->bnd_lt[ibnd] + ipix + npix * ilin);
139  igain = 1;
140  dn_sat = 0;
141  dark = *(gain.dark + ibnd + gain.nbnd * (igain + gain.ngain *
142  (idet + gain.ndet * iham)));
143  /*
144  * get the gain, rvs coeffs
145  */
146  c0 = *(gain.c0 + ibnd + gain.nbnd * (igain + gain.ngain *
147  (idet + gain.ndet * iham)));
148  c1 = *(gain.c1 + ibnd + gain.nbnd * (igain + gain.ngain *
149  (idet + gain.ndet * iham)));
150  c2 = *(gain.c2 + ibnd + gain.nbnd * (igain + gain.ngain *
151  (idet + gain.ndet * iham)));
152 
153  a0 = *(rvs.a0 + ibnd + rvs.nbnd * (idet + rvs.ndet * iham));
154  a1 = *(rvs.a1 + ibnd + rvs.nbnd * (idet + rvs.ndet * iham));
155  a2 = *(rvs.a2 + ibnd + rvs.nbnd * (idet + rvs.ndet * iham));
156 
157  rvs_val = a0 + a1 * aoi + a2 * aoi * aoi;
158  if (rvs_note == 0) {
159  /*
160  * record the min and max rvs for each band
161  */
162  if (rvs_val < min_rvs[ibnd])
163  min_rvs[ibnd] = rvs_val;
164  if (rvs_val > max_rvs[ibnd])
165  max_rvs[ibnd] = rvs_val;
166  }
167  /*
168  * apply the gain, rvs to de cal
169  */
170  if (c2 == 0) /* just linear fit */ {
171  dn = (lt * rvs_val - c0) / c1;
172  } else /* a quadratic fit */ {
173  dn = (-c1 + sqrt(c1 * c1 - 4. * c2 * (c0 - lt * rvs_val)))
174  / (2. * c2);
175  }
176  /*
177  * if a dual gain band, see if dn is above the transition
178  */
179  if (gain.gain_ct[ibnd] == 2) {
180  if (dn > (dn_max * dn_trans_pct)) {
181  igain = 0;
182  dark = *(gain.dark + ibnd + gain.nbnd * (igain + gain.ngain *
183  (idet + gain.ndet * iham)));
184  /*
185  * get the low gain coefficients
186  */
187  c0 = *(gain.c0 + ibnd + gain.nbnd * (igain + gain.ngain *
188  (idet + gain.ndet * iham)));
189  c1 = *(gain.c1 + ibnd + gain.nbnd * (igain + gain.ngain *
190  (idet + gain.ndet * iham)));
191  c2 = *(gain.c2 + ibnd + gain.nbnd * (igain + gain.ngain *
192  (idet + gain.ndet * iham)));
193  /*
194  * apply the gain, rvs to de cal
195  */
196  if (c2 == 0) /* just linear fit */ {
197  dn = (lt * rvs_val - c0) / c1;
198  } else /* a quadratic fit */ {
199  dn = (-c1 + sqrt(c1 * c1 - 4. * c2 * (c0 - lt * rvs_val)))
200  / (2. * c2);
201  }
202  big_dn = dn + dark;
203  /*
204  * if it saturates at low gain too, note it
205  */
206  if (big_dn > dn_max) {
207  dn_sat = 1;
208  big_dn = dn_max;
209  }
210  } else /* below, dual gain transition, set the raw dn */ {
211  big_dn = dn + dark;
212  }
213  dn = big_dn - dark;
214  } else /* single gain treatment */ {
215  big_dn = dn + dark;
216  if (big_dn > dn_max) {
217  dn_sat = 1;
218  big_dn = dn_max;
219  }
220  dn = big_dn - dark;
221  }
222  /*
223  * if DN is wanted use big_dn, else, remove the dark from big_dn
224  */
225  if (ctl->count_dark_opt == 0)
226  dn = big_dn - dark;
227  else
228  dn = big_dn;
229  } else /* bad lt val, leave dn 0 */ {
230  dn = 0.;
231  dn_sat = -1;
232  }
233  /*
234  * place the count... in the structure
235  */
236  *(in_rec->dn[ibnd] + ipix + npix * ilin) = dn;
237  *(in_rec->dn_sat[ibnd] + ipix + npix * ilin) = dn_sat;
238  *(in_rec->gain_bit[ibnd] + ipix + npix * ilin) = igain;
239  }
240  }
241  }
242  /*
243  * report the rvs min, max
244  */
245  if (rvs_note == 0) {
246  rvs_note = 1;
247  printf("\n\n%s, %d:info\n", __FILE__, __LINE__);
248  printf("\nDe-calibration RVS min and max / band:\n");
249  printf("(file: %s\n", ctl->count_decal_rvs_file);
250  printf("\nM band Min RVS Max RVS\n");
251  for (ibnd = 0; ibnd < N_VNIR_BND; ibnd++)
252  printf(" %3d %9.6f %9.6f\n", ibnd + 1,
253  min_rvs[ibnd], max_rvs[ibnd]);
254  printf("----------------------------------------\n\n");
255  }
256  /*
257  * end loops and done
258  */
259  return 0;
260 }
#define VIR_SCAN_ANG
Definition: viirs_sim_sdr.h:53
int16 * gain
Definition: l1_czcs_hdf.c:33
#define MAX_BND
Definition: viirs_sim_sdr.h:34
int nbnd
Definition: get_cmp.c:29
int vset_cal_gain(char *, vir_gain_struc *)
Definition: vset_cal.c:16
int vset_cal_rvs(char *, vir_rvs_struc *)
Definition: vset_cal.c:280
int viirs_decal(ctl_struc *ctl, in_rec_struc *in_rec)
Definition: viirs_decal.c:4
#define VIR_SCAN_AOI
Definition: viirs_sim_sdr.h:54
int vir_xf_scan(float, int, int, float *)
Definition: vir_xf_scan.c:3
#define VIR_SCAN_UASMP
Definition: viirs_sim_sdr.h:52
#define NDET
Definition: polcor.c:13
#define N_VNIR_BND
Definition: viirs_sim_sdr.h:31
int npix
Definition: get_cmp.c:27