OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
smile.c
Go to the documentation of this file.
1 
7 #include "smile.h"
8 
9 #include <genutils.h>
10 
11 #include <math.h>
12 #include <stdlib.h>
13 
14 
15 // max line length in a bandinfo.txt file
16 #define BANDINFO_LINE_MAX 255
17 
18 // this is also used as a flag to see if smile correction has been initialized
19 static int numBands = 0;
20 
21 static int numDetectors;
22 
23 static int *switch_land; // [bands]
24 static int *lower_land; // [bands]
25 static int *upper_land; // [bands]
26 static int *switch_water; // [bands]
27 static int *lower_water; // [bands]
28 static int *upper_water; // [bands]
29 static float *theoWL; // [bands]
30 static float *theoE0; // [bands]
31 
32 static float *detectorWL; // [detector][band]
33 static float *detectorE0; // [detector][band]
34 
35 // set the detector center wavelengths
36 //
37 // note: that the dimensions are detectorWLs[numDetectors][numBands]
38 
48 void smile_init(int num_bands, int num_detectors, const char* bandinfo_filename,
49  float* detectorWLs, float* detectorE0s) {
50  char line[BANDINFO_LINE_MAX];
51  FILE *fp = NULL;
52  int count;
53  int dummy;
54  int band;
55 
56  if (numBands != 0) {
57  printf("-E- %s:%d - Can not re-initialize the smile correction.", __FILE__, __LINE__);
58  exit(1);
59  }
60  if (bandinfo_filename == NULL) {
61  printf("-E- %s:%d - bandinfo_filename can not be NULL.", __FILE__, __LINE__);
62  exit(1);
63  }
64  if (detectorWLs == NULL) {
65  printf("-E- %s:%d - detectorWLs can not be NULL.", __FILE__, __LINE__);
66  exit(1);
67  }
68  if (detectorE0s == NULL) {
69  printf("-E- %s:%d - detectorE0s can not be NULL.", __FILE__, __LINE__);
70  exit(1);
71  }
72 
73  numBands = num_bands;
74  numDetectors = num_detectors;
75  detectorWL = detectorWLs;
76  detectorE0 = detectorE0s;
77 
78  switch_land = (int*) allocateMemory(sizeof (int)*numBands, "smile switch_land");
79  lower_land = (int*) allocateMemory(sizeof (int)*numBands, "smile lower_land");
80  upper_land = (int*) allocateMemory(sizeof (int)*numBands, "smile upper_land");
81  switch_water = (int*) allocateMemory(sizeof (int)*numBands, "smile switch_water");
82  lower_water = (int*) allocateMemory(sizeof (int)*numBands, "smile lower_water");
83  upper_water = (int*) allocateMemory(sizeof (int)*numBands, "smile upper_water");
84  theoWL = (float*) allocateMemory(sizeof (float)*numBands, "smile theoWL");
85  theoE0 = (float*) allocateMemory(sizeof (float)*numBands, "smile theoE0");
86 
87  /*-------------------------------------------------------------*/
88  // read the band_info file
89  if ((fp = fopen(bandinfo_filename, "r")) == NULL) {
90  fprintf(stderr,
91  "-E- %s:%d: unable to open %s for reading\n", __FILE__, __LINE__, bandinfo_filename);
92  exit(1);
93  }
94 
95  // discard the first line of column labels
96  fgets(line, BANDINFO_LINE_MAX, fp);
97  for (band = 0; band < numBands; band++) {
98  if (!fgets(line, BANDINFO_LINE_MAX, fp)) {
99  fprintf(stderr, "-E- %s line %d: unable to read band %d from file %s\n",
100  __FILE__, __LINE__, band, bandinfo_filename);
101  exit(1);
102  }
103  count = sscanf(line, "%d %d %d %d %d %d %d %f %f", &dummy,
104  &switch_water[band], &lower_water[band], &upper_water[band],
105  &switch_land[band], &lower_land[band], &upper_land[band],
106  &theoWL[band], &theoE0[band]);
107  if (count != 9) {
108  fprintf(stderr,
109  "-E- %s line %d: unable to read band %d line from file %s, count = %d\n",
110  __FILE__, __LINE__, band, bandinfo_filename, count);
111  exit(1);
112  }
113 
114  // now change the indexes to 0 based array indexes
115  lower_land[band]--;
116  upper_land[band]--;
117  lower_water[band]--;
118  upper_water[band]--;
119 
120  } // for band
121  fclose(fp);
122 
123  if (want_verbose)
124  printf("\nSmile corrections enabled.\n\n");
125 
126 }
127 
128 /* ------------------------------------------------------------------------ */
129 /* */
130 /* smile_calc_delta() */
131 /* calculates the smile delta for all of the bands of a pixel */
132 /* */
133 /* int *shouldCorrect true if the reflectance correction should be made */
134 /* int *indexes1 index of lower band to use for interpolation */
135 /* int *indexes2 upper band to use for intrepolation */
136 /* float *radiances original measurment */
137 /* float *theoretWLs theoretical wavelengths for each band */
138 /* float *theoretE0s theoretical sun spectral fluxes for each band */
139 /* float *detectorWLs detector wavelengths for each band */
140 /* float *detectorE0s sun spectral fluxes for the detector wavelengths */
141 /* float *delta resulting smile delta correction */
142 /* */
143 /* D. Shea, SAIC, Jan 2009. */
144 
145 /* ------------------------------------------------------------------------ */
146 void smile_calc_delta(int *shouldCorrect,
147  int *indexes1,
148  int *indexes2,
149  float *radiances,
150  float *theoretWLs,
151  float *theoretE0s,
152  float fsol,
153  float *detectorWLs,
154  float *detectorE0s,
155  float *delta) {
156  double r0, r1, r2, rc, dl, dr;
157  int i0, i1, i2;
158 
159  for (i0 = 0; i0 < numBands; i0++) {
160 
161  // perform irradiance correction
162  r0 = radiances[i0] / detectorE0s[i0];
163  rc = r0 * theoretE0s[i0] * fsol;
164  delta[i0] = rc - radiances[i0];
165  if (shouldCorrect[i0]) {
166  // perform reflectance correction
167  i1 = indexes1[i0];
168  i2 = indexes2[i0];
169  r1 = radiances[i1] / detectorE0s[i1];
170  r2 = radiances[i2] / detectorE0s[i2];
171  dl = (theoretWLs[i0] - detectorWLs[i0]) / (detectorWLs[i2] - detectorWLs[i1]);
172  dr = (r2 - r1) * dl * theoretE0s[i0] * fsol;
173  delta[i0] += dr;
174  delta[i0] /= 10.0; // put delta into l2gen units
175  } else {
176  delta[i0] /= 10.0; // put delta into l2gen units
177  }
178  } // for bands
179 
180 }
181 
182 
183 /* ------------------------------------------------------------------------ */
184 /* radcor() */
185 /* loads smile calibration deltas into the radcor array of l1rec */
186 /* */
187 /* l1rec level 1 record to set radcor in */
188 /* ip pixel number used to calculate the smile correction */
189 /* land 0=ocean, else=land */
190 /* */
191 /* */
192 /* D. Shea, SAIC, Jan 2009. */
193 
194 /* ------------------------------------------------------------------------ */
195 void radcor(l1str *l1rec, int32_t ip, int32_t land, int32_t escorrected) {
196 
197  int ib;
198  int ipb;
199  int *shouldCorrect;
200  int correctionPossible;
201  int *index1;
202  int *index2;
203  int detectorIndex;
204  static float *Ltemp;
205 
206  // not initialized so do nothing
207  if (numBands == 0)
208  return;
209 
210  if (!Ltemp) {
211  Ltemp = (float*) allocateMemory(sizeof (float)*numBands, "smile temp Lt array");
212  }
213 
214  /*-------------------------------------------------------------*/
215  // do the correction
216 
217  detectorIndex = l1rec->pixdet[ip];
218  correctionPossible = ((detectorIndex >= 0) && (detectorIndex < numDetectors));
219 
220  if (correctionPossible) {
221  if (land) {
222  shouldCorrect = switch_land;
223  index1 = lower_land;
224  index2 = upper_land;
225  } else {
226  shouldCorrect = switch_water;
227  index1 = lower_water;
228  index2 = upper_water;
229  }
230 
231  // correct all bands for ozone
232  for (ib = 0; ib < numBands; ib++) {
233  ipb = ip * l1rec->l1file->nbands + ib; // use the real nbands here to index properly
234 
235  /* Correct for ozone absorption. We correct for inbound and outbound here, */
236  /* then we put the inbound back when computing Lw. */
237  Ltemp[ib] = l1rec->Lt[ipb] * 10.0;
238  } // for ib
239  // OLCI and MERIS 'SAFE' format "solar_flux" data are Earth-Sun distance corrected,
240  // MERIS N1 are not account for that with fsol, as appropriate
241  float fsol = l1rec->fsol;
242  if (!escorrected)
243  fsol = 1.0;
244  smile_calc_delta(shouldCorrect,
245  index1,
246  index2,
247  Ltemp,
248  theoWL,
249  theoE0,
250  fsol,
251  &(detectorWL[detectorIndex * numBands]),
252  &(detectorE0[detectorIndex * numBands]),
253  &(l1rec->radcor[ip * l1rec->l1file->nbands]));
254 
255  } else {
256  // if correction not possible, ensure radcor delta is zero
257  for (ib = 0; ib < numBands; ib++) {
258  ipb = ip * l1rec->l1file->nbands + ib;
259  l1rec->radcor[ipb] = 0;
260  }
261  } // correction possible
262 
263 }
void radcor(l1str *l1rec, int32_t ip, int32_t land, int32_t escorrected)
Definition: smile.c:195
void * allocateMemory(size_t numBytes, const char *name)
Definition: allocateMemory.c:7
#define NULL
Definition: decode_rs.h:63
read l1rec
PARAM_TYPE_NONE Default value No parameter is buried in the product name name_prefix is case insensitive string compared to the product name PARAM_TYPE_VIS_WAVE The visible wavelength bands from the sensor are buried in the product name The product name is compared by appending and name_suffix ie aph_412_giop where prod_ix will be set to PARAM_TYPE_IR_WAVE same search method as PARAM_TYPE_VIS_WAVE except only wavelength above are looped through but prod_ix is still based ie aph_2_giop for the second band
#define BANDINFO_LINE_MAX
Definition: smile.c:16
void smile_calc_delta(int *shouldCorrect, int *indexes1, int *indexes2, float *radiances, float *theoretWLs, float *theoretE0s, float fsol, float *detectorWLs, float *detectorE0s, float *delta)
Definition: smile.c:146
const double delta
float rc(float x, float y)
int want_verbose
void smile_init(int num_bands, int num_detectors, const char *bandinfo_filename, float *detectorWLs, float *detectorE0s)
Definition: smile.c:48
#define numDetectors
int count
Definition: decode_rs.h:79