!---------------------------------------------------------------------- ! MODULE name: NETCDF_READ_MODULE ! ! Routines for reading in netCDF files, such as AHI data ! ! Authors: Andrew Heidinger, NOAA/NESDIS ! Andi Walther, CIMSS ! Denis Botambekov, CIMSS ! ! DEPENDENCIES: Constants, NETCDF library ! !---------------------------------------------------------------------- module NB_CLOUD_MASK_NETCDF_READ_MODULE use NETCDF implicit none public :: OPEN_NETCDF public :: CLOSE_NETCDF public :: READ_NETCDF_GLOBAL_ATTRIBUTE_I4 public :: READ_NETCDF_GLOBAL_ATTRIBUTE_R4 public :: READ_NETCDF_GLOBAL_ATTRIBUTE_CHAR public :: GET_GROUP_ID public :: READ_NETCDF_2D_CHAR public :: READ_NETCDF_1D_REAL public :: READ_NETCDF_1D_INT public :: READ_NETCDF_2D_REAL public :: READ_NETCDF_3D_REAL public :: READ_NETCDF_4D_REAL !!!! THIS IS TO WRITE OUTPUT NetCDF SHOULDN't BE IN CLAVR-x public :: OPEN_NETCDF_WRITE public :: DEFINE_SDS_DIMS_NETCDF public :: WRITE_SDS_NETCDF_2D_R4 public :: WRITE_SDS_NETCDF_2D_I4 public :: WRITE_SDS_NETCDF_3D_R4 character(len=120), parameter, private:: EXE_PROMPT_NAV = "CLAVR-x NetCdf Read Module >> " real, parameter, private:: Missing_Value_Netcdf = -999.0 contains !------------------------------------------------------------------------------ ! open netcdf file for writing !------------------------------------------------------------------------------ subroutine OPEN_NETCDF_WRITE(nc_file, ncid) character(len=*), intent(in):: nc_file integer, intent(out):: ncid integer:: status !status = nf90_open(trim(nc_file), mode = nf90_write, ncid = ncid) status = nf90_create(trim(nc_file), IOR(NF90_NETCDF4, NF90_CLOBBER), ncid = ncid) if (status /= nf90_noerr) then print *, EXE_PROMPT_NAV , 'ERROR: Failed Open on NetCdf File' print*, EXE_PROMPT_NAV ,' filename is: ', nc_file return endif end subroutine OPEN_NETCDF_WRITE !------------------------------------------------------------------------------ ! define NETCDF sds !------------------------------------------------------------------------------ subroutine DEFINE_SDS_DIMS_NETCDF(Sd_Id, Nx, Ny, N_Class, Dimids, Istatus) integer,intent(in) :: Sd_Id, Nx, Ny, N_Class integer, dimension(3), intent(out) :: Dimids integer,intent(out) :: Istatus integer :: X_Dimid, Y_Dimid, Class_Dimid Istatus = 0 Istatus = nf90_def_dim(Sd_Id, "Nx", Nx, X_Dimid) + Istatus Istatus = nf90_def_dim(Sd_Id, "Ny", Ny, Y_Dimid) + Istatus Istatus = nf90_def_dim(Sd_Id, "N_Class", N_Class, Class_Dimid) + Istatus Dimids = (/X_Dimid, Y_Dimid, Class_Dimid/) end subroutine DEFINE_SDS_DIMS_NETCDF !------------------------------------------------------------------------------ ! NETCDF Write Routine 2D Integer4 !------------------------------------------------------------------------------ subroutine WRITE_SDS_NETCDF_2D_I4(Sd_Id, Nx, Ny, Dimids, Sds_Name, Sds_Data_2d_I4, Istatus) integer,intent(in):: Sd_Id, Nx, Ny integer,dimension(2),intent(in):: Dimids character(len=*),intent(in):: Sds_Name integer, dimension(:,:),intent(in):: Sds_Data_2d_I4 integer,intent(out):: Istatus integer, dimension(2) :: Sds_Start_2d, Sds_Stride_2d, Sds_Edge_2d integer :: Sds_Id Istatus = 0 Sds_Start_2d = 1 Sds_Stride_2d = 1 Sds_Edge_2d(1) = Nx Sds_Edge_2d(2) = Ny Istatus = nf90_def_var(Sd_Id, Sds_Name, NF90_INT, Dimids, Sds_Id) + Istatus Istatus = nf90_enddef(Sd_Id) + Istatus Istatus = nf90_put_var(Sd_Id, Sds_Id, & Sds_Data_2d_I4, & start = Sds_Start_2d, & count = Sds_Edge_2d, & stride = Sds_Stride_2d) + Istatus Istatus = nf90_redef(Sd_Id) + Istatus end subroutine WRITE_SDS_NETCDF_2D_I4 !------------------------------------------------------------------------------ ! NETCDF Write Routine 2D Real4 !------------------------------------------------------------------------------ subroutine WRITE_SDS_NETCDF_2D_R4(Sd_Id, Nx, Ny, Dimids, Sds_Name, Sds_Data_2d_R4, Istatus) integer,intent(in):: Sd_Id, Nx, Ny integer,dimension(2),intent(in):: Dimids character(len=*),intent(in):: Sds_Name real, dimension(:,:),intent(in):: Sds_Data_2d_R4 integer,intent(out):: Istatus integer, dimension(2) :: Sds_Start_2d, Sds_Stride_2d, Sds_Edge_2d integer, save :: Sds_Id Istatus = 0 Sds_Start_2d = 1 Sds_Stride_2d = 1 Sds_Edge_2d(1) = Nx Sds_Edge_2d(2) = Ny Istatus = nf90_def_var(Sd_Id, Sds_Name, NF90_REAL4, Dimids, Sds_Id) + Istatus Istatus = nf90_enddef(Sd_Id) + Istatus Istatus = nf90_put_var(Sd_Id, Sds_Id, & Sds_Data_2d_R4, & start = Sds_Start_2d, & count = Sds_Edge_2d, & stride = Sds_Stride_2d) + Istatus Istatus = nf90_redef(Sd_Id) + Istatus end subroutine WRITE_SDS_NETCDF_2D_R4 !------------------------------------------------------------------------------ ! NETCDF Write Routine 3D Real4 !------------------------------------------------------------------------------ subroutine WRITE_SDS_NETCDF_3D_R4(Sd_Id, Nx, Ny, NClass, Dimids, Sds_Name, Sds_Data_3d_R4, Istatus) integer,intent(in):: Sd_Id, Nx, Ny, NClass integer,dimension(3),intent(in):: Dimids character(len=*),intent(in):: Sds_Name real, dimension(:,:,:),intent(in):: Sds_Data_3d_R4 integer,intent(out):: Istatus integer, dimension(3) :: Sds_Start_3d, Sds_Stride_3d, Sds_Edge_3d integer, save :: Sds_Id Istatus = 0 Sds_Start_3d = 1 Sds_Stride_3d = 1 Sds_Edge_3d(1) = Nx Sds_Edge_3d(2) = Ny Sds_Edge_3d(3) = NClass Istatus = nf90_def_var(Sd_Id, Sds_Name, NF90_REAL4, Dimids, Sds_Id) + Istatus Istatus = nf90_enddef(Sd_Id) + Istatus Istatus = nf90_put_var(Sd_Id, Sds_Id, & Sds_Data_3d_R4, & start = Sds_Start_3d, & count = Sds_Edge_3d, & stride = Sds_Stride_3d) + Istatus Istatus = nf90_redef(Sd_Id) + Istatus end subroutine WRITE_SDS_NETCDF_3D_R4 !------------------------------------------------------------------------------ ! open netcdf file for reading !------------------------------------------------------------------------------ subroutine OPEN_NETCDF(nc_file, ncid) character(len=*), intent(in):: nc_file integer, intent(out):: ncid integer:: status status = nf90_open(trim(nc_file), mode = nf90_nowrite, ncid = ncid) if (status /= nf90_noerr) then print *, EXE_PROMPT_NAV , 'ERROR: Failed Open on NetCdf File' print*, EXE_PROMPT_NAV ,' filename is: ', nc_file return endif end subroutine OPEN_NETCDF !------------------------------------------------------------------------------ ! close netcdf file !------------------------------------------------------------------------------ subroutine CLOSE_NETCDF(ncid) integer,intent(in):: ncid integer:: status status = nf90_close(ncid) if (status /= nf90_noerr) then print *, EXE_PROMPT_NAV , 'ERROR: Failed Close on NetCdf File' return endif end subroutine CLOSE_NETCDF !------------------------------------------------------------------------------ ! read global/group attribute INTEGER !------------------------------------------------------------------------------ subroutine READ_NETCDF_GLOBAL_ATTRIBUTE_I4(ncid, attr_name, attr_value) integer(kind=4), intent(in):: ncid character(len=*), intent(in):: attr_name integer(kind=4), intent(out):: attr_value integer:: status status = nf90_get_att(ncid, nf90_global, attr_name, attr_value) if (status /= nf90_noerr) then print *, EXE_PROMPT_NAV , 'ERROR: Reading NETCDF Attribute: ',trim(attr_name) return endif end subroutine READ_NETCDF_GLOBAL_ATTRIBUTE_I4 !------------------------------------------------------------------------------ ! read global/group attribute REAL !------------------------------------------------------------------------------ subroutine READ_NETCDF_GLOBAL_ATTRIBUTE_R4(ncid, attr_name, attr_value) integer(kind=4), intent(in):: ncid character(len=*), intent(in):: attr_name real(kind=4), intent(out):: attr_value integer:: status status = nf90_get_att(ncid, nf90_global, attr_name, attr_value) if (status /= nf90_noerr) then print *, EXE_PROMPT_NAV , 'ERROR: Reading NETCDF Attribute: ',trim(attr_name) return endif end subroutine READ_NETCDF_GLOBAL_ATTRIBUTE_R4 !------------------------------------------------------------------------------ ! read global/group attribute CHARACTER !------------------------------------------------------------------------------ subroutine READ_NETCDF_GLOBAL_ATTRIBUTE_CHAR(ncid, attr_name, attr_value) integer(kind=4), intent(in):: ncid character(len=*), intent(in):: attr_name character(len=30), intent(out):: attr_value integer:: status status = nf90_get_att(ncid, nf90_global, attr_name, attr_value) if (status /= nf90_noerr) then print *, EXE_PROMPT_NAV , 'ERROR: Reading NETCDF Attribute: ',trim(attr_name) return endif end subroutine READ_NETCDF_GLOBAL_ATTRIBUTE_CHAR !------------------------------------------------------------------------------ ! get group id !------------------------------------------------------------------------------ subroutine GET_GROUP_ID(ncid, group_name, group_id) integer, intent(in) :: ncid character(len=*), intent(in) :: group_name integer, intent(out) :: group_id integer:: status Status = nf90_inq_ncid(ncid, trim(group_name), group_id) if (status /= nf90_noerr) then print *, EXE_PROMPT_NAV , 'ERROR: Failed to Get GROUP_ID = ',trim(group_name) return endif end subroutine GET_GROUP_ID ! ---------------------------------------------------------- ! Read in 1D Real arrays ! ---------------------------------------------------------- subroutine READ_NETCDF_1D_REAL(nc_file_id, var_start, var_stride, & var_dim, var_name, var_output) implicit none integer, intent(in) :: nc_file_id integer, dimension(:), intent(in) :: var_start integer, dimension(:), intent(in) :: var_stride integer, dimension(:), intent(in) :: var_dim character(len=*), intent(in) :: var_name real, intent(out), dimension(:) :: var_output integer :: nc_var_id integer :: status status = nf90_inq_varid(nc_file_id,trim(var_name), nc_var_id) if (status /= nf90_noerr) then print *, "Error: Unable to get variable id for ", trim(var_name) return endif !get Variable status = nf90_get_var(nc_file_id, nc_var_id, var_output, start=var_start, & count=var_dim, stride=var_stride) if (status /= nf90_noerr) then print *,'Error: ', trim(nf90_strerror(status)),' ', trim(var_name) return endif end subroutine READ_NETCDF_1D_REAL ! ---------------------------------------------------------- ! Read in 1D Integer arrays ! ---------------------------------------------------------- subroutine READ_NETCDF_1D_INT(nc_file_id, var_start, var_stride, & var_dim, var_name, var_output) implicit none integer, intent(in) :: nc_file_id integer, dimension(:), intent(in) :: var_start integer, dimension(:), intent(in) :: var_stride integer, dimension(:), intent(in) :: var_dim character(len=*), intent(in) :: var_name integer, intent(out), dimension(:) :: var_output integer :: nc_var_id integer :: status status = nf90_inq_varid(nc_file_id,trim(var_name), nc_var_id) if (status /= nf90_noerr) then print *, "Error: Unable to get variable id for ", trim(var_name) return endif !get Variable status = nf90_get_var(nc_file_id, nc_var_id, var_output, start=var_start, & count=var_dim, stride=var_stride) if (status /= nf90_noerr) then print *,'Error: ', trim(nf90_strerror(status)),' ', trim(var_name) return endif end subroutine READ_NETCDF_1D_INT ! ---------------------------------------------------------- ! Read in 2D arrays Characters ! ---------------------------------------------------------- subroutine READ_NETCDF_2D_CHAR(nc_file_id, start_var, var_name, var_output) implicit none integer, intent(in) :: nc_file_id integer, intent(in) :: start_var(:) character(len=*), intent(in) :: var_name character(len=30) , intent(out), dimension(:) :: var_output character(len=30), allocatable, dimension(:,:) :: var integer :: nc_var_id integer :: status, tmp1, tmp2, i integer, dimension(2) ::dimIDs status = nf90_inq_varid(nc_file_id, trim(var_name), nc_var_id) if (status /= nf90_noerr) then print *, "Error: Unable to get variable id for ", trim(var_name) return endif !find dimentions status = nf90_inquire_variable(nc_file_id, nc_var_id, dimids = dimIDs) status = nf90_inquire_dimension(nc_file_id, dimIDs(1), len = tmp1) status = nf90_inquire_dimension(nc_file_id, dimIDs(2), len = tmp2) allocate (var(tmp1,tmp2)) !get Variable status = nf90_get_var(nc_file_id, nc_var_id, var, start=start_var, count=(/tmp1,tmp2/) ) if ((status /= nf90_noerr)) THEN print *,'Error: ', trim(nf90_strerror(status)),' ', trim(var_name) return endif !extract and save classifier names to the final array do i = 1, tmp2 !if ((var(i,1) .ge. 'a' .and. var(i,1) .le. 'z') & !.or.(var(i,1) .ge. 'A' .and. var(i,1) .le. 'Z') & !.or.(var(i,1) .ge. '0' .and. var(i,1) .le. '9') ) then var_output(i) = trim(var(i,1)) !endif enddo if (allocated(var)) deallocate (var) end subroutine READ_NETCDF_2D_CHAR ! ---------------------------------------------------------- ! Read in 2D arrays ! ---------------------------------------------------------- subroutine READ_NETCDF_2D_REAL(nc_file_id, var_start, var_stride, & var_dim, var_name, var_output) implicit none integer, intent(in) :: nc_file_id integer, dimension(:), intent(in) :: var_start integer, dimension(:), intent(in) :: var_stride integer, dimension(:), intent(in) :: var_dim character(len=*), intent(in) :: var_name real, intent(out), dimension(:,:) :: var_output integer :: nc_var_id integer :: status status = nf90_inq_varid(nc_file_id, trim(var_name), nc_var_id) if (status /= nf90_noerr) then print *, "Error: Unable to get variable id for ", trim(var_name) return endif !get Variable status = nf90_get_var(nc_file_id, nc_var_id, var_output, start=var_start, & count=var_dim, stride=var_stride) if ((status /= nf90_noerr)) then print *,'Error: ', trim(nf90_strerror(status)),' ', trim(var_name) return endif end subroutine READ_NETCDF_2D_REAL ! ---------------------------------------------------------- ! Read in 3D arrays ! ---------------------------------------------------------- subroutine READ_NETCDF_3D_REAL(nc_file_id, var_start, var_stride, & var_dim, var_name, var_output) implicit none integer, intent(in) :: nc_file_id integer, dimension(:), intent(in) :: var_start integer, dimension(:), intent(in) :: var_stride integer, dimension(:), intent(in) :: var_dim character(len=*), intent(in) :: var_name real, intent(out), dimension(:,:,:) :: var_output integer :: nc_var_id integer :: status = 0 status = nf90_inq_varid(nc_file_id, trim(var_name), nc_var_id) if (status /= nf90_noerr) then print *, "Error: Unable to get variable id for ", trim(var_name) return endif !get Variable status = nf90_get_var(nc_file_id, nc_var_id, var_output, start=var_start, stride=var_stride, count=var_dim) if ((status /= nf90_noerr)) then print *,'Error: ', trim(nf90_strerror(status)),' ', trim(var_name) return endif end subroutine READ_NETCDF_3D_REAL ! ---------------------------------------------------------- ! Read in 4D arrays ! ---------------------------------------------------------- subroutine READ_NETCDF_4D_REAL(nc_file_id, var_start, var_stride, & var_dim, var_name, var_output) implicit none integer, intent(in) :: nc_file_id integer, dimension(:), intent(in) :: var_start integer, dimension(:), intent(in) :: var_stride integer, dimension(:), intent(in) :: var_dim character(len=*), intent(in) :: var_name real, intent(out), dimension(:,:,:,:) :: var_output integer :: nc_var_id integer :: status = 0 status = nf90_inq_varid(nc_file_id, trim(var_name), nc_var_id) if (status /= nf90_noerr) then print *, "Error: Unable to get variable id for ", trim(var_name) return endif !get Variable status = nf90_get_var(nc_file_id, nc_var_id, var_output, start=var_start, stride=var_stride, count=var_dim) if ((status /= nf90_noerr)) then print *,'Error: ', trim(nf90_strerror(status)),' ', trim(var_name) return endif end subroutine READ_NETCDF_4D_REAL end module NB_CLOUD_MASK_NETCDF_READ_MODULE