Пример #1
0
def extract_GOT_constants(ilon,
                          ilat,
                          model_files,
                          METHOD=None,
                          EXTRAPOLATE=False,
                          GZIP=True,
                          SCALE=1.0):
    """
    Reads files for Richard Ray's Global Ocean Tide (GOT) models
    Makes initial calculations to run the tide program
    Spatially interpolates tidal constituents to input coordinates

    Arguments
    ---------
    ilon: longitude to interpolate
    ilat: latitude to interpolate
    model_files: list of model files for each constituent

    Keyword arguments
    -----------------
    METHOD: interpolation method
        bilinear: quick bilinear interpolation
        spline: scipy bivariate spline interpolation
        linear, nearest: scipy regular grid interpolations
    EXTRAPOLATE: extrapolate model using nearest-neighbors
    GZIP: input files are compressed
    SCALE: scaling factor for converting to output units

    Returns
    -------
    amplitude: amplitudes of tidal constituents
    phase: phases of tidal constituents
    constituents: list of model constituents
    """

    #-- adjust dimensions of input coordinates to be iterable
    ilon = np.atleast_1d(ilon)
    ilat = np.atleast_1d(ilat)
    #-- adjust longitudinal convention of input latitude and longitude
    #-- to fit tide model convention
    if (np.min(ilon) < 0.0):
        lt0, = np.nonzero(ilon < 0)
        ilon[lt0] += 360.0

    #-- number of points
    npts = len(ilon)
    #-- amplitude and phase
    constituents = []
    nc = len(model_files)
    amplitude = np.ma.zeros((npts, nc))
    amplitude.mask = np.zeros((npts, nc), dtype=bool)
    ph = np.ma.zeros((npts, nc))
    ph.mask = np.zeros((npts, nc), dtype=bool)
    #-- read and interpolate each constituent
    for i, model_file in enumerate(model_files):
        #-- read constituent from elevation file
        hc, lon, lat, cons = read_GOT_grid(os.path.expanduser(model_file),
                                           GZIP=GZIP)
        #-- append to the list of constituents
        constituents.append(cons)
        #-- grid step size of tide model
        dlon = np.abs(lon[1] - lon[0])
        dlat = np.abs(lat[1] - lat[0])
        #-- replace original values with extend matrices
        lon = extend_array(lon, dlon)
        hc = extend_matrix(hc)
        #-- interpolated complex form of constituent oscillation
        hci = np.ma.zeros((npts), dtype=hc.dtype, fill_value=hc.fill_value)
        hci.mask = np.zeros((npts), dtype=bool)
        #-- interpolate amplitude and phase of the constituent
        if (METHOD == 'bilinear'):
            #-- replace invalid values with nan
            hc[hc.mask] = np.nan
            #-- use quick bilinear to interpolate values
            hci.data[:] = bilinear_interp(lon,
                                          lat,
                                          hc,
                                          ilon,
                                          ilat,
                                          dtype=hc.dtype)
            #-- replace nan values with fill_value
            hci.mask[:] |= np.isnan(hci.data)
            hci.data[hci.mask] = hci.fill_value
        elif (METHOD == 'spline'):
            #-- interpolate complex form of the constituent with scipy
            f1 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.data.real.T,
                                                       kx=1,
                                                       ky=1)
            f2 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.data.imag.T,
                                                       kx=1,
                                                       ky=1)
            f3 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.mask.T,
                                                       kx=1,
                                                       ky=1)
            hci.data.real[:] = f1.ev(ilon, ilat)
            hci.data.imag[:] = f2.ev(ilon, ilat)
            hci.mask[:] = f3.ev(ilon, ilat).astype(bool)
            #-- replace invalid values with fill_value
            hci.data[hci.mask] = hci.fill_value
        else:
            #-- use scipy regular grid to interpolate values for a given method
            r1 = scipy.interpolate.RegularGridInterpolator(
                (lat, lon),
                hc.data,
                method=METHOD,
                bounds_error=False,
                fill_value=hci.fill_value)
            r2 = scipy.interpolate.RegularGridInterpolator((lat, lon),
                                                           hc.mask,
                                                           method=METHOD,
                                                           bounds_error=False,
                                                           fill_value=1)
            hci.data[:] = r1.__call__(np.c_[ilat, ilon])
            hci.mask[:] = np.ceil(r2.__call__(np.c_[ilat, ilon])).astype(bool)
            #-- replace invalid values with fill_value
            hci.mask[:] |= (hci.data == hci.fill_value)
            hci.data[hci.mask] = hci.fill_value
        #-- extrapolate data using nearest-neighbors
        if EXTRAPOLATE and np.any(hci.mask):
            #-- find invalid data points
            inv, = np.nonzero(hci.mask)
            #-- replace invalid values with nan
            hc[hc.mask] = np.nan
            #-- extrapolate points within 10km of valid model points
            hci.data[inv] = nearest_extrap(lon,
                                           lat,
                                           hc,
                                           ilon[inv],
                                           ilat[inv],
                                           dtype=hc.dtype,
                                           cutoff=10.0)
            #-- replace nan values with fill_value
            hci.mask[inv] = np.isnan(hci.data[inv])
            hci.data[hci.mask] = hci.fill_value
        #-- convert amplitude from input units to meters
        amplitude.data[:, i] = np.abs(hci.data) * SCALE
        amplitude.mask[:, i] = np.copy(hci.mask)
        #-- phase of the constituent in radians
        ph.data[:, i] = np.arctan2(-np.imag(hci.data), np.real(hci.data))
        ph.mask[:, i] = np.copy(hci.mask)

    #-- convert phase to degrees
    phase = ph * 180.0 / np.pi
    phase.data[phase.data < 0] += 360.0
    #-- replace data for invalid mask values
    amplitude.data[amplitude.mask] = amplitude.fill_value
    phase.data[phase.mask] = phase.fill_value
    #-- return the interpolated values
    return (amplitude, phase, constituents)
Пример #2
0
def check_tide_points(x,y,DIRECTORY=None,MODEL=None,EPSG=3031,METHOD='spline'):
    """
    Check if points are within a tide model domain

    Arguments
    ---------
    x: x-coordinates in projection EPSG
    y: y-coordinates in projection EPSG

    Keyword arguments
    -----------------
    DIRECTORY: working data directory for tide models
    MODEL: Tide model to use in correction
    EPSG: input coordinate system
        default: 3031 Polar Stereographic South, WGS84
    METHOD: interpolation method
        bilinear: quick bilinear interpolation
        spline: scipy bivariate spline interpolation
        linear, nearest: scipy regular grid interpolations

    Returns
    -------
    valid: array describing if input coordinate is within model domain
    """

    # select between tide models
    if (MODEL == 'CATS0201'):
        grid_file = os.path.join(DIRECTORY,'cats0201_tmd','grid_CATS')
        model_format = 'OTIS'
        model_EPSG = '4326'
    elif (MODEL == 'CATS2008'):
        grid_file = os.path.join(DIRECTORY,'CATS2008','grid_CATS2008')
        model_format = 'OTIS'
        model_EPSG = 'CATS2008'
    elif (MODEL == 'TPXO9-atlas'):
        grid_file = os.path.join(DIRECTORY,'TPXO9_atlas','grid_tpxo9_atlas.nc.gz')
        model_format = 'netcdf'
    elif (MODEL == 'TPXO9-atlas-v2'):
        grid_file = os.path.join(DIRECTORY,'TPXO9_atlas_v2','grid_tpxo9_atlas_30_v2.nc.gz')
        model_format = 'netcdf'
    elif (MODEL == 'TPXO9-atlas-v3'):
        grid_file = os.path.join(DIRECTORY,'TPXO9_atlas_v3','grid_tpxo9_atlas_30_v3.nc.gz')
        model_format = 'netcdf'
    elif (MODEL == 'TPXO9-atlas-v4'):
        grid_file = os.path.join(DIRECTORY,'TPXO9_atlas_v4','grid_tpxo9_atlas_30_v4')
        model_format = 'OTIS'
        model_EPSG = '4326'
    elif (MODEL == 'TPXO9.1'):
        grid_file = os.path.join(DIRECTORY,'TPXO9.1','DATA','grid_tpxo9')
        model_format = 'OTIS'
        model_EPSG = '4326'
    elif (MODEL == 'TPXO8-atlas'):
        grid_file = os.path.join(DIRECTORY,'tpxo8_atlas','grid_tpxo8atlas_30_v1')
        model_format = 'ATLAS'
        model_EPSG = '4326'
    elif (MODEL == 'TPXO7.2'):
        grid_file = os.path.join(DIRECTORY,'TPXO7.2_tmd','grid_tpxo7.2')
        model_format = 'OTIS'
        model_EPSG = '4326'
    elif (MODEL == 'AODTM-5'):
        grid_file = os.path.join(DIRECTORY,'aodtm5_tmd','grid_Arc5km')
        model_format = 'OTIS'
        model_EPSG = 'PSNorth'
    elif (MODEL == 'AOTIM-5'):
        grid_file = os.path.join(DIRECTORY,'aotim5_tmd','grid_Arc5km')
        model_format = 'OTIS'
        model_EPSG = 'PSNorth'
    elif (MODEL == 'AOTIM-5-2018'):
        grid_file = os.path.join(DIRECTORY,'Arc5km2018','grid_Arc5km2018')
        model_format = 'OTIS'
        model_EPSG = 'PSNorth'
    elif (MODEL == 'GOT4.7'):
        model_directory = os.path.join(DIRECTORY,'GOT4.7','grids_oceantide')
        model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz',
            'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz']
        model_format = 'GOT'
    elif (MODEL == 'GOT4.8'):
        model_directory = os.path.join(DIRECTORY,'got4.8','grids_oceantide')
        model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz',
            'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz']
        model_format = 'GOT'
    elif (MODEL == 'GOT4.10'):
        model_directory = os.path.join(DIRECTORY,'GOT4.10c','grids_oceantide')
        model_files = ['q1.d.gz','o1.d.gz','p1.d.gz','k1.d.gz','n2.d.gz',
            'm2.d.gz','s2.d.gz','k2.d.gz','s1.d.gz','m4.d.gz']
        model_format = 'GOT'
    elif (MODEL == 'FES2014'):
        model_directory = os.path.join(DIRECTORY,'fes2014','ocean_tide')
        model_files = ['2n2.nc.gz','eps2.nc.gz','j1.nc.gz','k1.nc.gz',
            'k2.nc.gz','l2.nc.gz','la2.nc.gz','m2.nc.gz','m3.nc.gz','m4.nc.gz',
            'm6.nc.gz','m8.nc.gz','mf.nc.gz','mks2.nc.gz','mm.nc.gz',
            'mn4.nc.gz','ms4.nc.gz','msf.nc.gz','msqm.nc.gz','mtm.nc.gz',
            'mu2.nc.gz','n2.nc.gz','n4.nc.gz','nu2.nc.gz','o1.nc.gz','p1.nc.gz',
            'q1.nc.gz','r2.nc.gz','s1.nc.gz','s2.nc.gz','s4.nc.gz','sa.nc.gz',
            'ssa.nc.gz','t2.nc.gz']
        model_format = 'FES'

    # input shape of data
    idim = np.shape(x)
    # converting x,y from EPSG to latitude/longitude
    try:
        # EPSG projection code string or int
        crs1 = pyproj.CRS.from_string("epsg:{0:d}".format(int(EPSG)))
    except (ValueError,pyproj.exceptions.CRSError):
        # Projection SRS string
        crs1 = pyproj.CRS.from_string(EPSG)
    crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326))
    transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True)
    lon,lat = transformer.transform(np.atleast_1d(x).flatten(),
        np.atleast_1d(y).flatten())

    # read tidal constants and interpolate to grid points
    if model_format in ('OTIS','ATLAS'):
        # if reading a single OTIS solution
        xi,yi,hz,mz,iob,dt = pyTMD.read_tide_model.read_tide_grid(grid_file)
        # invert model mask
        mz = np.logical_not(mz)
        # adjust dimensions of input coordinates to be iterable
        # run wrapper function to convert coordinate systems of input lat/lon
        X,Y = pyTMD.convert_ll_xy(lon,lat,model_EPSG,'F')
    elif (model_format == 'netcdf'):
        # if reading a netCDF OTIS atlas solution
        xi,yi,hz = pyTMD.read_netcdf_model.read_netcdf_grid(grid_file,
            GZIP=True, TYPE='z')
        # copy bathymetry mask
        mz = np.copy(hz.mask)
        # copy latitude and longitude and adjust longitudes
        X,Y = np.copy([lon,lat]).astype(np.float64)
        lt0, = np.nonzero(X < 0)
        X[lt0] += 360.0
    elif (model_format == 'GOT'):
        # if reading a NASA GOT solution
        input_file = os.path.join(model_directory,model_files[0])
        hc,xi,yi,c = pyTMD.read_GOT_model.read_GOT_grid(input_file, GZIP=True)
        # copy tidal constituent mask
        mz = np.copy(hc.mask)
        # copy latitude and longitude and adjust longitudes
        X,Y = np.copy([lon,lat]).astype(np.float64)
        lt0, = np.nonzero(X < 0)
        X[lt0] += 360.0
    elif (model_format == 'FES'):
        # if reading a FES netCDF solution
        input_file = os.path.join(model_directory,model_files[0])
        hc,xi,yi = pyTMD.read_FES_model.read_netcdf_file(input_file,GZIP=True,
            TYPE='z',VERSION='FES2014')
        # copy tidal constituent mask
        mz = np.copy(hc.mask)
        # copy latitude and longitude and adjust longitudes
        X,Y = np.copy([lon,lat]).astype(np.float64)
        lt0, = np.nonzero(X < 0)
        X[lt0] += 360.0

    # interpolate masks
    if (METHOD == 'bilinear'):
        # replace invalid values with nan
        mz1 = bilinear_interp(xi,yi,mz,X,Y)
        mask = np.floor(mz1).astype(mz.dtype)
    elif (METHOD == 'spline'):
        f1=scipy.interpolate.RectBivariateSpline(xi,yi,mz.T,kx=1,ky=1)
        mask = np.floor(f1.ev(X,Y)).astype(mz.dtype)
    else:
        # use scipy regular grid to interpolate values
        r1 = scipy.interpolate.RegularGridInterpolator((yi,xi),mz,
            method=METHOD,bounds_error=False,fill_value=1)
        mask = np.floor(r1.__call__(np.c_[y,x])).astype(mz.dtype)

    # reshape to original dimensions
    valid = np.logical_not(mask).reshape(idim).astype(mz.dtype)
    # replace points outside model domain with invalid
    valid &= (X >= xi.min()) & (X <= xi.max())
    valid &= (Y >= yi.min()) & (Y <= yi.max())
    # return the valid mask
    return valid
