-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ASCAT mask maker input utility program #729
Merged
Merged
Changes from 5 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
4c3062b
add ascat mask maker
amfox37 53065bb
discover filepath
amfox37 ff241e7
added header comment
amfox37 ae97130
change default file write to current directory
amfox37 199c730
minor cleanup and documentation (ascat_mask_maker.F90, CMakeLists.txt)
gmao-rreichle 9aa8ec7
declare mask variables as integers
amfox37 409cd2c
move lat/lon to grid cell center
amfox37 e0f3655
add combination choices
amfox37 5805a55
additional cleanup and documentation of ascat_mask_maker.F90:
gmao-rreichle 136df14
Merge branch 'develop' into feature/amfox/ascat_mask_maker
gmao-rreichle f7d0750
CMakeLists to build without install
amfox37 48c5ece
updated paths to ASCAT EUMETSAT soil moisture retrieval data and mask…
gmao-rreichle File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
199 changes: 199 additions & 0 deletions
199
src/Applications/LDAS_App/util/inputs/ASCAT_sm_mask/ascat_mask_maker.F90
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
! This program reads in a NetCDF file containing ASCAT soil moisture masks available from: | ||
! Lindorfer, R., Wagner, W., Hahn, S., Kim, H., Vreugdenhil, M., Gruber, A., Fischer, M., & Trnka, M. (2023). | ||
! Global Scale Maps of Subsurface Scattering Signals Impacting ASCAT Soil Moisture Retrievals (1.0.0) [Data set]. | ||
! TU Wien. https://doi.org/10.48436/9a2y9-e5z14 | ||
! | ||
! It provides the possibility to combine different masks (default case is combination of subsurface and wetland masks) | ||
! and interpolates onto a regular grid with a (hardwired) 0.1 degree lat/lon spacing and -90/-180 degree lower left | ||
! corner used for quick indexing in the ASCAT observation reader QC routine. | ||
! | ||
! Author: AM Fox, March, 2024 | ||
|
||
program ascat_mask_maker | ||
|
||
use netcdf | ||
|
||
implicit none | ||
|
||
integer :: ncid, varid, dimid, ierr, len, N_gpi, dimids(2) | ||
integer :: i, j, closest_index | ||
|
||
integer(kind=1), dimension(:,:), allocatable :: mask_out | ||
integer(kind=1) :: missing_value | ||
|
||
real, dimension(:), allocatable :: asc_lon, asc_lat, cold_mask, wet_mask, veg_mask, subsurface_mask, combined_mask | ||
gmao-rreichle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
real, dimension(:), allocatable :: lon, lat, distances | ||
real :: d_lon, d_lat, ll_lon, ll_lat | ||
|
||
character(400) :: fname_in | ||
|
||
! -------------------------------------------------------------------------------- | ||
! | ||
! hardwired variables | ||
|
||
! ASCAT soil moisture mask file from Lindorfer et al 2023 | ||
|
||
fname_in = '/discover/nobackup/amfox/subsurface_scattering_ASCAT_ERA5_Land.nc' | ||
gmao-rreichle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
! Specification of output grid and missing value | ||
|
||
d_lon = 0.1 | ||
d_lat = 0.1 | ||
ll_lon = -180.0 | ||
ll_lat = -90.0 | ||
|
||
missing_value = -128 | ||
|
||
! ------------------------------- | ||
|
||
! Open the NetCDF file | ||
ierr = nf90_open(fname_in, nf90_nowrite, ncid) | ||
if (ierr /= nf90_noerr) stop 'Error opening file' | ||
|
||
! Data in original mask file are on the 12.5 km fixed Earth grid used for ASCAT (WARP5 grid) and | ||
! stored in the NetCDF file as 1-dimensional arrays of length N_gpi (over land only). | ||
|
||
! Get the dimension ID | ||
ierr = nf90_inq_dimid(ncid, 'gpi', dimid) | ||
if (ierr /= nf90_noerr) stop 'Error getting dimension ID' | ||
|
||
! Get the length of the dimension | ||
ierr = nf90_inquire_dimension(ncid, dimid, len = N_gpi) | ||
if (ierr /= nf90_noerr) stop 'Error inquiring dimension' | ||
|
||
print*, 'N_gpi = ', N_gpi | ||
|
||
! Allocate the arrays | ||
allocate(asc_lon( N_gpi)) | ||
allocate(asc_lat( N_gpi)) | ||
allocate(cold_mask( N_gpi)) | ||
allocate(wet_mask( N_gpi)) | ||
allocate(veg_mask( N_gpi)) | ||
allocate(subsurface_mask(N_gpi)) | ||
allocate(combined_mask( N_gpi)) | ||
|
||
! Get the variable IDs and read the variables | ||
ierr = nf90_inq_varid(ncid, 'lon', varid) | ||
ierr = nf90_get_var(ncid, varid, asc_lon) | ||
ierr = nf90_inq_varid(ncid, 'lat', varid) | ||
ierr = nf90_get_var(ncid, varid, asc_lat) | ||
ierr = nf90_inq_varid(ncid, 'cold_mask', varid) | ||
ierr = nf90_get_var(ncid, varid, cold_mask) | ||
ierr = nf90_inq_varid(ncid, 'wet_mask', varid) | ||
ierr = nf90_get_var(ncid, varid, wet_mask) | ||
ierr = nf90_inq_varid(ncid, 'veg_mask', varid) | ||
ierr = nf90_get_var(ncid, varid, veg_mask) | ||
ierr = nf90_inq_varid(ncid, 'subsurface_mask', varid) | ||
ierr = nf90_get_var(ncid, varid, subsurface_mask) | ||
|
||
! Close the NetCDF file | ||
ierr = nf90_close(ncid) | ||
if (ierr /= nf90_noerr) stop 'Error closing file' | ||
|
||
! Combine the masks (1-dim arrays) | ||
where (wet_mask == 1) | ||
combined_mask = 1 | ||
elsewhere | ||
combined_mask = subsurface_mask | ||
end where | ||
|
||
! Re-map "combined_mask" from WARP5 input grid to regular lat/lon output grid (2-dim array) | ||
|
||
allocate(lon(int(360.0 / d_lon))) | ||
allocate(lat(int(180.0 / d_lat))) | ||
|
||
lon = [(ll_lon + i * d_lon, i = 0, size(lon) - 1)] | ||
lat = [(ll_lat + i * d_lat, i = 0, size(lat) - 1)] | ||
gmao-rreichle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
allocate(mask_out(size(lon), size(lat))) | ||
|
||
do i = 1, size(lon) | ||
print*, lon(i) | ||
do j = 1, size(lat) | ||
allocate(distances(size(asc_lon))) | ||
distances = (asc_lon - lon(i))**2 + (asc_lat - lat(j))**2 | ||
closest_index = minloc(distances, dim = 1) | ||
if (distances(closest_index) > 0.14**2) then | ||
mask_out(i, j) = missing_value | ||
else | ||
mask_out(i, j) = combined_mask(closest_index) | ||
end if | ||
deallocate(distances) | ||
end do | ||
end do | ||
|
||
! Write out the mask to netcdf | ||
ierr = nf90_create('ascat_combined_mask_p1.nc', nf90_clobber, ncid) | ||
if (ierr /= nf90_noerr) stop 'Error creating file' | ||
|
||
! Define the dimensions | ||
ierr = nf90_def_dim(ncid, 'lon', size(lon), dimids(1)) | ||
ierr = nf90_def_dim(ncid, 'lat', size(lat), dimids(2)) | ||
|
||
! Define the variables | ||
ierr = nf90_def_var(ncid, 'lat', nf90_real, dimids(2), varid) | ||
ierr = nf90_put_att(ncid, varid, 'standard_name', 'latitude') | ||
ierr = nf90_put_att(ncid, varid, 'long_name', 'latitude') | ||
ierr = nf90_put_att(ncid, varid, 'units', 'degrees_north') | ||
ierr = nf90_put_att(ncid, varid, 'axis', 'Y') | ||
|
||
ierr = nf90_def_var(ncid, 'lon', nf90_real, dimids(1), varid) | ||
ierr = nf90_put_att(ncid, varid, 'standard_name', 'longitude') | ||
ierr = nf90_put_att(ncid, varid, 'long_name', 'longitude') | ||
ierr = nf90_put_att(ncid, varid, 'units', 'degrees_east') | ||
ierr = nf90_put_att(ncid, varid, 'axis', 'X') | ||
|
||
ierr = nf90_def_var(ncid, 'mask', nf90_byte, dimids, varid) | ||
ierr = nf90_put_att(ncid, varid, 'standard_name', 'combined_mask') | ||
ierr = nf90_put_att(ncid, varid, 'long_name', 'Combined mask') | ||
ierr = nf90_put_att(ncid, varid, 'units', 'boolean') | ||
ierr = nf90_put_att(ncid, varid, '_FillValue', missing_value) | ||
|
||
ierr = nf90_def_var(ncid, 'll_lon', nf90_real, varid) | ||
ierr = nf90_put_att(ncid, varid, 'standard_name', 'longitude of lower left corner') | ||
ierr = nf90_put_att(ncid, varid, 'long_name', 'longitude of lower left corner') | ||
ierr = nf90_put_att(ncid, varid, 'units', 'degrees_east') | ||
ierr = nf90_put_att(ncid, varid, 'axis', 'X') | ||
|
||
ierr = nf90_def_var(ncid, 'll_lat', nf90_real, varid) | ||
ierr = nf90_put_att(ncid, varid, 'standard_name', 'latitude of lower left corner') | ||
ierr = nf90_put_att(ncid, varid, 'long_name', 'latitude of lower left corner') | ||
ierr = nf90_put_att(ncid, varid, 'units', 'degrees_north') | ||
ierr = nf90_put_att(ncid, varid, 'axis', 'Y') | ||
|
||
ierr = nf90_def_var(ncid, 'd_lon', nf90_real, varid) | ||
ierr = nf90_put_att(ncid, varid, 'standard_name', 'longitude grid spacing') | ||
ierr = nf90_put_att(ncid, varid, 'long_name', 'longitude grid spacing') | ||
ierr = nf90_put_att(ncid, varid, 'units', 'degrees') | ||
ierr = nf90_put_att(ncid, varid, 'axis', 'X') | ||
|
||
ierr = nf90_def_var(ncid, 'd_lat', nf90_real, varid) | ||
ierr = nf90_put_att(ncid, varid, 'long_name', 'latitude grid spacing') | ||
ierr = nf90_put_att(ncid, varid, 'units', 'degrees') | ||
ierr = nf90_put_att(ncid, varid, 'axis', 'Y') | ||
|
||
! End define mode | ||
ierr = nf90_enddef(ncid) | ||
|
||
! Write the variables | ||
ierr = nf90_inq_varid(ncid, 'lat', varid) | ||
ierr = nf90_put_var(ncid, varid, lat) | ||
ierr = nf90_inq_varid(ncid, 'lon', varid) | ||
ierr = nf90_put_var(ncid, varid, lon) | ||
ierr = nf90_inq_varid(ncid, 'mask', varid) | ||
ierr = nf90_put_var(ncid, varid, mask_out) | ||
if (ierr /= nf90_noerr) stop 'Error writing variable' | ||
ierr = nf90_inq_varid(ncid, 'll_lon', varid) | ||
ierr = nf90_put_var(ncid, varid, ll_lon) | ||
ierr = nf90_inq_varid(ncid, 'll_lat', varid) | ||
ierr = nf90_put_var(ncid, varid, ll_lat) | ||
ierr = nf90_inq_varid(ncid, 'd_lon', varid) | ||
ierr = nf90_put_var(ncid, varid, d_lon) | ||
ierr = nf90_inq_varid(ncid, 'd_lat', varid) | ||
ierr = nf90_put_var(ncid, varid, d_lat) | ||
|
||
! Close the NetCDF file | ||
ierr = nf90_close(ncid) | ||
if (ierr /= nf90_noerr) stop 'Error closing file' | ||
|
||
end program ascat_mask_maker |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@weiyuan-jiang @gmao-rreichle My update to the CMakeLists works OK and builds but doesn't install, but I don't know if adding
esma_add_subdirectories(util/inputs/ASCAT_sm_mask)
is the correct thing to do?