OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
get_ndvi.c
Go to the documentation of this file.
1 /*---------------------------------------------------------------------*/
2 /* get_ndvi.c - vegetation index classification for MSl12. */
3 /* */
4 /* Inputs: */
5 /* l2rec - level-2 structure containing one complete scan after */
6 /* atmospheric correction. */
7 /* Outputs: */
8 /* ndvi - vegetation index for land, 1 value per pixel. */
9 /* */
10 /* Written by: Bryan Franz, SAIC-GSC, February 2000 */
11 /* */
12 /*---------------------------------------------------------------------*/
13 
14 #include <stdlib.h>
15 #include <math.h>
16 #include "l12_proto.h"
17 
18 static float undef = -2.0;
19 static int ibblue = -1;
20 static int ibred = -1;
21 static int ibnir = -1;
22 
23 //static float minval = -2.0;
24 //static float maxval = 2.0;
25 
26 // as per C. Tucker (11/2014), no cut-off at -2
27 static float minval = -1000.0;
28 static float maxval = 1000.0;
29 static int32_t mask = LAND;
30 
31 void get_ndvi(l1str *l1rec, float ndvi[]) {
32  int32_t ip, ipb;
33  float red;
34  float nir;
35 
36  if (ibred < 0 || ibnir < 0) {
37  printf("NDVI requires bands near 670 and 865nm\n");
38  exit(1);
39  }
40 
41  for (ip = 0; ip < l1rec->npix; ip++) {
42  ndvi[ip] = undef;
43 
44  ipb = l1rec->l1file->nbands*ip;
45  red = l1rec->rhos[ipb + ibred];
46  nir = l1rec->rhos[ipb + ibnir];
47 
48  if (l1rec->dem[ip] < -500 ||
49  (l1rec->flags[ip] & mask) == 0 ||
50  red <= 0.0 || nir <= 0.0 ||
51  red > 1.0 || nir > 1.0) {
52  l1rec->flags[ip] |= PRODFAIL;
53  continue;
54  } else {
55  ndvi[ip] = (nir - red)
56  / (nir + red);
57 
58  ndvi[ip] = MIN(MAX(ndvi[ip], minval), maxval);
59  }
60  }
61 }
62 
63 void get_evi(l1str *l1rec, float evi[]) {
64  static float L = 1.0, c1 = 6.0, c2 = 7.5;
65 
66  int32_t ip, ipb;
67  float blu;
68  float red;
69  float nir;
70  double val;
71 
72  if (ibblue < 0 || ibred < 0 || ibnir < 0) {
73  printf("EVI requires bands near 412, 670, and 865nm\n");
74  exit(1);
75  }
76 
77  for (ip = 0; ip < l1rec->npix; ip++) {
78  evi[ip] = undef;
79 
80  ipb = l1rec->l1file->nbands*ip;
81  blu = l1rec->rhos[ipb + ibblue];
82  red = l1rec->rhos[ipb + ibred];
83  nir = l1rec->rhos[ipb + ibnir];
84 
85  if (l1rec->dem[ip] < -500 ||
86  (l1rec->flags[ip] & mask) == 0 ||
87  red <= 0.0 || nir <= 0.0 ||
88  red > 1.0 || nir > 1.0) {
89  l1rec->flags[ip] |= PRODFAIL;
90  continue;
91 
92  } else {
93 
94  if (blu > 0.0 && (blu <= red || red <= nir)) {
95 
96  /* Most cases - EVI formula */
97 
98  if ((val = L + nir + c1 * red - c2 * blu) == 0)
99  continue;
100  else
101  evi[ip] = 2.5 * (nir - red) / val;
102 
103  } else {
104 
105  /* Backup - SAVI formula */
106 
107  if ((val = 0.5 + nir + red) == 0)
108  continue;
109  else
110  evi[ip] = 1.5 * (nir - red) / val;
111  }
112  evi[ip] = MIN(MAX(evi[ip], minval), maxval);
113 
114  }
115  }
116 }
117 
118 // From Compton Tucker 07/30/2016
119 //EVI3=2.5*(nir-red)/(nir+6*red-7.5*blue+1)
120 //EVI2=2.5*(NIR-Red)/(NIR+2.4*Red+1)
121 
122 void get_evi2(l1str *l1rec, float evi2[]) {
123  int32_t ip, ipb;
124  float red;
125  float nir;
126 
127  if (ibred < 0 || ibnir < 0) {
128  printf("EVI2 requires bands near 670, and 865nm\n");
129  exit(1);
130  }
131 
132  for (ip = 0; ip < l1rec->npix; ip++) {
133  evi2[ip] = undef;
134 
135  ipb = l1rec->l1file->nbands*ip;
136  red = l1rec->rhos[ipb + ibred];
137  nir = l1rec->rhos[ipb + ibnir];
138 
139  if (l1rec->dem[ip] < -500 ||
140  (l1rec->flags[ip] & mask) == 0 ||
141  red <= 0.0 || nir <= 0.0 ||
142  red > 1.0 || nir > 1.0) {
143  l1rec->flags[ip] |= PRODFAIL;
144  continue;
145 
146  } else {
147 
148  if (red <= nir) {
149  evi2[ip] = 2.5 * (nir - red) / (nir + 2.4 * red + 1);
150  }
151  evi2[ip] = MIN(MAX(evi2[ip], minval), maxval);
152  }
153  }
154 }
155 
156 void get_evi3(l1str *l1rec, float evi3[]) {
157  static float L = 1.0, c1 = 6.0, c2 = 7.5;
158 
159  int32_t ip, ipb;
160  float blu;
161  float red;
162  float nir;
163  double val;
164 
165  if (ibblue < 0 || ibred < 0 || ibnir < 0) {
166  printf("EVI requires bands near 412, 670, and 865nm\n");
167  exit(1);
168  }
169 
170  for (ip = 0; ip < l1rec->npix; ip++) {
171  evi3[ip] = undef;
172 
173  ipb = l1rec->l1file->nbands*ip;
174  blu = l1rec->rhos[ipb + ibblue];
175  red = l1rec->rhos[ipb + ibred];
176  nir = l1rec->rhos[ipb + ibnir];
177 
178  if (l1rec->dem[ip] < -500 ||
179  (l1rec->flags[ip] & mask) == 0 ||
180  red <= 0.0 || nir <= 0.0 ||
181  red > 1.0 || nir > 1.0) {
182  l1rec->flags[ip] |= PRODFAIL;
183  continue;
184 
185  } else {
186 
187 
188  if (blu > 0.0 && (blu <= red || red <= nir)) {
189 
190  /* Most cases - EVI formula */
191 
192  if ((val = L + nir + c1 * red - c2 * blu) == 0)
193  continue;
194  else
195  evi3[ip] = 2.5 * (nir - red) / val;
196 
197  }
198  evi3[ip] = MIN(MAX(evi3[ip], minval), maxval);
199  }
200  }
201 }
202 
203 void get_ndvi_evi(l1str *l1rec, int prodnum, float prod[]) {
204 
205  static int firstCall = 1;
206  if (firstCall) {
207  ibblue = bindex_get(412);
208  ibred = bindex_get(670);
209  ibnir = bindex_get(865);
210 
211  if (l1rec->l1file->sensorID == MODISA ||
212  l1rec->l1file->sensorID == MODIST) {
213  ibred = bindex_get(645);
214  ibnir = bindex_get(859);
215  }
216  }
217 
218  switch (prodnum) {
219  case CAT_ndvi:
220  get_ndvi(l1rec, prod);
221  break;
222  case CAT_evi:
223  get_evi(l1rec, prod);
224  break;
225  case CAT_evi2:
226  get_evi2(l1rec, prod);
227  break;
228  case CAT_evi3:
229  get_evi3(l1rec, prod);
230  break;
231  default:
232  printf("Error: %s : Unknown product specifier: %d\n", __FILE__, prodnum);
233  exit(FATAL_ERROR);
234  break;
235  }
236 
237 }
#define MAX(A, B)
Definition: swl0_utils.h:26
#define MIN(x, y)
Definition: rice.h:169
void red(int iz1, int iz2, int jz1, int jz2, int jm1, int jm2, int jmf, int ic1, int jc1, int jcf, int kc, float ***c, float **s)
#define L(lambda, T)
Definition: PreprocessP.h:185
#define CAT_evi2
Definition: l2prod.h:73
read l1rec
void get_ndvi(l1str *l1rec, float ndvi[])
Definition: get_ndvi.c:31
#define MODIST
Definition: sensorDefs.h:18
#define PRODFAIL
Definition: l2_flags.h:41
void get_evi(l1str *l1rec, float evi[])
Definition: get_ndvi.c:63
int bindex_get(int32_t wave)
Definition: windex.c:45
void get_ndvi_evi(l1str *l1rec, int prodnum, float prod[])
Definition: get_ndvi.c:203
#define CAT_evi
Definition: l2prod.h:45
#define CAT_evi3
Definition: l2prod.h:74
#define FATAL_ERROR
Definition: swl0_parms.h:5
a context in which it is NOT documented to do so subscript which cannot be easily calculated when extracting TONS attitude data from the Terra L0 files Corrected several defects in extraction of entrained ephemeris and and as HDF file for both the L1A and Geolocation enabling retrieval of South Polar DEM data Resolved Bug by changing to opent the geolocation file only after a successful read of the L1A and also by checking for fatal errors from not restoring C5 and to report how many of those high resolution values were water in the new WaterPresent SDS Added valid_range attribute to Land SeaMask Changed to bilinearly interpolate the geoid_height to remove artifacts at one degree lines Made corrections to const qualification of pointers allowed by new version of M API library Removed casts that are no longer for same not the geoid Corrected off by one error in calculation of high resolution offsets Corrected parsing of maneuver list configuration parameter Corrected to set Height SDS to fill values when geolocation when for elevation and land water mask
Definition: HISTORY.txt:114
#define LAND
Definition: l2_flags.h:12
void get_evi3(l1str *l1rec, float evi3[])
Definition: get_ndvi.c:156
#define CAT_ndvi
Definition: l2prod.h:39
msiBandIdx val
Definition: l1c_msi.cpp:34
#define MODISA
Definition: sensorDefs.h:19
void get_evi2(l1str *l1rec, float evi2[])
Definition: get_ndvi.c:122