Пример #3
0
def extract_FES_constants(ilon,
                          ilat,
                          directory,
                          model_files,
                          TYPE='z',
                          VERSION=None,
                          METHOD='spline',
                          GZIP=True,
                          SCALE=1):
    """
    Reads files for an ascii or netCDF4 tidal model
    Makes initial calculations to run the tide program
    Spatially interpolates tidal constituents to input coordinates

    Arguments
    ---------
    ilon: longitude to interpolate
    ilat: latitude to interpolate
    directory: data directory for tide data files
    grid_file: grid file for model (can be gzipped)
    model_files: list of model files for each constituent (can be gzipped)

    Keyword arguments
    -----------------
    TYPE: tidal variable to run
        z: heights
        u: horizontal transport velocities
        v: vertical transport velocities
    VERSION: model version to run
        FES1999
        FES2004
        FES2012
        FES2014
    METHOD: interpolation method
        bilinear: quick bilinear interpolation
        spline: scipy bivariate spline interpolation
        linear, nearest: scipy regular grid interpolations
    GZIP: input files are compressed
    SCALE: scaling factor for converting to output units

    Returns
    -------
    amplitude: amplitudes of tidal constituents
    phase: phases of tidal constituents
    """

    #-- adjust dimensions of input coordinates to be iterable
    ilon = np.atleast_1d(ilon)
    ilat = np.atleast_1d(ilat)
    #-- adjust longitudinal convention of input latitude and longitude
    #-- to fit tide model convention
    if (np.min(ilon) < 0.0):
        lt0, = np.nonzero(ilon < 0)
        ilon[lt0] += 360.0

    #-- number of points
    npts = len(ilon)
    #-- number of constituents
    nc = len(model_files)
    #-- amplitude and phase
    amplitude = np.ma.zeros((npts, nc))
    amplitude.mask = np.zeros((npts, nc), dtype=np.bool)
    phase = np.ma.zeros((npts, nc))
    phase.mask = np.zeros((npts, nc), dtype=np.bool)
    #-- read and interpolate each constituent
    for i, fi in enumerate(model_files):
        #-- read constituent from elevation file
        if VERSION in ('FES1999', 'FES2004'):
            hc, lon, lat = read_ascii_file(os.path.join(directory, fi),
                                           GZIP=GZIP,
                                           TYPE=TYPE,
                                           VERSION=VERSION)
        elif VERSION in ('FES2012', 'FES2014'):
            hc, lon, lat = read_netcdf_file(os.path.join(directory, fi),
                                            GZIP=GZIP,
                                            TYPE=TYPE,
                                            VERSION=VERSION)
        #-- interpolated complex form of constituent oscillation
        hci = np.ma.zeros((npts), dtype=hc.dtype, fill_value=hc.fill_value)
        hci.mask = np.zeros((npts), dtype=np.bool)
        #-- interpolate amplitude and phase of the constituent
        if (METHOD == 'bilinear'):
            #-- replace invalid values with nan
            hc[hc.mask] = np.nan
            #-- use quick bilinear to interpolate values
            hci.data[:] = bilinear_interp(lon,
                                          lat,
                                          hc,
                                          ilon,
                                          ilat,
                                          dtype=hc.dtype)
            #-- replace nan values with fill_value
            hci.mask[:] |= np.isnan(hci.data)
            hci.data[hci.mask] = hci.fill_value
        elif (METHOD == 'spline'):
            #-- interpolate complex form of the constituent with scipy
            f1 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.data.real.T,
                                                       kx=1,
                                                       ky=1)
            f2 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.data.imag.T,
                                                       kx=1,
                                                       ky=1)
            f3 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.mask.T,
                                                       kx=1,
                                                       ky=1)
            hci.data.real[:] = f1.ev(ilon, ilat)
            hci.data.imag[:] = f2.ev(ilon, ilat)
            hci.mask[:] = f3.ev(ilon, ilat).astype(np.bool)
            #-- replace invalid values with fill_value
            hci.data[hci.mask] = hci.fill_value
        else:
            #-- use scipy regular grid to interpolate values for a given method
            r1 = scipy.interpolate.RegularGridInterpolator(
                (lat, lon),
                hc.data,
                method=METHOD,
                bounds_error=False,
                fill_value=hci.fill_value)
            r2 = scipy.interpolate.RegularGridInterpolator((lat, lon),
                                                           hc.mask,
                                                           method=METHOD,
                                                           bounds_error=False,
                                                           fill_value=1)
            hci.data[:] = r1.__call__(np.c_[ilat, ilon])
            hci.mask[:] = np.ceil(r2.__call__(np.c_[ilat,
                                                    ilon])).astype(np.bool)
            #-- replace invalid values with fill_value
            hci.mask[:] |= (hci.data == hci.fill_value)
            hci.data[hci.mask] = hci.fill_value
        #-- convert amplitude from input units to meters
        amplitude.data[:, i] = np.abs(hci) * SCALE
        amplitude.mask[:, i] = np.copy(hci.mask)
        #-- convert phase to degrees
        phase.data[:,
                   i] = np.arctan2(-np.imag(hci), np.real(hci)) * 180.0 / np.pi
        phase.mask[:, i] = np.copy(hci.mask)
        phase.data[phase.data < 0] += 360.0

    #-- replace data for invalid mask values
    amplitude.data[amplitude.mask] = amplitude.fill_value
    phase.data[phase.mask] = phase.fill_value
    #-- return the interpolated values
    return (amplitude, phase)
