OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
clear_sky_restoral.f90
Go to the documentation of this file.
2 !-------------------------------------------------------------------------------
3 ! DESCRIPTION:
4 ! this module contains the routines used to perform spatial variability
5 ! tests and 250m cloudiness evaluation.
6 !
7 !
8 ! PROGRAMMER:
9 ! Gala Wind (L3 GSI)
10 ! Climate and Radiation Branch
11 ! Code 913, NASA Goddard Space Flight Center
12 ! Greenbelt, Maryland 20771, U.S.A.
13 !
14 ! Mark Gray (L3 GSI)
15 ! Climate and Radiation Branch
16 ! Code 913, NASA Goddard Space Flight Center
17 ! Greenbelt, Maryland 20771, U.S.A.
18 ! gray@climate.gsfc.nasa.gov
19 !------------------------------------------------------------------------------
20 ! REVISION:
21 ! 10.22.04 integrated with MOD_PR06OD, substantial style changes.
22 ! 10.07.04 Initial revision
23 ! 10.12.04 added more inputs and tests to be potentially included
24 !------------------------------------------------------------------------------
25 
26  use generalauxtype
29 
30  implicit none
31 
32  private
33 
34 
35  public :: cloudiness_test
36 
37  contains
38 
39 
40 
41 !====================================================================
42  subroutine cloudiness_test &
43  ( cloudmask, &
44  process_summary, &
45  measurement, &
46  reflectance_box, &
47  not_cloud, &
48  lowvariability_confidence_test, csr_qa, latitude, &
49  chm, vis1km_test) ! KGM 3-4-13
50 !====================================================================
51 
52 ! NOTES TO Gala:
53 !
54 ! This subroutine name should be changed to "cloudiness_test", while the above routine could be something
55 ! like "cloudiness_test_alternate"; similar changes in modis_science_module are also needed, of course.
56 ! This routine has not for a long time been equivalent to the original Riedi work, but includes contributions
57 ! from all of us and so is a misnomer. Furthermore, I have added absolute variability calculations for testing
58 ! purposes only (presently commented out) so this routine now essentially contains the "alternate" structure anyway.
59 
60 !-----------------------------------------------------------------------
61 ! !f90
62 !
63 ! !Description:
64 ! This subroutine performs Clear Sky Restoral (CSR) tests
65 ! in an attempt to eliminate sunglint or heavy aerosol pixels falsely flagged as
66 ! cloudy by the cloud mask. Examples of this include bright ocean sunglint,
67 ! smoke, and dust.
68 !
69 ! !Input Parameters:
70 ! cloudmask -- structure -- all cloud mask tests
71 ! process_summary -- structure -- process flags, surface type etc
72 ! measurements -- 4 byte real vector -- reflectances/ radiances for all bands
73 ! reflectance_box -- 4 byte real array -- all reflectances for 2x2 box
74 !
75 ! !Output Parameters:
76 ! not_cloud -- logical -- true indicates the presence of sunglint/dust or other non-cloud situation
77 ! lowvariability_confidence_test - Indicates went with a "cloudy" determination but are unsure so set confidence QA to a lower value
78 ! CSR_QA --
79 ! CSR_flag_array=0 => cloudy, all CSR tests negative
80 ! CSR_flag_array=1 => edge test positive (determined in subroutine remove_edge_scenes.f90)
81 ! CSR_flag_array=2 => spatial, etc. tests positive
82 ! CSR_flag_array=3 => 250 m test positive
83 !
84 ! !Revision History:
85 ! 2009/04/28, G. Wind:
86 ! changed the way the 250m tests are handled by the code. Now everything will start from being all cloudy and cleared if clear
87 ! 250m bit is encountered. This will help with any dead 250m detectors.
88 !
89 ! 2005/09/14, S. Plantick:
90 ! An error was found in the implementation of the CSR flow chart. The 250 cloudiness test
91 ! was not being used for clouds brighter than the reflectance threshold. This was fixed, along with:
92 ! (1) Additional comments and edits of existing comments.
93 ! (2) Local variable name changes and additional variables to implement correct 250 test logic.
94 ! (3) For testing/comparison purposes - the calculation of an absolute spatial variability metric.
95 !
96 ! 2005, May-June: several iterations with a number of authors.
97 !
98 ! 2005/02/08 wind
99 ! implemented Riedi algorithm as per the flow chart from Dec.10.2004
100 ! 2004/10/23 mag
101 ! integrated into MOD_PR06OD
102 ! - added logical structures, variable types used by MOD_PR06OD
103 ! - cleaned up variable naming, code formatting, style.
104 !
105 ! 2004/10/07 wind: Gala Wind
106 ! Revision 1.0 Initial revision
107 !
108 ! !Team-Unique Header:
109 ! Developed by the Cloud Retrieval Group, NASA GSFC, Greenbelt, Maryland, USA.
110 !
111 ! !References and Credits:
112 ! Written by:
113 ! Gala Wind
114 ! L3 GSI
115 ! Code 913, NASA/GSFC
116 ! Greenbelt, MD 20771
117 ! wind@climate.gsfc.nasa.gov
118 !
119 ! Mark Gray
120 ! L3 GSI
121 ! Code 913, NASA/GSFC
122 ! Greenbelt, MD 20771
123 ! gray@climate.gsfc.nasa.gov
124 !
125 !
126 ! !END
127 !
128 !-----------------------------------------------------------------------
129 
130  type(processflag), intent(in) :: process_summary
131  type(cloudmask_type), intent(in) :: cloudmask
132  real(single), dimension(:), intent(in) :: measurement
133  real(single), dimension(:,:,:), intent(in) :: reflectance_box
134  real(single), intent(in) :: latitude
135  integer*1, intent(in) :: chm ! KGM 3-4-13
136  integer*1, intent(inout) :: csr_qa
137  logical, intent(in) :: vis1km_test ! KGM 3-4-13
138  logical, intent(out) :: lowvariability_confidence_test
139  logical, intent(out) :: not_cloud
140 
141 ! local variables
142  logical :: cloudy_250
143  integer(integer_fourbyte) :: cloudiness_degree
144  real :: average, r21_r138, r124_r21, r086_r124, &
145  standard_deviation_val, rbox(3,3), th_ri, th_ri_qa, &
146  dispersion_val, dispersion_ri, dispersion_ri_qa, &
147  rmeas, rth_ocean, rth_land, rth_desert, rth_snowice
148  integer :: rbox_x, rbox_y
149 
150  rbox = 0 ! WDR-UIV
151 
152 ! Initialize outputs for no restoral, and 250m cloudiness variables
153  csr_qa = 0 ; not_cloud = .false. ; lowvariability_confidence_test = .false.
154  cloudiness_degree = 16 ; cloudy_250 = .true.
155 
156 
157 
158 
159 ! Con't run this code if there is no cloud observed.
160  if (.not. process_summary%cloudobserved) return
161 
162  r21_r138 = measurement(band_0213) - measurement(band_0138)
163  r124_r21 = measurement(band_0124) - measurement(band_0213)
164  r086_r124 = measurement(band_0086) - measurement(band_0124)
165 
166 
167 ! For use in Part V, compute the degree of cloudiness from the 250m cloud mask bytes for this pixel
168 ! of course we need to check (for each test) that the test was actually run
169 !
170 ! The cloudiness degree is a number between 0 and 16, representing the number of
171 ! cloudy pixels in the 250m box corresponding to a particular 1km pixel. The box is 4x4, so
172 ! if the 1km pixel is completely overcaset, the degree of cloudiness would be 16.
173 
174  If (process_summary%ocean_surface) then
175 
176 
177  if (cloudmask%visible_cloudtest_250m <= 8) then
178  cloudy_250 = .false.
179  endif
180 
181  End if
182 
183 ! TO TURN OFF 250m TEST, UNCOMMENT THE FOLLOWING LINE:
184 ! cloudy_250 = .true.
185 
186 ! ENTER PART I: PERFORM SPATIAL VARIABLILITY TESTS
187 
188 ! original:
189 ! Rth_ocean = 0.35; Rth_land = 0.45; Rth_desert = NA; Rth_snowice = 0.65
190 
191 ! threshold test 1: USED FOR COLLECTION 5 OPERATIONAL VERSION
192  rth_ocean = 0.65; rth_land = 0.65; rth_desert = 0.65; rth_snowice = 0.65
193 
194 ! threshold test 2:
195 ! Rth_ocean = 0.50; Rth_land = 0.50; Rth_desert = 0.55; Rth_snowice = 0.65
196 
197 
198  If ( &
199  ( process_summary%land_surface .and. (measurement(band_0065) > rth_land) ) .OR. &
200  ( process_summary%desert_surface .and. (measurement(band_0065) > rth_desert) ) .OR. &
201  ( process_summary%snowice_surface .and. (measurement(band_0124) > rth_snowice) ) .OR. &
202  ( (process_summary%ocean_surface .or. process_summary%coastal_surface) &
203  .and. (measurement(band_0086) > rth_ocean) ) ) Then
204 
205  ! PART V (via PART I):
206  if (.not. cloudy_250 .and. vis1km_test) then
207  not_cloud = .true.
208  csr_qa = 3 ! restored by 250m test
209  end If
210  return
211 
212  End if
213 
214  rbox_x = size(reflectance_box, 1)
215  rbox_y = size(reflectance_box, 3)
216 
217  rmeas = 0 ! WDR-UIV
218 ! Pick the reflectance box according to the surface type
219  if (process_summary%land_surface .or. process_summary%desert_surface) then
220  rbox(1:rbox_x, 1:rbox_y) = reflectance_box(:,band_0065,:)
221  rmeas = measurement(band_0065)
222  endif
223 
224  if (process_summary%ocean_surface .or. process_summary%coastal_surface) then
225  rbox(1:rbox_x, 1:rbox_y) = reflectance_box(:,band_0086,:)
226  rmeas = measurement(band_0086)
227  endif
228 
229  if (process_summary%snowice_surface) then
230  rbox(1:rbox_x, 1:rbox_y) = reflectance_box(:,band_0124,:)
231  rmeas = measurement(band_0124)
232  endif
233 
234  average = array_mean(rbox)
235  standard_deviation_val = standard_deviation(rbox(1:rbox_x, 1:rbox_y), average)
236 
237  if(average > 0.001) then
238  dispersion_val = 100 * standard_deviation_val/average
239  else
240  dispersion_val = -1.
241  end if
242 
243 
244 ! *** For spatial varobility clear sky restoral based on box absolute sdev: TO BE USED FOR COLLECTION 5 OPERATIONAL VERSION
245 
246 ! 1km spatial variability (sdev) thresholds
247 
248 ! early version of sdev thresholds:
249 ! if (process_summary%ocean_surface) then
250 ! th_Ri = 0.004
251 ! th_Ri_QA = 0.003
252 ! else
253 ! th_Ri = 0.005
254 ! th_Ri_QA = 0.004
255 ! endif
256 
257 ! sdev threshold test 1:
258 ! if (process_summary%ocean_surface) then
259 ! th_Ri = 0.005
260 ! th_Ri_QA = 0.004
261 ! else
262 ! th_Ri = 0.006
263 ! th_Ri_QA = 0.005
264 ! endif
265 
266 ! sdev threshold test 2: TO BE USED FOR COLLECTION 5 OPERATIONAL VERSION
267  if (process_summary%ocean_surface) then
268  th_ri = 0.006
269  th_ri_qa = 0.005
270  else
271  th_ri = 0.007
272  th_ri_qa = 0.006
273  endif
274 
275  IF (rmeas > 0. .and. standard_deviation_val < th_ri) THEN ! candidate for restoral
276 
277 ! *** For spatial variability clear sky restoral based on box dispersion: FOR TESTING PURPOSES
278 
279 ! dispersion = 100*sdev/avg thresholds:
280 ! if (process_summary%ocean_surface) then
281 ! dispersion_Ri = 3.5
282 ! dispersion_Ri_QA = 3.0
283 ! else
284 ! dispersion_Ri = 4.0
285 ! dispersion_Ri_QA = 3.5
286 ! endif
287 
288 ! IF (Rmeas > 0. .and. dispersion_val > 0. .and. dispersion_val < dispersion_Ri) THEN ! candidate for restoral
289 
290 
291 ! ENTER PART II: ALTITUDE INDICATOR
292 
293 ! sep, 17May: previous version used IR phase, this version is using "not ice " from the decision tree phase
294 ! If ( (.not. process_summary%icecloud) & !.and. measurement(band_0138) > -1.0 &
295 ! .and. measurement(band_0138) < 0.1) Then ! candidate for restoral
296 ! If ( (.not. process_summary%icecloud) & !.and. measurement(band_0138) > -1.0 &
297 ! .and. (measurement(band_0138) < 0.1) .and. (ctp > 350.0)) Then ! candidate for restoral
298 ! .and. (measurement(band_0138) < 0.1) .and. (chm .eq. 6)) Then ! candidate for restoral
299  If ((measurement(band_0138) .lt. 0.1) .and. (chm .gt. 2)) Then ! candidate for restoral ! KGM 3-4-13
300 
301 ! ENTER PART III: SPECTRAL BEHAVIOR
302 
303  if (measurement(band_0138) > 0.015) then
304 
305  if ( (1.0 > r21_r138 .and. r21_r138 > r124_r21 .and. r124_r21 > r086_r124) .or. &
306  (r21_r138 < r124_r21 .and. r124_r21 < r086_r124 .and. r086_r124 < 1.0)) then
307 
308  ! Restore pixel and thereby pass through PART IV (branch 2 in flow chart)
309  not_cloud = .true.
310  csr_qa = 2
311  else
312  ! PART V (via PART III): probaby thin cirrus
313  if (.not. cloudy_250 .and. vis1km_test) then ! KGM 3-4-13
314  not_cloud = .true.
315  csr_qa = 3 ! restored by 250m test
316  end if
317  return
318  endif
319 
320  else
321  ! Restore pixel and thereby pass through PART IV (branch 1 in flow chart)
322  not_cloud = .true.
323  csr_qa = 2
324  endif
325 
326  Else
327 
328  ! PART V (via PART II): probably cirrus or high cloud
329  if (.not. cloudy_250 .and. vis1km_test) then ! KGM 3-4-13
330  not_cloud = .true.
331  csr_qa = 3 ! restored by 250m test
332  end if
333  return
334 
335  End If
336 
337  ELSE
338 
339  ! PART V (via PART I):
340  if (.not. cloudy_250 .and. vis1km_test) then ! KGM 3-4-13
341  not_cloud = .true.
342  csr_qa = 3 ! restored by 250m test
343  end if
344  return
345 
346  END IF
347 
348 ! ENTER PART IV: check variability again, if not_cloud is .true. but variability is still
349 ! fairly high then process as cloud but only lower the retrieval confidence QA
350 
351 ! *** For spatial varobility clear sky restoral based on box absolute sdev: TO BE USED FOR COLLECTION 5 OPERATIONAL VERSION
352  if ( not_cloud .and. standard_deviation_val > th_ri_qa ) then
353 
354 ! *** For spatial variability clear sky restoral based on box dispersion: FOR TESTING PURPOSES
355 ! if ( not_cloud .and. dispersion_val > dispersion_Ri_QA ) then
356 
357  not_cloud = .false. ! RESET PIXEL TO CLOUDY
358  csr_qa = 0
359  lowvariability_confidence_test = .true.
360 
361  ! PART V (via PART IV):
362  if (.not. cloudy_250 .and. vis1km_test) then ! KGM 3-4-13
363  not_cloud = .true.
364  csr_qa = 3 ! restored by 250m test
365  end If
366 
367  endif
368 
369 end subroutine cloudiness_test
370 
371 function array_mean(array)
372  real*4 :: array_mean, temp
373  real*4, dimension(:,:), intent(in) :: array
374  integer :: n1, n2, i, j, cnt
375 
376  n1 = size(array, 1)
377  n2 = size(array, 2)
378 
379  temp = 0.
380  cnt = 0
381  do i=1, n1
382  do j=1, n2
383  if (array(i,j) > 0.) then
384  temp = temp + array(i,j)
385  cnt = cnt + 1
386  endif
387  end do
388  end do
389 
390  if (cnt > 0) then
391  array_mean = temp / real(cnt)
392  else
393  array_mean = 0.
394  endif
395 
396 end function array_mean
397 
398 !=====================================
399 function standard_deviation(array, average)
400 !=====================================
401 !-----------------------------------------------------------------------
402 ! !f90
403 !
404 ! !Description:
405 ! This function computes standard deviation of a 2D array
406 !
407 ! !Input Parameters:
408 ! array -- real*4, dimension(:,:) -- an array of data
409 ! average -- real*4 -- mean value of the array
410 !
411 ! !Output Parameters:
412 ! standard_deviation -- real*4 -- the standard deviation value
413 !
414 ! !Revision History:
415 ! 2004/06/02 wind: Gala Wind
416 ! Revision 1.0 clean-up
417 !
418 ! !Team-Unique Header:
419 ! Developed by the Cloud Retrieval Group, NASA GSFC, Greenbelt, Maryland, USA.
420 !
421 ! !References and Credits:
422 ! Written by:
423 ! Gala Wind
424 ! L3 GSI
425 ! Code 913, NASA/GSFC
426 ! Greenbelt, MD 20771
427 ! wind@climate.gsfc.nasa.gov
428 !
429 ! !Design Notes:
430 ! NONE
431 !
432 ! !END
433 !
434 !-----------------------------------------------------------------------
435  real, intent(in) :: average
436  real, dimension(:,:), intent(in) :: array
437  real :: standard_deviation, temp
438  integer :: i,j, cnt, n1, n2
439 
440  n1 = size(array, 1)
441  n2 = size(array, 2)
442  temp = 0.
443  cnt = 0
444  do i=1, n1
445  do j=1, n2
446  if ( array(i,j) > 0. ) then
447  temp = temp + (average - array(i,j))**2
448  cnt = cnt + 1
449  endif
450  end do
451  end do
452 
453  if ( (cnt-1) > 0) then
454  standard_deviation= sqrt( temp / real(cnt - 1) )
455  else
456  standard_deviation = 0.
457  endif
458 
459 end function standard_deviation
460 
461 
462 
463 
464 end module clear_sky_restoral
465 
integer, parameter band_0124
integer, parameter band_0138
#define real
Definition: DbAlgOcean.cpp:26
integer, parameter band_0086
integer, parameter band_0213
integer, parameter single
subroutine, public cloudiness_test(cloudmask, process_summary, measurement, reflectance_box, not_cloud, lowvariability_confidence_test, CSR_QA, latitude, chm, vis1km_test)
integer, parameter band_0065