NASA Logo
Ocean Color Science Software

ocssw V2022
get_avw.c
Go to the documentation of this file.
1 /*
2  * get_avw.c
3  *
4  * This algorithm returns the weighted harmonic mean of the visible-range (400 – 700 nm) remote sensing reflectance (Rrs) wavelengths,
5  * outputting the Apparent Visible Wavelength (AVW) in units of nanometers.
6  * The AVW is an optical water classification index, representing a one-dimensional geophysical metric that is inherently correlated
7  * to Rrs spectral shape (Vandermeulen et al. 2020).
8  *
9  *
10  *Vandermeulen, R. A., Mannino, A., Craig, S.E., Werdell, P.J., 2020: “150 shades of green: Using the full spectrum of remote sensing reflectance
11  * to elucidate color shifts in the ocean,” Remote Sensing of Environment, 247, 111900, https://doi.org/10.1016/j.rse.2020.111900
12  *
13  * Created on: Sep 30, 2020
14  * Author: M. Zhang
15  */
16 
17 #include "l12_proto.h"
18 
19 
20 float avw_cal_hypspectral(float *Rrs, float *wave, int nwave){
21 
22  float avw=BAD_FLT;
23  int32_t ib;
24 
25  float dfirst=0,dlast=0;
26  float *Secondderiv=(float *)malloc(nwave*sizeof(float));
27 
28  int32_t nwave_out=700-400+1;
29  float *wave_out=(float *)malloc(nwave_out*sizeof(float));
30  float *Rrs_out =(float *)malloc(nwave_out*sizeof(float));
31  double nominator=0., denominator=0.;
32 
33  for(ib=0;ib<nwave_out;ib++)
34  wave_out[ib]=400+ib;
35 
36  dfirst=first_deriv(wave,Rrs,0);
37  dlast=first_deriv(wave,Rrs,nwave);
38 
39  spline(wave,Rrs,nwave,dfirst,dlast,Secondderiv);
40 
41  for(ib=0;ib<nwave_out;ib++)
42  splint(wave,Rrs,Secondderiv,nwave,wave_out[ib],&Rrs_out[ib]);
43 
44  for(ib=0;ib<nwave_out;ib++){
45  nominator+=Rrs_out[ib];
46  denominator+=(Rrs_out[ib]/wave_out[ib]);
47  }
48  avw=nominator/denominator;
49 
50  free(wave_out);free(Rrs_out);
51  free(Secondderiv);
52  return avw;
53 
54 }
55 
56 
57 float avw_cal_multispectral(float *Rrs, float *wave, int nwave){
58 
59  float avw=BAD_FLT;
60  int32_t ib;
61  float *avw_coef=input->avw_coef;
62 
63  double nominator=0., denominator=0.,temp=0.;
64 
65  for(ib=0;ib<nwave; ib++){
66  nominator+=Rrs[ib];
67  denominator+=(Rrs[ib]/wave[ib]);
68  }
69  avw=nominator/denominator;
70 
71  for(ib=0;ib<6;ib++)
72  temp+=avw_coef[ib]*pow(avw,ib);
73 
74  avw=temp;
75 
76  return avw;
77 
78 }
79 
80 void get_avw(l2str *l2rec, float avw[]){
81  filehandle* l1file = l2rec->l1rec->l1file;
82 
83  int32_t ip,ib;
84  int32_t ipb;
85 
86  int32_t sensorID = l1file->sensorID;
87  int32_t nbands = l1file->nbands;
88  int32_t npix = l2rec->l1rec->npix;
89  static float fsol;
90  float *wave = l1file->fwave;
91  float *Rrs;
92  static float *Rrs_avw, *wave_avw;
93  static int firstcall=1;
94  int32_t nwave_avw;
95  int32_t negative=0;
96  static int ifhyper=0;
97  static int ib400=0,ib700=0;
98 
99  if(firstcall){
100  firstcall=0;
101  Rrs_avw =(float *)malloc(nbands*sizeof(float));
102  wave_avw=(float *)malloc(nbands*sizeof(float));
103  switch (sensorID){
104  case HICO:
105  case PRISM:
106  case OCI:
107  case OCIS:
108  ifhyper=1;
109  break;
110  }
111  if(ifhyper){
112  ib400=windex(400, wave,nbands);
113  ib700=windex(700, wave,nbands);
114 
115  if(ib400>0 && wave[ib400]>=400)
116  ib400--;
117  if(ib700<nbands-1 && wave[ib700]<700)
118  ib700++;
119  }
120  fsol=l2rec->l1rec->fsol;
121  }
122 
123  /* */
124  /* Compute desired products at each pixel */
125  /* */
126  for (ip = 0; ip < npix; ip++) {
127  avw[ip]=BAD_FLT;
128 
129  if(l2rec->l1rec->mask[ip] || l2rec->l1rec->solz[ip] >= SOLZNIGHT)
130  continue;
131 
132  ipb=ip*nbands;
133  Rrs=&l2rec->Rrs[ipb];
134 
135  nwave_avw=0;
136  negative=0;
137  if(ifhyper){
138  for(ib=ib400;ib<=ib700;ib++){
139  if(Rrs[ib]!=BAD_FLT){
140  Rrs_avw [nwave_avw]=Rrs[ib] * (l1file->Fonom[ib]*fsol/l2rec->l1rec->Fo[ib])/l2rec->outband_correction[ipb+ib];
141  wave_avw[nwave_avw]=wave[ib];
142  nwave_avw++;
143  }
144  else if(Rrs[ib]<0)
145  negative=1;
146  }
147  }
148  else{
149  for(ib=0;ib<nbands;ib++){
150  if(wave[ib]>=400 && wave[ib]<=700){
151  if(Rrs[ib]!=BAD_FLT){
152  Rrs_avw [nwave_avw]=Rrs[ib] * (l1file->Fonom[ib]*fsol/l2rec->l1rec->Fo[ib])/l2rec->outband_correction[ipb+ib];
153  wave_avw[nwave_avw]=wave[ib];
154  nwave_avw++;
155  }
156  else if(Rrs[ib]<0)
157  negative=1;
158  }
159  }
160  }
161 
162  if(negative)
163  l2rec->l1rec->flags[ip] |=PRODWARN;
164 
165  if(ifhyper)
166  avw[ip]=avw_cal_hypspectral(Rrs_avw,wave_avw,nwave_avw);
167  else
168  avw[ip]=avw_cal_multispectral(Rrs_avw,wave_avw,nwave_avw);
169 
170  }
171 }
172 void get_Rrs_brightness(l2str *l2rec, float Rrs_brightness[]){
173 
174  int32_t ip,ib;
175  int32_t ipb;
176 
177  int32_t nbands = l2rec->l1rec->l1file->nbands;
178  int32_t npix = l2rec->l1rec->npix;
179  float *wave=l2rec->l1rec->l1file->fwave;
180  float *Rrs;
181  static float *Rrs_avw, *wave_avw;
182  static int firstcall=1;
183  int32_t nwave_avw;
184  static int ib400=0,ib700=0;
185 
186  if(firstcall){
187  firstcall=0;
188  Rrs_avw =(float *)malloc(nbands*sizeof(float));
189  wave_avw=(float *)malloc(nbands*sizeof(float));
190 
191  ib400=windex(400, wave,nbands);
192  ib700=windex(700, wave,nbands);
193  }
194 
195  /* */
196  /* Compute desired products at each pixel */
197  /* */
198  for (ip = 0; ip < npix; ip++) {
199  Rrs_brightness[ip]=BAD_FLT;
200 
201  if(l2rec->l1rec->mask[ip] || l2rec->l1rec->solz[ip] >= SOLZNIGHT)
202  continue;
203 
204  ipb=ip*nbands;
205  Rrs=&l2rec->Rrs[ipb];
206  nwave_avw=0;
207 
208  for(ib=ib400;ib<=ib700;ib++){
209  if(Rrs[ib]!=BAD_FLT){
210  Rrs_avw [nwave_avw]=Rrs[ib];
211  wave_avw[nwave_avw]=wave[ib];
212  nwave_avw++;
213  }
214  else if (Rrs[ib]<0)
215  l2rec->l1rec->flags[ip]|=PRODWARN;
216  }
217 
218  if(nwave_avw<2)
219  continue;
220 
221  Rrs_brightness[ip]=0;
222  for(ib=0;ib<nwave_avw-1;ib++){
223  Rrs_brightness[ip]+=(Rrs_avw[ib]+Rrs_avw[ib+1])/2.0*(wave_avw[ib+1]-wave_avw[ib]);
224  }
225  }
226 }
227 
228 void get_lambda_max(l2str *l2rec, float lambda_max[]){
229 
230  int32_t ip,ib;
231  int32_t ipb;
232 
233  int32_t nbands = l2rec->l1rec->l1file->nbands;
234  int32_t npix = l2rec->l1rec->npix;
235  float *wave=l2rec->l1rec->l1file->fwave;
236  float *Rrs;
237  float Rrs_temp;
238  static int firstcall=1;
239  static int ib400, ib700;
240  int negative=0;
241 
242  if(firstcall){
243  ib400=windex(400, wave,nbands);
244  ib700=windex(700, wave,nbands);
245  firstcall=0;
246  }
247 
248  /* */
249  /* Compute desired products at each pixel */
250  /* */
251  for (ip = 0; ip < npix; ip++) {
252  negative=0;
253  lambda_max[ip]=BAD_FLT;
254 
255  if(l2rec->l1rec->mask[ip] || l2rec->l1rec->solz[ip] >= SOLZNIGHT)
256  continue;
257 
258  ipb=ip*nbands;
259  Rrs=&l2rec->Rrs[ipb];
260  Rrs_temp=Rrs[ib400];
261 
262  if(Rrs_temp>=0)
263  lambda_max[ip]=wave[ib400];
264  else
265  negative=1;
266 
267  for(ib=ib400+1;ib<=ib700;ib++){
268  if(Rrs[ib]<0)
269  negative=1;
270  if(Rrs[ib]>Rrs_temp){
271  Rrs_temp=Rrs[ib];
272  lambda_max[ip]=wave[ib];
273  }
274  }
275  if(negative)
276  l2rec->l1rec->flags[ip] |=PRODWARN;
277  }
278 }
int32 l1file(int32 sdfid, int32 *nsamp, int32 *nscans, int16 *dtynum)
Definition: l1stat_chk.c:586
#define OCI
Definition: sensorDefs.h:42
float avw_cal_multispectral(float *Rrs, float *wave, int nwave)
Definition: get_avw.c:57
void get_lambda_max(l2str *l2rec, float lambda_max[])
Definition: get_avw.c:228
void get_avw(l2str *l2rec, float avw[])
Definition: get_avw.c:80
#define PRODWARN
Definition: l2_flags.h:13
subroutine spline(s, x, y, n, in, t, il, iu, vl, vu, e, u)
Definition: phs.f:1348
void get_Rrs_brightness(l2str *l2rec, float Rrs_brightness[])
Definition: get_avw.c:172
instr * input
float avw_cal_hypspectral(float *Rrs, float *wave, int nwave)
Definition: get_avw.c:20
#define OCIS
Definition: sensorDefs.h:43
#define PRISM
Definition: sensorDefs.h:31
#define SOLZNIGHT
Definition: l1.h:58
#define BAD_FLT
Definition: jplaeriallib.h:19
int32_t nbands
int windex(float wave, float twave[], int ntwave)
Definition: windex.c:73
subroutine splint(xa, ya, y2a, n, x, y)
float first_deriv(float x[], float y[], int n)
Definition: aerosol.c:289
#define HICO
Definition: sensorDefs.h:25
int32_t sensorID[MAXNFILES]
Definition: l2bin.cpp:91
int npix
Definition: get_cmp.c:28