Пример #4
0
def check_tide_points(x, y, DIRECTORY=None, MODEL=None,
    ATLAS_FORMAT='netcdf', GZIP=False, DEFINITION_FILE=None,
    EPSG=3031, METHOD='spline'):
    """
    Check if points are within a tide model domain

    Parameters
    ----------
    x: float
        x-coordinates in projection EPSG
    y: float
        y-coordinates in projection EPSG
    DIRECTORY: str or NoneType, default None
        working data directory for tide models
    MODEL:  str or NoneType, default None
        Tide model to use
    ATLAS_FORMAT: str, default 'netcdf'
        ATLAS tide model format

            - ``'OTIS'``
            - ``'netcdf'``
    GZIP: bool, default False
        Tide model files are gzip compressed
    DEFINITION_FILE: str or NoneType, default None
        Tide model definition file for use
    EPSG: int, default: 3031 (Polar Stereographic South, WGS84)
        Input coordinate system
    METHOD: str
        interpolation method

            - ```bilinear```: quick bilinear interpolation
            - ```spline```: scipy bivariate spline interpolation
            - ```linear```, ```nearest```: scipy regular grid interpolations

    Returns
    -------
    valid: bool
        array describing if input coordinate is within model domain
    """

    #-- check that tide directory is accessible
    try:
        os.access(DIRECTORY, os.F_OK)
    except:
        raise FileNotFoundError("Invalid tide directory")

    #-- get parameters for tide model
    if DEFINITION_FILE is not None:
        model = pyTMD.model(DIRECTORY).from_file(DEFINITION_FILE)
    else:
        model = pyTMD.model(DIRECTORY, format=ATLAS_FORMAT,
            compressed=GZIP).elevation(MODEL)

    # input shape of data
    idim = np.shape(x)
    # converting x,y from EPSG to latitude/longitude
    try:
        # EPSG projection code string or int
        crs1 = pyproj.CRS.from_string("epsg:{0:d}".format(int(EPSG)))
    except (ValueError,pyproj.exceptions.CRSError):
        # Projection SRS string
        crs1 = pyproj.CRS.from_string(EPSG)
    crs2 = pyproj.CRS.from_string("epsg:{0:d}".format(4326))
    transformer = pyproj.Transformer.from_crs(crs1, crs2, always_xy=True)
    lon,lat = transformer.transform(np.atleast_1d(x).flatten(),
        np.atleast_1d(y).flatten())

    # read tidal constants and interpolate to grid points
    if model.format in ('OTIS','ATLAS'):
        # if reading a single OTIS solution
        xi,yi,hz,mz,iob,dt = pyTMD.read_tide_model.read_tide_grid(model.grid_file)
        # invert model mask
        mz = np.logical_not(mz)
        # adjust dimensions of input coordinates to be iterable
        # run wrapper function to convert coordinate systems of input lat/lon
        X,Y = pyTMD.convert_ll_xy(lon,lat,model.projection,'F')
    elif (model.format == 'netcdf'):
        # if reading a netCDF OTIS atlas solution
        xi,yi,hz = pyTMD.read_netcdf_model.read_netcdf_grid(model.grid_file,
            GZIP=model.compressed, TYPE=model.type)
        # copy bathymetry mask
        mz = np.copy(hz.mask)
        # copy latitude and longitude and adjust longitudes
        X,Y = np.copy([lon,lat]).astype(np.float64)
        lt0, = np.nonzero(X < 0)
        X[lt0] += 360.0
    elif (model.format == 'GOT'):
        # if reading a NASA GOT solution
        hc,xi,yi,c = pyTMD.read_GOT_model.read_GOT_grid(model.model_file[0],
            GZIP=model.compressed)
        # copy tidal constituent mask
        mz = np.copy(hc.mask)
        # copy latitude and longitude and adjust longitudes
        X,Y = np.copy([lon,lat]).astype(np.float64)
        lt0, = np.nonzero(X < 0)
        X[lt0] += 360.0
    elif (model.format == 'FES'):
        # if reading a FES netCDF solution
        hc,xi,yi = pyTMD.read_FES_model.read_netcdf_file(model.model_file[0],
            GZIP=model.compressed, TYPE=model.type, VERSION=model.version)
        # copy tidal constituent mask
        mz = np.copy(hc.mask)
        # copy latitude and longitude and adjust longitudes
        X,Y = np.copy([lon,lat]).astype(np.float64)
        lt0, = np.nonzero(X < 0)
        X[lt0] += 360.0

    # interpolate masks
    if (METHOD == 'bilinear'):
        # replace invalid values with nan
        mz1 = bilinear_interp(xi,yi,mz,X,Y)
        mask = np.floor(mz1).astype(mz.dtype)
    elif (METHOD == 'spline'):
        f1=scipy.interpolate.RectBivariateSpline(xi,yi,mz.T,kx=1,ky=1)
        mask = np.floor(f1.ev(X,Y)).astype(mz.dtype)
    else:
        # use scipy regular grid to interpolate values
        r1 = scipy.interpolate.RegularGridInterpolator((yi,xi),mz,
            method=METHOD,bounds_error=False,fill_value=1)
        mask = np.floor(r1.__call__(np.c_[y,x])).astype(mz.dtype)

    # reshape to original dimensions
    valid = np.logical_not(mask).reshape(idim).astype(mz.dtype)
    # replace points outside model domain with invalid
    valid &= (X >= xi.min()) & (X <= xi.max())
    valid &= (Y >= yi.min()) & (Y <= yi.max())
    # return the valid mask
    return valid
Пример #5
0
def extract_FES_constants(ilon, ilat, model_files, TYPE='z', VERSION=None,
    METHOD='spline', EXTRAPOLATE=False, CUTOFF=10.0, GZIP=True, SCALE=1.0):
    """
    Reads files for an ascii or netCDF4 tidal model

    Makes initial calculations to run the tide program

    Spatially interpolates tidal constituents to input coordinates

    Parameters
    ----------
    ilon: float
        longitude to interpolate
    ilat: float
        latitude to interpolate
    grid_file: str
        grid file for model
    model_files: list
        list of model files for each constituent
    TYPE: str, default 'z'
        Tidal variable to read

            - ``'z'``: heights
            - ``'u'``: horizontal transport velocities
            - ``'v'``: vertical transport velocities
    VERSION: str or NoneType, default None
        Model version to read

            - ``'FES1999'``
            - ``'FES2004'``
            - ``'FES2012'``
            - ``'FES2014'``
            - ``'EOT20'``
    METHOD: str, default 'spline'
        Interpolation method

            - ``'bilinear'``: quick bilinear interpolation
            - ``'spline'``: scipy bivariate spline interpolation
            - ``'linear'``, ``'nearest'``: scipy regular grid interpolations
    EXTRAPOLATE: bool, default False
        Extrapolate model using nearest-neighbors
    CUTOFF: float, default 10.0
        Extrapolation cutoff in kilometers

        Set to np.inf to extrapolate for all points
    GZIP: bool, default False
        Input files are compressed
    SCALE: float, default 1.0
        Scaling factor for converting to output units

    Returns
    -------
    amplitude: float
        amplitudes of tidal constituents
    phase: float
        phases of tidal constituents
    """

    #-- raise warning if model files are entered as a string
    if isinstance(model_files,str):
        warnings.warn("Tide model is entered as a string")
        model_files = [model_files]

    #-- adjust dimensions of input coordinates to be iterable
    ilon = np.atleast_1d(ilon)
    ilat = np.atleast_1d(ilat)
    #-- number of points
    npts = len(ilon)
    #-- number of constituents
    nc = len(model_files)

    #-- amplitude and phase
    amplitude = np.ma.zeros((npts,nc))
    amplitude.mask = np.zeros((npts,nc),dtype=bool)
    ph = np.ma.zeros((npts,nc))
    ph.mask = np.zeros((npts,nc),dtype=bool)
    #-- read and interpolate each constituent
    for i,fi in enumerate(model_files):
        #-- check that model file is accessible
        if not os.access(os.path.expanduser(fi), os.F_OK):
            raise FileNotFoundError(os.path.expanduser(fi))
        #-- read constituent from elevation file
        if VERSION in ('FES1999','FES2004'):
            #-- FES ascii constituent files
            hc,lon,lat = read_ascii_file(os.path.expanduser(fi),
                GZIP=GZIP, TYPE=TYPE, VERSION=VERSION)
        elif VERSION in ('FES2012','FES2014','EOT20'):
            #-- FES netCDF4 constituent files
            hc,lon,lat = read_netcdf_file(os.path.expanduser(fi),
                GZIP=GZIP, TYPE=TYPE, VERSION=VERSION)
        #-- adjust longitudinal convention of input latitude and longitude
        #-- to fit tide model convention
        if (np.min(ilon) < 0.0) & (np.max(lon) > 180.0):
            #-- input points convention (-180:180)
            #-- tide model convention (0:360)
            ilon[ilon<0.0] += 360.0
        elif (np.max(ilon) > 180.0) & (np.min(lon) < 0.0):
            #-- input points convention (0:360)
            #-- tide model convention (-180:180)
            ilon[ilon>180.0] -= 360.0
        #-- interpolated complex form of constituent oscillation
        hci = np.ma.zeros((npts),dtype=hc.dtype,fill_value=hc.fill_value)
        hci.mask = np.zeros((npts),dtype=bool)
        #-- interpolate amplitude and phase of the constituent
        if (METHOD == 'bilinear'):
            #-- replace invalid values with nan
            hc[hc.mask] = np.nan
            #-- use quick bilinear to interpolate values
            hci.data[:] = bilinear_interp(lon,lat,hc,ilon,ilat,dtype=hc.dtype)
            #-- replace nan values with fill_value
            hci.mask[:] |= np.isnan(hci.data)
            hci.data[hci.mask] = hci.fill_value
        elif (METHOD == 'spline'):
            #-- interpolate complex form of the constituent with scipy
            f1=scipy.interpolate.RectBivariateSpline(lon,lat,
                hc.data.real.T,kx=1,ky=1)
            f2=scipy.interpolate.RectBivariateSpline(lon,lat,
                hc.data.imag.T,kx=1,ky=1)
            f3=scipy.interpolate.RectBivariateSpline(lon,lat,
                hc.mask.T,kx=1,ky=1)
            hci.data.real[:] = f1.ev(ilon,ilat)
            hci.data.imag[:] = f2.ev(ilon,ilat)
            hci.mask[:] = f3.ev(ilon,ilat).astype(bool)
            #-- replace invalid values with fill_value
            hci.data[hci.mask] = hci.fill_value
        else:
            #-- use scipy regular grid to interpolate values for a given method
            r1 = scipy.interpolate.RegularGridInterpolator((lat,lon),
                hc.data, method=METHOD, bounds_error=False,
                fill_value=hci.fill_value)
            r2 = scipy.interpolate.RegularGridInterpolator((lat,lon),
                hc.mask, method=METHOD, bounds_error=False, fill_value=1)
            hci.data[:] = r1.__call__(np.c_[ilat,ilon])
            hci.mask[:] = np.ceil(r2.__call__(np.c_[ilat,ilon])).astype(bool)
            #-- replace invalid values with fill_value
            hci.mask[:] |= (hci.data == hci.fill_value)
            hci.data[hci.mask] = hci.fill_value
        #-- extrapolate data using nearest-neighbors
        if EXTRAPOLATE and np.any(hci.mask):
            #-- find invalid data points
            inv, = np.nonzero(hci.mask)
            #-- replace invalid values with nan
            hc[hc.mask] = np.nan
            #-- extrapolate points within cutoff of valid model points
            hci[inv] = nearest_extrap(lon,lat,hc,ilon[inv],ilat[inv],
                dtype=hc.dtype,cutoff=CUTOFF)
        #-- convert amplitude from input units to meters
        amplitude.data[:,i] = np.abs(hci.data)*SCALE
        amplitude.mask[:,i] = np.copy(hci.mask)
        #-- phase of the constituent in radians
        ph.data[:,i] = np.arctan2(-np.imag(hci.data),np.real(hci.data))
        ph.mask[:,i] = np.copy(hci.mask)

    #-- convert phase to degrees
    phase = ph*180.0/np.pi
    phase.data[phase.data < 0] += 360.0
    #-- replace data for invalid mask values
    amplitude.data[amplitude.mask] = amplitude.fill_value
    phase.data[phase.mask] = phase.fill_value
    #-- return the interpolated values
    return (amplitude,phase)
