From 0390872e2d4df67609e64545b40750eaf5d5989a Mon Sep 17 00:00:00 2001 From: Adam Povey Date: Wed, 10 Mar 2021 11:45:50 +0000 Subject: [PATCH] Add instrument-specific bias correction to setup, addressing #44 --- pre_processing/allocate_channel_info.F90 | 3 + pre_processing/channel_structures.F90 | 5 + pre_processing/deallocate_channel_info.F90 | 2 + pre_processing/read_imager.F90 | 11 +- pre_processing/read_slstr.F90 | 23 ---- pre_processing/read_slstr_main.F90 | 8 +- pre_processing/setup.F90 | 129 ++++++++++++++++++--- 7 files changed, 132 insertions(+), 49 deletions(-) diff --git a/pre_processing/allocate_channel_info.F90 b/pre_processing/allocate_channel_info.F90 index 1965318c..e3ad1f00 100644 --- a/pre_processing/allocate_channel_info.F90 +++ b/pre_processing/allocate_channel_info.F90 @@ -75,4 +75,7 @@ subroutine allocate_channel_info(channel_info) allocate(channel_info%channel_fm_sea_uncertainty( & channel_info%nchannels_total)) + allocate(channel_info%channel_absolute_bias(channel_info%nchannels_total)) + allocate(channel_info%channel_relative_bias(channel_info%nchannels_total)) + end subroutine allocate_channel_info diff --git a/pre_processing/channel_structures.F90 b/pre_processing/channel_structures.F90 index 453174c3..e8597b16 100644 --- a/pre_processing/channel_structures.F90 +++ b/pre_processing/channel_structures.F90 @@ -20,6 +20,7 @@ ! 2016/07/01, GT: Added map_ids_sw_to_channel and map_ids_lw_to_channel. ! 2016/08/04, GM: Added map_ids_channel_to_sw and map_ids_channel_to_lw. ! 2017/07/05, AP: Add NAll to track the total number of channels. +! 2021/03/09, AP: Add radiance bias corrections. ! ! Bugs: ! None known. @@ -98,6 +99,10 @@ module channel_structures_m real(kind=sreal), dimension(:), pointer :: channel_fm_lnd_uncertainty real(kind=sreal), dimension(:), pointer :: channel_fm_sea_uncertainty + ! Bias correction for each channel + real(kind=sreal, dimension(:), pointer :: channel_absolute_bias + real(kind=sreal, dimension(:), pointer :: channel_relative_bias + end type channel_info_t contains diff --git a/pre_processing/deallocate_channel_info.F90 b/pre_processing/deallocate_channel_info.F90 index d7e75c67..1f083b14 100644 --- a/pre_processing/deallocate_channel_info.F90 +++ b/pre_processing/deallocate_channel_info.F90 @@ -49,6 +49,8 @@ subroutine deallocate_channel_info(channel_info) deallocate(channel_info%channel_minimum_uncertainty) deallocate(channel_info%channel_fm_lnd_uncertainty) deallocate(channel_info%channel_fm_sea_uncertainty) + deallocate(channel_info%channel_absolute_bias) + deallocate(channel_info%channel_relative_bias) deallocate(channel_info%sw_rttov_viewone_id) deallocate(channel_info%sw_view_ids) deallocate(channel_info%lw_rttov_viewone_id) diff --git a/pre_processing/read_imager.F90 b/pre_processing/read_imager.F90 index 96500223..ea81f7c4 100644 --- a/pre_processing/read_imager.F90 +++ b/pre_processing/read_imager.F90 @@ -55,7 +55,8 @@ ! instead of IMPF (as previous). The new driver file option ! USE_GSICS enables this to be disabled. ! 2018/06/08, SP: New global attribute to store satellite position information -! 2019/8/14, SP: Add Fengyun-4A support. +! 2019/08/14, SP: Add Fengyun-4A support. +! 2021/03/09, AP: Add radiance bias corrections. ! ! Bugs: ! None known. @@ -255,7 +256,15 @@ subroutine read_imager(sensor, platform, path_to_l1b_file, path_to_geo_file, & stop error_stop_code end if + ! Bias correction (these are defined in the appropriate setup.F90 routine) + do k = 1, channel_info%nchannels_total + imager_measurements%data(:,:,k) = channel_info%channel_absolute_bias(k) + & + channel_info%channel_relative_bias(k) * & + imager_measurements%data(:,:,k) + end do + ! Estimate measurement uncertainty + ! NOTE: Doing this here as instruments will eventually provide L1 uncs do k = 1, channel_info%nchannels_total do j = 1, imager_geolocation%ny do i = imager_geolocation%startx, imager_geolocation%endx diff --git a/pre_processing/read_slstr.F90 b/pre_processing/read_slstr.F90 index e5c3a7f1..c4fa9a11 100644 --- a/pre_processing/read_slstr.F90 +++ b/pre_processing/read_slstr.F90 @@ -16,29 +16,6 @@ module read_slstr_m implicit none - ! The calibration of SLSTR is under ongoing revisions, such that the - ! application of empirical correction factors is currently required. - ! These are taken from the SLSTR User Guide and/or personal communications. - real, parameter :: slstr_correction_factor(18) = [ & - 0.95, & ! Ch1 - -1.0, & ! Ch2 - -1.0, & ! Ch3 - -1.0, & ! Ch4 - 1.10, & ! Ch5 - 1.10, & ! Ch6 - -1.0, & ! Ch7 - -1.0, & ! Ch8 - -1.0, & ! Ch9 - 0.92, & ! Ch10 - 0.93, & ! Ch11 - 0.93, & ! Ch12 - -1.0, & ! Ch13 - -1.0, & ! Ch14 - -1.0, & ! Ch15 - -1.0, & ! Ch16 - -1.0, & ! Ch17 - -1.0 ] ! Ch18 - contains ! When defined, the offset between the nadir and oblique views is assumed diff --git a/pre_processing/read_slstr_main.F90 b/pre_processing/read_slstr_main.F90 index 523bbc44..5a53b8cc 100644 --- a/pre_processing/read_slstr_main.F90 +++ b/pre_processing/read_slstr_main.F90 @@ -256,13 +256,7 @@ subroutine read_slstr(infile, imager_geolocation, imager_measurements, & stop error_stop_code end if - ! Apply some correction factors - if (slstr_correction_factor(band_ids(i)) .gt. 0.0) then - imager_measurements%data(:,:,i) = imager_measurements%data(:,:,i) * & - slstr_correction_factor(band_ids(i)) - end if - - ! Other corrections have previously been applied in this code to minimise + ! Corrections have previously been applied in this code to minimise ! problems with the geolocation, dynamic range, and calibration of SLSTR. ! These have been removed at this point, as many are now included in the ! L1B files but may still be necessary for earlier data. The main one is diff --git a/pre_processing/setup.F90 b/pre_processing/setup.F90 index e605c1ab..bce9c587 100644 --- a/pre_processing/setup.F90 +++ b/pre_processing/setup.F90 @@ -86,7 +86,8 @@ ! l1b_version and level1b_orbit_number attributes from the L1b file. ! Extending this change to the other supported instruments is worth ! considering... -! 2019/8/14, SP: Add Fengyun-4A support. +! 2019/08/14, SP: Add Fengyun-4A support. +! 2021/03/09, AP: Add radiance bias corrections. ! ! Bugs: ! None known. @@ -187,6 +188,14 @@ subroutine setup_aatsr(l1b_path_file, geo_path_file, platform, sensor, year, & (/ 0.0200, 0.0236, 0.0263, 0.0461, 0.0, 0.0, 0.0, & 0.0132, 0.0150, 0.0161, 0.0294, 0.0, 0.0, 0.0 /) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, & + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, & + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -248,7 +257,7 @@ subroutine setup_aatsr(l1b_path_file, geo_path_file, platform, sensor, year, & all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_aatsr()' @@ -339,6 +348,14 @@ subroutine setup_abi(l1b_path_file, geo_path_file, platform, year, month, day, & (/ 0., 0., 0., 0., 0., 0., 0., 0., & 0., 0., 0., 0., 0., 0., 0., 0. /) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0., 0., 0. /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1., 1., 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1., 1., 1. /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -404,7 +421,7 @@ subroutine setup_abi(l1b_path_file, geo_path_file, platform, year, month, day, & all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_abi()' @@ -495,6 +512,14 @@ subroutine setup_agri(l1b_path_file, geo_path_file, platform, year, month, day, (/ 0., 0., 0., 0., 0., 0., 0., & 0., 0., 0., 0., 0., 0. /) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0. /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1., 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1. /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -537,13 +562,13 @@ subroutine setup_agri(l1b_path_file, geo_path_file, platform, year, month, day, ! now set up the channels call common_setup(channel_info, channel_ids_user, channel_ids_default, & - all_channel_wl_abs, all_channel_sw_flag, all_channel_lw_flag, & - all_channel_ids_rttov_coef_sw, all_channel_ids_rttov_coef_lw, & - all_map_ids_abs_to_ref_band_land, all_map_ids_abs_to_ref_band_sea, & - all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & - all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & - all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_wl_abs, all_channel_sw_flag, all_channel_lw_flag, & + all_channel_ids_rttov_coef_sw, all_channel_ids_rttov_coef_lw, & + all_map_ids_abs_to_ref_band_land, all_map_ids_abs_to_ref_band_sea, & + all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & + all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & + all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_agri()' @@ -634,6 +659,14 @@ subroutine setup_ahi(l1b_path_file, geo_path_file, platform, year, month, day, & (/ 0., 0., 0., 0., 0., 0., 0., 0., & 0., 0., 0., 0., 0., 0., 0., 0. /) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0., 0., 0. /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1., 1., 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1., 1., 1. /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -702,7 +735,7 @@ subroutine setup_ahi(l1b_path_file, geo_path_file, platform, year, month, day, & all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_ahi()' @@ -782,6 +815,12 @@ subroutine setup_avhrr(l1b_path_file, geo_path_file, platform, year, month, day, real, parameter :: all_channel_sea_uncertainty(all_nchannels_total) = & (/ 0., 0., 0., 0., 0., 0. /) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0., 0. /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1., 1., 1., 1., 1., 1. /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -918,7 +957,7 @@ subroutine setup_avhrr(l1b_path_file, geo_path_file, platform, year, month, day, all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_avhrr()' @@ -1078,6 +1117,22 @@ subroutine setup_modis(l1b_path_file, geo_path_file, platform, year, month, day, 0., 0., 0., 0., 0., 0., & 0., 0., 0., 0., 0., 0. /) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0. /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1. /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -1141,7 +1196,7 @@ subroutine setup_modis(l1b_path_file, geo_path_file, platform, year, month, day, all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_modis()' @@ -1219,6 +1274,12 @@ subroutine setup_seviri(l1b_path_file, geo_path_file, platform, year, month, day real, parameter :: all_channel_sea_uncertainty(all_nchannels_total) = & (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. /) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1. /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -1317,7 +1378,7 @@ subroutine setup_seviri(l1b_path_file, geo_path_file, platform, year, month, day all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_seviri()' @@ -1417,6 +1478,17 @@ subroutine setup_slstr(l1b_path_file, geo_path_file, source_attributes, platform (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., & 0., 0., 0., 0., 0., 0., 0., 0., 0. /) + ! Bias correction + ! The calibration of SLSTR is under ongoing revisions, such that the + ! application of empirical correction factors is currently required. + ! These are taken from the SLSTR User Guide and/or personal communications. + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0., 0., 0., 0. /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 0.95, 1., 1., 1., 1.10, 1.10, 1., 1., 1., & + 0.92, 0.93, 0.93, 1., 1., 1., 1., 1., 1. /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -1547,7 +1619,7 @@ subroutine setup_slstr(l1b_path_file, geo_path_file, source_attributes, platform all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_slstr()' @@ -1641,6 +1713,14 @@ subroutine setup_viirs_mband(l1b_path_file, geo_path_file, platform, year, month (/ 0., 0., 0., 0., 0., 0., 0., 0., & 0., 0., 0., 0., 0., 0., 0., 0. /) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0., 0., 0., 0., & + 0., 0., 0., 0., 0., 0., 0., 0. /) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1., 1., 1., 1., 1., 1., 1., 1., & + 1., 1., 1., 1., 1., 1., 1., 1. /) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -1717,7 +1797,7 @@ subroutine setup_viirs_mband(l1b_path_file, geo_path_file, platform, year, month all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_viirs_mband()' @@ -1798,6 +1878,12 @@ subroutine setup_viirs_iband(l1b_path_file, geo_path_file, platform, year, month real, parameter :: all_channel_sea_uncertainty(all_nchannels_total) = & (/ 0., 0., 0., 0., 0./) + ! Bias correction + real, parameter :: all_channel_absolute_bias(all_nchannels_total) = & + (/ 0., 0., 0., 0., 0./) + real, parameter :: all_channel_relative_bias(all_nchannels_total) = & + (/ 1., 1., 1., 1., 1./) + ! Only this below needs to be set to change the desired default channels. All ! other channel related arrays/indexes are set automatically given the static ! instrument channel definition above. @@ -1885,7 +1971,7 @@ subroutine setup_viirs_iband(l1b_path_file, geo_path_file, platform, year, month all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) if (verbose) write(*,*) '>>>>>>>>>>>>>>> Leaving setup_viirs_iband()' @@ -1899,7 +1985,7 @@ subroutine common_setup(channel_info, channel_ids_user, channel_ids_default, & all_map_ids_abs_to_snow_and_ice, all_map_ids_view_number, & all_channel_fractional_uncertainty, all_channel_minimum_uncertainty, & all_channel_numerical_uncertainty, all_channel_lnd_uncertainty, & - all_channel_sea_uncertainty, all_nchannels_total) + all_channel_sea_uncertainty, all_channel_absolute_bias, all_channel_relative_bias, all_nchannels_total) use channel_structures_m @@ -1922,6 +2008,8 @@ subroutine common_setup(channel_info, channel_ids_user, channel_ids_default, & real, intent(in) :: all_channel_numerical_uncertainty(:) real, intent(in) :: all_channel_lnd_uncertainty(:) real, intent(in) :: all_channel_sea_uncertainty(:) + real, intent(in) :: all_channel_absolute_bias(:) + real, intent(in) :: all_channel_relative_bias(:) integer, intent(in) :: all_nchannels_total integer, dimension(:), allocatable :: unique_views @@ -1975,6 +2063,11 @@ subroutine common_setup(channel_info, channel_ids_user, channel_ids_default, & all_channel_numerical_uncertainty(channel_info%channel_ids_instr(i)) + & all_channel_sea_uncertainty(channel_info%channel_ids_instr(i)) * & all_channel_sea_uncertainty(channel_info%channel_ids_instr(i))) + + channel_info%channel_absolute_bias(i) = & + all_channel_absolute_bias(channel_info%channel_ids_instr(i)) + channel_info%channel_relative_bias(i) = & + all_channel_relative_bias(channel_info%channel_ids_instr(i)) end do ! This section computes the actual number of views in the scene