Example #1
0
def write_bathy(outfld, lon, lat, depth, spherical=True):
    '''
    Function to generate bathymetry files to be used as input for WW3 v4.18
    
    PARAMETERS:
    -----------
    outfld        : folder to write the files to
    lon           : longitudes (or x for cartesian) at every grid point 
                    (I assume they have been meshgridded)
    lat           : latitudes (or y for cartesian) at every grid point
    spherical     : True for spherical grids and False for cartesian grids    
    
    OUTPUT:
    -------
    ww3_grid.bot  : ASCII file containing the grid depths
    ww3_grid.lon  : ASCII file containing the longitudes (or x locations)
    ww3_grid.lat  : ASCII file containing the latitudes (or y locations)
    ww3_grid.nc   : NetCDF file containing the grid information
    ww3_grid.inp  : Input file template to be used for the grid preprocessor. 
                    You will need to fix many things it will probably not
                    work out of the box. 
    
    NOTES:   
    ------
    I assume that if the grid is in spherical coordiantes the latitude and 
        longitudes are given in decimal degrees (east). On the other hand if the 
        grid is cartesian I assume meters.
    
    '''

    # Convert longitudes to degrees east
    lon = gangles.wrapto360(lon)

    # Write ascii files --------------------------------------------------------
    # Bathymetry
    fid = open(outfld + 'ww3_grid.bot', 'w')
    for aa in range(depth.shape[0]):
        for bb in range(depth.shape[1]):
            fid.write('%12.4f' % depth[aa, bb])
        fid.write('\n')
    fid.close()

    # Latitude File
    fid = open(outfld + 'ww3_grid.lat', 'w')
    for aa in range(lat.shape[0]):
        for bb in range(lat.shape[1]):
            fid.write('%12.4f' % lat[aa, bb])
        fid.write('\n')
    fid.close()

    # Longitude File
    fid = open(outfld + 'ww3_grid.lon', 'w')
    for aa in range(lon.shape[0]):
        for bb in range(lon.shape[1]):
            fid.write('%12.4f' % lon[aa, bb])
        fid.write('\n')
    fid.close()

    # Write netcdf file --------------------------------------------------------

    # Global attributes
    nc = netCDF4.Dataset(outfld + 'ww3_grid.nc', 'w', format='NETCDF4')
    nc.Description = 'Wavewatch III Bathymetry'
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    nc.Owner = 'Nearshore Modeling Group (http://ozkan.oce.orst.edu/nmg)'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Script = os.path.realpath(__file__)

    # Create dimensions
    nc.createDimension('xi_rho', lon.shape[1])
    nc.createDimension('eta_rho', lon.shape[0])

    # Write coordinates and depth to netcdf file
    if spherical:
        nc.createVariable('lat_rho', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['lat_rho'].units = 'degree_north'
        nc.variables['lat_rho'].long_name = 'latitude of RHO-points'
        nc.variables['lat_rho'][:] = lat
    else:
        nc.createVariable('y_rho', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['y_rho'].units = 'meter'
        nc.variables['y_rho'].long_name = 'y location of RHO-points'
        nc.variables['y_rho'][:] = lat

    # Write longitude
    if spherical:
        nc.createVariable('lon_rho', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['lon_rho'].units = 'degree_east'
        nc.variables['lon_rho'].long_name = 'latitude of RHO-points'
        nc.variables['lon_rho'][:] = lon
    else:
        nc.createVariable('x_rho', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].long_name = 'x location of RHO-points'
        nc.variables['x_rho'][:] = lon

    # Write water depth
    nc.createVariable('h', 'f8', ('eta_rho', 'xi_rho'))
    nc.variables['h'].units = 'meter'
    nc.variables['h'].long_name = 'bathymetry at RHO-points'
    nc.variables['h'][:] = depth

    # Close NetCDF file
    nc.close()

    # Write input file for grid preprocessor ----------------------------------

    # Create a generic input file
    fid = open(outfld + 'ww3_grid.inp', 'w')

    fid.write(
        '$ ----------------------------------------------------------$\n')
    fid.write(
        '$ WAVEWATCH III Grid preprocessor input file                $\n')
    fid.write(
        '$ ----------------------------------------------------------$\n')
    fid.write('\'Grid Name\'\n')
    fid.write('$\n')
    fid.write('1.1  0.030  40  36  0.\n')
    fid.write('$\n')
    fid.write('F T T T T T\n')
    fid.write('$\n')
    fid.write('3600. 600. 3600. 300.\n')
    fid.write('$\n')
    fid.write('END OF NAMELISTS\n')
    fid.write('$\n')
    fid.write(
        '$ Define grid --------------------------------------------- $\n')
    fid.write('$ Five records containing :\n')
    fid.write(
        '$  1 Type of grid, coordinate system and type of closure: GSTRG, FLAGLL,\n'
    )
    fid.write(
        '$    CSTRG. Grid closure can only be applied in spherical coordinates.\n'
    )
    fid.write('$      GSTRG  : String indicating type of grid :\n')
    fid.write('$               ' 'RECT' '  : rectilinear\n')
    fid.write('$               ' 'CURV' '  : curvilinear\n')
    fid.write('$      FLAGLL : Flag to indicate coordinate system :\n')
    fid.write('$               T  : Spherical (lon/lat in degrees)\n')
    fid.write('$               F  : Cartesian (meters)\n')
    fid.write(
        '$      CSTRG  : String indicating the type of grid index space closure :\n'
    )
    fid.write('$               ' 'NONE' '  : No closure is applied\n')
    fid.write('$               '
              'SMPL'
              '  : Simple grid closure : Grid is periodic in the\n')
    fid.write(
        '$                         : i-index and wraps at i=NX+1. In other words,\n'
    )
    fid.write(
        '$                         : (NX+1,J) => (1,J). A grid with simple closure\n'
    )
    fid.write(
        '$                         : may be rectilinear or curvilinear.\n')
    fid.write('$               '
              'TRPL'
              '  : Tripole grid closure : Grid is periodic in the\n')
    fid.write(
        '$                         : i-index and wraps at i=NX+1 and has closure at\n'
    )
    fid.write(
        '$                         : j=NY+1. In other words, (NX+1,J<=NY) => (1,J)\n'
    )
    fid.write(
        '$                         : and (I,NY+1) => (MOD(NX-I+1,NX)+1,NY). Tripole\n'
    )
    fid.write(
        '$                         : grid closure requires that NX be even. A grid\n'
    )
    fid.write(
        '$                         : with tripole closure must be curvilinear.\n'
    )
    fid.write(
        '$  2 NX, NY. As the outer grid lines are always defined as land\n')
    fid.write('$    points, the minimum size is 3x3.\n')
    fid.write('$  3 Unit number of file with x-coordinate.\n')
    fid.write(
        '$    Scale factor and add offset: x <= scale_fac * x_read + add_offset.\n'
    )
    fid.write(
        '$    IDLA, IDFM, format for formatted read, FROM and filename.\n')
    fid.write('$  4 Unit number of file with y-coordinate.\n')
    fid.write(
        '$    Scale factor and add offset: y <= scale_fac * y_read + add_offset.\n'
    )
    fid.write(
        '$    IDLA, IDFM, format for formatted read, FROM and filename.\n')
    fid.write(
        '$  5 Limiting bottom depth (m) to discriminate between land and sea\n'
    )
    fid.write(
        '$    points, minimum water depth (m) as allowed in model, unit number\n'
    )
    fid.write(
        '$    of file with bottom depths, scale factor for bottom depths (mult.),\n'
    )
    fid.write(
        '$    IDLA, IDFM, format for formatted read, FROM and filename.\n')
    fid.write('$      IDLA : Layout indicator :\n')
    fid.write('$                  1   : Read line-by-line bottom to top.\n')
    fid.write('$                  2   : Like 1, single read statement.\n')
    fid.write('$                  3   : Read line-by-line top to bottom.\n')
    fid.write('$                  4   : Like 3, single read statement.\n')
    fid.write('$      IDFM : format indicator :\n')
    fid.write('$                  1   : Free format.\n')
    fid.write(
        '$                  2   : Fixed format with above format descriptor.\n'
    )
    fid.write('$                  3   : Unformatted.\n')
    fid.write('$      FROM : file type parameter\n')
    fid.write('$             ' 'UNIT' ' : open file by unit number only.\n')
    fid.write('$             '
              'NAME'
              ' : open file by name and assign to unit.\n')
    fid.write(
        '$  If the Unit Numbers in above files is 10 then data is read from this file\n'
    )
    fid.write('$\n')

    # I prefer considering only curvilinear grids.
    if spherical:
        fid.write('\'CURV\' T \'NONE\'\n')
    else:
        fid.write('\'CURV\' F \'NONE\'\n')

    # Grid size
    fid.write(np.str(lon.shape[1]) + '  ' + np.str(lon.shape[0]) + '\n')

    # Path to grid name
    fid.write(
        '           11 1.0 0. 1 1 \'(....)\'  \'NAME\'  \'ww3_grid.lon\'\n')
    fid.write(
        '           12 1.0 0. 1 1 \'(....)\'  \'NAME\'  \'ww3_grid.lat\'\n')

    # Bottom bathymetry information
    fid.write('$ Bottom bathymetry\n')
    fid.write(
        ' -0.5 0.05 13        1 1 \'(....)\'  \'NAME\'  \'ww3_grid.bot\'\n')
    fid.write('$ Subgrid Information\n')
    fid.write('           10        1 1 \'(....)\'  \'PART\'  \'dummy\'\n')

    # Subgrid information
    fid.write('$\n')
    fid.write('  0   0   F\n')
    fid.write('$\n')
    fid.write('  0   0   F\n')
    fid.write('  0   0\n')
    fid.write('$\n')
    fid.write('  0.  0.  0.  0.  0\n')
    fid.write(
        '$ ----------------------------------------------------------$\n')
    fid.write(
        '$ End of input file                                         $\n')
    fid.write(
        '$ ----------------------------------------------------------$\n')

    # Close input file
    fid.close()
Example #2
0
def write_nc_spec(latitude,
                  longitude,
                  spectrum,
                  frequency,
                  direction,
                  time1,
                  station,
                  fileout=None,
                  spherical=True):
    '''
    
    Parameters
    ----------
    latitude     : Array of the latitudes of each spectra point [Degree]
                   Dimension (time,station)
    longitude    : Array of the longitudes of each spectra point [Degree east]
                   Dimension (time,station)
    spectrum     : Variance spectrum [m2/Hz/rad]
                   Dimensions (time,station,frequency,direction)
    frequency    : frequency at each bin center [Hz]
    direction    : direction of propagation of each spectral bin [rad]
    time         : vector with days from 1900-01-01 00:00:00
    station      : Array with station names (not longer than 16 characters)
    fileout      : Output netCDF file
    spherical    : Flag for metadata. For spherical coordinates True and False
                   for cartesian coordiantes. 
    
    Notes:
    ------
    Direction of where waves are traveling to.
    
    Version:
    --------
    v0.1 code created:
      Gabriel Garcia Medina, Saeed Moghimi, April 2015
                   
    '''

    # For testing purposes only ------------------------------------------------
    #nctest = netCDF4.Dataset('/home/shusin2/shared/nmg/pycodes/'
    #                         'ww3.basin.201401_spec.nc','r')
    #fileout = '/home/shusin2/shared/nmg/pycodes/test2.nc'
    #time1 = nctest.variables['time'][:]
    #station = nctest.variables['station'][:1]
    #latitude = nctest.variables['latitude'][:,:1]   * 0.0
    #longitude = nctest.variables['longitude'][:,:1] * 0.0+15.0
    #frequency = nctest.variables['frequency'][:]
    #direction = nctest.variables['direction'][:]
    #spectrum = nctest.variables['efth'][:,:1,:,:]
    # -------------------------------------------------------------------------

    #     # Variable dictionary
    #     varinfo = defaultdict(dict)
    #     varinfo['frequency']['units'] = 's-1'
    #     varinfo['frequency']['long_name'] = 'frequency of center band'
    #     varinfo['frequency']['standard_name'] = 'sea_surface_wave_frequency'
    #     varinfo['direction']['units'] = 'degree'
    #     varinfo['direction']['long_name'] = 'sea surface wave to direction'
    #     varinfo['direction']['standard_name'] = 'sea_surface_wave_to_direction'
    #     varinfo['latitude']['units'] = 'degree_north'
    #     varinfo['latitude']['long_name'] = 'latitude'
    #     varinfo['latitude']['standard_name'] = 'latitude'
    #     varinfo['longitude']['units'] = 'degree_east'
    #     varinfo['longitude']['long_name'] = 'longitude'
    #     varinfo['longitude']['standard_name'] = 'longitude'
    #     varinfo['efth']['units'] = 'm2 s rad-1'
    #     varinfo['efth']['long_name'] = ('sea surface wave directional variance' +
    #                                     ' spectral density')

    # Create netcdf file
    if fileout:
        nc = netCDF4.Dataset(fileout, 'w')
    else:
        print("Writing NetCDF file " + os.getcwd() + "/ww3_spec_inp.nc")
        nc = netCDF4.Dataset('./ww3_spec_inp.nc', 'w')

    # Create general attributes
    nc.Description = 'Wavewatch III 4.18 input spectra file'
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    nc.Owner = 'Nearshore Modeling Group (http://ozkan.oce.orst.edu/nmg)'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Script = os.path.realpath(__file__)

    # Create dimensions
    nc.createDimension('time', 0)
    nc.createDimension('frequency', frequency.shape[0])
    nc.createDimension('direction', direction.shape[0])
    nc.createDimension('string16', 16)
    nc.createDimension('station', len(station))

    # Write time
    nc.createVariable('time', 'f8', ('time'))
    nc.variables['time'].long_name = 'julian day (UT)'
    nc.variables['time'].standard_time = 'time'
    nc.variables['time'].units = 'days since 1900-01-01T00:00:00Z'
    nc.variables['time'].conventions = ('Relative julian days with decimal ' +
                                        'part (as parts of the day)')
    nc.variables['time'][:] = time1

    # Write station id and name
    nc.createVariable('station', 'i8', ('station'))
    nc.variables['station'].long_name = 'station id'
    nc.variables['station'].axis = 'X'
    nc.variables['station'][:] = np.arange(0, len(station), 1)

    # IDK why they do this in WW3 so I am trying to mimic this behaviour
    nc.createVariable('string16', 'i8', ('string16'))
    nc.variables['string16'].long_name = 'station_name number of characters'
    nc.variables['string16'].axis = 'W'
    nc.variables['string16'][:] = np.empty((16, ), dtype=int)

    # Write station names
    nc.createVariable('station_name', 'S1', ('station', 'string16'))
    nc.variables['station_name'].long_name = 'station name'
    nc.variables['station_name'].content = 'XW'
    nc.variables['station_name'].associates = 'station string16'
    for aa in range(len(station)):
        nc.variables['station_name'][aa] = station[aa]

    # Spatial dimensions
    nc.createVariable('latitude', 'f8', ('time', 'station'))
    nc.variables['latitude'].long_name = 'latitude'
    nc.variables['latitude'].standard_name = 'latitude'
    nc.variables['latitude'].units = 'degree_north'
    nc.variables['latitude'].valid_min = -90.0
    nc.variables['latitude'].valid_max = 90.0
    nc.variables['latitude'].content = 'TX'
    nc.variables['latitude'].associates = 'time station'
    nc.variables['latitude'][:] = latitude

    nc.createVariable('longitude', 'f8', ('time', 'station'))
    nc.variables['longitude'].long_name = 'longitude'
    nc.variables['longitude'].standard_name = 'longitude'
    nc.variables['longitude'].units = 'degree_east'
    nc.variables['longitude'].valid_min = -180.0
    nc.variables['longitude'].valid_max = 180.0
    nc.variables['longitude'].content = 'TX'
    nc.variables['longitude'].associates = 'time station'
    nc.variables['longitude'][:] = gangles.wrapto180(latitude)

    # Create frequency and direction vectors
    nc.createVariable('frequency', 'f8', ('frequency'))
    nc.variables['frequency'].long_name = 'frequency of center band'
    nc.variables['frequency'].standard_name = 'sea_surface_wave_frequency'
    nc.variables['frequency'].globwave_name = 'frequency'
    nc.variables['frequency'].units = 's-1'
    nc.variables['frequency'].valid_min = 0.0
    nc.variables['frequency'].valid_max = 10.0
    nc.variables['frequency'].axis = 'Y'
    nc.variables['frequency'][:] = frequency

    nc.createVariable('direction', 'f8', ('direction'))
    nc.variables['direction'].long_name = 'sea surface wave to direction'
    nc.variables['direction'].standard_name = 'sea_surface_wave_to_direction'
    nc.variables['direction'].globwave_name = 'direction'
    nc.variables['direction'].units = 'degree'
    nc.variables['direction'].valid_min = 0.0
    nc.variables['direction'].valid_max = 360.0
    nc.variables['direction'][:] = gangles.wrapto360(direction)

    # Write spectral data
    nc.createVariable('efth', 'f8',
                      ('time', 'station', 'frequency', 'direction'))
    nc.variables['efth'].long_name = ('sea surface wave directional variance' +
                                      ' spectral density')
    nc.variables['efth'].standard_name = ('sea_surface_wave_directional_' +
                                          'variance_spectral_density')
    nc.variables[
        'efth'].globwave_name = 'directional_variance_spectral_density'
    nc.variables['efth'].units = 'm2 s rad-1'
    nc.variables['efth'].scale_factor = 1.0
    nc.variables['efth'].add_offset = 0.0
    nc.variables['efth'].valid_min = 0.0
    nc.variables['efth'].valid_max = 1.0e20
    nc.variables['efth'].content = 'TXYZ'
    nc.variables['efth'].associates = 'time station frequency direction'
    nc.variables['efth'][:] = spectrum

    nc.close()
Example #3
0
def write_wind_nc(outfld,timeVec,lon,lat,uwnd,vwnd,temp=False):
    '''
    Function to generate bathymetry files to be used as input for WW3 v4.18
    
    PARAMETERS:
    -----------
    outfld        : folder to write the files to
    timeVec       : Time vector (datetime array)
    lon           : longitudes (or x for cartesian) at every grid point 
                    (I assume they have been meshgridded)
    lat           : latitudes (or y for cartesian) at every grid point
    uwnd          : zonal component of wind [m/s]
    vwnd          : meridional component of wind [m/s]
    temp          : (optional) Air-sea temperature differences [C]
    
    OUTPUT:
    -------
    ww3_wind.nc   : NetCDF file containing the grid information
    
    NOTES:   
    ------
    I assume that if the grid is in spherical coordiantes the latitude and 
        longitudes are given in decimal degrees (east). On the other hand if the 
        grid is cartesian I assume meters.
    
    '''
    spherical = True # Placeholder for future expansion to cartesian

    # Convert longitudes to degrees east 
    lon = _gangles.wrapto360(lon)
    
    # Write netcdf file --------------------------------------------------------
    
    # Global attributes  
    nc = _netCDF4.Dataset(outfld + '/ww3_wind.nc', 'w', format='NETCDF4')
    nc.Description = 'Wavewatch III Wind Input'
    nc.Author = _getpass.getuser()
    nc.Created = _time.ctime()
    nc.Software = 'Created with Python ' + _sys.version
    nc.NetCDF_Lib = str(_netCDF4.getlibversion())
    nc.Script = _os.path.realpath(__file__)           
        
    # Create dimensions
    nc.createDimension('longitude', lon.shape[1])
    nc.createDimension('latitude',lon.shape[0])
    nc.createDimension('time',0)
    
    # Write coordinates and depth to netcdf file    
    if spherical:
        nc.createVariable('latitude','f8',('latitude','longitude'))
        nc.variables['latitude'].units = 'degree_north'
        nc.variables['latitude'].long_name = 'latitude of RHO-points'
        nc.variables['latitude'][:] = lat
    else:
        nc.createVariable('y_rho','f8',('eta_rho','xi_rho'))
        nc.variables['y_rho'].units = 'meter'
        nc.variables['y_rho'].long_name = 'y location of RHO-points'
        nc.variables['y_rho'][:] = lat
    
    # Write longitude
    if spherical:
        nc.createVariable('longitude','f8',('latitude','longitude'))
        nc.variables['longitude'].units = 'degree_east'
        nc.variables['longitude'].long_name = 'latitude of RHO-points'
        nc.variables['longitude'][:] = lon
    else:
        nc.createVariable('x_rho','f8',('eta_rho','xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].long_name = 'x location of RHO-points'
        nc.variables['x_rho'][:] = lon

    # Time vector 
    nc.createVariable('time','f8',('time'))
    nc.variables['time'].units = 'seconds since 1900-01-01 00:00:00'
    nc.variables['time'].conventions = 'relative julian seconds'
    baseTime = _datetime.datetime(1900,1,1)
    timeVec = _np.array([(aa - baseTime).total_seconds() for aa in timeVec])
    nc.variables['time'][:] = timeVec
           
    # Write wind components
    nc.createVariable('UWND','f8',('time','latitude','longitude'))
    nc.variables['UWND'].units = 'meter second-1'
    nc.variables['UWND'].long_name = 'Zonal component of wind'
    nc.variables['UWND'][:] = uwnd

    nc.createVariable('VWND','f8',('time','latitude','longitude'))
    nc.variables['VWND'].units = 'meter second-1'
    nc.variables['VWND'].long_name = 'Meridional component of wind'
    nc.variables['VWND'][:] = vwnd

    if temp:
        nc.createVariable('temp','f8',('time','latitude','longitude'))
        nc.variables['temp'].units = 'degrees C'
        nc.variables['temp'].long_name = 'Air-sea temperature differences'
        nc.variables['temp'][:] = temp
        
    # Close NetCDF file
    nc.close()
Example #4
0
def spec_bulk_params(freq, dirs, spec, IGBand=[0.005, 0.05], zeroth=True):
    """
    Function to compute bulk wave parameters from frequency-direction spectrum

    Parameters:
    -----------
    freq    : Vector of spectral frequencies [Hz]
    dirs    : Vector of directions (nautical convention) [Deg or Rad]
    spec    : Wave spectrum [m2/Hz/Deg or m2/Hz/Deg]
              The shape must be [freq,dirs]
    IGBand  : Infragravity wave frequency cutoff 
              defaults to 0.005-0.05 Hz
    zeroth  : If true will remove the first frequency from the analysis

    Returns:
    --------
    Dictionary containing bulk wave parameters
    Hs         : Significant wave height [m]
    H1         : Mean wave height [m]
    Tp         : Peak wave period [s]
    Tp_fit     : Peak wave period computed from second order polynomial fit
                 near Tp[s]
    Tm01       : First moment wave period [s]
    Tm02       : Second moment wave period [s]
    Te         : Energy period [s]
    Sw         : Spectral width (m0*m2/m1/m1 - 1)**2
    Tm01IG     : First moment wave period over the infragravity frequency band
    TpIG       : Peak wave period over the infragravity frequency band [s]
    HsIG       : Significant wave height in the infragravity frequency band [m]
    Dm         : Mean wave direction, second moment (Kuik et al. 1988)
    Dp         : Peak wave direction (computed from directional spectrum)
    
    Notes:
    ------
    - mn are the different spectral moments
    - First frequency will be discarded from the analysis. It is assumed to be
      the zeroth-frequency.

    REFERENCES:
    -----------
    Kuik, A.J., G.P. Van Vledder, and L.H. Holthuijsen, 1988: A method for the
        routine analysis of pitch-and-roll buoy wave data. Journal of Physical
        Oceanography, 18(7), pp.1020-1034.
    """

    # Get directional properties
    dirSpec = np.trapz(spec, freq, axis=0)

    # Find peak wave directon
    Dp = np.argmax(dirSpec)
    Dp = dirs[Dp]
    dirDict = dict(Dp=Dp)

    # Find mean wave direction (Kuik et al 1988)
    a1 = np.trapz(dirSpec * np.cos((270.0 - dirs) * np.pi / 180), dirs)
    b1 = np.trapz(dirSpec * np.sin((270.0 - dirs) * np.pi / 180), dirs)
    # Mean wave direction in nautical coordinates
    Dm = _gangles.wrapto360(270.0 - np.arctan2(b1, a1) * 180.0 / np.pi)
    dirDict.update(Dm=Dm)

    # Get the parameter from the frequency spectrum
    #freqSpec = np.trapz(spec,dirs,axis=-1)
    dth = np.abs(dirs[2] - dirs[1])
    freqSpec = np.sum(spec, axis=-1) * dth
    bp = fspec_bulk_params(freq, freqSpec, IGBand, zeroth=zeroth)
    bp.update(dirDict)

    return bp
Example #5
0
def write_bathy(outfld, lon, lat, depth, spherical=True):
    """
    Function to generate bathymetry files to be used as input for WW3 v4.18
    
    PARAMETERS:
    -----------
    outfld        : folder to write the files to
    lon           : longitudes (or x for cartesian) at every grid point 
                    (I assume they have been meshgridded)
    lat           : latitudes (or y for cartesian) at every grid point
    spherical     : True for spherical grids and False for cartesian grids    
    
    OUTPUT:
    -------
    ww3_grid.bot  : ASCII file containing the grid depths
    ww3_grid.lon  : ASCII file containing the longitudes (or x locations)
    ww3_grid.lat  : ASCII file containing the latitudes (or y locations)
    ww3_grid.nc   : NetCDF file containing the grid information
    ww3_grid.inp  : Input file template to be used for the grid preprocessor. 
                    You will need to fix many things it will probably not
                    work out of the box. 
    
    NOTES:   
    ------
    I assume that if the grid is in spherical coordiantes the latitude and 
        longitudes are given in decimal degrees (east). On the other hand if the 
        grid is cartesian I assume meters.
    
    """

    # Convert longitudes to degrees east
    lon = gangles.wrapto360(lon)

    # Write ascii files --------------------------------------------------------
    # Bathymetry
    fid = open(outfld + "ww3_grid.bot", "w")
    for aa in range(depth.shape[0]):
        for bb in range(depth.shape[1]):
            fid.write("%12.4f" % depth[aa, bb])
        fid.write("\n")
    fid.close()

    # Latitude File
    fid = open(outfld + "ww3_grid.lat", "w")
    for aa in range(lat.shape[0]):
        for bb in range(lat.shape[1]):
            fid.write("%12.4f" % lat[aa, bb])
        fid.write("\n")
    fid.close()

    # Longitude File
    fid = open(outfld + "ww3_grid.lon", "w")
    for aa in range(lon.shape[0]):
        for bb in range(lon.shape[1]):
            fid.write("%12.4f" % lon[aa, bb])
        fid.write("\n")
    fid.close()

    # Write netcdf file --------------------------------------------------------

    # Global attributes
    nc = netCDF4.Dataset(outfld + "ww3_grid.nc", "w", format="NETCDF4")
    nc.Description = "Wavewatch III Bathymetry"
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    nc.Owner = "Nearshore Modeling Group (http://ozkan.oce.orst.edu/nmg)"
    nc.Software = "Created with Python " + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Script = os.path.realpath(__file__)

    # Create dimensions
    nc.createDimension("xi_rho", lon.shape[1])
    nc.createDimension("eta_rho", lon.shape[0])

    # Write coordinates and depth to netcdf file
    if spherical:
        nc.createVariable("lat_rho", "f8", ("eta_rho", "xi_rho"))
        nc.variables["lat_rho"].units = "degree_north"
        nc.variables["lat_rho"].long_name = "latitude of RHO-points"
        nc.variables["lat_rho"][:] = lat
    else:
        nc.createVariable("y_rho", "f8", ("eta_rho", "xi_rho"))
        nc.variables["y_rho"].units = "meter"
        nc.variables["y_rho"].long_name = "y location of RHO-points"
        nc.variables["y_rho"][:] = lat

    # Write longitude
    if spherical:
        nc.createVariable("lon_rho", "f8", ("eta_rho", "xi_rho"))
        nc.variables["lon_rho"].units = "degree_east"
        nc.variables["lon_rho"].long_name = "latitude of RHO-points"
        nc.variables["lon_rho"][:] = lon
    else:
        nc.createVariable("x_rho", "f8", ("eta_rho", "xi_rho"))
        nc.variables["x_rho"].units = "meter"
        nc.variables["x_rho"].long_name = "x location of RHO-points"
        nc.variables["x_rho"][:] = lon

    # Write water depth
    nc.createVariable("h", "f8", ("eta_rho", "xi_rho"))
    nc.variables["h"].units = "meter"
    nc.variables["h"].long_name = "bathymetry at RHO-points"
    nc.variables["h"][:] = depth

    # Close NetCDF file
    nc.close()

    # Write input file for grid preprocessor ----------------------------------

    # Create a generic input file
    fid = open(outfld + "ww3_grid.inp", "w")

    fid.write("$ ----------------------------------------------------------$\n")
    fid.write("$ WAVEWATCH III Grid preprocessor input file                $\n")
    fid.write("$ ----------------------------------------------------------$\n")
    fid.write("'Grid Name'\n")
    fid.write("$\n")
    fid.write("1.1  0.030  40  36  0.\n")
    fid.write("$\n")
    fid.write("F T T T T T\n")
    fid.write("$\n")
    fid.write("3600. 600. 3600. 300.\n")
    fid.write("$\n")
    fid.write("END OF NAMELISTS\n")
    fid.write("$\n")
    fid.write("$ Define grid --------------------------------------------- $\n")
    fid.write("$ Five records containing :\n")
    fid.write("$  1 Type of grid, coordinate system and type of closure: GSTRG, FLAGLL,\n")
    fid.write("$    CSTRG. Grid closure can only be applied in spherical coordinates.\n")
    fid.write("$      GSTRG  : String indicating type of grid :\n")
    fid.write("$               " "RECT" "  : rectilinear\n")
    fid.write("$               " "CURV" "  : curvilinear\n")
    fid.write("$      FLAGLL : Flag to indicate coordinate system :\n")
    fid.write("$               T  : Spherical (lon/lat in degrees)\n")
    fid.write("$               F  : Cartesian (meters)\n")
    fid.write("$      CSTRG  : String indicating the type of grid index space closure :\n")
    fid.write("$               " "NONE" "  : No closure is applied\n")
    fid.write("$               " "SMPL" "  : Simple grid closure : Grid is periodic in the\n")
    fid.write("$                         : i-index and wraps at i=NX+1. In other words,\n")
    fid.write("$                         : (NX+1,J) => (1,J). A grid with simple closure\n")
    fid.write("$                         : may be rectilinear or curvilinear.\n")
    fid.write("$               " "TRPL" "  : Tripole grid closure : Grid is periodic in the\n")
    fid.write("$                         : i-index and wraps at i=NX+1 and has closure at\n")
    fid.write("$                         : j=NY+1. In other words, (NX+1,J<=NY) => (1,J)\n")
    fid.write("$                         : and (I,NY+1) => (MOD(NX-I+1,NX)+1,NY). Tripole\n")
    fid.write("$                         : grid closure requires that NX be even. A grid\n")
    fid.write("$                         : with tripole closure must be curvilinear.\n")
    fid.write("$  2 NX, NY. As the outer grid lines are always defined as land\n")
    fid.write("$    points, the minimum size is 3x3.\n")
    fid.write("$  3 Unit number of file with x-coordinate.\n")
    fid.write("$    Scale factor and add offset: x <= scale_fac * x_read + add_offset.\n")
    fid.write("$    IDLA, IDFM, format for formatted read, FROM and filename.\n")
    fid.write("$  4 Unit number of file with y-coordinate.\n")
    fid.write("$    Scale factor and add offset: y <= scale_fac * y_read + add_offset.\n")
    fid.write("$    IDLA, IDFM, format for formatted read, FROM and filename.\n")
    fid.write("$  5 Limiting bottom depth (m) to discriminate between land and sea\n")
    fid.write("$    points, minimum water depth (m) as allowed in model, unit number\n")
    fid.write("$    of file with bottom depths, scale factor for bottom depths (mult.),\n")
    fid.write("$    IDLA, IDFM, format for formatted read, FROM and filename.\n")
    fid.write("$      IDLA : Layout indicator :\n")
    fid.write("$                  1   : Read line-by-line bottom to top.\n")
    fid.write("$                  2   : Like 1, single read statement.\n")
    fid.write("$                  3   : Read line-by-line top to bottom.\n")
    fid.write("$                  4   : Like 3, single read statement.\n")
    fid.write("$      IDFM : format indicator :\n")
    fid.write("$                  1   : Free format.\n")
    fid.write("$                  2   : Fixed format with above format descriptor.\n")
    fid.write("$                  3   : Unformatted.\n")
    fid.write("$      FROM : file type parameter\n")
    fid.write("$             " "UNIT" " : open file by unit number only.\n")
    fid.write("$             " "NAME" " : open file by name and assign to unit.\n")
    fid.write("$  If the Unit Numbers in above files is 10 then data is read from this file\n")
    fid.write("$\n")

    # I prefer considering only curvilinear grids.
    if spherical:
        fid.write("'CURV' T 'NONE'\n")
    else:
        fid.write("'CURV' F 'NONE'\n")

    # Grid size
    fid.write(np.str(lon.shape[1]) + "  " + np.str(lon.shape[0]) + "\n")

    # Path to grid name
    fid.write("           11 1.0 0. 1 1 '(....)'  'NAME'  'ww3_grid.lon'\n")
    fid.write("           12 1.0 0. 1 1 '(....)'  'NAME'  'ww3_grid.lat'\n")

    # Bottom bathymetry information
    fid.write("$ Bottom bathymetry\n")
    fid.write(" -0.5 0.05 13        1 1 '(....)'  'NAME'  'ww3_grid.bot'\n")
    fid.write("$ Subgrid Information\n")
    fid.write("           10        1 1 '(....)'  'PART'  'dummy'\n")

    # Subgrid information
    fid.write("$\n")
    fid.write("  0   0   F\n")
    fid.write("$\n")
    fid.write("  0   0   F\n")
    fid.write("  0   0\n")
    fid.write("$\n")
    fid.write("  0.  0.  0.  0.  0\n")
    fid.write("$ ----------------------------------------------------------$\n")
    fid.write("$ End of input file                                         $\n")
    fid.write("$ ----------------------------------------------------------$\n")

    # Close input file
    fid.close()
Example #6
0
def write_nc_spec(latitude, longitude, spectrum, frequency, direction, time1, station, fileout=None, spherical=True):
    """
    
    Parameters
    ----------
    latitude     : Array of the latitudes of each spectra point [Degree]
                   Dimension (time,station)
    longitude    : Array of the longitudes of each spectra point [Degree east]
                   Dimension (time,station)
    spectrum     : Variance spectrum [m2/Hz/rad]
                   Dimensions (time,station,frequency,direction)
    frequency    : frequency at each bin center [Hz]
    direction    : direction of propagation of each spectral bin [rad]
    time         : vector with days from 1900-01-01 00:00:00
    station      : Array with station names (not longer than 16 characters)
    fileout      : Output netCDF file
    spherical    : Flag for metadata. For spherical coordinates True and False
                   for cartesian coordiantes. 
    
    Notes:
    ------
    Direction of where waves are traveling to.
    
    Version:
    --------
    v0.1 code created:
      Gabriel Garcia Medina, Saeed Moghimi, April 2015
                   
    """

    # For testing purposes only ------------------------------------------------
    # nctest = netCDF4.Dataset('/home/shusin2/shared/nmg/pycodes/'
    #                         'ww3.basin.201401_spec.nc','r')
    # fileout = '/home/shusin2/shared/nmg/pycodes/test2.nc'
    # time1 = nctest.variables['time'][:]
    # station = nctest.variables['station'][:1]
    # latitude = nctest.variables['latitude'][:,:1]   * 0.0
    # longitude = nctest.variables['longitude'][:,:1] * 0.0+15.0
    # frequency = nctest.variables['frequency'][:]
    # direction = nctest.variables['direction'][:]
    # spectrum = nctest.variables['efth'][:,:1,:,:]
    # -------------------------------------------------------------------------

    #     # Variable dictionary
    #     varinfo = defaultdict(dict)
    #     varinfo['frequency']['units'] = 's-1'
    #     varinfo['frequency']['long_name'] = 'frequency of center band'
    #     varinfo['frequency']['standard_name'] = 'sea_surface_wave_frequency'
    #     varinfo['direction']['units'] = 'degree'
    #     varinfo['direction']['long_name'] = 'sea surface wave to direction'
    #     varinfo['direction']['standard_name'] = 'sea_surface_wave_to_direction'
    #     varinfo['latitude']['units'] = 'degree_north'
    #     varinfo['latitude']['long_name'] = 'latitude'
    #     varinfo['latitude']['standard_name'] = 'latitude'
    #     varinfo['longitude']['units'] = 'degree_east'
    #     varinfo['longitude']['long_name'] = 'longitude'
    #     varinfo['longitude']['standard_name'] = 'longitude'
    #     varinfo['efth']['units'] = 'm2 s rad-1'
    #     varinfo['efth']['long_name'] = ('sea surface wave directional variance' +
    #                                     ' spectral density')

    # Create netcdf file
    if fileout:
        nc = netCDF4.Dataset(fileout, "w")
    else:
        print("Writing NetCDF file " + os.getcwd() + "/ww3_spec_inp.nc")
        nc = netCDF4.Dataset("./ww3_spec_inp.nc", "w")

    # Create general attributes
    nc.Description = "Wavewatch III 4.18 input spectra file"
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    nc.Owner = "Nearshore Modeling Group (http://ozkan.oce.orst.edu/nmg)"
    nc.Software = "Created with Python " + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Script = os.path.realpath(__file__)

    # Create dimensions
    nc.createDimension("time", 0)
    nc.createDimension("frequency", frequency.shape[0])
    nc.createDimension("direction", direction.shape[0])
    nc.createDimension("string16", 16)
    nc.createDimension("station", len(station))

    # Write time
    nc.createVariable("time", "f8", ("time"))
    nc.variables["time"].long_name = "julian day (UT)"
    nc.variables["time"].standard_time = "time"
    nc.variables["time"].units = "days since 1900-01-01T00:00:00Z"
    nc.variables["time"].conventions = "Relative julian days with decimal " + "part (as parts of the day)"
    nc.variables["time"][:] = time1

    # Write station id and name
    nc.createVariable("station", "i8", ("station"))
    nc.variables["station"].long_name = "station id"
    nc.variables["station"].axis = "X"
    nc.variables["station"][:] = np.arange(0, len(station), 1)

    # IDK why they do this in WW3 so I am trying to mimic this behaviour
    nc.createVariable("string16", "i8", ("string16"))
    nc.variables["string16"].long_name = "station_name number of characters"
    nc.variables["string16"].axis = "W"
    nc.variables["string16"][:] = np.empty((16,), dtype=int)

    # Write station names
    nc.createVariable("station_name", "S1", ("station", "string16"))
    nc.variables["station_name"].long_name = "station name"
    nc.variables["station_name"].content = "XW"
    nc.variables["station_name"].associates = "station string16"
    for aa in range(len(station)):
        nc.variables["station_name"][aa] = station[aa]

    # Spatial dimensions
    nc.createVariable("latitude", "f8", ("time", "station"))
    nc.variables["latitude"].long_name = "latitude"
    nc.variables["latitude"].standard_name = "latitude"
    nc.variables["latitude"].units = "degree_north"
    nc.variables["latitude"].valid_min = -90.0
    nc.variables["latitude"].valid_max = 90.0
    nc.variables["latitude"].content = "TX"
    nc.variables["latitude"].associates = "time station"
    nc.variables["latitude"][:] = latitude

    nc.createVariable("longitude", "f8", ("time", "station"))
    nc.variables["longitude"].long_name = "longitude"
    nc.variables["longitude"].standard_name = "longitude"
    nc.variables["longitude"].units = "degree_east"
    nc.variables["longitude"].valid_min = -180.0
    nc.variables["longitude"].valid_max = 180.0
    nc.variables["longitude"].content = "TX"
    nc.variables["longitude"].associates = "time station"
    nc.variables["longitude"][:] = gangles.wrapto180(latitude)

    # Create frequency and direction vectors
    nc.createVariable("frequency", "f8", ("frequency"))
    nc.variables["frequency"].long_name = "frequency of center band"
    nc.variables["frequency"].standard_name = "sea_surface_wave_frequency"
    nc.variables["frequency"].globwave_name = "frequency"
    nc.variables["frequency"].units = "s-1"
    nc.variables["frequency"].valid_min = 0.0
    nc.variables["frequency"].valid_max = 10.0
    nc.variables["frequency"].axis = "Y"
    nc.variables["frequency"][:] = frequency

    nc.createVariable("direction", "f8", ("direction"))
    nc.variables["direction"].long_name = "sea surface wave to direction"
    nc.variables["direction"].standard_name = "sea_surface_wave_to_direction"
    nc.variables["direction"].globwave_name = "direction"
    nc.variables["direction"].units = "degree"
    nc.variables["direction"].valid_min = 0.0
    nc.variables["direction"].valid_max = 360.0
    nc.variables["direction"][:] = gangles.wrapto360(direction)

    # Write spectral data
    nc.createVariable("efth", "f8", ("time", "station", "frequency", "direction"))
    nc.variables["efth"].long_name = "sea surface wave directional variance" + " spectral density"
    nc.variables["efth"].standard_name = "sea_surface_wave_directional_" + "variance_spectral_density"
    nc.variables["efth"].globwave_name = "directional_variance_spectral_density"
    nc.variables["efth"].units = "m2 s rad-1"
    nc.variables["efth"].scale_factor = 1.0
    nc.variables["efth"].add_offset = 0.0
    nc.variables["efth"].valid_min = 0.0
    nc.variables["efth"].valid_max = 1.0e20
    nc.variables["efth"].content = "TXYZ"
    nc.variables["efth"].associates = "time station frequency direction"
    nc.variables["efth"][:] = spectrum

    nc.close()