Пример #6
0
def extract_netcdf_constants(ilon, ilat, directory, grid_file, model_files,
    TYPE='z', METHOD='spline', GZIP=True, SCALE=1):
    """
    Reads files for a netCDF4 tidal model
    Makes initial calculations to run the tide program
    Spatially interpolates tidal constituents to input coordinates

    Arguments
    ---------
    ilon: longitude to interpolate
    ilat: latitude to interpolate
    directory: data directory for tide data files
    grid_file: grid file for model (can be gzipped)
    model_files: list of model files for each constituent (can be gzipped)
    TYPE: tidal variable to run
        z: heights
        u: horizontal transport velocities
        U: horizontal depth-averaged transport
        v: vertical transport velocities
        V: vertical depth-averaged transport

    Keyword arguments
    -----------------
    METHOD: interpolation method
        bilinear: quick bilinear interpolation
        spline: scipy bivariate spline interpolation
        linear, nearest: scipy regular grid interpolations
    GZIP: input netCDF4 files are compressed
    SCALE: scaling factor for converting to output units

    Returns
    -------
    amplitude: amplitudes of tidal constituents
    phase: phases of tidal constituents
    D: bathymetry of tide model
    constituents: list of model constituents
    """

    #-- read the netcdf format tide grid file
    #-- reading a combined global solution with localized solutions
    if GZIP:
        #-- open remote file with netCDF4
        #-- read GZIP file
        f = gzip.open(os.path.join(directory,grid_file),'rb')
        fileID = netCDF4.Dataset(grid_file,'r',memory=f.read())
    else:
        fileID = netCDF4.Dataset(os.path.join(directory,grid_file),'r')
    #-- variable dimensions
    nx = fileID.dimensions['nx'].size
    ny = fileID.dimensions['ny'].size
    #-- allocate numpy masked array for bathymetry
    bathymetry = np.ma.zeros((ny,nx))
    #-- read bathmetry and coordinates for variable type
    if (TYPE == 'z'):
        #-- get bathymetry at nodes
        bathymetry.data[:,:] = fileID.variables['hz'][:,:].T
        #-- read latitude and longitude at z-nodes
        lon = fileID.variables['lon_z'][:].copy()
        lat = fileID.variables['lat_z'][:].copy()
    elif TYPE in ('U','u'):
        #-- get bathymetry at u-nodes
        bathymetry.data[:,:] = fileID.variables['hu'][:,:].T
        #-- read latitude and longitude at u-nodes
        lon = fileID.variables['lon_u'][:].copy()
        lat = fileID.variables['lat_u'][:].copy()
    elif TYPE in ('V','v'):
        #-- get bathymetry at v-nodes
        bathymetry.data[:,:] = fileID.variables['hv'][:,:].T
        #-- read latitude and longitude at v-nodes
        lon = fileID.variables['lon_v'][:].copy()
        lat = fileID.variables['lat_v'][:].copy()
    #-- close the grid file
    fileID.close()
    f.close() if GZIP else None

    #-- grid step size of tide model
    dlon = lon[1] - lon[0]
    dlat = lat[1] - lat[0]
    #-- replace original values with extend arrays/matrices
    lon = extend_array(lon, dlon)
    bathymetry = extend_matrix(bathymetry)
    #-- create masks
    bathymetry.mask = (bathymetry.data == 0)
    #-- create meshes from latitude and longitude
    gridlon,gridlat = np.meshgrid(lon,lat)

    #-- adjust dimensions of input coordinates to be iterable
    ilon = np.atleast_1d(ilon)
    ilat = np.atleast_1d(ilat)
    #-- adjust longitudinal convention of input latitude and longitude
    #-- to fit tide model convention
    lt0, = np.nonzero(ilon < 0)
    ilon[lt0] += 360.0
    #-- number of points
    npts = len(ilon)

    #-- interpolate bathymetry and mask to output points
    D = np.ma.zeros((npts))
    D.mask = np.zeros((npts),dtype=np.bool)
    if (METHOD == 'bilinear'):
        #-- replace invalid values with nan
        bathymetry[bathymetry.mask] = np.nan
        #-- use quick bilinear to interpolate values
        D.data[:] = bilinear_interp(lon,lat,bathymetry,ilon,ilat)
        #-- replace nan values with fill_value
        D.mask[:] = np.isnan(D.data)
        D.data[D.mask] = D.fill_value
    elif (METHOD == 'spline'):
        #-- use scipy bivariate splines to interpolate values
        f1 = scipy.interpolate.RectBivariateSpline(lon,lat,
            bathymetry.data.T,kx=1,ky=1)
        f2 = scipy.interpolate.RectBivariateSpline(lon,lat,
            bathymetry.mask.T,kx=1,ky=1)
        D.data[:] = f1.ev(ilon,ilat)
        D.mask[:] = np.ceil(f2.ev(ilon,ilat).astype(np.bool))
    else:
        #-- use scipy regular grid to interpolate values for a given method
        r1 = scipy.interpolate.RegularGridInterpolator((lat,lon),
            bathymetry.data, method=METHOD, bounds_error=False)
        r2 = scipy.interpolate.RegularGridInterpolator((lat,lon),
            bathymetry.mask, method=METHOD, bounds_error=False, fill_value=1)
        D.data[:] = r1.__call__(np.c_[ilat,ilon])
        D.mask[:] = np.ceil(r2.__call__(np.c_[ilat,ilon])).astype(np.bool)

    #-- u and v are velocities in cm/s
    if TYPE in ('v','u'):
        unit_conv = (D.data/100.0)
    #-- U and V are transports in m^2/s
    elif TYPE in ('V','U'):
        unit_conv = 1.0

    #-- number of constituents
    nc = len(model_files)
    #-- list of constituents
    constituents = []
    #-- amplitude and phase
    ampl = np.ma.zeros((npts,nc))
    ampl.mask = np.zeros((npts,nc),dtype=np.bool)
    phase = np.ma.zeros((npts,nc))
    phase.mask = np.zeros((npts,nc),dtype=np.bool)
    #-- read and interpolate each constituent
    for i,fi in enumerate(model_files):
        if (TYPE == 'z'):
            #-- read constituent from elevation file
            z,con = read_elevation_file(os.path.join(directory,fi),GZIP)
            #-- append constituent to list
            constituents.append(con)
            #-- replace original values with extend matrices
            z = extend_matrix(z)
            #-- interpolate amplitude and phase of the constituent
            z1 = np.ma.zeros((npts),dtype=z.dtype)
            z1.mask = np.zeros((npts),dtype=np.bool)
            if (METHOD == 'bilinear'):
                z1.data[:] = bilinear_interp(lon,lat,z,ilon,ilat,dtype=z.dtype)
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            elif (METHOD == 'spline'):
                f1 = scipy.interpolate.RectBivariateSpline(lon,lat,
                    z.data.real.T,kx=1,ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(lon,lat,
                    z.data.imag.T,kx=1,ky=1)
                z1.data.real = f1.ev(ilon,ilat)
                z1.data.imag = f2.ev(ilon,ilat)
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator((lat,lon),
                    z.data, method=METHOD, bounds_error=False,
                    fill_value=z1.fill_value)
                z1.data[:] = r1.__call__(np.c_[ilat,ilon])
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            #-- amplitude and phase of the constituent
            ampl[:,i] = np.abs(z1)
            phase[:,i] = np.arctan2(-np.imag(z1),np.real(z1))
        elif TYPE in ('U','u','V','v'):
            #-- read constituent from transport file
            tr,con = read_transport_file(os.path.join(directory,fi),TYPE,GZIP)
            #-- append constituent to list
            constituents.append(con)
            #-- replace original values with extend matrices
            tr = extend_matrix(tr)
            #-- interpolate amplitude and phase of the constituent
            tr1 = np.ma.zeros((npts),dtype=tr.dtype)
            tr1.mask = np.zeros((npts),dtype=np.bool)
            if (METHOD == 'bilinear'):
                tr1.data[:]=bilinear_interp(lon,lat,tr,ilon,ilat,dtype=tr.dtype)
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = tr1.fill_value
            elif (METHOD == 'spline'):
                f1 = scipy.interpolate.RectBivariateSpline(lon,lat,
                    tr.data.real.T,kx=1,ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(lon,lat,
                    tr.data.imag.T,kx=1,ky=1)
                tr1.data.real = f1.ev(ilon,ilat)
                tr1.data.imag = f2.ev(ilon,ilat)
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = z1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator((lat,lon),
                    tr.data, method=METHOD, bounds_error=False,
                    fill_value=tr1.fill_value)
                tr1.data[:] = r1.__call__(np.c_[ilat,ilon])
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = tr1.fill_value
            #-- convert units
            tr1 = tr1/unit_conv
            #-- amplitude and phase of the constituent
            ampl[:,i] = np.abs(tr1)
            phase[:,i] = np.arctan2(-np.imag(tr1),np.real(tr1))

    #-- convert amplitude from input units to meters
    amplitude = ampl*SCALE
    #-- convert phase to degrees
    phase = phase*180.0/np.pi
    phase[phase < 0] += 360.0
    #-- return the interpolated values
    return (amplitude,phase,D,constituents)
Пример #7
0
def extract_netcdf_constants(ilon, ilat, grid_file, model_files, TYPE='z',
    METHOD='spline', EXTRAPOLATE=False, CUTOFF=10.0, GZIP=True, SCALE=1.0):
    """
    Reads files for ATLAS netCDF4 tidal models

    Makes initial calculations to run the tide program

    Spatially interpolates tidal constituents to input coordinates

    Parameters
    ----------
    ilon: float
        longitude to interpolate
    ilat: float
        latitude to interpolate
    grid_file: str
        grid file for model
    model_files: list
        list of model files for each constituent
    TYPE: str, default 'z'
        Tidal variable to read

            - ``'z'``: heights
            - ``'u'``: horizontal transport velocities
            - ``'U'``: horizontal depth-averaged transport
            - ``'v'``: vertical transport velocities
            - ``'V'``: vertical depth-averaged transport
    METHOD: str, default 'spline'
        Interpolation method

            - ``'bilinear'``: quick bilinear interpolation
            - ``'spline'``: scipy bivariate spline interpolation
            - ``'linear'``, ``'nearest'``: scipy regular grid interpolations
    EXTRAPOLATE: bool, default False
        Extrapolate model using nearest-neighbors
    CUTOFF: float, default 10.0
        Extrapolation cutoff in kilometers

        Set to np.inf to extrapolate for all points
    GZIP: bool, default False
        Input files are compressed
    SCALE: float, default 1.0
        Scaling factor for converting to output units

    Returns
    -------
    amplitude: float
        amplitudes of tidal constituents
    phase: float
        phases of tidal constituents
    D: float
        bathymetry of tide model
    constituents: list
        list of model constituents
    """

    #-- raise warning if model files are entered as a string
    if isinstance(model_files,str):
        warnings.warn("Tide model is entered as a string")
        model_files = [model_files]

    #-- check that grid file is accessible
    if not os.access(os.path.expanduser(grid_file), os.F_OK):
        raise FileNotFoundError(os.path.expanduser(grid_file))

    #-- read the tide grid file for bathymetry and spatial coordinates
    lon,lat,bathymetry = read_netcdf_grid(grid_file, TYPE, GZIP=GZIP)

    #-- adjust dimensions of input coordinates to be iterable
    ilon = np.atleast_1d(ilon)
    ilat = np.atleast_1d(ilat)
    #-- adjust longitudinal convention of input latitude and longitude
    #-- to fit tide model convention
    if (np.min(ilon) < 0.0) & (np.max(lon) > 180.0):
        #-- input points convention (-180:180)
        #-- tide model convention (0:360)
        ilon[ilon<0.0] += 360.0
    elif (np.max(ilon) > 180.0) & (np.min(lon) < 0.0):
        #-- input points convention (0:360)
        #-- tide model convention (-180:180)
        ilon[ilon>180.0] -= 360.0

    #-- grid step size of tide model
    dlon = lon[1] - lon[0]
    dlat = lat[1] - lat[0]
    #-- replace original values with extend arrays/matrices
    lon = extend_array(lon, dlon)
    bathymetry = extend_matrix(bathymetry)
    #-- create masks
    bathymetry.mask = (bathymetry.data == 0)

    #-- number of points
    npts = len(ilon)
    #-- interpolate bathymetry and mask to output points
    D = np.ma.zeros((npts))
    D.mask = np.zeros((npts),dtype=bool)
    if (METHOD == 'bilinear'):
        #-- replace invalid values with nan
        bathymetry[bathymetry.mask] = np.nan
        #-- use quick bilinear to interpolate values
        D.data[:] = bilinear_interp(lon,lat,bathymetry,ilon,ilat)
        #-- replace nan values with fill_value
        D.mask[:] = np.isnan(D.data)
        D.data[D.mask] = D.fill_value
    elif (METHOD == 'spline'):
        #-- use scipy bivariate splines to interpolate values
        f1 = scipy.interpolate.RectBivariateSpline(lon,lat,
            bathymetry.data.T,kx=1,ky=1)
        f2 = scipy.interpolate.RectBivariateSpline(lon,lat,
            bathymetry.mask.T,kx=1,ky=1)
        D.data[:] = f1.ev(ilon,ilat)
        D.mask[:] = np.ceil(f2.ev(ilon,ilat).astype(bool))
    else:
        #-- use scipy regular grid to interpolate values for a given method
        r1 = scipy.interpolate.RegularGridInterpolator((lat,lon),
            bathymetry.data, method=METHOD, bounds_error=False)
        r2 = scipy.interpolate.RegularGridInterpolator((lat,lon),
            bathymetry.mask, method=METHOD, bounds_error=False, fill_value=1)
        D.data[:] = r1.__call__(np.c_[ilat,ilon])
        D.mask[:] = np.ceil(r2.__call__(np.c_[ilat,ilon])).astype(bool)

    #-- u and v are velocities in cm/s
    if TYPE in ('v','u'):
        unit_conv = (D.data/100.0)
    #-- U and V are transports in m^2/s
    elif TYPE in ('V','U'):
        unit_conv = 1.0

    #-- number of constituents
    nc = len(model_files)
    #-- list of constituents
    constituents = []
    #-- amplitude and phase
    ampl = np.ma.zeros((npts,nc))
    ampl.mask = np.zeros((npts,nc),dtype=bool)
    ph = np.ma.zeros((npts,nc))
    ph.mask = np.zeros((npts,nc),dtype=bool)
    #-- read and interpolate each constituent
    for i,model_file in enumerate(model_files):
        #-- check that model file is accessible
        if not os.access(os.path.expanduser(model_file), os.F_OK):
            raise FileNotFoundError(os.path.expanduser(model_file))
        if (TYPE == 'z'):
            #-- read constituent from elevation file
            z,con = read_elevation_file(model_file, GZIP=GZIP)
            #-- append constituent to list
            constituents.append(con)
            #-- replace original values with extend matrices
            z = extend_matrix(z)
            #-- update constituent mask with bathymetry mask
            z.mask[:] |= bathymetry.mask[:]
            #-- interpolate amplitude and phase of the constituent
            z1 = np.ma.zeros((npts),dtype=z.dtype)
            z1.mask = np.zeros((npts),dtype=bool)
            if (METHOD == 'bilinear'):
                #-- replace invalid values with nan
                z[z.mask] = np.nan
                z1.data[:] = bilinear_interp(lon,lat,z,ilon,ilat,dtype=z.dtype)
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            elif (METHOD == 'spline'):
                f1 = scipy.interpolate.RectBivariateSpline(lon,lat,
                    z.data.real.T,kx=1,ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(lon,lat,
                    z.data.imag.T,kx=1,ky=1)
                z1.data.real = f1.ev(ilon,ilat)
                z1.data.imag = f2.ev(ilon,ilat)
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator((lat,lon),
                    z.data, method=METHOD, bounds_error=False,
                    fill_value=z1.fill_value)
                z1.data[:] = r1.__call__(np.c_[ilat,ilon])
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            #-- extrapolate data using nearest-neighbors
            if EXTRAPOLATE and np.any(z1.mask):
                #-- find invalid data points
                inv, = np.nonzero(z1.mask)
                #-- replace invalid values with nan
                z[z.mask] = np.nan
                #-- extrapolate points within cutoff of valid model points
                z1[inv] = nearest_extrap(lon,lat,z,ilon[inv],ilat[inv],
                    dtype=z.dtype,cutoff=CUTOFF)
            #-- amplitude and phase of the constituent
            ampl.data[:,i] = np.abs(z1.data)
            ampl.mask[:,i] = np.copy(z1.mask)
            ph.data[:,i] = np.arctan2(-np.imag(z1.data),np.real(z1.data))
            ph.mask[:,i] = np.copy(z1.mask)
        elif TYPE in ('U','u','V','v'):
            #-- read constituent from transport file
            tr,con = read_transport_file(model_file, TYPE, GZIP=GZIP)
            #-- append constituent to list
            constituents.append(con)
            #-- replace original values with extend matrices
            tr = extend_matrix(tr)
            #-- update constituent mask with bathymetry mask
            tr.mask[:] |= bathymetry.mask[:]
            #-- interpolate amplitude and phase of the constituent
            tr1 = np.ma.zeros((npts),dtype=tr.dtype)
            tr1.mask = np.zeros((npts),dtype=bool)
            if (METHOD == 'bilinear'):
                tr1.data[:]=bilinear_interp(lon,lat,tr,ilon,ilat,dtype=tr.dtype)
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = tr1.fill_value
            elif (METHOD == 'spline'):
                f1 = scipy.interpolate.RectBivariateSpline(lon,lat,
                    tr.data.real.T,kx=1,ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(lon,lat,
                    tr.data.imag.T,kx=1,ky=1)
                tr1.data.real = f1.ev(ilon,ilat)
                tr1.data.imag = f2.ev(ilon,ilat)
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = z1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator((lat,lon),
                    tr.data, method=METHOD, bounds_error=False,
                    fill_value=tr1.fill_value)
                tr1.data[:] = r1.__call__(np.c_[ilat,ilon])
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = tr1.fill_value
            #-- extrapolate data using nearest-neighbors
            if EXTRAPOLATE and np.any(tr1.mask):
                #-- find invalid data points
                inv, = np.nonzero(tr1.mask)
                #-- replace invalid values with nan
                tr[tr.mask] = np.nan
                #-- extrapolate points within cutoff of valid model points
                tr1[inv] = nearest_extrap(lon,lat,tr,ilon[inv],ilat[inv],
                    dtype=tr.dtype,cutoff=CUTOFF)
            #-- convert units
            #-- amplitude and phase of the constituent
            ampl.data[:,i] = np.abs(tr1.data)/unit_conv
            ampl.mask[:,i] = np.copy(tr1.mask)
            ph.data[:,i] = np.arctan2(-np.imag(tr1.data),np.real(tr1.data))
            ph.mask[:,i] = np.copy(tr1.mask)

    #-- convert amplitude from input units to meters
    amplitude = ampl*SCALE
    #-- convert phase to degrees
    phase = ph*180.0/np.pi
    phase[phase < 0] += 360.0
    #-- return the interpolated values
    return (amplitude,phase,D,constituents)
Пример #8
0
def extract_netcdf_constants(ilon,
                             ilat,
                             grid_file,
                             model_files,
                             TYPE='z',
                             METHOD='spline',
                             EXTRAPOLATE=False,
                             GZIP=True,
                             SCALE=1.0):
    """
    Reads files for a netCDF4 tidal model
    Makes initial calculations to run the tide program
    Spatially interpolates tidal constituents to input coordinates

    Arguments
    ---------
    ilon: longitude to interpolate
    ilat: latitude to interpolate
    grid_file: grid file for model (can be gzipped)
    model_files: list of model files for each constituent (can be gzipped)

    Keyword arguments
    -----------------
    TYPE: tidal variable to read
        z: heights
        u: horizontal transport velocities
        U: horizontal depth-averaged transport
        v: vertical transport velocities
        V: vertical depth-averaged transport
    METHOD: interpolation method
        bilinear: quick bilinear interpolation
        spline: scipy bivariate spline interpolation
        linear, nearest: scipy regular grid interpolations
    EXTRAPOLATE: extrapolate model using nearest-neighbors
    GZIP: input netCDF4 files are compressed
    SCALE: scaling factor for converting to output units

    Returns
    -------
    amplitude: amplitudes of tidal constituents
    phase: phases of tidal constituents
    D: bathymetry of tide model
    constituents: list of model constituents
    """

    #-- read the tide grid file for bathymetry and spatial coordinates
    lon, lat, bathymetry = read_netcdf_grid(grid_file, TYPE, GZIP=GZIP)
    #-- grid step size of tide model
    dlon = lon[1] - lon[0]
    dlat = lat[1] - lat[0]
    #-- replace original values with extend arrays/matrices
    lon = extend_array(lon, dlon)
    bathymetry = extend_matrix(bathymetry)
    #-- create masks
    bathymetry.mask = (bathymetry.data == 0)

    #-- adjust dimensions of input coordinates to be iterable
    ilon = np.atleast_1d(ilon)
    ilat = np.atleast_1d(ilat)
    #-- adjust longitudinal convention of input latitude and longitude
    #-- to fit tide model convention
    lt0, = np.nonzero(ilon < 0)
    ilon[lt0] += 360.0
    #-- number of points
    npts = len(ilon)

    #-- interpolate bathymetry and mask to output points
    D = np.ma.zeros((npts))
    D.mask = np.zeros((npts), dtype=bool)
    if (METHOD == 'bilinear'):
        #-- replace invalid values with nan
        bathymetry[bathymetry.mask] = np.nan
        #-- use quick bilinear to interpolate values
        D.data[:] = bilinear_interp(lon, lat, bathymetry, ilon, ilat)
        #-- replace nan values with fill_value
        D.mask[:] = np.isnan(D.data)
        D.data[D.mask] = D.fill_value
    elif (METHOD == 'spline'):
        #-- use scipy bivariate splines to interpolate values
        f1 = scipy.interpolate.RectBivariateSpline(lon,
                                                   lat,
                                                   bathymetry.data.T,
                                                   kx=1,
                                                   ky=1)
        f2 = scipy.interpolate.RectBivariateSpline(lon,
                                                   lat,
                                                   bathymetry.mask.T,
                                                   kx=1,
                                                   ky=1)
        D.data[:] = f1.ev(ilon, ilat)
        D.mask[:] = np.ceil(f2.ev(ilon, ilat).astype(bool))
    else:
        #-- use scipy regular grid to interpolate values for a given method
        r1 = scipy.interpolate.RegularGridInterpolator((lat, lon),
                                                       bathymetry.data,
                                                       method=METHOD,
                                                       bounds_error=False)
        r2 = scipy.interpolate.RegularGridInterpolator((lat, lon),
                                                       bathymetry.mask,
                                                       method=METHOD,
                                                       bounds_error=False,
                                                       fill_value=1)
        D.data[:] = r1.__call__(np.c_[ilat, ilon])
        D.mask[:] = np.ceil(r2.__call__(np.c_[ilat, ilon])).astype(bool)

    #-- u and v are velocities in cm/s
    if TYPE in ('v', 'u'):
        unit_conv = (D.data / 100.0)
    #-- U and V are transports in m^2/s
    elif TYPE in ('V', 'U'):
        unit_conv = 1.0

    #-- number of constituents
    nc = len(model_files)
    #-- list of constituents
    constituents = []
    #-- amplitude and phase
    ampl = np.ma.zeros((npts, nc))
    ampl.mask = np.zeros((npts, nc), dtype=bool)
    ph = np.ma.zeros((npts, nc))
    ph.mask = np.zeros((npts, nc), dtype=bool)
    #-- read and interpolate each constituent
    for i, model_file in enumerate(model_files):
        if (TYPE == 'z'):
            #-- read constituent from elevation file
            z, con = read_elevation_file(model_file, GZIP=GZIP)
            #-- append constituent to list
            constituents.append(con)
            #-- replace original values with extend matrices
            z = extend_matrix(z)
            #-- interpolate amplitude and phase of the constituent
            z1 = np.ma.zeros((npts), dtype=z.dtype)
            z1.mask = np.zeros((npts), dtype=bool)
            if (METHOD == 'bilinear'):
                #-- replace invalid values with nan
                z[z.mask] = np.nan
                z1.data[:] = bilinear_interp(lon,
                                             lat,
                                             z,
                                             ilon,
                                             ilat,
                                             dtype=z.dtype)
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            elif (METHOD == 'spline'):
                f1 = scipy.interpolate.RectBivariateSpline(lon,
                                                           lat,
                                                           z.data.real.T,
                                                           kx=1,
                                                           ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(lon,
                                                           lat,
                                                           z.data.imag.T,
                                                           kx=1,
                                                           ky=1)
                z1.data.real = f1.ev(ilon, ilat)
                z1.data.imag = f2.ev(ilon, ilat)
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator(
                    (lat, lon),
                    z.data,
                    method=METHOD,
                    bounds_error=False,
                    fill_value=z1.fill_value)
                z1.data[:] = r1.__call__(np.c_[ilat, ilon])
                #-- mask invalid values
                z1.mask[:] |= np.copy(D.mask)
                z1.data[z1.mask] = z1.fill_value
            #-- extrapolate data using nearest-neighbors
            if EXTRAPOLATE and np.any(z1.mask):
                #-- find invalid data points
                inv, = np.nonzero(z1.mask)
                #-- replace invalid values with nan
                z[z.mask] = np.nan
                #-- extrapolate points within 10km of valid model points
                z1.data[inv] = nearest_extrap(lon,
                                              lat,
                                              z,
                                              ilon[inv],
                                              ilat[inv],
                                              dtype=z.dtype,
                                              cutoff=10.0)
                #-- replace nan values with fill_value
                z1.mask[inv] = np.isnan(z1.data[inv])
                z1.data[z1.mask] = z1.fill_value
            #-- amplitude and phase of the constituent
            ampl.data[:, i] = np.abs(z1.data)
            ampl.mask[:, i] = np.copy(z1.mask)
            ph.data[:, i] = np.arctan2(-np.imag(z1.data), np.real(z1.data))
            ph.mask[:, i] = np.copy(z1.mask)
        elif TYPE in ('U', 'u', 'V', 'v'):
            #-- read constituent from transport file
            tr, con = read_transport_file(model_file, TYPE, GZIP=GZIP)
            #-- append constituent to list
            constituents.append(con)
            #-- replace original values with extend matrices
            tr = extend_matrix(tr)
            #-- interpolate amplitude and phase of the constituent
            tr1 = np.ma.zeros((npts), dtype=tr.dtype)
            tr1.mask = np.zeros((npts), dtype=bool)
            if (METHOD == 'bilinear'):
                tr1.data[:] = bilinear_interp(lon,
                                              lat,
                                              tr,
                                              ilon,
                                              ilat,
                                              dtype=tr.dtype)
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = tr1.fill_value
            elif (METHOD == 'spline'):
                f1 = scipy.interpolate.RectBivariateSpline(lon,
                                                           lat,
                                                           tr.data.real.T,
                                                           kx=1,
                                                           ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(lon,
                                                           lat,
                                                           tr.data.imag.T,
                                                           kx=1,
                                                           ky=1)
                tr1.data.real = f1.ev(ilon, ilat)
                tr1.data.imag = f2.ev(ilon, ilat)
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = z1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator(
                    (lat, lon),
                    tr.data,
                    method=METHOD,
                    bounds_error=False,
                    fill_value=tr1.fill_value)
                tr1.data[:] = r1.__call__(np.c_[ilat, ilon])
                #-- mask invalid values
                tr1.mask[:] |= np.copy(D.mask)
                tr1.data[tr1.mask] = tr1.fill_value
            #-- extrapolate data using nearest-neighbors
            if EXTRAPOLATE and np.any(tr1.mask):
                #-- find invalid data points
                inv, = np.nonzero(tr1.mask)
                #-- replace invalid values with nan
                tr[tr.mask] = np.nan
                #-- extrapolate points within 10km of valid model points
                tr1.data[inv] = nearest_extrap(lon,
                                               lat,
                                               tr,
                                               ilon[inv],
                                               ilat[inv],
                                               dtype=tr.dtype,
                                               cutoff=10.0)
                #-- replace nan values with fill_value
                tr1.mask[inv] = np.isnan(tr1.data[inv])
                tr1.data[tr1.mask] = tr1.fill_value
            #-- convert units
            #-- amplitude and phase of the constituent
            ampl.data[:, i] = np.abs(tr1.data) / unit_conv
            ampl.mask[:, i] = np.copy(tr1.mask)
            ph.data[:, i] = np.arctan2(-np.imag(tr1.data), np.real(tr1.data))
            ph.mask[:, i] = np.copy(tr1.mask)

    #-- convert amplitude from input units to meters
    amplitude = ampl * SCALE
    #-- convert phase to degrees
    phase = ph * 180.0 / np.pi
    phase[phase < 0] += 360.0
    #-- return the interpolated values
    return (amplitude, phase, D, constituents)
Пример #9
0
def extract_tidal_constants(ilon,
                            ilat,
                            grid_file,
                            model_file,
                            EPSG,
                            TYPE='z',
                            METHOD='spline',
                            GRID='OTIS'):
    """
    Reads files for an OTIS-formatted tidal model
    Makes initial calculations to run the tide program
    Spatially interpolates tidal constituents to input coordinates

    Arguments
    ---------
    ilon: longitude to interpolate
    ilat: latitude to interpolate
    grid_file: grid file for model
    model_file: model file containing each constituent
    EPSG: projection of tide model data
    TYPE: tidal variable to run
        z: heights
        u: horizontal transport velocities
        v: vertical transport velocities

    Keyword arguments
    -----------------
    METHOD: interpolation method
        bilinear: quick bilinear interpolation
        spline: scipy bivariate spline interpolation
        linear, nearest: scipy regular grid interpolations
    GRID: binary file type to read
        ATLAS: reading a global solution with localized solutions
        OTIS: combined global solution

    Returns
    -------
    amplitude: amplitudes of tidal constituents
    phase: phases of tidal constituents
    D: bathymetry of tide model
    constituents: list of model constituents
    """
    #-- read the OTIS-format tide grid file
    if (GRID == 'ATLAS'):
        #-- if reading a global solution with localized solutions
        x0, y0, hz0, mz0, iob, dt, pmask, local = read_atlas_grid(grid_file)
        xi, yi, hz = combine_atlas_model(x0,
                                         y0,
                                         hz0,
                                         pmask,
                                         local,
                                         VARIABLE='depth')
        mz = create_atlas_mask(x0, y0, mz0, local, VARIABLE='depth')
    else:
        #-- if reading a single OTIS solution
        xi, yi, hz, mz, iob, dt = read_tide_grid(grid_file)
    #-- adjust dimensions of input coordinates to be iterable
    #-- run wrapper function to convert coordinate systems of input lat/lon
    x, y = convert_ll_xy(np.atleast_1d(ilon), np.atleast_1d(ilat), EPSG, 'F')
    invalid = (x < xi.min()) | (x > xi.max()) | (y < yi.min()) | (y > yi.max())
    #-- grid step size of tide model
    dx = xi[1] - xi[0]
    dy = yi[1] - yi[0]

    if (TYPE != 'z'):
        mz, mu, mv = Muv(hz)
        hu, hv = Huv(hz)

    #-- if global: extend limits
    GLOBAL = False
    #-- replace original values with extend arrays/matrices
    if ((xi[-1] - xi[0]) == (360.0 - dx)) & (EPSG == '4326'):
        xi = extend_array(xi, dx)
        hz = extend_matrix(hz)
        mz = extend_matrix(mz)
        #-- set global flag
        GLOBAL = True

    #-- adjust longitudinal convention of input latitude and longitude
    #-- to fit tide model convention
    if (np.min(x) < np.min(xi)) & (EPSG == '4326'):
        lt0, = np.nonzero(x < 0)
        x[lt0] += 360.0
    if (np.max(x) > np.max(xi)) & (EPSG == '4326'):
        gt180, = np.nonzero(x > 180)
        x[gt180] -= 360.0

    #-- masks zero values
    hz = np.ma.array(hz, mask=(hz == 0))
    if (TYPE != 'z'):
        #-- replace original values with extend matrices
        if GLOBAL:
            hu = extend_matrix(hu)
            hv = extend_matrix(hv)
            mu = extend_matrix(mu)
            mv = extend_matrix(mv)
        #-- masks zero values
        hu = np.ma.array(hu, mask=(hu == 0))
        hv = np.ma.array(hv, mask=(hv == 0))

    #-- interpolate depth and mask to output points
    if (METHOD == 'bilinear'):
        #-- use quick bilinear to interpolate values
        D = bilinear_interp(xi, yi, hz, x, y)
        mz1 = bilinear_interp(xi, yi, mz, x, y)
        mz1 = np.ceil(mz1).astype(mz.dtype)
        if (TYPE != 'z'):
            mu1 = bilinear_interp(xi, yi, mu, x, y)
            mu1 = np.ceil(mu1).astype(mu.dtype)
            mv1 = bilinear_interp(xi, yi, mv, x, y)
            mv1 = np.ceil(mv1).astype(mz.dtype)
    elif (METHOD == 'spline'):
        #-- use scipy bivariate splines to interpolate values
        f1 = scipy.interpolate.RectBivariateSpline(xi, yi, hz.T, kx=1, ky=1)
        f2 = scipy.interpolate.RectBivariateSpline(xi, yi, mz.T, kx=1, ky=1)
        D = f1.ev(x, y)
        mz1 = np.ceil(f2.ev(x, y)).astype(mz.dtype)
        if (TYPE != 'z'):
            f3 = scipy.interpolate.RectBivariateSpline(xi,
                                                       yi,
                                                       mu.T,
                                                       kx=1,
                                                       ky=1)
            f4 = scipy.interpolate.RectBivariateSpline(xi,
                                                       yi,
                                                       mv.T,
                                                       kx=1,
                                                       ky=1)
            mu1 = np.ceil(f3.ev(x, y)).astype(mu.dtype)
            mv1 = np.ceil(f4.ev(x, y)).astype(mv.dtype)
    else:
        #-- use scipy regular grid to interpolate values for a given method
        r1 = scipy.interpolate.RegularGridInterpolator((yi, xi),
                                                       hz,
                                                       method=METHOD,
                                                       bounds_error=False)
        r2 = scipy.interpolate.RegularGridInterpolator((yi, xi),
                                                       mz,
                                                       method=METHOD,
                                                       bounds_error=False,
                                                       fill_value=0)
        D = r1.__call__(np.c_[y, x])
        mz1 = np.ceil(r2.__call__(np.c_[y, x])).astype(mz.dtype)
        if (TYPE != 'z'):
            r3 = scipy.interpolate.RegularGridInterpolator((yi, xi),
                                                           mu,
                                                           method=METHOD,
                                                           bounds_error=False,
                                                           fill_value=0)
            r4 = scipy.interpolate.RegularGridInterpolator((yi, xi),
                                                           mv,
                                                           method=METHOD,
                                                           bounds_error=False,
                                                           fill_value=0)
            mu1 = np.ceil(r3.__call__(np.c_[y, x])).astype(mu.dtype)
            mv1 = np.ceil(r4.__call__(np.c_[y, x])).astype(mv.dtype)

    #-- u and v are velocities in cm/s
    if TYPE in ('v', 'u'):
        unit_conv = (D / 100.0)
    #-- U and V are transports in m^2/s
    elif TYPE in ('V', 'U'):
        unit_conv = 1.0

    #-- read and interpolate each constituent
    constituents, nc = read_constituents(model_file)
    npts = len(D)
    amplitude = np.ma.zeros((npts, nc))
    amplitude.mask = np.zeros((npts, nc), dtype=np.bool)
    ph = np.ma.zeros((npts, nc))
    ph.mask = np.zeros((npts, nc), dtype=np.bool)
    for i, c in enumerate(constituents):
        if (TYPE == 'z'):
            #-- read constituent from elevation file
            if (GRID == 'ATLAS'):
                z0, zlocal = read_atlas_elevation(model_file, i, c)
                xi, yi, z = combine_atlas_model(x0,
                                                y0,
                                                z0,
                                                pmask,
                                                zlocal,
                                                VARIABLE='z')
            else:
                z = read_elevation_file(model_file, i)
            #-- replace original values with extend matrices
            if GLOBAL:
                z = extend_matrix(z)
            #-- interpolate amplitude and phase of the constituent
            z1 = np.ma.zeros((npts), dtype=z.dtype)
            if (METHOD == 'bilinear'):
                #-- replace zero values with nan
                z[z == 0] = np.nan
                #-- use quick bilinear to interpolate values
                z1.data[:] = bilinear_interp(xi,
                                             yi,
                                             z,
                                             x,
                                             y,
                                             dtype=np.complex128)
                #-- replace nan values with fill_value
                z1.mask = (np.isnan(z1.data) | (~mz1.astype(np.bool)))
                z1.data[z1.mask] = z1.fill_value
            elif (METHOD == 'spline'):
                #-- use scipy bivariate splines to interpolate values
                f1 = scipy.interpolate.RectBivariateSpline(xi,
                                                           yi,
                                                           z.real.T,
                                                           kx=1,
                                                           ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(xi,
                                                           yi,
                                                           z.imag.T,
                                                           kx=1,
                                                           ky=1)
                z1.data.real = f1.ev(x, y)
                z1.data.imag = f2.ev(x, y)
                #-- replace zero values with fill_value
                z1.mask = (~mz1.astype(np.bool))
                z1.data[z1.mask] = z1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator(
                    (yi, xi),
                    z,
                    method=METHOD,
                    bounds_error=False,
                    fill_value=z1.fill_value)
                z1 = np.ma.zeros((npts), dtype=z.dtype)
                z1.data[:] = r1.__call__(np.c_[y, x])
                #-- replace invalid values with fill_value
                z1.mask = (z1.data == z1.fill_value) | (~mz1.astype(np.bool))
                z1.data[z1.mask] = z1.fill_value
            #-- amplitude and phase of the constituent
            amplitude.data[:, i] = np.abs(z1.data)
            amplitude.mask[:, i] = np.copy(z1.mask)
            ph.data[:, i] = np.arctan2(-np.imag(z1.data), np.real(z1.data))
            ph.mask[:, i] = np.copy(z1.mask)
        elif TYPE in ('U', 'u'):
            #-- read constituent from transport file
            if (GRID == 'ATLAS'):
                u0, v0, uvlocal = read_atlas_transport(model_file, i, c)
                xi, yi, u = combine_atlas_model(x0,
                                                y0,
                                                u0,
                                                pmask,
                                                uvlocal,
                                                VARIABLE='u')
            else:
                u, v = read_transport_file(model_file, i)
            #-- replace original values with extend matrices
            if GLOBAL:
                u = extend_matrix(u)
            #-- x coordinates for u transports
            xu = xi - dx / 2.0
            #-- interpolate amplitude and phase of the constituent
            u1 = np.ma.zeros((npts), dtype=u.dtype)
            if (METHOD == 'bilinear'):
                #-- replace zero values with nan
                u[u == 0] = np.nan
                #-- use quick bilinear to interpolate values
                u1.data[:] = bilinear_interp(xu,
                                             yi,
                                             u,
                                             x,
                                             y,
                                             dtype=np.complex128)
                #-- replace nan values with fill_value
                u1.mask = (np.isnan(u1.data) | (~mu1.astype(np.bool)))
                u1.data[u1.mask] = u1.fill_value
            elif (METHOD == 'spline'):
                f1 = scipy.interpolate.RectBivariateSpline(xu,
                                                           yi,
                                                           u.real.T,
                                                           kx=1,
                                                           ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(xu,
                                                           yi,
                                                           u.imag.T,
                                                           kx=1,
                                                           ky=1)
                u1.data.real = f1.ev(x, y)
                u1.data.imag = f2.ev(x, y)
                #-- replace zero values with fill_value
                u1.mask = (~mu1.astype(np.bool))
                u1.data[u1.mask] = u1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator(
                    (yi, xu),
                    u,
                    method=METHOD,
                    bounds_error=False,
                    fill_value=u1.fill_value)
                u1.data[:] = r1.__call__(np.c_[y, x])
                #-- replace invalid values with fill_value
                u1.mask = (u1.data == u1.fill_value) | (~mu1.astype(np.bool))
                u1.data[u1.mask] = u1.fill_value
            #-- convert units
            u1 = u1 / unit_conv
            #-- amplitude and phase of the constituent
            amplitude.data[:, i] = np.abs(u1)
            amplitude.mask[:, i] = np.copy(u1.mask)
            ph.data[:, i] = np.arctan2(-np.imag(u1), np.real(u1))
            ph.mask[:, i] = np.copy(u1.mask)
        elif TYPE in ('V', 'v'):
            #-- read constituent from transport file
            if (GRID == 'ATLAS'):
                u0, v0, uvlocal = read_atlas_transport(model_file, i, c)
                xi, yi, v = combine_atlas_model(x0,
                                                y0,
                                                v0,
                                                pmask,
                                                local,
                                                VARIABLE='v')
            else:
                u, v = read_transport_file(model_file, i)
            #-- replace original values with extend matrices
            if GLOBAL:
                v = extend_matrix(v)
            #-- y coordinates for v transports
            yv = yi - dy / 2.0
            #-- interpolate amplitude and phase of the constituent
            v1 = np.ma.zeros((npts), dtype=v.dtype)
            if (METHOD == 'bilinear'):
                #-- replace zero values with nan
                v[v == 0] = np.nan
                #-- use quick bilinear to interpolate values
                v1.data = bilinear_interp(xi, yv, v, x, y, dtype=np.complex128)
                #-- replace nan values with fill_value
                v1.mask = (np.isnan(v1.data) | (~mv1.astype(np.bool)))
                v1.data[v1.mask] = v1.fill_value
            elif (METHOD == 'spline'):
                f1 = scipy.interpolate.RectBivariateSpline(xi,
                                                           yv,
                                                           v.real.T,
                                                           kx=1,
                                                           ky=1)
                f2 = scipy.interpolate.RectBivariateSpline(xi,
                                                           yv,
                                                           v.imag.T,
                                                           kx=1,
                                                           ky=1)
                v1.data.real = f1.ev(x, y)
                v1.data.imag = f2.ev(x, y)
                #-- replace zero values with fill_value
                v1.mask = (~mv1.astype(np.bool))
                v1.data[v1.mask] = v1.fill_value
            else:
                #-- use scipy regular grid to interpolate values
                r1 = scipy.interpolate.RegularGridInterpolator(
                    (yv, xi),
                    v,
                    method=METHOD,
                    bounds_error=False,
                    fill_value=v1.fill_value)
                v1.data[:] = r1.__call__(np.c_[y, x])
                #-- replace invalid values with fill_value
                v1.mask = (v1.data == v1.fill_value) | (~mv1.astype(np.bool))
                v1.data[v1.mask] = v1.fill_value
            #-- convert units
            v1 = v1 / unit_conv
            #-- amplitude and phase of the constituent
            amplitude.data[:, i] = np.abs(v1)
            amplitude.mask[:, i] = np.copy(v1.mask)
            ph.data[:, i] = np.arctan2(-np.imag(v1), np.real(v1))
            ph.mask[:, i] = np.copy(v1.mask)
        #-- update mask to invalidate points outside model domain
        ph.mask[:, i] |= invalid
        amplitude.mask[:, i] |= invalid

    #-- convert phase to degrees
    phase = ph * 180.0 / np.pi
    phase.data[phase.data < 0] += 360.0
    #-- replace data for invalid mask values
    amplitude.data[amplitude.mask] = amplitude.fill_value
    phase.data[phase.mask] = phase.fill_value
    #-- return the interpolated values
    return (amplitude, phase, D, constituents)
Пример #10
0
def extract_GOT_constants(ilon,
                          ilat,
                          model_files,
                          METHOD=None,
                          EXTRAPOLATE=False,
                          CUTOFF=10.0,
                          GZIP=True,
                          SCALE=1.0):
    """
    Reads files for Richard Ray's Global Ocean Tide (GOT) models

    Makes initial calculations to run the tide program

    Spatially interpolates tidal constituents to input coordinates

    Parameters
    ----------
    ilon: float
        longitude to interpolate
    ilat: float
        latitude to interpolate
    model_files: list
        list of model files for each constituent
    METHOD: str, default 'spline'
        Interpolation method

            - ``'bilinear'``: quick bilinear interpolation
            - ``'spline'``: scipy bivariate spline interpolation
            - ``'linear'``, ``'nearest'``: scipy regular grid interpolations
    EXTRAPOLATE: bool, default False
        Extrapolate model using nearest-neighbors
    CUTOFF: float, default 10.0
        Extrapolation cutoff in kilometers

        Set to np.inf to extrapolate for all points
    GZIP: bool, default False
        Input files are compressed
    SCALE: float, default 1.0
        Scaling factor for converting to output units

    Returns
    -------
    amplitude: float
        amplitudes of tidal constituents
    phase: float
        phases of tidal constituents
    constituents: list
        list of model constituents
    """

    #-- raise warning if model files are entered as a string
    if isinstance(model_files, str):
        warnings.warn("Tide model is entered as a string")
        model_files = [model_files]

    #-- adjust dimensions of input coordinates to be iterable
    ilon = np.atleast_1d(ilon)
    ilat = np.atleast_1d(ilat)
    #-- number of points
    npts = len(ilon)
    #-- number of constituents
    nc = len(model_files)
    constituents = []

    #-- amplitude and phase
    amplitude = np.ma.zeros((npts, nc))
    amplitude.mask = np.zeros((npts, nc), dtype=bool)
    ph = np.ma.zeros((npts, nc))
    ph.mask = np.zeros((npts, nc), dtype=bool)
    #-- read and interpolate each constituent
    for i, model_file in enumerate(model_files):
        #-- check that model file is accessible
        if not os.access(os.path.expanduser(model_file), os.F_OK):
            raise FileNotFoundError(os.path.expanduser(model_file))
        #-- read constituent from elevation file
        hc, lon, lat, cons = read_GOT_grid(os.path.expanduser(model_file),
                                           GZIP=GZIP)
        #-- append to the list of constituents
        constituents.append(cons)
        #-- adjust longitudinal convention of input latitude and longitude
        #-- to fit tide model convention
        if (np.min(ilon) < 0.0) & (np.max(lon) > 180.0):
            #-- input points convention (-180:180)
            #-- tide model convention (0:360)
            ilon[ilon < 0.0] += 360.0
        elif (np.max(ilon) > 180.0) & (np.min(lon) < 0.0):
            #-- input points convention (0:360)
            #-- tide model convention (-180:180)
            ilon[ilon > 180.0] -= 360.0
        #-- grid step size of tide model
        dlon = np.abs(lon[1] - lon[0])
        dlat = np.abs(lat[1] - lat[0])
        #-- replace original values with extend matrices
        lon = extend_array(lon, dlon)
        hc = extend_matrix(hc)
        #-- interpolated complex form of constituent oscillation
        hci = np.ma.zeros((npts), dtype=hc.dtype, fill_value=hc.fill_value)
        hci.mask = np.zeros((npts), dtype=bool)
        #-- interpolate amplitude and phase of the constituent
        if (METHOD == 'bilinear'):
            #-- replace invalid values with nan
            hc[hc.mask] = np.nan
            #-- use quick bilinear to interpolate values
            hci.data[:] = bilinear_interp(lon,
                                          lat,
                                          hc,
                                          ilon,
                                          ilat,
                                          dtype=hc.dtype)
            #-- replace nan values with fill_value
            hci.mask[:] |= np.isnan(hci.data)
            hci.data[hci.mask] = hci.fill_value
        elif (METHOD == 'spline'):
            #-- interpolate complex form of the constituent with scipy
            f1 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.data.real.T,
                                                       kx=1,
                                                       ky=1)
            f2 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.data.imag.T,
                                                       kx=1,
                                                       ky=1)
            f3 = scipy.interpolate.RectBivariateSpline(lon,
                                                       lat,
                                                       hc.mask.T,
                                                       kx=1,
                                                       ky=1)
            hci.data.real[:] = f1.ev(ilon, ilat)
            hci.data.imag[:] = f2.ev(ilon, ilat)
            hci.mask[:] = f3.ev(ilon, ilat).astype(bool)
            #-- replace invalid values with fill_value
            hci.data[hci.mask] = hci.fill_value
        else:
            #-- use scipy regular grid to interpolate values for a given method
            r1 = scipy.interpolate.RegularGridInterpolator(
                (lat, lon),
                hc.data,
                method=METHOD,
                bounds_error=False,
                fill_value=hci.fill_value)
            r2 = scipy.interpolate.RegularGridInterpolator((lat, lon),
                                                           hc.mask,
                                                           method=METHOD,
                                                           bounds_error=False,
                                                           fill_value=1)
            hci.data[:] = r1.__call__(np.c_[ilat, ilon])
            hci.mask[:] = np.ceil(r2.__call__(np.c_[ilat, ilon])).astype(bool)
            #-- replace invalid values with fill_value
            hci.mask[:] |= (hci.data == hci.fill_value)
            hci.data[hci.mask] = hci.fill_value
        #-- extrapolate data using nearest-neighbors
        if EXTRAPOLATE and np.any(hci.mask):
            #-- find invalid data points
            inv, = np.nonzero(hci.mask)
            #-- replace invalid values with nan
            hc[hc.mask] = np.nan
            #-- extrapolate points within cutoff of valid model points
            hci[inv] = nearest_extrap(lon,
                                      lat,
                                      hc,
                                      ilon[inv],
                                      ilat[inv],
                                      dtype=hc.dtype,
                                      cutoff=CUTOFF)
        #-- convert amplitude from input units to meters
        amplitude.data[:, i] = np.abs(hci.data) * SCALE
        amplitude.mask[:, i] = np.copy(hci.mask)
        #-- phase of the constituent in radians
        ph.data[:, i] = np.arctan2(-np.imag(hci.data), np.real(hci.data))
        ph.mask[:, i] = np.copy(hci.mask)

    #-- convert phase to degrees
    phase = ph * 180.0 / np.pi
    phase.data[phase.data < 0] += 360.0
    #-- replace data for invalid mask values
    amplitude.data[amplitude.mask] = amplitude.fill_value
    phase.data[phase.mask] = phase.fill_value
    #-- return the interpolated values
    return (amplitude, phase, constituents)