!! advanced operations on grids
!|author: Giovanni Ravazzani
! license: GPL
!
!### History
!
! current version 1.8 - 19th January 2021
!
!
! | Version | Date | Comment |
! |---------|-------------|------------------|
! | 0.1 | 29/Jun/2009 | Original code. giovanni ravazzani |
! | 0.2 | 09/Aug/2009 | Added GridByIni |
! | 0.3 | 07/Apr/2010 | Added GridResample |
! | 0.4 | 16/Oct/2010 | function to compute cell area and distance |
! | 0.5 | 03/Feb/2011 | Distance moved to GeoLib |
! | 0.6 | 01/Aug/2011 | optional argument for cellsize output from GridConvert |
! | 0.7 | 19/Oct/2011 | added getSum routines |
! | 0.8 | 03/Dec/2012 | GetMin function |
! | 0.9 | 20/Mar/2013 | correct a bug in SUBROUTINE ResampleFloat |
! | 1.0 | 09/Apr/2013 | MinMaxNormalization and GetMax routines |
! | 1.1 | 11/Apr/2013 | ZscoreNormalization and GetStDev routines |
! | 1.2 | 12/Mar/2016 | GetRMSE function to compute Root Mean Square Error between two grids real |
! | 1.3 | 10/May/2016 | GetBias function to compute Bias between two grids real |
! | 1.4 | 19/Dec/2016 | statistic routines moved to new module GridStatistics |
! | 1.5 | 28/Nov/2017 | GridByIni modified to read epsg code |
! | 1.6 | 03/Mar/2018 | Added functions CellIsNoData and CellIsValid |
! | 1.7 | 28/Jan/2020 | Grid2vector subroutine to transform grid content to an array 1D |
! | 1.8 | 19/Jan/2021 | Added CellLength, moved ExtractBorder from function to subroutine |
!
!### License
! license: GNU GPL
!
! This file is part of
!
! MOSAICO -- MOdular library for raSter bAsed hydrologIcal appliCatiOn.
!
! Copyright (C) 2011 Giovanni Ravazzani
!
!### Module Description:
! library to operate on grids
MODULE GridOperations
! History:
! Modules used:
USE DataTypeSizes, ONLY: &
! Imported type definitions:
short, long, float
USE LogLib, ONLY: &
! Imported routines:
Catch
USE ErrorCodes, ONLY: &
!Imported parameters:
memAllocError, unknownOption
USE GridLib, ONLY: &
!Imported type definitions:
grid_integer, grid_real, &
! Imported routines:
NewGrid, SyncTime, &
!Imported parameters:
ESRI_ASCII, ESRI_BINARY, NET_CDF
USE GeoLib, ONLY: &
!Imported operators:
OPERATOR (==)
IMPLICIT NONE
!global (public declarations)
INTERFACE ASSIGNMENT(=)
MODULE PROCEDURE AssignGridReal
MODULE PROCEDURE AssignGridInteger
MODULE PROCEDURE AssignReal
MODULE PROCEDURE AssignInteger
MODULE PROCEDURE AssignGridRealInteger
MODULE PROCEDURE AssignGridIntegerReal
END INTERFACE
INTERFACE GridConvert
MODULE PROCEDURE GridConvertFloat
MODULE PROCEDURE GridConvertInteger
END INTERFACE
INTERFACE GridShift
MODULE PROCEDURE ShiftInteger
MODULE PROCEDURE ShiftReal
END INTERFACE
INTERFACE GetXY
MODULE PROCEDURE GetXYFloat
MODULE PROCEDURE GetXYInteger
END INTERFACE
INTERFACE GetIJ
MODULE PROCEDURE GetIJFloat
MODULE PROCEDURE GetIJInteger
END INTERFACE
INTERFACE CRSisEqual
MODULE PROCEDURE CRSisEqualIntInt
MODULE PROCEDURE CRSisEqualFloatFloat
MODULE PROCEDURE CRSisEqualFloatInt
MODULE PROCEDURE CRSisEqualIntFloat
END INTERFACE
INTERFACE GridByIni
MODULE PROCEDURE GridByIniFloat
MODULE PROCEDURE GridByIniInteger
MODULE PROCEDURE GridByIniFloatSubSection
MODULE PROCEDURE GridByIniIntegerSubSection
END INTERFACE
INTERFACE IsOutOfGrid
MODULE PROCEDURE IsOutOfGridFloat
MODULE PROCEDURE IsOutOfGridInteger
END INTERFACE
INTERFACE ExtractBorder
MODULE PROCEDURE ExtractBorderFloat
MODULE PROCEDURE ExtractBorderInteger
END INTERFACE
INTERFACE GridResample
MODULE PROCEDURE ResampleFloatCell
MODULE PROCEDURE ResampleIntegerCell
MODULE PROCEDURE ResampleFloat
MODULE PROCEDURE ResampleInteger
END INTERFACE
INTERFACE CellArea
MODULE PROCEDURE CellAreaFloat
MODULE PROCEDURE CellAreaInteger
END INTERFACE
INTERFACE CellLength
MODULE PROCEDURE CellLengthFloat
MODULE PROCEDURE CellLengthInteger
END INTERFACE
INTERFACE GetArea
MODULE PROCEDURE GetAreaOfGridFloat
MODULE PROCEDURE GetAreaOfGridInteger
END INTERFACE
INTERFACE CellIsNoData
MODULE PROCEDURE CellIsNoDataInteger
MODULE PROCEDURE CellIsNoDataFloat
END INTERFACE
INTERFACE CellIsValid
MODULE PROCEDURE CellIsValidInteger
MODULE PROCEDURE CellIsValidFloat
END INTERFACE
INTERFACE Grid2vector
MODULE PROCEDURE Grid2vectorInteger
MODULE PROCEDURE Grid2vectorFloat
END INTERFACE
!global procedures:
PUBLIC :: GridConvert
PUBLIC :: GetXY
PUBLIC :: GetIJ
PUBLIC :: CRSisEqual
PUBLIC :: GridByIni
PUBLIC :: IsOutOfGrid
PUBLIC :: ExtractBorder
PUBLIC :: GridResample
PUBLIC :: CellArea
PUBLIC :: CellIsNoData
PUBLIC :: CellIsValid
PUBLIC :: Grid2vector
PUBLIC :: CellLength
! Local (i.e. private) Declarations:
! Local Procedures:
PRIVATE :: GridConvertFloat
PRIVATE :: GridConvertInteger
PRIVATE :: CRSisEqualFloatFloat
PRIVATE :: CRSisEqualIntInt
PRIVATE :: CRSisEqualIntFloat
PRIVATE :: CRSisEqualFloatInt
PRIVATE :: GetXYinteger
PRIVATE :: GetXYFloat
PRIVATE :: GetIJinteger
PRIVATE :: GetIJFloat
PRIVATE :: GridByIniFloat
PRIVATE :: GridByIniInteger
PRIVATE :: IsOutOfGridInteger
PRIVATE :: IsOutOfGridFloat
PRIVATE :: ExtractBorderFloat
PRIVATE :: ExtractBorderInteger
PRIVATE :: ResampleFloatCell
PRIVATE :: ResampleIntegerCell
PRIVATE :: ResampleFloat
PRIVATE :: ResampleInteger
PRIVATE :: AssignGridIntegerReal
PRIVATE :: AssignGridReal
PRIVATE :: AssignGridInteger
PRIVATE :: AssignGridRealInteger
PRIVATE :: AssignReal
PRIVATE :: AssignInteger
PRIVATE :: CellAreaFloat
PRIVATE :: CellAreaInteger
PRIVATE :: GetAreaOfGridInteger
PRIVATE :: GetAreaOfGridFloat
PRIVATE :: CellIsNoDataInteger
PRIVATE :: CellIsNoDataFloat
PRIVATE :: CellIsValidInteger
PRIVATE :: CellIsValidFloat
PRIVATE :: CellLengthFloat
PRIVATE :: CellLengthInteger
!=======
CONTAINS
!=======
! Define procedures contained in this module.
!------------------------------------------------------------------------------
!| Description
! compute area (m2) of a cell of a grid as a function of latitude defined by
! the position of cell in local coordinate system (row, column).
! Input grid of type grid_real
! ***
! Reference:
!
! Sivakholundu, K. M., Prabaharan, N. (1998). A program to
! compute the area of an irregular polygon on a spheroidal surface,
! Computers & Geosciences, 24(8), 823-826.
FUNCTION CellAreaFloat &
!
(gridIn, i, j) &
!
RESULT(cellarea)
USE GeoLib , ONLY: &
!Imported parameters:
GEODETIC
USE Units, ONLY: &
!Imported parameters:
degToRad, squareKilometer
!arguments with intent(in):
TYPE(grid_real), INTENT (IN) :: gridIn
INTEGER, INTENT (IN) :: i,j !!row and column of cell
!Local variables
REAL (KIND = float) :: midLatitude !mid-latitude of cell
REAL (KIND = float) :: cellWidht !cell width in angular terms
REAL (KIND = float) :: re !!semi-major axis of spheroid
REAL (KIND = float) :: ecc !!eccentricity of spheroid
REAL (KIND = float) :: cellarea
REAL (KIND = float) :: x, y
LOGICAL :: check
SELECT CASE (gridIn % grid_mapping % system)
CASE (GEODETIC)
CALL GetXY (i, j, gridIn, x, y, check)
IF (.NOT. check) THEN
CALL Catch ('error', 'GridOperations', &
'cell out of grid calculating cell area' )
ENDIF
midLatitude = y * degToRad
cellWidht = gridIn % cellsize * degToRad
re = gridIn % grid_mapping % ellipsoid % a
ecc = gridIn % grid_mapping % ellipsoid % e
cellarea = re**2. * (1.-ecc**2.) * SIN(cellWidht)**2. * COS(midLatitude) / &
(1.-ecc**2.*SIN(midLatitude)**2.)**2.
CASE DEFAULT
cellarea = gridIn % cellsize ** 2.
END SELECT
END FUNCTION CellAreaFloat
!------------------------------------------------------------------------------
!| Description
! compute area (m2) of a cell of a grid as a function of latitude defined by
! the position of cell in local coordinate system (row, column).
! Input grid of type grid_integer
! ***
! Reference:
!
! Sivakholundu, K. M., Prabaharan, N. (1998). A program to
! compute the area of an irregular polygon on a spheroidal surface,
! Computers & Geosciences, 24(8), 823-826.
FUNCTION CellAreaInteger &
!
(gridIn, i, j) &
!
RESULT(cellarea)
USE GeoLib , ONLY: &
!Imported parameters:
GEODETIC
USE Units, ONLY: &
!Imported parameters:
degToRad, squareKilometer
!arguments with intent(in):
TYPE(grid_integer), INTENT (IN) :: gridIn
INTEGER, INTENT (IN) :: i,j !!row and column of cell
!Local variables
REAL (KIND = float) :: midLatitude !mid-latitude of cell
REAL (KIND = float) :: cellWidht !cell width in angular terms
REAL (KIND = float) :: re !!semi-major axis of spheroid
REAL (KIND = float) :: ecc !!eccentricity of spheroid
REAL (KIND = float) :: cellarea
REAL (KIND = float) :: x, y
LOGICAL :: check
!------------------------------end of declarations-----------------------------
SELECT CASE (gridIn % grid_mapping % system)
CASE (GEODETIC)
CALL GetXY (i, j, gridIn, x, y, check)
IF (.NOT. check) THEN
CALL Catch ('error', 'GridOperations', &
'cell out of grid calculating cell area' )
ENDIF
midLatitude = y * degToRad
cellWidht = gridIn % cellsize * degToRad
re = gridIn % grid_mapping % ellipsoid % a
ecc = gridIn % grid_mapping % ellipsoid % e
cellarea = re**2. * (1.-ecc**2.) * SIN(cellWidht)**2. * COS(midLatitude) / &
(1.-ecc**2.*SIN(midLatitude)**2.)**2.
CASE DEFAULT
cellarea = gridIn % cellsize ** 2.
END SELECT
END FUNCTION CellAreaInteger
!------------------------------------------------------------------------------
!| Description
! compute average length (m) of a cell of a grid as the squareroot of area
! Input grid of type grid_integer
FUNCTION CellLengthInteger &
!
(gridIn, i, j) &
!
RESULT(length)
!arguments with intent(in):
TYPE(grid_integer), INTENT (IN) :: gridIn
INTEGER, INTENT (IN) :: i,j !!row and column of cell
!Local variables
REAL (KIND = float) :: length
!------------------------------end of declarations-----------------------------
length = ( CellArea (gridin,i,j) ) ** 0.5
RETURN
END FUNCTION CellLengthInteger
!------------------------------------------------------------------------------
!| Description
! compute average length (m) of a cell of a grid as the squareroot of area
! Input grid of type grid_real
FUNCTION CellLengthFloat &
!
(gridIn, i, j) &
!
RESULT(length)
!arguments with intent(in):
TYPE(grid_real), INTENT (IN) :: gridIn
INTEGER, INTENT (IN) :: i,j !!row and column of cell
!Local variables
REAL (KIND = float) :: length
!------------------------------end of declarations-----------------------------
length = ( CellArea (gridin,i,j) ) ** 0.5
RETURN
END FUNCTION CellLengthFloat
!==============================================================================
!| Description:
! coordinate conversion of a `grid_real`
! definition of corner points:
!
!```
! A---------B
! | |
! | |
! | |
! C---------D
!```
SUBROUTINE GridConvertFloat &
!
(GridIn, GridOut, cellsize)
USE GeoLib, ONLY: &
!Imported type definitions:
Coordinate, &
! Imported routines:
SetCoord, Convert, ASSIGNMENT(=)
!arguments with intent(in):
TYPE (grid_real), INTENT (IN) :: GridIn
REAL (KIND = float), OPTIONAL, INTENT (IN) :: cellsize
!arguments with intent (inout):
TYPE (grid_real), INTENT (INOUT) :: GridOut
!local variables:
TYPE (Coordinate) :: Ain, Bin, Cin, Din !!corner points of input grid
TYPE (Coordinate) :: Aout, Bout, Cout, Dout !!corner points converted to new CRS
TYPE (Coordinate) :: Arec, Brec, Crec, Drec !!corner points of rectangle
TYPE (Coordinate) :: pointNew !!generic point in the new CRS
TYPE (Coordinate) :: pointOld !!generic point in the old CRS
REAL (KIND = float) :: Xdim, Ydim
INTEGER :: newXsize, newYsize
REAL (KIND = float) :: CellSizeX, CellSizeY, newCellSize
INTEGER (KIND = short) :: ios !!error return code
INTEGER (KIND = short) :: i, j, iOld, jOld
REAL (KIND = float) :: X, Y
LOGICAL :: checkBound
!------------end of declaration------------------------------------------------
!------------------------------------------------------------------------------
! calculate corner points
!------------------------------------------------------------------------------
!Set coordinate of corner Ain
CALL SetCoord (GridIn % xllcorner , GridIn % yllcorner + &
GridIn % idim * GridIn % cellsize, Ain)
!copy coordinate reference system parameters
Ain % system = GridIn % grid_mapping
Aout %system = GridOut % grid_mapping
!calculate coordinate in the new reference system
CALL Convert (Ain, Aout)
!Set coordinate of corner Bin
CALL SetCoord (GridIn % xllcorner + GridIn % jdim * GridIn % cellsize , &
GridIn % yllcorner + GridIn % idim * GridIn % cellsize, Bin)
!copy corrdinate reference system parameters
Bin % system = GridIn % grid_mapping
Bout % system = GridOut % grid_mapping
!calculate coordinate in the new reference system
CALL Convert (Bin, Bout)
!Set coordinate of corner Cin
CALL SetCoord (GridIn % xllcorner, GridIn % yllcorner, Cin)
!copy coordinate reference system parameters
Cin % system = GridIn % grid_mapping
Cout % system = GridOut % grid_mapping
!calculate coordinate in the new reference system
CALL Convert (Cin, Cout)
!Set coordinate of corner Din
CALL SetCoord (GridIn % xllcorner + GridIn % jdim * GridIn % cellsize, &
GridIn % yllcorner, Din)
!copy corrdinate reference system parameters
Din % system = GridIn % grid_mapping
Dout % system = GridOut % grid_mapping
!calculate coordinate in the new reference system
CALL Convert (Din, Dout)
!------------------------------------------------------------------------------
! define minimum rectangular view that contains the 4 converted points
!------------------------------------------------------------------------------
!calculate Arec
CALL SetCoord ( MIN (Aout % easting, Cout % easting), &
MAX (Aout % northing, Bout % northing), Arec )
!copy corrdinate reference system parameters
Arec % system = Aout % system
!calculate Brec
CALL SetCoord ( MAX (Bout % easting, Dout % easting), &
MAX (Aout % northing, Bout % northing), Brec )
!copy corrdinate reference system parameters
Brec % system = Bout % system
!calculate Crec
CALL SetCoord ( MIN (Aout % easting, Cout % easting), &
MIN (Cout % northing, Dout % northing), Crec )
!copy corrdinate reference system parameters
Crec % system = Cout % system
!calculate Drec
CALL SetCoord ( MAX (Bout % easting, Dout % easting), &
MIN (Cout % northing, Dout % northing), Drec )
!copy corrdinate reference system parameters
Drec % system = Dout % system
!------------------------------------------------------------------------------
! calculate cellsize of gridout, number of rows and columns
!------------------------------------------------------------------------------
Xdim = Brec % easting - Arec % easting
Ydim = Brec % northing - Drec % northing
IF (PRESENT (cellsize) ) THEN
!set cellsize of new grid to cellsize
newCellSize = cellsize
!calculate number of columns of new grid
newXsize = INT ( Xdim / newCellSize ) + 1
!calculate number of rows of new grid
newYsize = INT ( Ydim / newCellSize ) + 1
ELSE
CellSizeX = Xdim / GridIn % jdim
CellSizeY = Ydim / GridIn % idim
!set cellsize of new grid to CellSizeX
newCellSize = CellSizeX
!set number of columns of new grid equals to GridIn
newXsize = GridIn % jdim
!calculate number of rows of new grid
newYsize = INT ( Ydim / newCellSize ) + 1
END IF
!------------------------------------------------------------------------------
! define new grid
!------------------------------------------------------------------------------
GridOut % jdim = newXsize
GridOut % idim = newYsize
GridOut % standard_name = GridIn % standard_name
GridOut % long_name = GridIn % long_name
GridOut % units = GridIn % units
GridOut % varying_mode = GridIn % varying_mode
GridOut % nodata = GridIn % nodata
GridOut % valid_min = GridIn % valid_min
GridOut % valid_max = GridIn % valid_max
GridOut % reference_time = GridIn % reference_time
GridOut % current_time = GridIn % current_time
GridOut % time_index = GridIn % time_index
GridOut % time_unit = GridIn % time_unit
GridOut % cellsize = newCellSize
GridOut % xllcorner = Crec % easting
GridOut % yllcorner = Crec % northing
!esri_pe_string !!used by ArcMap 9.2
IF (ALLOCATED(GridOut % mat)) THEN
DEALLOCATE (GridOut % mat)
END IF
ALLOCATE ( GridOut % mat ( newYsize, newXsize ), STAT = ios )
IF (ios /= 0) THEN
CALL Catch ('error', 'GridOperations', &
'memory allocation: ', &
code = memAllocError,argument = 'converted grid' )
ENDIF
DO i = 1, GridOut % idim
DO j = 1, GridOut % jdim
GridOut % mat (i,j) = GridOut % nodata
END DO
END DO
!------------------------------------------------------------------------------
! fill in new grid with values
!------------------------------------------------------------------------------
!set CRS of pointOld and pointNew
pointOld % system = GridIn % grid_mapping
pointNew % system = GridOut % grid_mapping
!loop
DO i = 1, GridOut % idim
DO j = 1, GridOut % jdim
!set pointNew
CALL GetXY (i, j, GridOut, X, Y, checkBound)
CALL SetCoord (X, Y, pointNew)
!calculate pointOld
CALL Convert (pointNew, pointOld)
CALL GetIJ (pointOld % easting, pointOld % northing, GridIn, iOld, jOld, checkBound)
IF (checkBound) THEN
IF (GridIn % mat (iOld, jOld) /= GridIn % nodata) THEN
GridOut % mat (i,j) = GridIn % mat (iOld, jOld)
END IF
END IF
END DO
END DO
END SUBROUTINE GridConvertFloat
!==============================================================================
!| Description:
! coordinate conversion of a `grid_integer`
! definition of corner points:
!
!```
! A---------B
! | |
! | |
! | |
! C---------D
!```
!
SUBROUTINE GridConvertInteger &
!
(GridIn, GridOut, cellsize)
USE GeoLib, ONLY: &
!Imported type definitions:
Coordinate, &
! Imported routines:
SetCoord, Convert, ASSIGNMENT(=)
!arguments with intent(in):
TYPE (grid_integer), INTENT (IN) :: GridIn
REAL (KIND = float), OPTIONAL, INTENT (IN) :: cellsize
!arguments with intent (inout):
TYPE (grid_integer), INTENT (INOUT) :: GridOut
!local variables:
TYPE (Coordinate) :: Ain, Bin, Cin, Din !!corner points of input grid
TYPE (Coordinate) :: Aout, Bout, Cout, Dout !!corner points converted to new CRS
TYPE (Coordinate) :: Arec, Brec, Crec, Drec !!corner points of rectangle
TYPE (Coordinate) :: pointNew !!generic point in the new CRS
TYPE (Coordinate) :: pointOld !!generic point in the old CRS
REAL (KIND = float) :: Xdim, Ydim
INTEGER :: newXsize, newYsize
REAL (KIND = float) :: CellSizeX, CellSizeY, newCellSize
INTEGER (KIND = short) :: ios !!error return code
INTEGER (KIND = short) :: i, j, iOld, jOld
REAL (KIND = float) :: X, Y
LOGICAL :: checkBound
!------------end of declaration------------------------------------------------
!------------------------------------------------------------------------------
! calculate corner points
!------------------------------------------------------------------------------
!Set coordinate of corner Ain
CALL SetCoord (GridIn % xllcorner , GridIn % yllcorner + &
GridIn % idim * GridIn % cellsize, Ain)
!copy corrdinate reference system parameters
Ain % system = GridIn % grid_mapping
Aout %system = GridOut % grid_mapping
!calculate coordinate in the new reference system
CALL Convert (Ain, Aout)
!Set coordinate of corner Bin
CALL SetCoord (GridIn % xllcorner + GridIn % jdim * GridIn % cellsize , &
GridIn % yllcorner + GridIn % idim * GridIn % cellsize, Bin)
!copy corrdinate reference system parameters
Bin % system = GridIn % grid_mapping
Bout %system = GridOut % grid_mapping
!calculate coordinate in the new reference system
CALL Convert (Bin, Bout)
!Set coordinate of corner Cin
CALL SetCoord (GridIn % xllcorner, GridIn % yllcorner, Cin)
!copy corrdinate reference system parameters
Cin % system = GridIn % grid_mapping
Cout %system = GridOut % grid_mapping
!calculate coordinate in the new reference system
CALL Convert (Cin, Cout)
!Set coordinate of corner Din
CALL SetCoord (GridIn % xllcorner + GridIn % jdim * GridIn % cellsize, &
GridIn % yllcorner, Din)
!copy corrdinate reference system parameters
Din % system = GridIn % grid_mapping
Dout % system = GridOut % grid_mapping
!calculate coordinate in the new reference system
CALL Convert (Din, Dout)
!------------------------------------------------------------------------------
! define minimum rectangular view that contains the 4 converted points
!------------------------------------------------------------------------------
!calculate Arec
CALL SetCoord ( MIN (Aout % easting, Cout % easting), &
MAX (Aout % northing, Bout % northing), Arec )
!copy corrdinate reference system parameters
Arec % system = Aout % system
!calculate Brec
CALL SetCoord ( MAX (Bout % easting, Dout % easting), &
MAX (Aout % northing, Bout % northing), Brec )
!copy corrdinate reference system parameters
Brec % system = Bout % system
!calculate Crec
CALL SetCoord ( MIN (Aout % easting, Cout % easting), &
MIN (Cout % northing, Dout % northing), Crec )
!copy corrdinate reference system parameters
Crec % system = Cout % system
!calculate Drec
CALL SetCoord ( MAX (Bout % easting, Dout % easting), &
MIN (Cout % northing, Dout % northing), Drec )
!copy corrdinate reference system parameters
Drec % system = Dout % system
!------------------------------------------------------------------------------
! calculate cellsize of gridout, number of rows and columns
!------------------------------------------------------------------------------
Xdim = Brec % easting - Arec % easting
Ydim = Brec % northing - Drec % northing
IF (PRESENT (cellsize) ) THEN
!set cellsize of new grid to cellsize
newCellSize = cellsize
!calculate number of columns of new grid
newXsize = INT ( Xdim / newCellSize ) + 1
!calculate number of rows of new grid
newYsize = INT ( Ydim / newCellSize ) + 1
ELSE
CellSizeX = Xdim / GridIn % jdim
CellSizeY = Ydim / GridIn % idim
!set cellsize of new grid to CellSizeX
newCellSize = CellSizeX
!set number of columns of new grid equals to GridIn
newXsize = GridIn % jdim
!calculate number of rows of new grid
newYsize = INT ( Ydim / newCellSize ) + 1
END IF
!------------------------------------------------------------------------------
! define new grid
!------------------------------------------------------------------------------
GridOut % jdim = newXsize
GridOut % idim = newYsize
GridOut % standard_name = GridIn % standard_name
GridOut % long_name = GridIn % long_name
GridOut % units = GridIn % units
GridOut % varying_mode = GridIn % varying_mode
GridOut % nodata = GridIn % nodata
GridOut % valid_min = GridIn % valid_min
GridOut % valid_max = GridIn % valid_max
GridOut % reference_time = GridIn % reference_time
GridOut % current_time = GridIn % current_time
GridOut % time_index = GridIn % time_index
GridOut % time_unit = GridIn % time_unit
GridOut % cellsize = newCellSize
GridOut % xllcorner = Crec % easting
GridOut % yllcorner = Crec % northing
!esri_pe_string !!used by ArcMap 9.2
IF (ALLOCATED(GridOut % mat)) THEN
DEALLOCATE (GridOut % mat)
END IF
ALLOCATE ( GridOut % mat ( newYsize, newXsize ), STAT = ios )
IF (ios /= 0) THEN
CALL Catch ('error', 'GridOperations', &
'memory allocation ', &
code = memAllocError,argument = 'converted grid' )
ENDIF
DO i = 1, GridOut % idim
DO j = 1, GridOut % jdim
GridOut % mat (i,j) = GridOut % nodata
END DO
END DO
!------------------------------------------------------------------------------
! fill in new grid with values
!------------------------------------------------------------------------------
!set CRS of pointOld and pointNew
pointOld % system = GridIn % grid_mapping
pointNew % system = GridOut % grid_mapping
!loop
DO i = 1, GridOut % idim
DO j = 1, GridOut % jdim
!set pointNew
CALL GetXY (i, j, GridOut, X, Y, checkBound)
CALL SetCoord (X, Y, pointNew)
!calculate pointOld
CALL Convert (pointNew, pointOld)
CALL GetIJ (pointOld % easting, pointOld % northing, GridIn, iOld, jOld, checkBound)
IF (checkBound) THEN
IF (GridIn % mat (iOld, jOld) /= GridIn % nodata) THEN
GridOut % mat (i,j) = GridIn % mat (iOld, jOld)
END IF
END IF
END DO
END DO
END SUBROUTINE GridConvertInteger
!==============================================================================
!| Description:
! returns X and Y coordinate given i and j position in grid(i,j)
SUBROUTINE GetIJfloat &
!
(X, Y, grid, i, j, check)
IMPLICIT NONE
!Arguments with intent(in):
REAL (KIND = float), INTENT(IN) :: X,Y
TYPE (grid_real), INTENT(IN) :: grid
!Arguments with intent(out):
INTEGER, INTENT(OUT) :: i, j
LOGICAL, OPTIONAL, INTENT(OUT) :: check !!return false if i and j are outside grid definition
!------------end of declaration------------------------------------------------
j = INT ( (X - grid % xllcorner) / grid %cellsize ) + 1
i = INT ( (grid % yllcorner + grid % idim * grid % cellsize - y) &
/ grid%cellsize ) + 1
IF (PRESENT (check)) THEN
IF (i < 1 .OR. i > grid % idim .OR. j < 1 .OR. j > grid % jdim ) THEN
check = .FALSE.
ELSE
check = .TRUE.
END IF
END IF
END SUBROUTINE GetIJfloat
!==============================================================================
!| Description:
! returns X and Y coordinate given i and j position in grid(i,j)
SUBROUTINE GetIJinteger &
!
(X, Y, grid, i, j, check)
IMPLICIT NONE
!Arguments with intent(in):
REAL (KIND = float), INTENT(IN) :: X,Y
TYPE (grid_integer), INTENT(IN) :: grid
!Arguments with intent(out):
INTEGER, INTENT(OUT) :: i, j
LOGICAL, OPTIONAL, INTENT(OUT) :: check !!return false if i and j are outside grid definition
!------------end of declaration------------------------------------------------
j = INT ( (X - grid % xllcorner) / grid %cellsize ) + 1
i = INT ( (grid % yllcorner + grid % idim * grid % cellsize - y) &
/ grid%cellsize ) + 1
IF (PRESENT (check)) THEN
IF (i < 1 .OR. i > grid % idim .OR. j < 1 .OR. j > grid % jdim ) THEN
check = .FALSE.
ELSE
check = .TRUE.
END IF
END IF
END SUBROUTINE GetIJinteger
!==============================================================================
!| Description:
! returns X and Y coordinate given i and j position in grid(i,j)
SUBROUTINE GetXYfloat &
!
(i, j, grid, X, Y, check)
IMPLICIT NONE
!Arguments with intent(in):
TYPE (grid_real), INTENT(IN) :: grid
INTEGER, INTENT(IN) :: i, j
!Arguments with intent(out):
REAL (KIND = float), INTENT(OUT) :: X,Y
LOGICAL, OPTIONAL, INTENT(OUT) :: check !!return false if i and j are outside grid definition
!------------end of declaration------------------------------------------------
IF (i < 1 .OR. i > grid % idim .OR. j < 1 .OR. j > grid % jdim ) THEN
X = 0.
Y = 0.
IF ( PRESENT(check) ) check = .FALSE.
ELSE
X = grid % xllcorner + (j - 0.5) * grid % cellsize
Y = grid % yllcorner + (grid % idim - i + 0.5) * grid % cellsize
IF ( PRESENT(check) ) check = .TRUE.
END IF
END SUBROUTINE GetXYfloat
!==============================================================================
!| Description:
! returns X and Y coordinate given i and j position in grid(i,j)
SUBROUTINE GetXYinteger &
!
(i, j, grid, X, Y, check)
IMPLICIT NONE
!Arguments with intent(in):
TYPE (grid_integer), INTENT(IN) :: grid
INTEGER, INTENT(IN) :: i, j
!Arguments with intent(out):
REAL (KIND = float), INTENT(OUT) :: X,Y
LOGICAL, OPTIONAL, INTENT(OUT) :: check !!return false if i and j are outside grid definition
!------------end of declaration------------------------------------------------
IF (i < 1 .OR. i > grid % idim .OR. j < 1 .OR. j > grid % jdim ) THEN
X = 0.
Y = 0.
IF ( PRESENT(check) ) check = .FALSE.
ELSE
X = grid % xllcorner + (j - 0.5) * grid % cellsize
Y = grid % yllcorner + (grid % idim - i + 0.5) * grid % cellsize
IF ( PRESENT(check) ) check = .TRUE.
END IF
END SUBROUTINE GetXYinteger
!==============================================================================
!| Description:
! return `.TRUE.` if the two grids have the same Coordinate Reference System,
! and the same spatial reference (cellsize, xllxorner, yllcorner, idim, jdim)
! If checkCells is given the function checks that grid has
! the same active cells of mask.
FUNCTION CRSisEqualFloatFloat &
!
(mask, grid, checkCells) &
!
RESULT (isEqual)
IMPLICIT NONE
! Arguments with intent(in):
TYPE (grid_real), INTENT(IN) :: mask, grid
LOGICAL, OPTIONAL, INTENT(IN) :: checkCells
!Local declarations:
LOGICAL :: isEqual
INTEGER :: i,j
!------------------------end of declaration------------------------------------
IF ( mask % grid_mapping == grid % grid_mapping .AND. &
mask % cellsize == grid % cellsize .AND. &
mask % xllcorner == grid % xllcorner .AND. &
mask % yllcorner == grid % yllcorner .AND. &
mask % idim == grid % idim .AND. &
mask % jdim == grid % jdim ) THEN
isEqual = .TRUE.
ELSE
isEqual = .FALSE.
END IF
IF ( PRESENT (checkCells) ) THEN
IF (checkCells) THEN
DO i = 1, mask % idim
DO j = 1, mask % jdim
IF ( mask % mat (i,j) /= mask % nodata .AND. &
grid % mat (i,j) == grid % nodata ) THEN
isEqual = .FALSE.
EXIT
END IF
END DO
END DO
END IF
END IF
END FUNCTION CRSisEqualFloatFloat
!==============================================================================
!| Description:
! return `.TRUE.` if the two grids have the same Coordinate Reference System,
! and the same spatial reference (cellsize, xllxorner, yllcorner, idim, jdim)
! If `checkCells` is given the function checks that grid has
! the same active cells of mask.
FUNCTION CRSisEqualIntInt &
!
(mask, grid, checkCells) &
!
RESULT (isEqual)
IMPLICIT NONE
! Arguments with intent(in):
TYPE (grid_integer), INTENT(IN) :: mask, grid
LOGICAL, OPTIONAL, INTENT(IN) :: checkCells
!Local declarations:
LOGICAL :: isEqual
INTEGER :: i,j
!------------------------end of declaration------------------------------------
IF ( mask % grid_mapping == grid % grid_mapping .AND. &
mask % cellsize == grid % cellsize .AND. &
mask % xllcorner == grid % xllcorner .AND. &
mask % yllcorner == grid % yllcorner .AND. &
mask % idim == grid % idim .AND. &
mask % jdim == grid % jdim ) THEN
isEqual = .TRUE.
ELSE
isEqual = .FALSE.
END IF
IF ( PRESENT (checkCells) ) THEN
IF (checkCells) THEN
DO i = 1, mask % idim
DO j = 1, mask % jdim
IF ( mask % mat (i,j) /= mask % nodata .AND. &
grid % mat (i,j) == grid % nodata ) THEN
isEqual = .FALSE.
EXIT
END IF
END DO
END DO
END IF
END IF
END FUNCTION CRSisEqualIntInt
!==============================================================================
!| Description:
! return `.TRUE.` if the two grids have the same Coordinate Reference System,
! and the same spatial reference (cellsize, xllxorner, yllcorner, idim, jdim)
! If `checkCells` is given the function checks that grid has
! the same active cells of mask.
FUNCTION CRSisEqualFloatInt &
!
(mask, grid, checkCells) &
!
RESULT (isEqual)
IMPLICIT NONE
! Arguments with intent(in):
TYPE (grid_real), INTENT(IN) :: mask
TYPE (grid_integer), INTENT(IN) :: grid
LOGICAL, OPTIONAL, INTENT(IN) :: checkCells
!Local declarations:
LOGICAL :: isEqual
INTEGER :: i,j
!------------------------end of declaration------------------------------------
IF ( mask % grid_mapping == grid % grid_mapping .AND. &
mask % cellsize == grid % cellsize .AND. &
mask % xllcorner == grid % xllcorner .AND. &
mask % yllcorner == grid % yllcorner .AND. &
mask % idim == grid % idim .AND. &
mask % jdim == grid % jdim ) THEN
isEqual = .TRUE.
ELSE
isEqual = .FALSE.
END IF
IF ( PRESENT (checkCells) ) THEN
IF (checkCells) THEN
DO i = 1, mask % idim
DO j = 1, mask % jdim
IF ( mask % mat (i,j) /= mask % nodata .AND. &
grid % mat (i,j) == grid % nodata ) THEN
isEqual = .FALSE.
EXIT
END IF
END DO
END DO
END IF
END IF
END FUNCTION CRSisEqualFloatInt
!==============================================================================
!| Description:
! return `.TRUE.` if the two grids have the same Coordinate Reference System,
! and the same spatial reference (cellsize, xllxorner, yllcorner, idim, jdim)
! If `checkCells` is given the function checks that grid has
! the same active cells of mask.
FUNCTION CRSisEqualIntFloat &
!
(mask, grid, checkCells) &
!
RESULT (isEqual)
IMPLICIT NONE
! Arguments with intent(in):
TYPE (grid_real), INTENT(IN) :: grid
TYPE (grid_integer), INTENT(IN) :: mask
LOGICAL, OPTIONAL, INTENT(IN) :: checkCells
!Local declarations:
LOGICAL :: isEqual
INTEGER :: i,j
!------------------------end of declaration------------------------------------
IF ( mask % grid_mapping == grid % grid_mapping .AND. &
mask % cellsize == grid % cellsize .AND. &
mask % xllcorner == grid % xllcorner .AND. &
mask % yllcorner == grid % yllcorner .AND. &
mask % idim == grid % idim .AND. &
mask % jdim == grid % jdim ) THEN
isEqual = .TRUE.
ELSE
isEqual = .FALSE.
END IF
IF ( PRESENT (checkCells) ) THEN
IF (checkCells) THEN
DO i = 1, mask % idim
DO j = 1, mask % jdim
IF ( mask % mat (i,j) /= mask % nodata .AND. &
grid % mat (i,j) == grid % nodata ) THEN
isEqual = .FALSE.
EXIT
END IF
END DO
END DO
END IF
END IF
END FUNCTION CRSisEqualIntFloat
!==============================================================================
!| Description:
! read a `grid_real` using information stored in ini configuration file
SUBROUTINE GridByIniFloat &
!
(ini, grid, section, time)
USE Inilib, ONLY: &
!Imported type definitions:
IniList, &
!imported routines:
IniReadString, IniReadReal, KeyIsPresent, IniReadReal, IniReadInt
USE StringManipulation, ONLY: &
!Imported routines:
StringToUpper, StringToLower, StringToShort
USE Chronos, ONLY: &
!Imported type definitions:
DateTime, &
!Imported operands:
ASSIGNMENT( = )
USE GeoLib , ONLY: &
!Imported routines:
DecodeEPSG
!SetCRS, ScanDatum, &
!SetGeodeticParameters, SetTransverseMercatorParameters, &
!SetSwissParameters, &
!Imported parameters:
!GEODETIC, TM, SOC, &
!EAST, WEST, NORTH, SOUTH, ROME40
USE Units, ONLY: &
!Imported parameters:
degToRad
IMPLICIT NONE
!arguments with intent in:
TYPE (IniList), INTENT(IN) :: ini
CHARACTER (LEN = *), INTENT (IN) :: section
TYPE (DateTime), OPTIONAL, INTENT (IN) :: time
!arguments with intent out:
TYPE (grid_real), INTENT (OUT) :: grid
!local variables:
CHARACTER (LEN = 100) :: fileFormat
CHARACTER (LEN = 300) :: file
CHARACTER (LEN = 100) :: variable !!variable to read
CHARACTER (LEN = 100) :: stdName !!standard name of the variable to read
!CHARACTER (LEN = 100) :: grid_mapping
INTEGER :: epsg
INTEGER ( KIND = short) :: timeSync
!CHARACTER (LEN = 100) :: datum
TYPE (DateTime) :: gridTime !!time of the grid to read
REAL (KIND = float) :: scale_factor
REAL (KIND = float) :: offset
REAL (KIND = float) :: valid_min
REAL (KIND = float) :: valid_max
REAL (KIND = float) :: centralMeridian
!INTEGER :: grid_datum
!INTEGER (KIND = short) :: utm_zone
INTEGER :: i,j
!-----------------------------end of declaration-------------------------------
file = IniReadString ('file', ini, section)
IF (KeyIsPresent ('format', ini, section)) THEN
fileFormat = StringToUpper ( IniReadString ('format', ini, section) )
ELSE
CALL Catch ('error', 'GridOperations', &
'format not specified for grid: ', &
argument = section )
END IF
!read grid
IF ( fileFormat == 'ESRI-ASCII' ) THEN
CALL NewGrid (grid, file, ESRI_ASCII)
ELSE IF (fileFormat == 'ESRI-BINARY' ) THEN
CALL NewGrid (grid, file, ESRI_BINARY)
ELSE IF ( fileFormat == 'NET-CDF' ) THEN
IF (KeyIsPresent('variable', ini, section)) THEN
variable = IniReadString ('variable', ini, section)
IF (KeyIsPresent('time', ini, section)) THEN
gridTime = IniReadString ('time', ini, section)
CALL NewGrid (grid, file, NET_CDF, variable = variable, time = gridTime)
ELSE IF (KeyIsPresent('sync-initial-time', ini, section)) THEN
timeSync = IniReadInt ('sync-initial-time', ini, section)
IF ( timeSync == 1) THEN
CALL SyncTime ( file, time, gridTime )
CALL NewGrid (grid, file, NET_CDF, variable = variable, time = gridTime)
END IF
ELSE
CALL NewGrid (grid, file, NET_CDF, variable = variable)
END IF
ELSE IF (KeyIsPresent('standard_name', ini, section)) THEN
stdName = IniReadString ('standard_name', ini, section)
IF (KeyIsPresent('time', ini, section)) THEN
gridTime = IniReadString ('time', ini, section)
CALL NewGrid (grid, file, NET_CDF, stdName = stdName, time = gridtime)
ELSE
CALL NewGrid (grid, file, NET_CDF, stdName = stdName)
END IF
ELSE
CALL Catch ('error', 'GridOperations', &
'variable or standard name not defined while reading netcdf: ', &
argument = section )
END IF
ELSE
CALL Catch ('error', 'GridOperations', &
'format not supported: ', &
argument = fileFormat )
END IF
!apply scale factor if given
IF (KeyIsPresent ('scale_factor', ini, section) ) THEN
scale_factor = IniReadReal ('scale_factor', ini, section)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
grid % mat (i,j) = grid % mat (i,j) * scale_factor
END IF
END DO
END DO
END IF
!add offset if given
IF (KeyIsPresent ('offset', ini, section) ) THEN
offset = IniReadReal ('offset', ini, section)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
grid % mat (i,j) = grid % mat (i,j) + offset
END IF
END DO
END DO
END IF
!check upper bound if given
IF (KeyIsPresent ('valid_max', ini, section) ) THEN
valid_max = IniReadInt ('valid_max', ini, section)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
IF (grid % mat (i,j) > valid_max ) THEN
grid % mat (i,j) = valid_max
END IF
END IF
END DO
END DO
END IF
!check lower bound if given
IF (KeyIsPresent ('valid_min', ini, section) ) THEN
valid_min = IniReadInt ('valid_min', ini, section)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
IF (grid % mat (i,j) < valid_min ) THEN
grid % mat (i,j) = valid_min
END IF
END IF
END DO
END DO
END IF
!read coordinate reference system if given
IF (KeyIsPresent ('epsg', ini, section) ) THEN
epsg = IniReadInt ('epsg', ini, section)
grid % grid_mapping = DecodeEPSG (epsg)
ELSE
CALL Catch ('error', 'GridOperations', &
'epsg not specified for grid: ', &
argument = section )
END IF
!IF (KeyIsPresent ('grid_mapping', ini, section) ) THEN
! grid_mapping = IniReadString ('grid_mapping', ini, section)
! IF (KeyIsPresent ('datum', ini, section) ) THEN
! datum = IniReadString ('datum', ini, section)
! ELSE
! datum = 'WGS84'
! END IF
! grid_datum = ScanDatum (datum)
! !set reference system
! IF (StringToUpper(grid_mapping) == 'GEODETIC') THEN
! CALL SetCRS (GEODETIC, grid_datum, grid % grid_mapping)
! !default prime_meridian = 0.
! CALL SetGeodeticParameters (grid % grid_mapping, prime_meridian = 0.0)
! ELSE IF (StringToUpper(grid_mapping(1:11)) == 'GAUSS-BOAGA') THEN
! !gauss boaga is a particular case of transverse-mercator
! CALL SetCRS (TM, ROME40, grid % grid_mapping)
! IF (StringToUpper(grid_mapping(13:16)) == 'EAST') THEN
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = 15. * degToRad, &
! falseE = 2520000., falseN = 0., k = 0.9996)
! ELSE
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = 9. * degToRad, &
! falseE = 1500000., falseN = 0., k = 0.9996)
! END IF
! ELSE IF (StringToUpper(grid_mapping(1:3)) == 'UTM') THEN
! !UTM is a particular case of transverse-mercator
! CALL SetCRS (TM, grid_datum, grid % grid_mapping)
! utm_zone = StringToShort(grid_mapping(4:5))
! IF ( utm_zone >= 31) THEN
! centralMeridian = (6 * utm_zone - 183) * degToRad
! ELSE
! centralMeridian = (6 * utm_zone + 177) * degToRad
! END IF
! IF (StringToUpper(grid_mapping(6:6)) == 'N' ) THEN
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = centralMeridian, &
! falseE = 500000., falseN = 0., k = 0.9996)
! ELSE
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = centralMeridian, &
! falseE = 500000., falseN = 10000000., k = 0.9996)
! END IF
!
! ELSE IF (StringToUpper(grid_mapping(1:5)) == 'SWISS') THEN
! CALL SetCRS (SOC, grid_datum, grid % grid_mapping)
! CALL SetSwissParameters &
! (grid % grid_mapping, latc = 0.819474, lonc = 0.129845, &
! azimuth = 1.570796, falseE = 600000., falseN = 200000., k = 1.)
! END IF
!
!END IF
!varying mode
IF (KeyIsPresent ('varying_mode', ini, section) ) THEN
grid % varying_mode = StringToLower(IniReadString ('varying_mode', ini, section))
!check option is valid
IF (grid % varying_mode (1:8) /= 'sequence' .AND. &
grid % varying_mode (1:6) /= 'linear' ) THEN
CALL Catch ('error', 'GridOperations', &
'invalid varying_mode option for grid: ', &
code = unknownOption, argument = section )
END IF
ELSE !default to 'sequence'
grid % varying_mode = 'sequence'
END IF
END SUBROUTINE GridByIniFloat
!==============================================================================
!| Description:
! read a `grid_integer` using information stored in ini configuration file
SUBROUTINE GridByIniInteger &
!
(ini, grid, section)
USE Inilib, ONLY: &
!Imported type definitions:
IniList, &
!imported routines:
IniReadString, IniReadReal, KeyIsPresent, IniReadReal, IniReadInt
USE StringManipulation, ONLY: &
!Imported routines:
StringToUpper, StringToLower, StringToShort
USE Chronos, ONLY: &
!Imported type definitions:
DateTime, &
!Imported operands:
ASSIGNMENT( = )
USE GeoLib , ONLY: &
!Imported routines:
DecodeEPSG
!SetCRS, ScanDatum, &
!SetGeodeticParameters, SetTransverseMercatorParameters, &
!SetSwissParameters, &
!Imported parameters:
!GEODETIC, TM, SOC, &
!EAST, WEST, NORTH, SOUTH, ROME40
USE Units, ONLY: &
!Imported parameters:
degToRad
IMPLICIT NONE
!arguments with intent in:
TYPE (IniList), INTENT(IN) :: ini
CHARACTER (LEN = *), INTENT (IN) :: section
!arguments with intent out:
TYPE (grid_integer), INTENT (OUT) :: grid
!local variables:
CHARACTER (LEN = 100) :: fileFormat
CHARACTER (LEN = 300) :: file
CHARACTER (LEN = 100) :: variable !!variable to read
CHARACTER (LEN = 100) :: stdName !!standard name of the variable to read
INTEGER :: epsg
!CHARACTER (LEN = 100) :: grid_mapping
!CHARACTER (LEN = 100) :: datum
TYPE (DateTime) :: gridTime !!time of the grid to read
REAL (KIND = float) :: scale_factor
REAL (KIND = float) :: offset
INTEGER (KIND = long) :: valid_min
INTEGER (KIND = long) :: valid_max
!REAL (KIND = float) :: centralMeridian
!INTEGER :: grid_datum
!INTEGER (KIND = short) :: utm_zone
INTEGER :: i,j
!-----------------------------end of declaration-------------------------------
file = IniReadString ('file', ini, section)
IF (KeyIsPresent ('format', ini, section)) THEN
fileFormat = StringToUpper ( IniReadString ('format', ini, section) )
ELSE
CALL Catch ('error', 'GridOperations', &
'format not specified for grid: ', &
argument = section )
END IF
!read grid
IF ( fileFormat == 'ESRI-ASCII' ) THEN
CALL NewGrid (grid, file, ESRI_ASCII)
ELSE IF (fileFormat == 'ESRI-BINARY' ) THEN
CALL NewGrid (grid, file, ESRI_BINARY)
ELSE IF ( fileFormat == 'NET-CDF' ) THEN
IF (KeyIsPresent('variable', ini, section)) THEN
variable = IniReadString ('variable', ini, section)
IF (KeyIsPresent('time', ini, section)) THEN
gridTime = IniReadString ('time', ini, section)
CALL NewGrid (grid, file, NET_CDF, variable = variable, time = gridTime)
ELSE
CALL NewGrid (grid, file, NET_CDF, variable = variable)
END IF
ELSE IF (KeyIsPresent('standard_name', ini, section)) THEN
stdName = IniReadString ('standard_name', ini, section)
IF (KeyIsPresent('time', ini, section)) THEN
gridTime = IniReadString ('time', ini, section)
CALL NewGrid (grid, file, NET_CDF, stdName = stdName, time = gridtime)
ELSE
CALL NewGrid (grid, file, NET_CDF, stdName = stdName)
END IF
ELSE
CALL Catch ('error', 'GridOperations', &
'variable or standard name not defined while reading netcdf: ', &
argument = section )
END IF
ELSE
CALL Catch ('error', 'GridOperations', &
'format not supported: ', &
argument = fileFormat )
END IF
!apply scale factor if given
IF (KeyIsPresent ('scale_factor', ini, section) ) THEN
scale_factor = IniReadReal ('scale_factor', ini, section)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
grid % mat (i,j) = grid % mat (i,j) * scale_factor
END IF
END DO
END DO
END IF
!add offset if given
IF (KeyIsPresent ('offset', ini, section) ) THEN
offset = IniReadReal ('offset', ini, section)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
grid % mat (i,j) = grid % mat (i,j) + offset
END IF
END DO
END DO
END IF
!check upper bound if given
IF (KeyIsPresent ('valid_max', ini, section) ) THEN
valid_max = IniReadInt ('valid_max', ini, section)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
IF (grid % mat (i,j) > valid_max ) THEN
grid % mat (i,j) = valid_max
END IF
END IF
END DO
END DO
END IF
!check lower bound if given
IF (KeyIsPresent ('valid_min', ini, section) ) THEN
valid_min = IniReadInt ('valid_min', ini, section)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
IF (grid % mat (i,j) < valid_min ) THEN
grid % mat (i,j) = valid_min
END IF
END IF
END DO
END DO
END IF
!read coordinate reference system if given
IF (KeyIsPresent ('epsg', ini, section) ) THEN
epsg = IniReadInt ('epsg', ini, section)
grid % grid_mapping = DecodeEPSG (epsg)
ELSE
CALL Catch ('error', 'GridOperations', &
'epsg not specified for grid: ', &
argument = section )
END IF
!IF (KeyIsPresent ('grid_mapping', ini, section) ) THEN
! grid_mapping = IniReadString ('grid_mapping', ini, section)
! IF (KeyIsPresent ('datum', ini, section) ) THEN
! datum = IniReadString ('datum', ini, section)
! ELSE
! datum = 'WGS84'
! END IF
! grid_datum = ScanDatum (datum)
! !set reference system
! IF (StringToUpper(grid_mapping) == 'GEODETIC') THEN
! CALL SetCRS (GEODETIC, grid_datum, grid % grid_mapping)
! !default prime_meridian = 0.
! CALL SetGeodeticParameters (grid % grid_mapping, prime_meridian = 0.0)
! ELSE IF (StringToUpper(grid_mapping(1:11)) == 'GAUSS-BOAGA') THEN
! !gauss boaga is a particular case of transverse-mercator
! CALL SetCRS (TM, ROME40, grid % grid_mapping)
! IF (StringToUpper(grid_mapping(13:16)) == 'EAST') THEN
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = 15. * degToRad, &
! falseE = 2520000., falseN = 0., k = 0.9996)
! ELSE
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = 9. * degToRad, &
! falseE = 1500000., falseN = 0., k = 0.9996)
! END IF
! ELSE IF (StringToUpper(grid_mapping(1:3)) == 'UTM') THEN
! !UTM is a particular case of transverse-mercator
! CALL SetCRS (TM, grid_datum, grid % grid_mapping)
! utm_zone = StringToShort(grid_mapping(4:5))
! IF ( utm_zone >= 31) THEN
! centralMeridian = (6 * utm_zone - 183) * degToRad
! ELSE
! centralMeridian = (6 * utm_zone + 177) * degToRad
! END IF
! IF (StringToUpper(grid_mapping(6:6)) == 'N' ) THEN
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = centralMeridian, &
! falseE = 500000., falseN = 0., k = 0.9996)
! ELSE
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = centralMeridian, &
! falseE = 500000., falseN = 10000000., k = 0.9996)
! END IF
!
! ELSE IF (StringToUpper(grid_mapping(1:5)) == 'SWISS') THEN
! CALL SetCRS (SOC, grid_datum, grid % grid_mapping)
! CALL SetSwissParameters &
! (grid % grid_mapping, latc = 0.819474, lonc = 0.129845, &
! azimuth = 1.570796, falseE = 600000., falseN = 200000., k = 1.)
! END IF
!
!END IF
!
!varying mode
IF (KeyIsPresent ('varying_mode', ini, section) ) THEN
grid % varying_mode = StringToLower(IniReadString ('varying_mode', ini, section))
!check option is valid
IF (grid % varying_mode /= 'sequence' .OR. &
grid % varying_mode /= 'linear' ) THEN
CALL Catch ('error', 'GridOperations', &
'invalid varying_mode option for grid: ', &
code = unknownOption, argument = section )
END IF
ELSE !default to 'sequence'
grid % varying_mode = 'sequence'
END IF
END SUBROUTINE GridByIniInteger
!==============================================================================
!| Description:
! read a `grid_real` using information stored in ini configuration file
! defined in subsection `[[...]]`
SUBROUTINE GridByIniFloatSubSection &
!
(ini, grid, section, subsection)
USE Inilib, ONLY: &
!Imported type definitions:
IniList, &
!imported routines:
IniReadString, IniReadReal, KeyIsPresent, IniReadReal, IniReadInt
USE StringManipulation, ONLY: &
!Imported routines:
StringToUpper, StringToShort
USE Chronos, ONLY: &
!Imported type definitions:
DateTime, &
!Imported operands:
ASSIGNMENT( = )
USE GeoLib , ONLY: &
!Imported routines:
DecodeEPSG
!SetCRS, ScanDatum, &
!SetGeodeticParameters, SetTransverseMercatorParameters, &
!SetSwissParameters, &
!Imported parameters:
!GEODETIC, TM, SOC, &
!EAST, WEST, NORTH, SOUTH, ROME40
USE Units, ONLY: &
!Imported parameters:
degToRad
IMPLICIT NONE
!arguments with intent in:
TYPE (IniList), INTENT(IN) :: ini
CHARACTER (LEN = *), INTENT (IN) :: section
CHARACTER (LEN = *), INTENT (IN) :: subsection
!arguments with intent out:
TYPE (grid_real), INTENT (OUT) :: grid
!local variables:
CHARACTER (LEN = 100) :: fileFormat
CHARACTER (LEN = 300) :: file
CHARACTER (LEN = 100) :: variable !!variable to read
CHARACTER (LEN = 100) :: stdName !!standard name of the variable to read
INTEGER :: epsg
!CHARACTER (LEN = 100) :: grid_mapping
!CHARACTER (LEN = 100) :: datum
TYPE (DateTime) :: gridTime !!time of the grid to read
REAL (KIND = float) :: scale_factor
REAL (KIND = float) :: offset
REAL (KIND = float) :: valid_min
REAL (KIND = float) :: valid_max
!REAL (KIND = float) :: centralMeridian
!INTEGER :: grid_datum
!INTEGER (KIND = short) :: utm_zone
INTEGER :: i,j
!-----------------------------end of declaration-------------------------------
file = IniReadString ('file', ini, section, subsection)
IF (KeyIsPresent ('format', ini, section, subsection)) THEN
fileFormat = StringToUpper ( IniReadString ('format', ini, section, subsection) )
ELSE
CALL Catch ('error', 'GridOperations', &
'format not specified for grid: ', &
argument = subsection )
END IF
!read grid
IF ( fileFormat == 'ESRI-ASCII' ) THEN
CALL NewGrid (grid, file, ESRI_ASCII)
ELSE IF (fileFormat == 'ESRI-BINARY' ) THEN
CALL NewGrid (grid, file, ESRI_BINARY)
ELSE IF ( fileFormat == 'NET-CDF' ) THEN
IF (KeyIsPresent('variable', ini, section, subsection)) THEN
variable = IniReadString ('variable', ini, section, subsection)
IF (KeyIsPresent('time', ini, section, subsection)) THEN
gridTime = IniReadString ('time', ini, section, subsection)
CALL NewGrid (grid, file, NET_CDF, variable = variable, time = gridTime)
ELSE
CALL NewGrid (grid, file, NET_CDF, variable = variable)
END IF
ELSE IF (KeyIsPresent('standard_name', ini, section, subsection)) THEN
stdName = IniReadString ('standard_name', ini, section, subsection)
IF (KeyIsPresent('time', ini, section, subsection)) THEN
gridTime = IniReadString ('time', ini, section, subsection)
CALL NewGrid (grid, file, NET_CDF, stdName = stdName, time = gridtime)
ELSE
CALL NewGrid (grid, file, NET_CDF, stdName = stdName)
END IF
ELSE
CALL Catch ('error', 'GridOperations', &
'variable or standard name not defined while reading netcdf: ', &
argument = subsection )
END IF
ELSE
CALL Catch ('error', 'GridOperations', &
'format not supported: ', &
argument = fileFormat )
END IF
!apply scale factor if given
IF (KeyIsPresent ('scale_factor', ini, section, subsection) ) THEN
scale_factor = IniReadReal ('scale_factor', ini, section, subsection)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
grid % mat (i,j) = grid % mat (i,j) * scale_factor
END IF
END DO
END DO
END IF
!add offset if given
IF (KeyIsPresent ('offset', ini, section, subsection) ) THEN
offset = IniReadReal ('offset', ini, section, subsection)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
grid % mat (i,j) = grid % mat (i,j) + offset
END IF
END DO
END DO
END IF
!check upper bound if given
IF (KeyIsPresent ('valid_max', ini, section, subsection) ) THEN
valid_max = IniReadInt ('valid_max', ini, section, subsection)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
IF (grid % mat (i,j) > valid_max ) THEN
grid % mat (i,j) = valid_max
END IF
END IF
END DO
END DO
END IF
!check lower bound if given
IF (KeyIsPresent ('valid_min', ini, section, subsection) ) THEN
valid_min = IniReadInt ('valid_min', ini, section, subsection)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
IF (grid % mat (i,j) < valid_min ) THEN
grid % mat (i,j) = valid_min
END IF
END IF
END DO
END DO
END IF
!read coordinate reference system if given
IF (KeyIsPresent ('epsg', ini, section, subsection) ) THEN
epsg = IniReadInt ('epsg', ini, section, subsection)
grid % grid_mapping = DecodeEPSG (epsg)
ELSE
CALL Catch ('error', 'GridOperations', &
'epsg not specified for grid: ', &
argument = subsection )
END IF
!IF (KeyIsPresent ('grid_mapping', ini, section, subsection) ) THEN
! grid_mapping = IniReadString ('grid_mapping', ini, section, subsection)
! IF (KeyIsPresent ('datum', ini, section, subsection) ) THEN
! datum = IniReadString ('datum', ini, section, subsection)
! ELSE
! datum = 'WGS84'
! END IF
! grid_datum = ScanDatum (datum)
! !set reference system
! IF (StringToUpper(grid_mapping) == 'GEODETIC') THEN
! CALL SetCRS (GEODETIC, grid_datum, grid % grid_mapping)
! !default prime_meridian = 0.
! CALL SetGeodeticParameters (grid % grid_mapping, prime_meridian = 0.0)
! ELSE IF (StringToUpper(grid_mapping(1:11)) == 'GAUSS-BOAGA') THEN
! !gauss boaga is a particular case of transverse-mercator
! CALL SetCRS (TM, ROME40, grid % grid_mapping)
! IF (StringToUpper(grid_mapping(13:16)) == 'EAST') THEN
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = 15. * degToRad, &
! falseE = 2520000., falseN = 0., k = 0.9996)
! ELSE
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = 9. * degToRad, &
! falseE = 1500000., falseN = 0., k = 0.9996)
! END IF
! ELSE IF (StringToUpper(grid_mapping(1:3)) == 'UTM') THEN
! !UTM is a particular case of transverse-mercator
! CALL SetCRS (TM, grid_datum, grid % grid_mapping)
! utm_zone = StringToShort(grid_mapping(4:5))
! IF ( utm_zone >= 31) THEN
! centralMeridian = (6 * utm_zone - 183) * degToRad
! ELSE
! centralMeridian = (6 * utm_zone + 177) * degToRad
! END IF
! IF (StringToUpper(grid_mapping(6:6)) == 'N' ) THEN
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = centralMeridian, &
! falseE = 500000., falseN = 0., k = 0.9996)
! ELSE
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = centralMeridian, &
! falseE = 500000., falseN = 10000000., k = 0.9996)
! END IF
!
! ELSE IF (StringToUpper(grid_mapping(1:5)) == 'SWISS') THEN
! CALL SetCRS (SOC, grid_datum, grid % grid_mapping)
! CALL SetSwissParameters &
! (grid % grid_mapping, latc = 0.819474, lonc = 0.129845, &
! azimuth = 1.570796, falseE = 600000., falseN = 200000., k = 1.)
! END IF
!
!END IF
RETURN
END SUBROUTINE GridByIniFloatSubSection
!==============================================================================
!| Description:
! read a `grid_integer` using information stored in ini configuration file
! defined in subsection `[[.. ]]`
SUBROUTINE GridByIniIntegerSubSection &
!
(ini, grid, section, subsection)
USE Inilib, ONLY: &
!Imported type definitions:
IniList, &
!imported routines:
IniReadString, IniReadReal, KeyIsPresent, IniReadReal, IniReadInt
USE StringManipulation, ONLY: &
!Imported routines:
StringToUpper, StringToShort
USE Chronos, ONLY: &
!Imported type definitions:
DateTime, &
!Imported operands:
ASSIGNMENT( = )
USE GeoLib , ONLY: &
!Imported routines:
DecodeEPSG
!SetCRS, ScanDatum, &
!SetGeodeticParameters, SetTransverseMercatorParameters, &
!SetSwissParameters, &
!Imported parameters:
!GEODETIC, TM, SOC, &
!EAST, WEST, NORTH, SOUTH, ROME40
USE Units, ONLY: &
!Imported parameters:
degToRad
IMPLICIT NONE
!arguments with intent in:
TYPE (IniList), INTENT(IN) :: ini
CHARACTER (LEN = *), INTENT (IN) :: section
CHARACTER (LEN = *), INTENT (IN) :: subsection
!arguments with intent out:
TYPE (grid_integer), INTENT (OUT) :: grid
!local variables:
CHARACTER (LEN = 100) :: fileFormat
CHARACTER (LEN = 300) :: file
CHARACTER (LEN = 100) :: variable !!variable to read
CHARACTER (LEN = 100) :: stdName !!standard name of the variable to read
INTEGER :: epsg
!CHARACTER (LEN = 100) :: grid_mapping
!CHARACTER (LEN = 100) :: datum
TYPE (DateTime) :: gridTime !!time of the grid to read
REAL (KIND = float) :: scale_factor
REAL (KIND = float) :: offset
INTEGER (KIND = long) :: valid_min
INTEGER (KIND = long) :: valid_max
!REAL (KIND = float) :: centralMeridian
!INTEGER :: grid_datum
!INTEGER (KIND = short) :: utm_zone
INTEGER :: i,j
!-----------------------------end of declaration-------------------------------
file = IniReadString ('file', ini, section, subsection)
IF (KeyIsPresent ('format', ini, section, subsection)) THEN
fileFormat = StringToUpper ( IniReadString ('format', ini, section, subsection) )
ELSE
CALL Catch ('error', 'GridOperations', &
'format not specified for grid: ', &
argument = subsection )
END IF
!read grid
IF ( fileFormat == 'ESRI-ASCII' ) THEN
CALL NewGrid (grid, file, ESRI_ASCII)
ELSE IF (fileFormat == 'ESRI-BINARY' ) THEN
CALL NewGrid (grid, file, ESRI_BINARY)
ELSE IF ( fileFormat == 'NET-CDF' ) THEN
IF (KeyIsPresent('variable', ini, section, subsection)) THEN
variable = IniReadString ('variable', ini, section, subsection)
IF (KeyIsPresent('time', ini, section, subsection)) THEN
gridTime = IniReadString ('time', ini, section, subsection)
CALL NewGrid (grid, file, NET_CDF, variable = variable, time = gridTime)
ELSE
CALL NewGrid (grid, file, NET_CDF, variable = variable)
END IF
ELSE IF (KeyIsPresent('standard_name', ini, section, subsection)) THEN
stdName = IniReadString ('standard_name', ini, section, subsection)
IF (KeyIsPresent('time', ini, section, subsection)) THEN
gridTime = IniReadString ('time', ini, section, subsection)
CALL NewGrid (grid, file, NET_CDF, stdName = stdName, time = gridtime)
ELSE
CALL NewGrid (grid, file, NET_CDF, stdName = stdName)
END IF
ELSE
CALL Catch ('error', 'GridOperations', &
'variable or standard name not defined while reading netcdf: ', &
argument = subsection )
END IF
ELSE
CALL Catch ('error', 'GridOperations', &
'format not supported: ', &
argument = fileFormat )
END IF
!apply scale factor if given
IF (KeyIsPresent ('scale_factor', ini, section, subsection) ) THEN
scale_factor = IniReadReal ('scale_factor', ini, section, subsection)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
grid % mat (i,j) = grid % mat (i,j) * scale_factor
END IF
END DO
END DO
END IF
!add offset if given
IF (KeyIsPresent ('offset', ini, section, subsection) ) THEN
offset = IniReadReal ('offset', ini, section, subsection)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
grid % mat (i,j) = grid % mat (i,j) + offset
END IF
END DO
END DO
END IF
!check upper bound if given
IF (KeyIsPresent ('valid_max', ini, section, subsection) ) THEN
valid_max = IniReadInt ('valid_max', ini, section, subsection)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
IF (grid % mat (i,j) > valid_max ) THEN
grid % mat (i,j) = valid_max
END IF
END IF
END DO
END DO
END IF
!check lower bound if given
IF (KeyIsPresent ('valid_min', ini, section, subsection) ) THEN
valid_min = IniReadInt ('valid_min', ini, section, subsection)
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF ( grid % mat (i,j) /= grid % nodata ) THEN
IF (grid % mat (i,j) < valid_min ) THEN
grid % mat (i,j) = valid_min
END IF
END IF
END DO
END DO
END IF
!read coordinate reference system if given
IF (KeyIsPresent ('epsg', ini, section, subsection) ) THEN
epsg = IniReadInt ('epsg', ini, section, subsection)
grid % grid_mapping = DecodeEPSG (epsg)
ELSE
CALL Catch ('error', 'GridOperations', &
'epsg not specified for grid: ', &
argument = subsection )
END IF
!IF (KeyIsPresent ('grid_mapping', ini, section, subsection) ) THEN
! grid_mapping = IniReadString ('grid_mapping', ini, section, subsection)
! IF (KeyIsPresent ('datum', ini, section, subsection) ) THEN
! datum = IniReadString ('datum', ini, section, subsection)
! ELSE
! datum = 'WGS84'
! END IF
! grid_datum = ScanDatum (datum)
! !set reference system
! IF (StringToUpper(grid_mapping) == 'GEODETIC') THEN
! CALL SetCRS (GEODETIC, grid_datum, grid % grid_mapping)
! !default prime_meridian = 0.
! CALL SetGeodeticParameters (grid % grid_mapping, prime_meridian = 0.0)
! ELSE IF (StringToUpper(grid_mapping(1:11)) == 'GAUSS-BOAGA') THEN
! !gauss boaga is a particular case of transverse-mercator
! CALL SetCRS (TM, ROME40, grid % grid_mapping)
! IF (StringToUpper(grid_mapping(13:16)) == 'EAST') THEN
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = 15. * degToRad, &
! falseE = 2520000., falseN = 0., k = 0.9996)
! ELSE
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = 9. * degToRad, &
! falseE = 1500000., falseN = 0., k = 0.9996)
! END IF
! ELSE IF (StringToUpper(grid_mapping(1:3)) == 'UTM') THEN
! !UTM is a particular case of transverse-mercator
! CALL SetCRS (TM, grid_datum, grid % grid_mapping)
! utm_zone = StringToShort(grid_mapping(4:5))
! IF ( utm_zone >= 31) THEN
! centralMeridian = (6 * utm_zone - 183) * degToRad
! ELSE
! centralMeridian = (6 * utm_zone + 177) * degToRad
! END IF
! IF (StringToUpper(grid_mapping(6:6)) == 'N' ) THEN
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = centralMeridian, &
! falseE = 500000., falseN = 0., k = 0.9996)
! ELSE
! CALL SetTransverseMercatorParameters &
! (grid % grid_mapping, lat0 = 0., centM = centralMeridian, &
! falseE = 500000., falseN = 10000000., k = 0.9996)
! END IF
!
! ELSE IF (StringToUpper(grid_mapping(1:5)) == 'SWISS') THEN
! CALL SetCRS (SOC, grid_datum, grid % grid_mapping)
! CALL SetSwissParameters &
! (grid % grid_mapping, latc = 0.819474, lonc = 0.129845, &
! azimuth = 1.570796, falseE = 600000., falseN = 200000., k = 1.)
! END IF
!
!
!END IF
END SUBROUTINE GridByIniIntegerSubSection
!==============================================================================
!| Description:
! calculates if cell is out of grid space limits
LOGICAL FUNCTION IsOutOfGridFloat &
!
(i, j, grid)
IMPLICIT NONE
!Arguments with intent in:
INTEGER, INTENT(IN) :: i,j
TYPE (grid_real), INTENT(IN) :: grid
!----------------------end of declarations-------------------------------------
IF (i > grid % idim .OR. j > grid % jdim .OR. i < 1 .OR. j < 1) THEN
IsOutOfGridFloat = .TRUE.
ELSE
IsOutOfGridFloat = .FALSE.
ENDIF
END FUNCTION IsOutOfGridFloat
!==============================================================================
!| Description:
! calculates if cell is out of grid space limits
LOGICAL FUNCTION IsOutOfGridInteger &
!
(i, j, grid)
IMPLICIT NONE
!Arguments with intent in:
INTEGER, INTENT(IN) :: i,j
TYPE (grid_integer), INTENT(IN) :: grid
!----------------------end of declarations-------------------------------------
IF (i > grid % idim .OR. j > grid % jdim .OR. i < 1 .OR. j < 1) THEN
IsOutOfGridInteger = .TRUE.
ELSE
IsOutOfGridInteger = .FALSE.
ENDIF
END FUNCTION IsOutOfGridInteger
!==============================================================================
!| Description:
! returns `true` if cell of grid_integer contains no data value
LOGICAL FUNCTION CellIsNoDataInteger &
!
(i, j, grid)
IMPLICIT NONE
!Arguments with intent in:
INTEGER, INTENT(IN) :: i,j
TYPE (grid_integer), INTENT(IN) :: grid
!----------------------end of declarations-------------------------------------
IF ( grid % mat (i,j) == grid % nodata ) THEN
CellIsNoDataInteger = .TRUE.
ELSE
CellIsNoDataInteger = .FALSE.
END IF
RETURN
END FUNCTION CellIsNoDataInteger
!==============================================================================
!| Description:
! return `true` if cell of `grid_real` contains no data value
LOGICAL FUNCTION CellIsNoDataFloat &
!
(i, j, grid)
IMPLICIT NONE
!Arguments with intent in:
INTEGER, INTENT(IN) :: i,j
TYPE (grid_real), INTENT(IN) :: grid
!----------------------end of declarations-------------------------------------
IF ( grid % mat (i,j) == grid % nodata ) THEN
CellIsNoDataFloat = .TRUE.
ELSE
CellIsNoDataFloat = .FALSE.
END IF
RETURN
END FUNCTION CellIsNoDataFloat
!==============================================================================
!| Description:
! return `false` if cell is out of grid either contains nodata value,
! `true` otherwise.
LOGICAL FUNCTION CellIsValidInteger &
!
(i, j, grid)
IMPLICIT NONE
!Arguments with intent in:
INTEGER, INTENT(IN) :: i,j
TYPE (grid_integer), INTENT(IN) :: grid
!----------------------end of declarations-------------------------------------
CellIsValidInteger = .TRUE.
IF ( IsOutOfGrid (i, j, grid) ) THEN
CellIsValidInteger = .FALSE.
RETURN
ELSE
IF ( grid % mat (i,j) == grid % nodata ) THEN
CellIsValidInteger = .FALSE.
ELSE
CellIsValidInteger = .TRUE.
END IF
END IF
RETURN
END FUNCTION CellIsValidInteger
!==============================================================================
!| Description:
! return `false` if cell is out of grid either contains nodata value,
! `true` otherwise.
LOGICAL FUNCTION CellIsValidFloat &
!
(i, j, grid)
IMPLICIT NONE
!Arguments with intent in:
INTEGER, INTENT(IN) :: i,j
TYPE (grid_real), INTENT(IN) :: grid
!----------------------end of declarations-------------------------------------
CellIsValidFloat = .TRUE.
IF ( IsOutOfGrid (i, j, grid) ) THEN
CellIsValidFloat = .FALSE.
RETURN
ELSE
IF ( grid % mat (i,j) == grid % nodata ) THEN
CellIsValidFloat = .FALSE.
ELSE
CellIsValidFloat = .TRUE.
END IF
END IF
RETURN
END FUNCTION CellIsValidFloat
!==============================================================================
!! Description:
!| Extracts only the cells on the external border. Other cells are
! assigned `nodata`. Border cell is the one that has at least a
! `nodata` value in the neighbouring 8 cells.
SUBROUTINE ExtractBorderFloat &
!
(grid, border, cardinal)
IMPLICIT NONE
!Arguments with intent in:
TYPE (grid_real), INTENT(IN) :: grid
LOGICAL, INTENT(IN), OPTIONAL :: cardinal
!Arguments with intent in:
TYPE (grid_real) :: border
!Local declaration:
INTEGER :: i,j
LOGICAL :: foundNodata
INTEGER :: row, col
LOGICAL :: fourCells !!true if to consider only four cells in cardinal directions
!---------------------------end of declarations--------------------------------
!Allocate space for grid containing values on the border
CALL NewGrid (border, grid)
IF (PRESENT(cardinal)) THEN
IF (cardinal) THEN
fourCells = .TRUE.
ELSE
fourCells = .FALSE.
END IF
ELSE
fourCells = .FALSE.
END IF
!scan grid
DO i = 1, border % idim
DO j = 1, border % jdim
IF (grid % mat (i,j) /= grid % nodata) THEN
foundNodata = .FALSE.
!check EAST cell
row = i
col = j + 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
!check SOUTH-EAST cell
IF ( .NOT. fourCells) THEN
row = i + 1
col = j + 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
END IF
!check SOUTH cell
row = i + 1
col = j
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
!check SOUTH-WEST cell
IF (.NOT. fourCells) THEN
row = i + 1
col = j - 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
END IF
!check WEST cell
row = i
col = j - 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
!check NORTH-EAST cell
IF (.NOT. fourCells) THEN
row = i - 1
col = j - 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
END IF
!check NORTH cell
row = i - 1
col = j
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
!check NORTH-EAST cell
IF (.NOT. fourCells) THEN
row = i - 1
col = j + 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
END IF
IF ( .NOT. foundNodata ) THEN
border % mat (i,j) = border % nodata
END IF
END IF
END DO
END DO
END SUBROUTINE ExtractBorderFloat
!==============================================================================
!| Description:
! Extracts only the cells on the external border. Other cells are
! assigned `nodata`. Border cell is the one that has at least a
! `nodata` value in the neighbouring 8 cells. If `cardinal` is passed
! the routine checks only the four cells in the cardinal direction.
! This option is used to obtain border without duplicates. Default is
! check all the cells.
SUBROUTINE ExtractBorderInteger &
!
(grid, border, cardinal)
IMPLICIT NONE
!Arguments with intent in:
TYPE (grid_integer), INTENT(IN) :: grid
LOGICAL, INTENT(IN), OPTIONAL :: cardinal
!Arguments with intent out:
TYPE (grid_integer), INTENT(OUT) :: border
!Local declaration:
INTEGER :: i,j
LOGICAL :: foundNodata
INTEGER :: row, col
LOGICAL :: fourCells !!true if to consider only four cells in cardinal directions
!---------------------------end of declarations--------------------------------
!Allocate space for grid containing values on the border
CALL NewGrid (border, grid)
IF (PRESENT(cardinal)) THEN
IF (cardinal) THEN
fourCells = .TRUE.
ELSE
fourCells = .FALSE.
END IF
ELSE
fourCells = .FALSE.
END IF
!scan grid
DO i = 1, border % idim
DO j = 1, border % jdim
IF (grid % mat (i,j) /= grid % nodata) THEN
foundNodata = .FALSE.
!check EAST cell
row = i
col = j + 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
!check SOUTH-EAST cell
IF ( .NOT. fourCells) THEN
row = i + 1
col = j + 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
END IF
!check SOUTH cell
row = i + 1
col = j
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
!check SOUTH-WEST cell
IF (.NOT. fourCells) THEN
row = i + 1
col = j - 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
END IF
!check WEST cell
row = i
col = j - 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
!check NORTH-EAST cell
IF (.NOT. fourCells) THEN
row = i - 1
col = j - 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
END IF
!check NORTH cell
row = i - 1
col = j
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
!check NORTH-EAST cell
IF (.NOT. fourCells) THEN
row = i - 1
col = j + 1
IF ( .NOT. IsOutOfGrid(row,col,border) ) THEN
IF (grid % mat (row,col) == grid % nodata) THEN
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
ELSE
foundNodata = .TRUE.
border % mat (i,j) = grid % mat (i,j)
CYCLE
END IF
END IF
IF ( .NOT. foundNodata ) THEN
border % mat (i,j) = border % nodata
END IF
END IF
END DO
END DO
RETURN
END SUBROUTINE ExtractBorderInteger
!==============================================================================
!| Description:
! Create a new `grid_real` with cellsize different from input grid
! The content of the created grid is filled in with nearest neighbor method
SUBROUTINE ResampleFloatCell &
!
(grid, resampledGrid, newCellsize)
IMPLICIT NONE
! Arguments with intent(in):
TYPE (grid_real), INTENT(IN) :: grid
REAL (KIND = float), INTENT(IN) :: newCellsize
!Arguments with intent(out):
TYPE (grid_real), INTENT(OUT) :: resampledGrid
!Local declarations:
REAL :: x, y
INTEGER :: i, j, iold, jold
!---------------------------end of declarations--------------------------------
!compute number of rows and columns of the resampled grid
resampledGrid % idim = INT(grid%cellsize * grid%idim / newCellsize) + 1
resampledGrid % jdim = INT(grid%cellsize * grid%jdim / newCellsize) + 1
!assign spatial information
resampledGrid % cellsize = newCellsize
resampledGrid % xllcorner = grid % xllcorner
resampledGrid % yllcorner = grid % yllcorner
!allocate resampled grid
ALLOCATE ( resampledGrid % mat (resampledGrid%idim, resampledGrid%jdim))
!copy information from grid to resampled grid
resampledGrid % standard_name = grid % standard_name
resampledGrid % long_name = grid % long_name
resampledGrid % units = grid % units
resampledGrid % varying_mode = grid % varying_mode
resampledGrid % nodata = grid % nodata
resampledGrid % valid_min = grid % valid_min
resampledGrid % valid_max = grid % valid_max
resampledGrid % reference_time = grid % reference_time
resampledGrid % current_time = grid % current_time
resampledGrid % time_index = grid % time_index
resampledGrid % time_unit = grid % time_unit
resampledGrid % esri_pe_string = grid % esri_pe_string
resampledGrid % grid_mapping = grid % grid_mapping
!fill in resampled grid
DO i = 1, resampledGrid % idim
DO j = 1, resampledGrid % jdim
CALL GetXY (i, j, resampledGrid, x, y)
CALL GetIJ (x, y, grid, iold, jold)
IF (iold > 0 .AND. jold > 0 .AND. iold <= grid % idim .AND. jold <= grid % jdim) THEN
resampledGrid % mat (i,j) = grid % mat (iold, jold)
ELSE
resampledGrid % mat (i,j) = resampledGrid % nodata
END IF
END DO
END DO
END SUBROUTINE ResampleFloatCell
!==============================================================================
!| Description:
! Create a new `grid_integer` with cellsize different from input grid
! The content of the created grid is filled in with nearest neighbor method
SUBROUTINE ResampleIntegerCell &
!
(grid, resampledGrid, newCellsize)
IMPLICIT NONE
! Arguments with intent(in):
TYPE (grid_integer), INTENT(IN) :: grid
REAL (KIND = float), INTENT(IN) :: newCellsize
!Arguments with intent(out):
TYPE (grid_integer), INTENT(OUT) :: resampledGrid
!Local declarations:
REAL :: x, y
INTEGER :: i, j, iold, jold
!---------------------------end of declarations--------------------------------
!compute number of rows and columns of the resampled grid
resampledGrid % idim = INT(grid%cellsize * grid%idim / newCellsize) + 1
resampledGrid % jdim = INT(grid%cellsize * grid%jdim / newCellsize) + 1
!assign spatial information
resampledGrid % cellsize = newCellsize
resampledGrid % xllcorner = grid % xllcorner
resampledGrid % yllcorner = grid % yllcorner
!allocate resampled grid
ALLOCATE ( resampledGrid % mat (resampledGrid%idim, resampledGrid%jdim))
!copy information from grid to resampled grid
resampledGrid % standard_name = grid % standard_name
resampledGrid % long_name = grid % long_name
resampledGrid % units = grid % units
resampledGrid % varying_mode = grid % varying_mode
resampledGrid % nodata = grid % nodata
resampledGrid % valid_min = grid % valid_min
resampledGrid % valid_max = grid % valid_max
resampledGrid % reference_time = grid % reference_time
resampledGrid % current_time = grid % current_time
resampledGrid % time_index = grid % time_index
resampledGrid % time_unit = grid % time_unit
resampledGrid % esri_pe_string = grid % esri_pe_string
resampledGrid % grid_mapping = grid % grid_mapping
!fill in resampled grid
DO i = 1, resampledGrid % idim
DO j = 1, resampledGrid % jdim
CALL GetXY (i, j, resampledGrid, x, y)
CALL GetIJ (x, y, grid, iold, jold)
IF (iold > 0 .AND. jold > 0 .AND. iold <= grid % idim .AND. jold <= grid % jdim) THEN
resampledGrid % mat (i,j) = grid % mat (iold, jold)
ELSE
resampledGrid % mat (i,j) = resampledGrid % nodata
END IF
END DO
END DO
END SUBROUTINE ResampleIntegerCell
!==============================================================================
!| Description:
! Fill in a grid with a different cellsize from input grid.
! Both input grid and output grid exist.
SUBROUTINE ResampleFloat &
!
(grid, resampledGrid)
IMPLICIT NONE
! Arguments with intent(in):
TYPE (grid_real), INTENT(IN) :: grid
!Arguments with intent(inout):
TYPE (grid_real), INTENT(INOUT) :: resampledGrid
!Local declarations:
REAL :: x, y
INTEGER :: i, j, iold, jold
LOGICAL :: check
!---------------------------end of declarations--------------------------------
!check that input and output grid have the same coordinate reference system
IF ( .NOT. grid % grid_mapping == resampledGrid % grid_mapping) THEN
CALL Catch ('error', 'GridOperations', &
'coordinate reference system of resampled grid differs from input grid' )
END IF
!fill in resampled grid. Skip nodata
DO i = 1, resampledGrid % idim
DO j = 1, resampledGrid % jdim
IF (resampledGrid % mat (i,j) /= resampledGrid % nodata) THEN
CALL GetXY (i, j, resampledGrid, x, y)
CALL GetIJ (x, y, grid, iold, jold, check)
IF (check) THEN
resampledGrid % mat (i,j) = grid % mat (iold, jold)
ELSE
resampledGrid % mat (i,j) = resampledGrid % nodata
END IF
END IF
END DO
END DO
END SUBROUTINE ResampleFloat
!==============================================================================
!| Description:
! Fill in a grid with a different cellsize from input grid.
! Both input grid and output grid exist.
SUBROUTINE ResampleInteger &
!
(grid, resampledGrid)
IMPLICIT NONE
! Arguments with intent(in):
TYPE (grid_integer), INTENT(IN) :: grid
!Arguments with intent(inout):
TYPE (grid_integer), INTENT(INOUT) :: resampledGrid
!Local declarations:
REAL :: x, y
INTEGER :: i, j, iold, jold
LOGICAL :: check
!---------------------------end of declarations--------------------------------
!check that input and output grid have the same coordinate reference system
IF ( .NOT. grid % grid_mapping == resampledGrid % grid_mapping) THEN
CALL Catch ('error', 'GridOperations', &
'coordinate reference system of resampled grid differs from input grid' )
END IF
!fill in resampled grid. The content of resampledGird is totally overwritten
DO i = 1, resampledGrid % idim
DO j = 1, resampledGrid % jdim
IF (resampledGrid % mat (i,j) /= resampledGrid % nodata) THEN
CALL GetXY (i, j, resampledGrid, x, y)
CALL GetIJ (x, y, grid, iold, jold, check)
IF (check) THEN
resampledGrid % mat (i,j) = grid % mat (iold, jold)
ELSE
resampledGrid % mat (i,j) = resampledGrid % nodata
END IF
END IF
END DO
END DO
END SUBROUTINE ResampleInteger
!==============================================================================
!| Description:
! assign value of mask real to mat real
SUBROUTINE AssignGridReal &
!
(mat, mask)
IMPLICIT NONE
!Arguments with intent(in):
TYPE(grid_real),INTENT(IN) :: mask
!Arguments with intent (inout)
TYPE(grid_real),INTENT(INOUT):: mat
!Local declarations:
INTEGER :: i,j
!---------------------------end of declarations--------------------------------
!check spatial reference
!IF ( .NOT. CRSisEqual (mask, mat, .TRUE.) ) THEN
IF ( .NOT. CRSisEqual (mask, mat) ) THEN
CALL Catch ('error', 'GridOperations', &
'while assigning grid content from another grid: ', &
argument = 'spatial reference not equal' )
END IF
DO i = 1, mat % idim
DO j = 1, mat % jdim
IF (mat % mat (i,j) /= mat % nodata) THEN
mat % mat(i,j) = mask % mat(i,j)
END IF
END DO
END DO
END SUBROUTINE AssignGridReal
!==============================================================================
!| Description:
! assign value of mask integer to mat integer
SUBROUTINE AssignGridInteger &
!
(mat, mask)
IMPLICIT NONE
!Arguments with intent(in):
TYPE(grid_integer),INTENT(IN) :: mask
!Arguments with intent (inout)
TYPE(grid_integer),INTENT(INOUT):: mat
!Local declarations:
INTEGER :: i,j
!---------------------------end of declarations--------------------------------
!check spatial reference
!IF ( .NOT. CRSisEqual (mask, mat, .TRUE.) ) THEN
IF ( .NOT. CRSisEqual (mask, mat) ) THEN
CALL Catch ('error', 'GridOperations', &
'while assigning grid content from another grid: ', &
argument = 'spatial reference not equal' )
END IF
DO i = 1, mat % idim
DO j = 1, mat % jdim
IF (mat % mat (i,j) /= mat % nodata) THEN
mat % mat(i,j) = mask % mat(i,j)
END IF
END DO
END DO
END SUBROUTINE AssignGridInteger
!==============================================================================
!| Description:
! assign value of mask real to mat integer. real numbers are truncated to
! integer part.
SUBROUTINE AssignGridRealInteger &
!
(mat, mask)
IMPLICIT NONE
!Arguments with intent(in):
TYPE(grid_real),INTENT(IN) :: mask
!Arguments with intent (inout)
TYPE(grid_integer),INTENT(INOUT):: mat
!Local declarations:
INTEGER :: i,j
!---------------------------end of declarations--------------------------------
!check spatial reference
!IF ( .NOT. CRSisEqual (mask, mat, .TRUE.) ) THEN
IF ( .NOT. CRSisEqual (mask, mat) ) THEN
CALL Catch ('error', 'GridOperations', &
'while assigning grid content from another grid: ', &
argument = 'spatial reference not equal' )
END IF
DO i = 1, mat % idim
DO j = 1, mat % jdim
IF (mat % mat (i,j) /= mat % nodata) THEN !truncate to integer part
mat % mat(i,j) = INT ( mask % mat(i,j) )
ELSE !fix nodata
mat % mat(i,j) = -9999
END IF
END DO
END DO
mat % nodata = -9999
END SUBROUTINE AssignGridRealInteger
!==============================================================================
!| Description:
! assign value of mask integer to mat real
SUBROUTINE AssignGridIntegerReal &
!
(mat, mask)
IMPLICIT NONE
!Arguments with intent(in):
TYPE(grid_integer),INTENT(IN) :: mask
!Arguments with intent (inout)
TYPE(grid_real),INTENT(INOUT):: mat
!Local declarations:
INTEGER :: i,j
!---------------------------end of declarations--------------------------------
!check spatial reference
!IF ( .NOT. CRSisEqual (mask, mat, .TRUE.) ) THEN
IF ( .NOT. CRSisEqual (mask, mat) ) THEN
CALL Catch ('error', 'GridOperations', &
'while assigning grid content from another grid: ', &
argument = 'spatial reference not equal' )
END IF
DO i = 1, mat % idim
DO j = 1, mat % jdim
IF (mat % mat (i,j) /= mat % nodata) THEN !cast to real number
mat % mat(i,j) = REAL ( mask % mat(i,j) )
ELSE !fix nodata
mat % mat(i,j) = -9999.9
END IF
END DO
END DO
mat % nodata = -9999.9
END SUBROUTINE AssignGridIntegerReal
!==============================================================================
!| Description:
! assign value to mat
SUBROUTINE AssignReal &
!
(mat, num)
IMPLICIT NONE
!Arguments with intent(in):
REAL (KIND = float),INTENT(IN) :: num
!Arguments with intent (inout)
TYPE(grid_real),INTENT(INOUT):: mat
!Local declarations:
INTEGER :: i,j
!---------------------------end of declarations--------------------------------
DO i = 1, mat % idim
DO j = 1, mat % jdim
IF (mat % mat (i,j) /= mat % nodata) THEN
mat % mat(i,j) = num
END IF
END DO
END DO
END SUBROUTINE AssignReal
!==============================================================================
!| Description:
! assign value to mat
SUBROUTINE AssignInteger &
!
(mat, num)
IMPLICIT NONE
!Arguments with intent(in):
INTEGER,INTENT(IN) :: num
!Arguments with intent (inout)
TYPE(grid_integer),INTENT(INOUT):: mat
!Local declarations:
INTEGER :: i,j
!---------------------------end of declarations--------------------------------
DO i = 1, mat % idim
DO j = 1, mat % jdim
IF (mat % mat (i,j) /= mat % nodata) THEN
mat % mat(i,j) = num
END IF
END DO
END DO
END SUBROUTINE AssignInteger
!------------------------------------------------------------------------------
!| Description
!! compute area ([m2) of grid excluding nodata
FUNCTION GetAreaOfGridInteger &
!
(grid) &
!
RESULT(area)
IMPLICIT NONE
!arguments with intent(in):
TYPE(grid_integer), INTENT (IN) :: grid
!Local declarations:
REAL (KIND = float) :: area
INTEGER (KIND = short) :: i, j
!------------------------------------end of declarations-----------------------
area = 0.
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF (grid % mat (i,j) /= grid % nodata) THEN
area = area + CellArea (grid, i, j)
END IF
END DO
END DO
END FUNCTION GetAreaOfGridInteger
!------------------------------------------------------------------------------
!| Description
! compute area (m2) of grid excluding nodata
FUNCTION GetAreaOfGridFloat &
!
(grid) &
!
RESULT(area)
IMPLICIT NONE
!arguments with intent(in):
TYPE(grid_real), INTENT (IN) :: grid
!Local declarations:
REAL (KIND = float) :: area
INTEGER (KIND = short) :: i, j
!------------------------------------end of declarations-----------------------
area = 0.
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF (grid % mat (i,j) /= grid % nodata) THEN
area = area + CellArea (grid, i, j)
END IF
END DO
END DO
END FUNCTION GetAreaOfGridFloat
!==============================================================================
!| Description:
! Apply a shift to `grid_real`. Modifies `xllcorner` and `yllcorner`
SUBROUTINE ShiftReal &
!
(gridin, gridout, shifteast, shiftnorth)
IMPLICIT NONE
!Arguments with intent in
TYPE (grid_real), INTENT(IN) :: gridin
REAL (KIND = float), INTENT(IN) :: shifteast !!amount of shift in east direction
REAL (KIND = float), INTENT(IN) :: shiftnorth !!amount of shift in north direction
!Arguments with intent(out):
TYPE (grid_real), INTENT(OUT) :: gridout
!---------------------end of declarations--------------------------------------
CALL NewGrid (gridout, gridin)
gridout = gridin
gridout % xllcorner = gridin % xllcorner + shifteast
gridout % yllcorner = gridin % yllcorner + shiftnorth
RETURN
END SUBROUTINE ShiftReal
!==============================================================================
!| Description:
! Apply a shift to` grid_integer`. Creates a new grid with `xllcorner`
! and `yllcorner` modified
SUBROUTINE ShiftInteger &
!
(gridin, gridout, shifteast, shiftnorth)
IMPLICIT NONE
!Arguments with intent in
TYPE (grid_integer), INTENT(IN) :: gridin
REAL (KIND = float), INTENT(IN) :: shifteast !!amount of shift in east direction
REAL (KIND = float), INTENT(IN) :: shiftnorth !!amount of shift in north direction
!Arguments with intent(out):
TYPE (grid_integer), INTENT(OUT) :: gridout
!---------------------end of declarations--------------------------------------
CALL NewGrid (gridout, gridin)
gridout = gridin
gridout % xllcorner = gridin % xllcorner + shifteast
gridout % yllcorner = gridin % yllcorner + shiftnorth
RETURN
END SUBROUTINE ShiftInteger
!==============================================================================
!| Description:
! return an array 1D of numbers different than `nodata` in a `grid_integer`
SUBROUTINE Grid2vectorInteger &
!
(grid, vector)
IMPLICIT NONE
!Arguments with intent in
TYPE (grid_integer), INTENT(IN) :: grid
!Arguments with intent out
INTEGER (KIND = short), INTENT (OUT), ALLOCATABLE :: vector (:)
!local declarations:
INTEGER (KIND = short) :: i, j, count, istat
!---------------------end of declarations--------------------------------------
!count number of actual values in grid, skip nodata
count = 0
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF (grid % mat (i,j) /= grid % nodata) THEN
count = count + 1
END IF
END DO
END DO
!allocate vector
ALLOCATE (vector (count), STAT = istat)
!fill in vector
count = 0
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF (grid % mat (i,j) /= grid % nodata) THEN
count = count + 1
vector (count) = grid % mat (i,j)
END IF
END DO
END DO
RETURN
END SUBROUTINE Grid2vectorInteger
!==============================================================================
!| Description:
! return an array 1D of numbers different than `nodata` in a `grid_real`
SUBROUTINE Grid2vectorFloat &
!
(grid, vector)
IMPLICIT NONE
!Arguments with intent in
TYPE (grid_real), INTENT(IN) :: grid
!Arguments with intent out
REAL (KIND = float), INTENT (OUT), ALLOCATABLE :: vector (:)
!local declarations:
INTEGER (KIND = short) :: i, j, count, istat
!---------------------end of declarations--------------------------------------
!count number of actual values in grid, skip nodata
count = 0
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF (grid % mat (i,j) /= grid % nodata) THEN
count = count + 1
END IF
END DO
END DO
!allocate vector
ALLOCATE (vector (count), STAT = istat)
!fill in vector
count = 0
DO i = 1, grid % idim
DO j = 1, grid % jdim
IF (grid % mat (i,j) /= grid % nodata) THEN
count = count + 1
vector (count) = grid % mat (i,j)
END IF
END DO
END DO
RETURN
END SUBROUTINE Grid2vectorFloat
END MODULE GridOperations