Exemple #1
0
    def check_dependencies(self):
        self._check_import("netCDF4")
        from netCDF4 import getlibversion

        version = StrictVersion(getlibversion().split(" ")[0])
        if version < StrictVersion("4.5"):
            raise ImportError("netCDF4 library must be at least version 4.5")
Exemple #2
0
def software_stack():
    """
    Import all the hard dependencies.
    Returns a dict with the version.
    """
    # Mandatory
    import numpy, scipy

    d = dict(
        numpy=numpy.version.version,
        scipy=scipy.version.version,
    )

    # Optional but strongly suggested.
    try:
        import netCDF4, matplotlib
        d.update(dict(
            netCDF4=netCDF4.getlibversion(),
            matplotlib="Version: %s, backend: %s" % (matplotlib.__version__, matplotlib.get_backend()),
            ))
    except ImportError:
        pass

    # Optional (GUIs).
    try:
        import wx
        d["wx"] = wx.version()
    except ImportError:
        pass

    return d
Exemple #3
0
    def check_dependencies(self):  # noqa: D102
        self._check_import("netCDF4")
        from netCDF4 import getlibversion

        version = StrictVersion(getlibversion().split(" ")[0])
        if version < StrictVersion("4.5"):
            raise ImportError("netCDF4 library must be at least version 4.5")
Exemple #4
0
def software_stack():
    """
    Import all the hard dependencies.
    Returns a dict with the version.
    """
    # Mandatory
    import numpy, scipy

    d = dict(
        numpy=numpy.version.version,
        scipy=scipy.version.version,
    )

    # Optional but strongly suggested.
    try:
        import netCDF4, matplotlib
        d.update(
            dict(
                netCDF4=netCDF4.getlibversion(),
                matplotlib="Version: %s, backend: %s" %
                (matplotlib.__version__, matplotlib.get_backend()),
            ))
    except ImportError:
        pass

    # Optional (GUIs).
    try:
        import wx
        d["wx"] = wx.version()
    except ImportError:
        pass

    return d
Exemple #5
0
def _ncversion(v=None):
    """Return the netCDF C library version. If v is None the full version
    number string is returned. If v is a full version number string the
    [major].[minor] number is returned as float"""
    if v is None:
        return str(netCDF4.getlibversion()).split()[0]  # Full string version
    v = v.split('.')
    if len(v) == 1: v.append('0')
    return float('.'.join(v[0:2]))  # [major].[minor] number as a float
Exemple #6
0
def _ncversion(v=None):
    """Return the netCDF C library version. If v is None the full version
    number string is returned. If v is a full version number string the
    [major].[minor] number is returned as float"""
    if v is None:
        return str(netCDF4.getlibversion()).split()[0]  # Full string version
    v = v.split('.')
    if len(v) == 1: v.append('0')
    return float('.'.join(v[0:2]))  # [major].[minor] number as a float
Exemple #7
0
def test_netcdf():
    import netCDF4 as nc
    from birdy.client.converters import Netcdf4Converter, JSONConverter

    # Xarray is the default converter. Use netCDF4 here.
    if nc.getlibversion() > "4.5":
        m = WPSClient(url=url, processes=["output_formats"], converters=[Netcdf4Converter, JSONConverter])
        ncdata, jsondata = m.output_formats().get(asobj=True)
        assert isinstance(ncdata, nc.Dataset)
        ncdata.close()
        assert isinstance(jsondata, dict)
Exemple #8
0
    def _show_system_info(self):
        super(MDTrajTester, self)._show_system_info()
        print('mdtraj version %s' % mdtraj.version.version)
        print('mdtraj is installed in %s' % os.path.dirname(mdtraj.__file__))

        try:
            import tables
            print('tables version %s' % tables.__version__)
            print('tables hdf5 version %s' % tables.hdf5Version)
        except ImportError:
            print('tables is not installed')

        try:
            import netCDF4
            print('netCDF4 version %s' % netCDF4.__version__)
            print('netCDF4 lib version %s' % netCDF4.getlibversion())
        except ImportError:
            print('netCDF4 not installed')
Exemple #9
0
def bulk2ncCanada(buoyFld, buoyId, verbose=True):
    '''
    Code to convert bulk parameter text files from Peches et Oceans Canada
    into netcdf file.
    
    Usage:
    ------
    bulk2ncCanada(buoyfld,buoyid,verbose)
    
    Input:
    ------
    buoyfld  = Folder where the bulk paramerter text files reside.
    buoyid   = Netcdf buoy identifier (to figure out the file names)
    verbose  = some extra information (True is default)
    
    Notes:
    Only the bulk parameter files must be present in that directory. The code is
    not smart enough (and I do not have the time to make it so) to figure out 
    the bulk parameter files. 
    
    '''

    #===========================================================================
    # Read and Clean Up Data
    #===========================================================================

    # Dictionary translating from Canadian to US
    varNames = {
        'VCAR': 'WVHT',
        'VTPK': 'DPD',
        'GSPD': 'GST',
        'SSTP': 'WTMP',
        'DATE': 'wave_time'
    }

    # They provide just one file
    archivo = buoyFld + '/c' + buoyId + '.csv'

    # Get the variable keys
    fobj = open(archivo)

    # Get variable names
    varkeys = fobj.readline().rstrip()[:-1].split(',')

    # Translate variables
    for aa in range(len(varkeys)):
        if varkeys[aa] in varNames:
            varkeys[aa] = varNames[varkeys[aa]]

    # Create netcdf file -------------------------------------------------------
    nc = netCDF4.Dataset(buoyFld + '/' + buoyId + '.nc', 'w', format='NETCDF4')
    nc.Description = buoyId + ' Environment Canada Bulk Parameter Data'
    nc.rawdata = (
        'Fisheries and Oceans Canada\n' +
        'http://www.meds-sdmm.dfo-mpo.gc.ca/isdm-gdsi/waves-vagues/index-eng.htm'
    )
    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('wave_time', None)

    # Create netcdf variables
    def create_nc_var(name, dimensions, units=None, longname=None):
        nc.createVariable(name, 'f8', dimensions)
        if units is not None:
            nc.variables[name].units = units
        if longname is not None:
            nc.variables[name].long_name = longname

    # Create NetCDF variables
    create_nc_var('wave_time', 'wave_time',
                  'seconds since 1900-01-01 00:00:00', 'measurement time UTC')
    if 'Q_FLAG' in varkeys:
        create_nc_var(
            'Q_FLAG', 'wave_time', '',
            'Quality Codes\n' + '0: No quality control has been performed\n' +
            '1: Good - QC has been performed: record appears correct\n' +
            '3: Doubtful - QC has been performed\n' +
            '4: Erroneous - QU has been performed\n' +
            '5: Changes - The record has been changed as a result of QC\n' +
            '6: Acceptable - QC has been performed: record seems ' +
            'inconsistent with other records\n' +
            '7: Off Position - There is a problem with the buoy ' +
            'position or mooring. Data may steel be useful')
    if 'LATITUDE' in varkeys:
        create_nc_var('LATITUDE', 'wave_time', 'degrees', 'Latitude')
    if 'LONGITUDE' in varkeys:
        create_nc_var('LONGITUDE', 'wave_time', 'degrees', 'Longitude')
    if 'DEPTH' in varkeys:
        create_nc_var('DEPTH', 'wave_time', 'meter', 'water depth')
    if 'WVHT' in varkeys:
        create_nc_var(
            'WVHT', 'wave_time', 'meter',
            'Significant wave height during the 20 minute sampling period')
    if 'DPD' in varkeys:
        create_nc_var(
            'DPD', 'wave_time', 'second',
            'Dominant wave period (period with the maximum wave energy)')
    if r'VWH$' in varkeys:
        create_nc_var('VWH$', 'wave_time', 'meter',
                      'Significant wave height (reported by the buoy)')
    if 'VCMX' in varkeys:
        create_nc_var('VCMX', 'wave_time', 'meter',
                      'Maximum zero crossing wave height (reported by buoy)')
    if r'VTP$' in varkeys:
        create_nc_var('VTP$', 'wave_time', 'second',
                      'Wave spectrum peak period (reported by the buoy)')
    if 'WDIR' in varkeys:
        create_nc_var(
            'WDIR', 'wave_time', 'degrees',
            'Wind direction (direction the wind is coming from in ' +
            'degrees clockwise from true North')
    if 'WSPD' in varkeys:
        create_nc_var('WSPD', 'wave_time', 'meter second-1',
                      'Horizontal wind speed')
    if r'WSS$' in varkeys:
        create_nc_var('WSS$', 'wave_time', 'meter second-1',
                      'Horizontal scalar wind speed')
    if 'GST' in varkeys:
        create_nc_var('GST', 'wave_time', 'meter second-1', 'Gust wind speed')
    if 'ATMS' in varkeys:
        create_nc_var('ATMS', 'wave_time', 'mbar',
                      'Atmospheric pressure at sea level')
    if 'DRYT' in varkeys:
        create_nc_var('DRYT', 'wave_time', 'Celsius', 'Dry bulb temperature')
    if 'WTMP' in varkeys:
        create_nc_var('WTMP', 'wave_time', 'Celsius',
                      'Sea surface temperature')

    if 'ATMS1' in varkeys:
        create_nc_var('ATMS1', 'wave_time', 'mbar',
                      'Atmospheric pressure at sea level')
    if 'WSPD1' in varkeys:
        create_nc_var('WSPD1', 'wave_time', 'meter second-1',
                      'Horizontal wind speed')

    # Load wave data ----------------------------------------------
    cnt = -1  # Counter variable for storing to file
    # Read line by line
    for tmpline in fobj:

        # Counter variable for NetCDF4 storage
        cnt += 1

        # Parse input line
        tmpline = tmpline.rstrip().split(',')

        # Process time file
        # Datetime object
        tmptime = datetime.datetime.strptime(tmpline[1], '%m/%d/%Y %H:%M')
        # Seconds since 20th Century
        sectime = tmptime - datetime.datetime(1900, 1, 1, 0, 0, 0)
        secsecs = sectime.total_seconds()
        # Write to file
        nc['wave_time'][cnt] = secsecs

        # Write the rest of the variables
        for aa in range(2, len(varkeys)):
            try:
                tmpvar = np.float(tmpline[aa])
            except:
                tmpvar = -99.0
            nc[varkeys[aa]][cnt] = tmpvar

    # Close files
    fobj.close()
    nc.close()
Exemple #10
0
def spec2nc(buoyfld, dtheta=5):
    '''
    Code to convert NDBC spectral data files to netCDF format. 
    
    Usage:
    ------
    spec2nc(buoyfld,dtheta)
    
    Input:
    ------
    buoyfld  : Folder where the text files reside. Those should be the only
               files in the folder.
    dtheta   : Directional resolution for the reconstruction of the frequency-
               direction spectrum. Defaults to 5 degrees. 
    
    Notes:
      1. NetCDF4 file will be generated
      2. Code is not optimized since this is not something you will want to be
         running often. Beware of slow performance for large datasets.
    
    References:
    Kuik, A.J., G.Ph. van Vledder, and L.H. Holthuijsen, 1998: "Method for
      the Routine Analysis of Pitch-and-Roll Buoy Wave Data", Journal of
      Physical Oceanography, 18, 1020-1034.
      
    TODO:
    - Only works with newer formats (YY MM DD hh mm)
    - Fix negative energy (the fix is in the code just incorporate)
    '''

    # For testing only ---------------------------------------------------------
    #buoyfld = '/home/shusin2/users/ggarcia/data/wave/b46029/spec/'
    #dtheta = 20
    # --------------------------------------------------------------------------

    # Construct directional angle
    angles = np.arange(0.0, 360.0, dtheta)

    # Time reference
    basetime = datetime.datetime(1900, 1, 1, 0, 0, 0)

    #===========================================================================
    # Read file information
    #===========================================================================

    # Get all files in folder
    archivos = glob.glob(buoyfld + '/*.txt')
    archivos = [x.split('/')[-1] for x in archivos]

    # Year information
    years = [x.split('.')[0][-4:] for x in archivos]  # Get all year stamps
    years = list(set(years))  # Find unique years
    years.sort()  # Sort years

    # Get buoy ID information
    buoyid = [x[0:5] for x in archivos]  # Find buoy ids
    buoyid = list(set(buoyid))  # Find unique ids
    if len(buoyid) > 1:
        print('This code does not support conversion for multiple buoys')
        buoyid = buoyid[0]
        print('  ' + buoyid + ' will be processed')
    else:
        buoyid = buoyid[0]

    # Info
    print('Found ' + np.str(len(years)) + ' files')
    print(buoyfld)

    # Create output netcdf file ------------------------------------------------
    # Global attributes
    nc = netCDF4.Dataset(buoyfld + '/' + buoyid + '_spec.nc',
                         'w',
                         format='NETCDF4')
    nc.Description = buoyid + ' NDBC Spectral Data'
    nc.Rawdata = 'National Data Buoy Center \nwww.ndbc.noaa.gov'
    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__)
    nc.Notes = 'Nautical convention used for directions'

    # Reconstruct the spectrum -------------------------------------------------

    # counter variable to create variables in the netcdf file
    masterCnt = 0
    cnt_freq = 0
    cnt_dir = 0
    tstep_freq = 0
    tstep_dir = 0

    # This variable will change if the format changes
    formIdCnt = 0
    formId = '0'

    # Frequency array to find if the reported frequencies changed
    freqArray = []

    # Loop over years
    for aa in years:

        # Info
        print('  Working on year ' + aa)

        # Load spectral density files
        # Check if file exists
        tmpfile = buoyfld + buoyid + 'w' + aa + '.txt'
        if os.path.isfile(tmpfile) == False:
            # No spectral density found for the given year, go to next one
            continue

        # Info
        print('    Spectral density data')

        # Increase master counter variable
        masterCnt += 1

        # Read spectral density data (frequency spectra) and identify the time
        # information given
        f_w = open(tmpfile, 'r')
        freq = f_w.readline().split()

        # Allocate the frequency array and determine if the format changed ----
        freqArray.append(freq)
        if masterCnt > 1:
            if freq != freqArray[masterCnt - 2]:

                # Reset counter variables
                cnt_freq = 0
                cnt_dir = 0
                tstep_freq = 0
                tstep_dir = 0

                # Update form Id counter
                formIdCnt += 1

                if formIdCnt > 9:
                    print('\n10 Different Formats Found')
                    print('Check your data, quitting ...')
                    nc.close()
                    sys.exit()

                # Update form Id text
                formId = '%01.0f' % formIdCnt

                # Message to user
                print('    Different format found')
                print('      New variables introduced')

        # Find if minutes are given
        if freq[4] == 'mm':
            freqInd0 = 5
        else:
            freqInd0 = 4

        # Read frequencies
        freq = np.array(freq[freqInd0:], dtype=float)
        f_w.close()

        # Load spectral density
        freq_spec = np.loadtxt(tmpfile, skiprows=1)

        # Allocate time and spectral density data
        freq_time = np.zeros((freq_spec.shape[0]))
        for bb in range(freq_time.shape[0]):
            tmpYear = np.int(freq_spec[bb, 0])
            tmpMonth = np.int(freq_spec[bb, 1])
            tmpDay = np.int(freq_spec[bb, 2])
            tmpHour = np.int(freq_spec[bb, 3])
            if freqInd0 == 4:
                tmpMin = np.int(0)
            else:
                tmpMin = np.int(freq_spec[bb, 4])

            if tmpYear < 100:
                tmpYear = tmpYear + 1900

            freq_time[bb] = (
                datetime.datetime(tmpYear, tmpMonth, tmpDay, tmpHour, tmpMin) -
                basetime).total_seconds()

        freq_spec = freq_spec[:, freqInd0:]

        # No Data Filter (NDBC uses 999.00 when there is no data)
        goodDataInd = freq_spec[:, 1] < 990.00
        freq_time = freq_time[goodDataInd]
        freq_spec = freq_spec[goodDataInd, :]

        # Create frequency spectra variables
        cnt_freq += 1
        if cnt_freq == 1:

            # Create dimensions  (NetCDF4 supports multiple unlimited dimensions)
            nc.createDimension('wave_time' + formId, None)

            # Create bulk parameter variables
            nc.createVariable('Hsig' + formId, 'f8', 'wave_time' + formId)
            nc.variables['Hsig' + formId].units = 'meter'
            nc.variables['Hsig' + formId].long_name = 'Significant wave height'

            # Create frequency dimension
            nc.createDimension('freq' + formId, freq.shape[0])

            nc.createVariable('wave_time' + formId, 'f8', 'wave_time' + formId)
            nc.variables['wave_time'+formId].units = \
            "seconds since 1900-01-01 00:00:00"
            nc.variables['wave_time' + formId].calendar = "julian"

            nc.createVariable('freq_spec' + formId, 'f8',
                              ('wave_time' + formId, 'freq' + formId))
            nc.variables['freq_spec' + formId].units = 'meter2 second'
            nc.variables['freq_spec' +
                         formId].long_name = 'Frequency variance spectrum'

            nc.createVariable('frequency' + formId, 'f8', ('freq' + formId))
            nc.variables['frequency' + formId].units = 'Hz'
            nc.variables['frequency' + formId].long_name = 'Spectral frequency'
            nc.variables['frequency' + formId][:] = freq

        # Information
        print('    Computing Bulk Parameters')

        # Compute bulk parameters
        moment0 = np.trapz(freq_spec.T, freq, axis=0)
        Hsig = 4.004 * (moment0)**0.5

        # Write to NetCDF file
        if cnt_freq == 1:
            nc.variables['Hsig' + formId][:] = Hsig
            nc.variables['freq_spec' + formId][:] = freq_spec
            nc.variables['wave_time' + formId][:] = freq_time
        else:
            nc.variables['Hsig' + formId][tstep_freq:] = Hsig
            nc.variables['freq_spec' + formId][tstep_freq:, :] = freq_spec
            nc.variables['wave_time' + formId][tstep_freq:] = freq_time

        # Check if directional data exists -------------------------------------
        tmp_alpha_1 = buoyfld + buoyid + 'd' + aa + '.txt'
        tmp_alpha_2 = buoyfld + buoyid + 'i' + aa + '.txt'
        tmp_r_1 = buoyfld + buoyid + 'j' + aa + '.txt'
        tmp_r_2 = buoyfld + buoyid + 'k' + aa + '.txt'

        if (os.path.isfile(tmp_alpha_1) and os.path.isfile(tmp_alpha_2)
                and os.path.isfile(tmp_r_1) and os.path.isfile(tmp_r_2)):

            # Information
            print('    Directional Data')

            # Read frequency of the directional spectra (not always agree with
            # the spectral densities)
            f_w2 = open(tmp_alpha_1, 'r')
            freqDirSpec = f_w2.readline().split()
            freqDirSpec = np.array(freqDirSpec[freqInd0:], dtype=float)
            f_w2.close()

            # Create directional spectra variables
            cnt_dir += 1
            if cnt_dir == 1:
                nc.createDimension('dir_time' + formId, None)
                nc.createDimension('dir' + formId, angles.shape[0])

                # Create frequency dimension
                nc.createDimension('freqDir' + formId, freqDirSpec.shape[0])

                nc.createVariable('dir_time' + formId, 'f8',
                                  'dir_time' + formId)
                nc.variables['dir_time'+formId].units = \
                "seconds since 1900-01-01 00:00:00"
                nc.variables['dir_time' + formId].calendar = "julian"

                nc.createVariable(
                    'dir_spec' + formId, 'f8',
                    ('dir_time' + formId, 'freqDir' + formId, 'dir' + formId))
                nc.variables['dir_spec' +
                             formId].units = 'meter2 second degree-1'
                nc.variables['dir_spec'+formId].long_name = \
                    'Frequency-Direction variance spectrum'

                nc.createVariable('direction' + formId, 'f8', ('dir' + formId))
                nc.variables['direction' + formId].units = 'degree'
                nc.variables['direction'+formId].long_name = \
                    'Degrees from true north in oceanographic convention'
                nc.variables['direction' + formId][:] = angles

                nc.createVariable('frequencyDir' + formId, 'f8',
                                  ('freqDir' + formId))
                nc.variables['frequencyDir' + formId].units = 'Hz'
                nc.variables[
                    'frequencyDir' +
                    formId].long_name = 'Spectral frequency for dir_spec'
                nc.variables['frequencyDir' + formId][:] = freqDirSpec

            # Read spectral data
            alpha_1 = np.loadtxt(tmp_alpha_1, skiprows=1)
            alpha_2 = np.loadtxt(tmp_alpha_2, skiprows=1)
            r_1 = np.loadtxt(tmp_r_1, skiprows=1) * 0.01
            r_2 = np.loadtxt(tmp_r_2, skiprows=1) * 0.01

            # Allocate date
            dir_time = np.zeros((alpha_1.shape[0]))
            for bb in range(dir_time.shape[0]):
                tmpYear = np.int(alpha_1[bb, 0])
                tmpMonth = np.int(alpha_1[bb, 1])
                tmpDay = np.int(alpha_1[bb, 2])
                tmpHour = np.int(alpha_1[bb, 3])
                if freqInd0 == 4:
                    tmpMin = np.int(0)
                else:
                    tmpMin = np.int(alpha_1[bb, 4])

                if tmpYear < 100:
                    tmpYear = tmpYear + 1900

                dir_time[bb] = (datetime.datetime(tmpYear, tmpMonth, tmpDay,
                                                  tmpHour, tmpMin) -
                                basetime).total_seconds()

            # Read data
            alpha_1 = alpha_1[:, freqInd0:]
            alpha_2 = alpha_2[:, freqInd0:]
            r_1 = r_1[:, freqInd0:]
            r_2 = r_2[:, freqInd0:]

            # No Data Filter (NDBC uses 999.00 when there is no data)
            goodDataInd = np.logical_and(alpha_1[:, 1] != 999.00,
                                         alpha_1[:, 2] != 999.00)
            alpha_1 = alpha_1[goodDataInd, :]
            alpha_2 = alpha_2[goodDataInd, :]
            r_1 = r_1[goodDataInd, :]
            r_2 = r_2[goodDataInd, :]
            dir_time = dir_time[goodDataInd]

            # Find where dir_time and freq_time match and compute those values
            # only
            repInd = np.in1d(dir_time, freq_time)
            alpha_1 = alpha_1[repInd]
            alpha_2 = alpha_2[repInd]
            r_1 = r_1[repInd]
            r_2 = r_2[repInd]
            dir_time = dir_time[repInd]

            repInd = np.in1d(freq_time, dir_time)
            freq_spec = freq_spec[repInd]

            # Interpolate density spectrum into directional bins
            if not np.array_equal(freq, freqDirSpec):
                freqSpecAll = np.copy(freq_spec)
                freq_spec = np.zeros_like((r_1)) * np.NAN
                for bb in range(freq_spec.shape[0]):
                    freq_spec[bb, :] = np.interp(freqDirSpec, freq,
                                                 freqSpecAll[bb, :])

            # Construct 2D spectra
            # See http://www.ndbc.noaa.gov/measdes.shtml
            wspec = np.NaN * np.zeros(
                (alpha_1.shape[0], alpha_1.shape[1], angles.shape[0]))

            # Time loop
            for bb in range(wspec.shape[0]):
                # Frequency loop
                for cc in range(wspec.shape[1]):
                    # Direction loop
                    for dd in range(wspec.shape[2]):
                        wspec[bb, cc, dd] = (
                            freq_spec[bb, cc] * np.pi / 180.0 * (1.0 / np.pi) *
                            (0.5 + r_1[bb, cc] * np.cos(
                                (angles[dd] - alpha_1[bb, cc]) * np.pi / 180.0)
                             + r_2[bb, cc] *
                             np.cos(2 * np.pi / 180.0 *
                                    (angles[dd] - alpha_2[bb, cc]))))
#             CLEAN ME UP---------------
#             # Get the positive energy
#             tmpSpec = spec.copy()
#             tmpSpec[tmpSpec<0] = 0.0
#             tmpFreqSpec = np.sum(tmpSpec,axis=-1)*(dirs[2]-dirs[1])
#             posEnergy = np.trapz(np.abs(tmpFreqSpec),freq,axis=-1)
#
#             # Get the total energy
#             tmpFreqSpec = np.sum(spec,axis=-1)*(dirs[2]-dirs[1])
#             totalEnergy = np.trapz(np.abs(tmpFreqSpec),freq,axis=-1)
#
#             # Scale the spectrum
#             spec = np.array([spec[aa,...] * totalEnergy[aa]/posEnergy[aa]
#                              for aa in range(spec.shape[0])])
#             spec[spec<0] = 0.0

# Write to file
            if cnt_dir == 1:
                nc.variables['dir_spec' + formId][:] = wspec
                nc.variables['dir_time' + formId][:] = dir_time
            else:
                nc.variables['dir_spec' + formId][tstep_dir:, :, :] = wspec
                nc.variables['dir_time' + formId][tstep_dir:] = dir_time

            tstep_dir += dir_time.shape[0]

        # Update frequency time step and go to next year
        tstep_freq += freq_time.shape[0]

    # Wrap up ------------------------------------------------------------------
    # Information
    print('Data stored as:')
    print('  ' + buoyfld + '/' + buoyid + '.nc')

    # Close NetCDF File
    nc.close()
Exemple #11
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()
Exemple #12
0
def fort61_to_nc(fort61,
                 staname,
                 x,
                 y,
                 varname='zeta',
                 longname='water surface elevation above geoid',
                 varunits='m',
                 ncdate='0000-00-00 00:00:00 UTC',
                 **kwargs):
    """ 
    Script to read fort.61-type (station scalar) files and store in a netcdf4 file

    PARAMETERS:
    -----------
    fort61 : Path to fort61-type file
    x,y    : Station coordinates
    ncdate : cold start date/time in CF standard: yyyy-MM-dd hh:mm:ss tz

    RETURNS:
    --------
    Netcdf containing
    time     : seconds since beginning of run 
    variable : temporal variable (called 'varname') recorded at stations. 
               Size: [time,station]
    """

    fobj = open(fort61, 'r')

    # Create the file and add global attributes
    if 'savename' in kwargs:
        ncfile = kwargs['savename']
    else:
        ncfile = fort61 + '.nc'
    nc = netCDF4.Dataset(ncfile, 'w', format='NETCDF4')

    # Global attributes
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    tmpline = fobj.readline()
    nc.description = tmpline[2:34]
    nc.rundes = tmpline[2:34]
    nc.runid = tmpline[36:60]
    nc.model = 'ADCIRC'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())

    # Record number of time steps and station
    tmpline = fobj.readline().split()
    ntsteps = np.int(tmpline[0])
    sta = np.int(tmpline[1])

    # Create dimensions
    nc.createDimension('time', 0)  # The unlimited dimension
    nc.createDimension('station', sta)  # Number of stations
    nc.createDimension('namelen', 50)  # Length of station names

    # Create time vector
    nc.createVariable('time', 'f8', ('time'))
    nc.variables['time'].long_name = 'model time'
    nc.variables['time'].standard_name = 'time'
    nc.variables['time'].units = 'seconds since ' + ncdate
    nc.variables['time'].base_date = ncdate

    # Create and store spatial variables
    nc.createVariable('station_name', 'S1', ('station', 'namelen'))
    nc.variables['station_name'].long_name = 'station name'
    nc.variables['station_name'][:] = netCDF4.stringtochar(
        np.array(staname, dtype='S50'))
    nc.createVariable('x', 'f8', 'station')
    nc.variables['x'].long_name = 'longitude'
    nc.variables['x'].units = 'degrees east'
    nc.variables['x'].positive = 'east'
    nc.variables['x'][:] = x
    nc.createVariable('y', 'f8', 'station')
    nc.variables['y'].long_name = 'latitude'
    nc.variables['y'].units = 'degrees north'
    nc.variables['y'].positive = 'north'
    nc.variables['y'][:] = y

    # Create station variable
    nc.createVariable(varname, 'f8', ('time', 'station'))
    nc.variables[varname].long_name = longname
    nc.variables[varname].units = varunits

    # Store time-series variables
    for tt in range(ntsteps):
        nc.variables['time'][tt] = np.float64(fobj.readline().split()[0])
        for aa in range(sta):
            nc.variables[varname][tt,
                                  aa] = np.float64(fobj.readline().split()[1])

    # All done here
    fobj.close()
    nc.close()
Exemple #13
0
def fort64_to_nc(fort64,
                 varname_xy=['u-vel', 'v-vel'],
                 longname='water column vertically averaged',
                 varunits='m s-1',
                 ncdate='0000-00-00 00:00:00 UTC',
                 **kwargs):
    """ 
    Script to read fort.64-type (vector) files and store in a netcdf4 file

    PARAMETERS:
    -----------
    fort64: Path to fort64-type file
    ncdate : cold start date/time in CF standard: yyyy-MM-dd hh:mm:ss tz

    RETURNS:
    --------
    Netcdf containing
    time         : seconds since beginning of run 
    x,y variable : temporal variables (name provided in 'xy_varname') recorded
                   at the nodes of an unstructured grid. Size: [time,nodes]
    """

    fobj = open(fort64, 'r')

    # Create the file and add global attributes
    if 'savename' in kwargs:
        ncfile = kwargs['savename']
    else:
        ncfile = fort64 + '.nc'
    nc = netCDF4.Dataset(ncfile, 'w', format='NETCDF4')

    # Global attributes
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    tmpline = fobj.readline()
    nc.description = tmpline[2:34]
    nc.rundes = tmpline[2:34]
    nc.runid = tmpline[36:60]
    nc.model = 'ADCIRC'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())

    # Record number of time steps and nodes
    tmpline = fobj.readline().split()
    ntsteps = np.int(tmpline[0])
    nodes = np.int(tmpline[1])

    # Create dimensions
    nc.createDimension('time', 0)  # The unlimited dimension
    nc.createDimension('node', nodes)  # Number of nodes

    # Create time vector
    nc.createVariable('time', 'f8', ('time'))
    nc.variables['time'].long_name = 'model time'
    nc.variables['time'].standard_name = 'time'
    nc.variables['time'].units = 'seconds since ' + ncdate
    nc.variables['time'].base_date = ncdate

    # Create the rest of the variables
    nc.createVariable(varname_xy[0], 'f8', ('time', 'node'))
    nc.variables[varname_xy[0]].long_name = longname + ' e/w velocity'
    nc.variables[varname_xy[0]].units = varunits

    nc.createVariable(varname_xy[1], 'f8', ('time', 'node'))
    nc.variables[varname_xy[1]].long_name = longname + ' n/s velocity'
    nc.variables[varname_xy[1]].units = varunits

    for tt in range(ntsteps):
        # Store variables
        nc.variables['time'][tt] = np.float64(fobj.readline().split()[0])

        for aa in range(nodes):
            tmpline = fobj.readline().split()
            nc.variables[varname_xy[0]][tt, aa] = np.float64(tmpline[1])
            nc.variables[varname_xy[1]][tt, aa] = np.float64(tmpline[2])

    # All done here
    fobj.close()
    nc.close()
Exemple #14
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()
Exemple #15
0
def convert_output(workfld, outfile, time_int, bathyfile=None, inpfile=None):
    '''
    
    Parameters:
    -----------
    workfld      : Path to the folder where output files reside
    outfile      : Output NetCDF file
    time_int     : Time interval between output files [s] (will be updated if
                   input file is provided)
    bathyfile    : Full path to input netcdf bathy file (optional)
    inpfile      : Funwave input file used for metadata (optional)
         
    Output:
    -------
    NetCDF File with the variables in the folder. Not all are supported so you 
    may need to edit this file.
    
    '''

    # For testing only
    #workfld = '/scratch/temp/ggarcia/spectralWidthFunwave/02-runs/results/'
    #outfile = '/scratch/temp/ggarcia/spectralWidthFunwave/02-runs/test.nc'
    #time_int = 0.1
    #bathyfile = '/scratch/temp/ggarcia/spectralWidthFunwave/02-runs/depth.nc'
    #inpfile = '/scratch/temp/ggarcia/spectralWidthFunwave/02-runs/input.txt'

    # Get variable information ------------------------------------------------
    archivos = os.listdir(workfld)  # Get all files
    tmpvars = [x.split('_')[0] for x in archivos]  # All variables
    tmpvars = list(set(tmpvars))  # Unique variables

    # If no variables found exit
    if not tmpvars:
        print('No files found in ' + workfld)
        print('Quitting ...')
        return None

    # Make sure variables are within the supported ones
    supported_vars_time = [
        'eta', 'etamean', 'havg', 'hmax', 'hmin', 'hrms', 'mask', 'mask9',
        'MFmax', 'u', 'umax', 'umean', 'v', 'vmean', 'VORmax'
    ]
    vars_2d = [x for x in tmpvars if x in supported_vars_time]

    # Read input file if provided ----------------------------------------------
    if inpfile:

        print("Reading data from input file:")
        print("  " + inpfile)

        # Open file
        tmpinpfile = open(inpfile, 'r')

        # Output dictionary
        inpinfo = {}

        # Extract information (need to add wavemaker support)
        for tmpline in tmpinpfile:

            # Skip blank lines
            if len(tmpline.strip()) == 0:
                continue

            if "TITLE" == tmpline.split()[0]:
                inpinfo['title'] = tmpline.split()[2]
            elif "PX" == tmpline.split()[0]:
                inpinfo['px'] = tmpline.split()[2]
            elif "PY" == tmpline.split()[0]:
                inpinfo["py"] = tmpline.split()[2]
            elif "Mglob" == tmpline.split()[0]:
                inpinfo['mglob'] = tmpline.split()[2]
            elif "Nglob" == tmpline.split()[0]:
                inpinfo['nglob'] = tmpline.split()[2]
            elif "TOTAL_TIME" == tmpline.split()[0]:
                inpinfo['total_time'] = tmpline.split()[2]
            elif "PLOT_INTV" == tmpline.split()[0]:
                inpinfo["plot_intv"] = tmpline.split()[2]
                time_int = np.double(tmpline.split()[2])
            elif "DX" == tmpline.split()[0]:
                inpinfo['dx'] = tmpline.split()[2]
                dx = float(tmpline.split()[2])
            elif "DY" == tmpline.split()[0]:
                inpinfo['dy'] = tmpline.split()[2]
                dy = float(tmpline.split()[2])
            elif "WAVEMAKER" == tmpline.split()[0]:
                inpinfo['wavemaker'] = tmpline.split()[2]
            elif "PERIODIC" == tmpline.split()[0]:
                inpinfo['periodic'] = tmpline.split()[2]
            elif "SPONGE_ON" == tmpline.split()[0]:
                sponge = tmpline.split()[2]
                inpinfo['sponge'] = sponge
            elif "Sponge_west_width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_west_width'] = tmpline.split()[2]
            elif "Sponge_east_width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_east_width'] = tmpline.split()[2]
            elif "Sponge_south_width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_south_width'] = tmpline.split()[2]
            elif "Sponge_north_width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_north_width'] = tmpline.split()[2]
            elif "R_sponge" == tmpline.split()[0] and sponge == 'T':
                inpinfo['r_sponge'] = tmpline.split()[2]
            elif "A_sponge" == tmpline.split()[0] and sponge == 'T':
                inpinfo['a_sponge'] = tmpline.split()[2]
            elif "DISPERSION" == tmpline.split()[0]:
                inpinfo['dispersion'] = tmpline.split()[2]
            elif "Gamma1" == tmpline.split()[0]:
                inpinfo['gamma1'] = tmpline.split()[2]
            elif "Gamma2" == tmpline.split()[0]:
                inpinfo['gamma2'] = tmpline.split()[2]
            elif "Gamma3" == tmpline.split()[0]:
                inpinfo['gamma3'] = tmpline.split()[2]
            elif "Beta_ref" == tmpline.split()[0]:
                inpinfo['beta_ref'] = tmpline.split()[2]
            elif "SWE_ETA_DEP" == tmpline.split()[0]:
                inpinfo['swe_eta_dep'] = tmpline.split()[2]
            elif "Friction_Matrix" == tmpline.split()[0]:
                inpinfo['friction_matrix'] = tmpline.split()[2]
            elif "Cd_file" == tmpline.split()[0]:
                inpinfo['cd_file'] = tmpline.split()[2]
            elif "Cd" == tmpline.split()[0]:
                inpinfo['cd'] = tmpline.split()[2]
            elif "Time_Scheme" == tmpline.split()[0]:
                inpinfo['time_scheme'] = tmpline.split()[2]
            elif "HIGH_ORDER" == tmpline.split()[0]:
                inpinfo['spatial_scheme'] = tmpline.split()[2]
            elif "CONSTRUCTION" == tmpline.split()[0]:
                inpinfo['construction'] = tmpline.split()[2]
            elif "CFL" == tmpline.split()[0]:
                inpinfo['cfl'] = tmpline.split()[2]
            elif "MinDepth" == tmpline.split()[0]:
                inpinfo['min_depth'] = tmpline.split()[2]
            elif "MinDepthFrc" == tmpline.split()[0]:
                inpinfo['mindepthfrc'] = tmpline.split()[2]

        # Close file
        tmpinpfile.close()

    else:

        # Assume grid spacing to be 1 meter
        print("Input file not provided")
        dx = 1
        dy = 1
        inpinfo = False

    # Coordinates and depth ---------------------------------------------------
    # Bathymetry file provided
    if bathyfile:

        print("Reading coordinates and depth from:")
        print("  " + bathyfile)

        ncfile = netCDF4.Dataset(bathyfile, 'r')
        x_rho = ncfile.variables['x_rho'][:]
        if ncfile.variables.has_key('y_rho'):
            y_rho = ncfile.variables['y_rho'][:]
        else:
            y_rho = None
        h = ncfile.variables['h'][:]
        ncfile.close()

    # Bathymetry file not provided but have output file
    elif os.path.isfile(workfld + '/dep.out'):

        # Fix this
        h = np.loadtxt(workfld + '/dep.out')

        hdims = h.ndim
        if hdims == 1:
            x_rho = np.arange(0, h.shape[0], dx)
        elif hdims == 2:
            x_rho, y_rho = np.meshgrid(np.arange(0, h.shape[1], dx),
                                       np.arange(0, h.shape[0], dy))
        else:
            print('Something is wrong with the depth file')
            return None

    # No bathymetry file provided (I am not capable of reading the input file)
    else:
        print("No bathymetry file provided")
        print("You could copy your input bathymetry text file to ")
        print(workfld + '/dep.out')
        return None

    # Get dimensions of variables
    hdims = h.ndim

    # Create NetCDF file -------------------------------------------------------

    print("Creating " + outfile)

    # Global attributes
    nc = netCDF4.Dataset(outfile, 'w', format='NETCDF4')
    nc.Description = 'Funwave Output'
    nc.Author = '*****@*****.**'
    nc.Created = time.ctime()
    nc.Type = 'Funwave v2.1 snapshot output'
    nc.Owner = 'Nearshore Modeling Group'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Source = workfld
    nc.Script = os.path.realpath(__file__)

    # Add more global variables to output
    if inpinfo:
        for tmpatt in inpinfo.keys():
            nc.__setattr__(tmpatt, inpinfo[tmpatt][:])

    # Create dimensions
    if hdims == 2:
        eta_rho, xi_rho = h.shape
        nc.createDimension('eta_rho', eta_rho)
    else:
        xi_rho = h.shape[0]
        eta_rho = 1
    nc.createDimension('xi_rho', xi_rho)
    nc.createDimension('ocean_time', 0)

    # Write coordinate axes ----------------------------------------------
    if hdims == 2:

        nc.createVariable('x_rho', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho

        nc.createVariable('y_rho', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['y_rho'].units = 'meter'
        nc.variables['y_rho'].longname = 'y-locations of RHO points'
        nc.variables['y_rho'][:] = y_rho

        nc.createVariable('h', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h

    else:

        nc.createVariable('x_rho', 'f8', ('xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho

        nc.createVariable('h', 'f8', ('xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h

    # Create time vector -------------------------------------------
    tmpruns = [x for x in archivos if x.split('_')[0] == vars_2d[0]]
    tmpruns.sort()
    time_max = float(tmpruns[-1].split('_')[-1])
    time_min = float(tmpruns[0].split('_')[-1])

    twave = np.arange(time_min - 1,
                      time_int * (time_max - time_min + 1) + time_min - 1,
                      time_int)
    if twave.shape[0] > len(tmpruns):
        twave = twave[:-1]

    nc.createVariable('ocean_time', 'f8', 'ocean_time')
    nc.variables['ocean_time'].units = 'seconds since 2000-01-01 00:00:00'
    nc.variables['ocean_time'].calendar = 'julian'
    nc.variables['ocean_time'].long_name = 'beach time'
    nc.variables['ocean_time'][:] = twave

    # Create variables --------------------------------------------------------

    # Variable information
    varinfo = defaultdict(dict)

    varinfo['eta']['units'] = 'meter'
    varinfo['eta']['longname'] = 'water surface elevation'
    varinfo['etamean']['units'] = 'meter'
    varinfo['etamean']['longname'] = 'Mean wave induced setup'

    varinfo['u']['units'] = 'meter second-1'
    varinfo['u']['longname'] = 'Flow velocity in the xi direction'
    varinfo['v']['units'] = 'meter second-1'
    varinfo['v']['longname'] = 'Flow velocity in the eta direction'

    varinfo['umean']['units'] = 'meter second-1'
    varinfo['umean'][
        'longname'] = 'Time-averaged flow velocity in xi direction'
    varinfo['vmean']['units'] = 'meter second-1'
    varinfo['vmean'][
        'longname'] = 'Time-averaged flow velocity in eta direction'

    varinfo['umax']['units'] = 'meter second-1'
    varinfo['umax']['longname'] = 'Maximum flow velocity in xi direction'
    varinfo['vmax']['units'] = 'meter second-1'
    varinfo['vmax']['longname'] = 'Maximum flow velocity in eta direction'

    varinfo['hmax']['units'] = 'meter'
    varinfo['hmax']['longname'] = 'Maximum wave height'
    varinfo['hmin']['units'] = 'meter'
    varinfo['hmin']['longname'] = 'Minimum wave height'
    varinfo['havg']['units'] = 'meter'
    varinfo['havg']['longname'] = 'Average wave height'
    varinfo['hrms']['units'] = 'meter'
    varinfo['hrms']['longname'] = 'Root mean squared wave height'

    varinfo['mask']['units'] = 'Boolean'
    varinfo['mask']['longname'] = 'Logical parameter for output wetting-drying'
    varinfo['mask9']['units'] = 'Boolean'
    varinfo['mask9']['longname'] = 'Logical parameter for output MASK9'

    varinfo['VORmax']['units'] = 'second-1'
    varinfo['VORmax']['longname'] = 'Maximum vorticity'
    varinfo['MFmax']['units'] = 'meter second-s'
    varinfo['MFmax']['longname'] = 'Maximum momentum flux'

    # Create variables
    if hdims == 1:
        nc_dims = ('ocean_time', 'xi_rho')
    else:
        nc_dims = ('ocean_time', 'eta_rho', 'xi_rho')

    print("Creating variables")
    for aa in vars_2d:

        print('  ' + aa)

        # Create variable
        create_nc_var(nc, aa, nc_dims, varinfo[aa]['units'],
                      varinfo[aa]['longname'])

        try:
            tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % time_min)
        except ValueError:
            tmpvar = np.zeros_like(h) * np.NAN

        nc.variables[aa][:] = np.expand_dims(tmpvar, axis=0)

        for bb in range(len(twave)):

            try:
                tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' %
                                    (bb + time_min))
            except ValueError:
                tmpvar = np.zeros_like(h) * np.NAN

            append_nc_var(nc, tmpvar, aa, bb - 1)

    # Close NetCDF file
    print('Closing ' + outfile)
    nc.close()
Exemple #16
0
def write_bathy(x,y,h,path,ncsave=True):
    '''
    
    Parameters:
    ----------
    x,y         : 2D arrays of coordinates
    h           : Bathymetry
    path        : Full path where the output will be saved
    ncsave      : Save as NetCDF4 file (optional, defaults to True)
    
    Output:
    -------
    bathy.nc    : NetCDF4 file with the bathymetry
    bathy.txt   : Text file with the depth information for Funwave input.
    
    '''
    
    # Get bathymetry dimensions
    eta_rho, xi_rho = x.shape
    
    if ncsave:
    
        # Global attributes  
        nc = netCDF4.Dataset(path + 'bathy.nc', 'w', format='NETCDF4')
        nc.Description = 'NHWAVE 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', xi_rho)
        nc.createDimension('eta_rho', eta_rho)
    
        # Write coordinates and depth to netcdf file
        create_nc_var(nc, 'x_rho',('eta_rho', 'xi_rho'),
                     'meter','x-locations of RHO-points')
        nc.variables['x_rho'][:] = x
        create_nc_var(nc, 'y_rho', ('eta_rho', 'xi_rho'),
                     'meter','y-locations of RHO-points')
        nc.variables['y_rho'][:] = y
        create_nc_var(nc,'h',('eta_rho', 'xi_rho'),
                     'meter','bathymetry at RHO-points') 
        nc.variables['h'][:] = h
                
        # Close NetCDF file
        nc.close()

    else: 
    
        print("NetCDF file not requested")
        
        

    # Output the text file -----------------------------------------------------        
    fid = open(path + 'bathy.txt','w')
    for aa in range(x.shape[0]):
        for bb in range(x.shape[1]):
            fid.write('%12.3f' % h[aa,bb])
        fid.write('\n')
    fid.close()



    #===========================================================================
    # Print input file options
    #===========================================================================
    print(' ')
    print('===================================================================')
    print('In your NHWAVE input file:')
    print('Mglob = ' + np.str(xi_rho))
    print('Nglob = ' + np.str(eta_rho))
    print('DX = ' + np.str(np.abs(x[0,1] - x[0,0])))
    print('DY = ' + np.str(np.abs(y[1,0] - y[0,0])))
    print('Ywidth_WK > ' + str(y.max() - y.min()))
    print('DEP_WK = ' + str(h.max()))
    print('Check sponge layer widths')
    print('===================================================================')
    print(' ')
Exemple #17
0
def write_bathy_1d(x,h,path,ncsave=True):
    '''
    
    Parameters:    
    ----------
    x           : 1D array of x coordinates
    h           : Bathymetry
    path        : Full path where the output will be saved
    ncsave      : Save bathy as NetCDF file
    
    Output:
    -------
    bathy.txt   : Text file with the depth information for Funwave input.
    bathy.nc    : (Optional) NetCDF4 bathymetry file. 
    
    Notes:
    ------
    Variables are assumed to be on a regularly spaced grid.
    
    '''

    # Output the text file -----------------------------------------------------        
    fid = open(path + 'depth.txt','w')
    for aa in range(len(h)):
        fid.write('%12.3f' % h[aa])
    fid.write('\n')
    fid.close()

    if ncsave:
    
        # Global attributes  
        nc = netCDF4.Dataset(path + 'depth.nc', 'w', format='NETCDF4')
        nc.Description = 'NHWAVE 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
        xi_rho = len(h)
        nc.createDimension('xi_rho', xi_rho)
    
        # Write coordinates and depth to netcdf file
        create_nc_var(nc,'x_rho',('xi_rho'),'meter','x-locations of RHO-points')
        nc.variables['x_rho'][:] = x
        create_nc_var(nc,'h',('xi_rho'),'meter','bathymetry at RHO-points')
        nc.variables['h'][:] = h
                
        # Close NetCDF file
        nc.close()

    else: 
    
        print("NetCDF file not requested")
        
        

    #===========================================================================
    # Print input file options
    #===========================================================================
    print(' ')
    print('===================================================================')
    print('In your NHWAVE input file:')
    print('Mglob = ' + np.str(len(x)))
    print('Nglob = 1')
    print('DX = ' + np.str(np.abs(x[1] - x[0])))
    print('DY = anything larger than DX works')
    print('DEP_WK = ' + str(h.max()))
    print('Check sponge layer widths')
    print('===================================================================')
    print(' ')
Exemple #18
0
def convert_output(workfld,outfile,bathyfile=None,inpfile=None,verbose=False):
    '''
    
    Tools to convert ASCII output from NHWAVE to NetCDF4
    
    Parameters:
    -----------
    workfld      : Path to the folder where output files reside
    outfile      : Output file
    bathyfile    : Full path to input NetCDF bathy file (optional) 
    inpfile      : NHwave input files used to add metadata (optional)
    verbose      : Display progress messages (optional)
    
    Output:
    -------
    NetCDF File with the variables in the folder. Not all are supported so you 
    may need to edit this file.
    
    Notes:
    ------    
    
    TODO:
    -----
    1. Need to test for 2DH simulations.
    2. Add support for exponential vertical layers
    
    '''

    # Get variable information -------------------------------------------------
    archivos = os.listdir(workfld)                          # All files   
    tmpvars = [x.split('_')[0] for x in archivos]           # Variables
    tmpvars = list(set(tmpvars))                            # Unique variables

    # If no variables found exit    
    if not tmpvars:
        print('No files found in ' + workfld)
        print('Quitting ...')
        return None
    
    # Make sure variables are within the supported ones (exclude time here)
    supported_vars_2d_time = ['eta']    
    vars_2d_time = [x for x in tmpvars if x in supported_vars_2d_time]
    supported_vars_2d = ['setup','waveheight','umean','vmean']    
    vars_2d = [x for x in tmpvars if x in supported_vars_2d]
    supported_vars_3d_time = ['u','v','w']
    vars_3d_time = [x for x in tmpvars if x in supported_vars_3d_time]        
    supported_vars_3d = ['euler','lag']
    vars_3d = [x for x in tmpvars if x in supported_vars_3d]        
    
    # Read input file if provided ----------------------------------------------
    if inpfile:
       
        if verbose: 
            print("Reading data from input file:")
            print("  " + inpfile)
        
        # Open file
        tmpinpfile = open(inpfile,'r')
        
        # Output dictionary
        inpinfo = {}
        
        # Extract information (need to add wavemaker support)
        for tmpline in tmpinpfile:
            
            # Skip blank lines
            if len(tmpline.strip()) == 0:
                continue
            
            # Read selected keywords
            if "TITLE" == tmpline.split()[0]:
                inpinfo['title'] = tmpline.split()[2]
            elif "Mglob" == tmpline.split()[0]:
                inpinfo['mglob'] = tmpline.split()[2]
            elif "Nglob" == tmpline.split()[0]:
                inpinfo['nglob'] = tmpline.split()[2]
            elif "Kglob" == tmpline.split()[0]:
                inpinfo['kglob'] = tmpline.split()[2]
            elif "PX" == tmpline.split()[0]:
                inpinfo['px'] = tmpline.split()[2]
            elif "PY" == tmpline.split()[0]:
                inpinfo["py"] = tmpline.split()[2]
            elif "TOTAL_TIME" == tmpline.split()[0]:
                inpinfo['total_time'] = tmpline.split()[2]
            elif "PLOT_START" == tmpline.split()[0]:
                inpinfo['plot_start'] = tmpline.split()[2]
            elif "PLOT_INTV" == tmpline.split()[0]:
                inpinfo["plot_intv"] = tmpline.split()[2]
            elif "DX" == tmpline.split()[0]:
                inpinfo['dx'] = tmpline.split()[2]
                dx = float(tmpline.split()[2])
            elif "DY" == tmpline.split()[0]:
                inpinfo['dy'] = tmpline.split()[2]
                dy = float(tmpline.split()[2])
            elif "IVGRD" == tmpline.split()[0]:
                inpinfo['ivgrd'] = tmpline.split()[2]
            elif "DT_INI" == tmpline.split()[0]:
                inpinfo['dt_ini'] = tmpline.split()[2]
            elif "DT_MIN" == tmpline.split()[0]:
                inpinfo['dt_min'] = tmpline.split()[2]
            elif "DT_MAX" == tmpline.split()[0]:
                inpinfo['dt_max'] = tmpline.split()[2]
            elif "HIGH_ORDER" == tmpline.split()[0]:
                inpinfo['high_order'] = tmpline.split()[2]
            elif "TIME_ORDER" == tmpline.split()[0]:
                inpinfo['time_order'] = tmpline.split()[2]
            elif "CONVECTION" == tmpline.split()[0]:
                inpinfo['convection'] = tmpline.split()[2]
            elif "HLLC" == tmpline.split()[0]:
                inpinfo['hllc'] = tmpline.split()[2]
            elif "Ibot" == tmpline.split()[0]:
                inpinfo['ibot'] = tmpline.split()[2]
                ibot = int(tmpline.split()[2])
            elif "Cd0" == tmpline.split()[0] and ibot == 1:
                inpinfo['cd0'] = tmpline.split()[2]
            elif "Zob" == tmpline.split()[0] and ibot == 2:
                inpinfo['zob'] = tmpline.split()[2]
            elif "Iws" == tmpline.split()[0]:
                inpinfo['Iws'] = tmpline.split()[2]
                iws = int(tmpline.split()[2])
            elif "WindU" == tmpline.split()[0] and iws == 1:
                inpinfo['windu'] = tmpline.split()[2]
            elif "WindV" == tmpline.split()[0] and iws == 1:
                inpinfo['windv'] = tmpline.split()[2]
            elif "slat" == tmpline.split()[0]:
                inpinfo['slat'] = tmpline.split()[2]
            elif "BAROTROPIC" == tmpline.split()[0]:
                inpinfo['barotropic'] = tmpline.split()[2]
            elif "NON_HYDRO" == tmpline.split()[0]:
                inpinfo['non_hydro'] = tmpline.split()[2]
            elif "CFL" == tmpline.split()[0]:
                inpinfo['cfl'] = tmpline.split()[2]
            elif "TRAMP" == tmpline.split()[0]:
                inpinfo['tramp'] = tmpline.split()[2]
            elif "MinDep" == tmpline.split()[0]:
                inpinfo['min_dep'] = tmpline.split()[2]
            elif "ISOLVER" == tmpline.split()[0]:
                inpinfo['isolver'] = tmpline.split()[2]
            elif "PERIODIC_X" == tmpline.split()[0]:
                inpinfo['periodic_x'] = tmpline.split()[2]
            elif "PERIODIC_Y" == tmpline.split()[0]:
                inpinfo['periodic_y'] = tmpline.split()[2]
            elif "BC_X0" == tmpline.split()[0]:
                inpinfo['bc_x0'] = tmpline.split()[2]
            elif "BC_Xn" == tmpline.split()[0]:
                inpinfo['bc_xn'] = tmpline.split()[2]
            elif "BC_Y0" == tmpline.split()[0]:
                inpinfo['bc_y0'] = tmpline.split()[2]
            elif "BC_Yn" == tmpline.split()[0]:
                inpinfo['bc_yn'] = tmpline.split()[2]
            elif "BC_Z0" == tmpline.split()[0]:
                inpinfo['bc_z0'] = tmpline.split()[2]
            elif "BC_Zn" == tmpline.split()[0]:
                inpinfo['bc_zn'] = tmpline.split()[2]
            elif "WAVEMAKER" == tmpline.split()[0]:
                inpinfo['wavemaker'] = tmpline.split()[2]
            elif "Xsource_West" == tmpline.split()[0] and \
                 inpinfo['wavemaker'][0:3] == 'INT':
                inpinfo['xsource_west'] = tmpline.split()[2]
            elif "Xsource_East" == tmpline.split()[0] and \
                 inpinfo['wavemaker'][0:3] == 'INT':
                inpinfo['xsource_east'] = tmpline.split()[2]
            elif "Ysource_Suth" == tmpline.split()[0] and \
                 inpinfo['wavemaker'][0:3] == 'INT':
                inpinfo['ysource_suth'] = tmpline.split()[2]
            elif "Ysource_Nrth" == tmpline.split()[0] and \
                 inpinfo['wavemaker'][0:3] == 'INT':
                inpinfo['xsource_nrth'] = tmpline.split()[2]               
            elif "SPONGE_ON" == tmpline.split()[0]:
                inpinfo['sponge'] = tmpline.split()[2]
                sponge = tmpline.split()[2]
            elif "Sponge_West_Width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_west_width'] = tmpline.split()[2]
            elif "Sponge_East_Width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_east_width'] = tmpline.split()[2]
            elif "Sponge_South_Width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_south_width'] = tmpline.split()[2]
            elif "Sponge_North_Width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_north_width'] = tmpline.split()[2]
            elif "Seed"  == tmpline.split()[0]:
                inpinfo['Seed'] = tmpline.split()[2]

            
        # Close file
        tmpinpfile.close()
            
    else:
        
        inpinfo = None
        
        if verbose:
            print("Input file not provided")
    


    # If bathymetry file is given then the coordinates should be taken from 
    # this file, otherwise unit coordinates will be assumed with the shape of 
    # one of the output files.
    if bathyfile: 
        ncfile = netCDF4.Dataset(bathyfile,'r')
        x_rho = ncfile.variables['x_rho'][:]
        if ncfile.variables.has_key('y_rho'):
            y_rho = ncfile.variables['y_rho'][:]
        h = ncfile.variables['h'][:]
        ncfile.close()
        hdims = h.ndim
        
    else:
        
        if not os.path.isfile(workfld + '/depth'):
            print('No depth file found in ' + workfld)
            return None
        
        h = np.loadtxt(workfld + '/depth')
        
        # Check if it is a 1D or 2D model
        hdims = h.ndim                              # Horizontal dimensions
        if hdims == 1:
            x_rho = np.arange(0,h.shape[0],1)
        elif hdims == 2:
            x_rho, y_rho = np.meshgrid(np.arange(0,h.shape[1],1),
                                       np.arange(0,h.shape[0],1))
        else:
            print('Something is wrong with the depth file')
            print('Quitting...')
            return None
        
        
    # Load time vector
    if not os.path.isfile(workfld + '/time'):
        print("No time file found in " + workfld)
        print("Quitting ...")
        return None
    
    ocean_time = np.loadtxt(workfld + '/time')
        
        
    
    # Create NetCDF file ------------------------------------------------------  
    nc = netCDF4.Dataset(outfile, 'w', format='NETCDF4')
    nc.Description = 'NHWAVE Output'
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    nc.Owner = 'Nearshore Modeling Group'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Source = workfld
    nc.Script = os.path.realpath(__file__)
    
    # Add more global variables to output (if input file is provided)
    if inpinfo:
        for tmpatt in inpinfo.keys():
            nc.__setattr__(tmpatt,inpinfo[tmpatt][:])
    
    # Create dimensions
    if verbose:
        print('Creating dimensions')
        
    if hdims == 2:
        eta_rho, xi_rho = h.shape
        nc.createDimension('eta_rho', eta_rho)
    else:
        xi_rho = h.shape[0]
        eta_rho = 1
    nc.createDimension('xi_rho', xi_rho)            
    nc.createDimension('ocean_time',0)
                
    # Get vertical layers
    if not vars_3d and not vars_3d_time:
        print("No 3D variables found")
        s_rho = False
    else:
        # Load any 3D variables
        if os.path.isfile(workfld + '/' + vars_3d_time[0] + '_00001'):
            tmpvar = np.loadtxt(workfld + '/' + vars_3d_time[0] + '_00001')
        elif os.path.isfile(workfld + '/' + vars_3d[0] + '_umean'):
            tmpvar = np.loadtxt(workfld + '/' + vars_3d[0] + '_umean')
        elif os.path.isfile(workfld + '/' + vars_3d[0] + '_vmean'):
            tmpvar = np.loadtxt(workfld + '/' + vars_3d[0] + '_vmean')            
        else:
            tmpvar = np.loadtxt(workfld + '/' + vars_3d[0])
        
        # Outputs are stacked on the first dimension of the file
        # I need to enhance this and will probably have to use the input file
#         if hdims == 2:
#             s_rho = tmpvar.shape[0]/h.shape[0]
#         else:
#             s_rho = tmpvar.shape[0]
        s_rho = tmpvar.size/h.shape[0]
        
        nc.createDimension('s_rho',s_rho)
        
    
    # Write coordinates, bathymetry and time ----------------------------------
    if verbose:
        print("Saving coordinates and time")
    
    if hdims == 2:
        
        nc.createVariable('x_rho','f8',('eta_rho','xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho
        
        nc.createVariable('y_rho','f8',('eta_rho','xi_rho'))
        nc.variables['y_rho'].units = 'meter'
        nc.variables['y_rho'].longname = 'y-locations of RHO points'
        nc.variables['y_rho'][:] = y_rho

        nc.createVariable('h','f8',('eta_rho','xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h


    else:
        
        nc.createVariable('x_rho','f8',('xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho
        
        nc.createVariable('h','f8',('xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h
        
    
    # Create s_rho vector
    if s_rho:
        ds    = 1.0/s_rho
        sigma = np.arange(ds/2.0,1-ds/2.0,ds)
        nc.createVariable('s_rho','f8',('s_rho'))
        nc.variables['s_rho'].longname = 's-coordinate at cell centers'
        nc.variables['s_rho'].positive = 'up'
        nc.variables['s_rho'].notes = 'small s_rho means close to bottom'
        nc.variables['s_rho'][:] = sigma 
    
    # Create time vector
    nc.createVariable('ocean_time','f8','ocean_time')
    nc.variables['ocean_time'].units = 'seconds since 2000-01-01 00:00:00'
    nc.variables['ocean_time'].calendar = 'julian'
    nc.variables['ocean_time'].long_name = 'beach time since initialization'
    nc.variables['ocean_time'].notes = 'units are arbitrary'
    nc.variables['ocean_time'][:] = ocean_time



    # Create variables ---------------------------------------------------------    

    # Variable information
    varinfo = defaultdict(dict)

    varinfo['eta']['units'] = 'meter'
    varinfo['eta']['longname'] = 'water surface elevation'

    varinfo['waveheight']['units'] = 'meter'
    varinfo['waveheight']['longname'] = 'Mean wave height'
    varinfo['setup']['units'] = 'meter'
    varinfo['setup']['longname'] = 'Mean wave induced setup'
    
    varinfo['u']['units'] = 'meter second-1'
    varinfo['u']['longname'] = 'Flow velocity in the xi direction'
    varinfo['v']['units'] = 'meter second-1'
    varinfo['v']['longname'] = 'Flow velocity in the eta direction'
    varinfo['w']['units'] = 'meter second-1'
    varinfo['w']['longname'] = 'Flow velocity in the vertical direction'
    
    varinfo['umean']['units'] = 'meter second-1'
    varinfo['umean']['longname'] = 'Depth-averaged flow velocity in xi direction'
    varinfo['vmean']['units'] = 'meter second-1'
    varinfo['vmean']['longname'] = 'Depth-averaged flow velocity in eta direction'    
    
    varinfo['lag_umean']['units'] = 'meter second-1'
    varinfo['lag_umean']['longname'] = 'Lagrangian mean velocity in xi direction'
    varinfo['lag_vmean']['units'] = 'meter second-1'
    varinfo['lag_vmean']['longname'] = 'Lagrangian mean velocity in eta direction'
    varinfo['lag_wmean']['units'] = 'meter second-1'
    varinfo['lag_wmean']['longname'] = 'Lagrangian mean velocity in vertical direction'
    
    varinfo['euler_umean']['units'] = 'meter second-1'
    varinfo['euler_umean']['longname'] = 'Eulerian mean velocity in xi direction'
    varinfo['euler_vmean']['units'] = 'meter second-1'
    varinfo['euler_vmean']['longname'] = 'Eulerian mean velocity in eta direction'
    varinfo['euler_wmean']['units'] = 'meter second-1'
    varinfo['euler_wmean']['longname'] = 'Eulerian mean velocity in vertical direction'
    


    # Loop over 2D variables that have no time component ----------------------
    if hdims == 1:
        nc_dims = ('xi_rho')
    else:
        nc_dims = ('eta_rho','xi_rho')
          
    for aa in vars_2d:
        
        if verbose:
            print('  Writing ' + aa)
            
        # Create variable
        create_nc_var(nc,aa,nc_dims,varinfo[aa]['units'],
                      varinfo[aa]['longname'])
        nc.variables[aa][:] = np.loadtxt(workfld + '/' + aa) 
        
    
    # Loop over 3D variables that have no time component ----------------------
    if hdims == 1:
        nc_dims = ('s_rho','xi_rho')
    else:
        nc_dims = ('s_rho','eta_rho','xi_rho')    
    
    for aa in vars_3d:
        
        if verbose:
            print('  Writing ' + aa)
        
        if aa == 'euler' or aa == 'lag':
            for bb in ['umean','vmean','wmean']:
                create_nc_var(nc,aa + '_' + bb,nc_dims,
                              varinfo[aa + '_' + bb]['units'],
                              varinfo[aa + '_' + bb]['longname'])                
                if hdims == 1:
                    nc.variables[aa + '_' + bb][:] = \
                    np.loadtxt(workfld + '/' + aa + '_' + bb)
                else:
                    tmpvar = np.loadtxt(workfld + '/' + aa + '_' + bb)
                    tmpvar2 = np.zeros((s_rho,eta_rho,xi_rho))
                    for cc in range(s_rho):                        
                        tmpvar2[cc,:,:] = tmpvar[cc*eta_rho:(cc+1)*eta_rho,:]
                        
                    nc.variables[aa + '_' + bb][:] = tmpvar2
                    del tmpvar,tmpvar2
                    
        else:
            # Need to test this part with a full 3d code
            print("need to fix this")

            
        
        
    # Loop over 2D variables that have a time component -----------------------        
    if hdims == 1:
        nc_dims = ('ocean_time','xi_rho')
    else:
        nc_dims = ('ocean_time','eta_rho','xi_rho')
          
          
    for aa in vars_2d_time:
        
        if verbose:
            print('  Writing ' + aa)
        
        # Create variable
        create_nc_var(nc,aa,nc_dims,varinfo[aa]['units'],
                      varinfo[aa]['longname'])
        
        tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % 1)        
        nc.variables[aa][:] = np.expand_dims(tmpvar,axis=0)
        
        for bb in range(2,len(ocean_time)+1):
            tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % bb)
            append_nc_var(nc,tmpvar,aa,bb-1)
             
    

    # Loop over 3D variables that have a time component -----------------------        
    if hdims == 1:
        nc_dims = ('ocean_time','s_rho','xi_rho')
    else:
        nc_dims = ('ocean_time','s_rho','eta_rho','xi_rho')
          
          
    for aa in vars_3d_time:
        
        if verbose:
            print('  Writing ' + aa)
        
        # Create variable
        create_nc_var(nc,aa,nc_dims,varinfo[aa]['units'],
                      varinfo[aa]['longname'])
        
        if hdims == 1:
            
            tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % 1)
            if s_rho == 1:
                nc.variables[aa][:] = np.expand_dims(np.expand_dims(tmpvar,
                                                                    axis=0),
                                                     axis=0)
            else:
                nc.variables[aa][:] = np.expand_dims(tmpvar,axis=0)
            for bb in range(2,len(ocean_time)+1):
                tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % bb)
                append_nc_var(nc,tmpvar,aa,bb-1)
        
        else:
            for bb in range(1,len(ocean_time)+1):
                tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % bb)
                tmpvar2 = np.zeros((s_rho,eta_rho,xi_rho))
                for cc in range(s_rho):
                    tmpvar2[cc,:,:] = tmpvar[cc*eta_rho:(cc+1)*eta_rho,:]
                
                if bb == 1:
                    nc.variables[aa][:] = np.expand_dims(tmpvar2,axis=0)
                else:
                    append_nc_var(nc,tmpvar2,aa,bb-1)
                del tmpvar,tmpvar2
                
                
                
    # Close NetCDF file -------------------------------------------------------
    if verbose:
        print('Created: ' + outfile)
    nc.close()
def main():
    # Parse arguments
    parse_cli_args()

    # Sanity checks

    # Check to make sure that the JSON resource file exists!
    try:
        resource_file_fh = open(args.resource_file, "r")
    except IOError:
        error_msg("Resource file '%s' is not accessible or does not exist!" %
                  args.resource_file)
        exit(1)

    # Check to make sure that the JSON resource file is valid!
    try:
        resource_data = json.loads(resource_file_fh.read())
    except KeyboardInterrupt:
        info_msg("CTRL-C detected, exiting.")
        exit(0)
    except:
        error_msg("Resource file '%s' is not a valid JSON file!" %
                  args.resource_file)
        print(traceback.format_exc())
        exit(1)

    # Close file - we got the data already!
    resource_file_fh.close()

    # Print verbose version information
    if args.verbose:
        info_msg("Using following versions:")
        info_msg("    netcdf4-python v%s" % netCDF4.__version__)
        info_msg("    NetCDF v%s" % getlibversion())
        info_msg("    HDF5 v%s" % netCDF4.__hdf5libversion__)
        info_msg("    Python v%s\n" % sys.version.split("\n")[0].strip())
        info_msg("Reading and validating NetCDF4 files...")

    # Check to make sure the NetCDF4 files are legitimate!
    nc4_files_root = []

    init_counter(len(args.nc4_files), "Reading/verifying file")
    for nc4_file in args.nc4_files:
        try:
            open(nc4_file, "r").close()
        except KeyboardInterrupt:
            info_msg("CTRL-C detected, exiting.")
            exit(0)
        except IOError:
            error_msg("The NetCDF4 file '%s' does not exist!" % nc4_file)
            exit(1)

        progress_counter(nc4_file)

        try:
            rootgrp = Dataset(nc4_file, "a", format="NETCDF4")
            nc4_files_root.append({"file": nc4_file, "group": rootgrp})
        except KeyboardInterrupt:
            info_msg("CTRL-C detected, exiting.")
            exit(0)
        except:
            error_msg("'%s' is not a valid NetCDF4 file!" % nc4_file)
            exit(1)

    line_msg_done()

    # Global attributes
    if args.global_attributes:
        # Check if we have a global attributes entry in the resource file
        if not "global_attributes" in resource_data:
            warning_msg(
                "Resource file '%s' does not have any global attributes, skipping."
                % args.resource_file)
        else:
            # Initialize our counter
            init_counter(len(nc4_files_root),
                         "Applying global attributes to file")

            for nc4_entry in nc4_files_root:
                # Update progress counter
                progress_counter(nc4_entry["file"])

                for global_attr_key in resource_data["global_attributes"]:
                    global_attr_val = resource_data["global_attributes"][
                        global_attr_key]

                    # We need to convert unicode to ASCII
                    if type(global_attr_val) == unicode:
                        global_attr_val = str(global_attr_val)

                    # BUG fix - NetCDF really, really, REALLY does not like
                    # 64-bit integers. We forcefully convert the value to a
                    # 32-bit signed integer, with some help from numpy!
                    if type(global_attr_val) == int:
                        global_attr_val = numpy.int32(global_attr_val)

                    setattr(nc4_entry["group"], global_attr_key,
                            global_attr_val)
            line_msg_done()

    # Variable attributes
    if args.var_attributes:
        # Check if we have a variable attributes entry in the resource file
        if not "variable_attributes" in resource_data:
            warning_msg(
                "Resource file '%s' does not have any variable attributes, skipping."
                % args.resource_file)
        else:
            # Initialize our counter
            init_counter(len(nc4_files_root),
                         "Applying variable attributes to file")

            for nc4_entry in nc4_files_root:
                # Update progress counter
                progress_counter(nc4_entry["file"])

                # Iterate through all of our var_attr variables
                for var in resource_data["variable_attributes"]:
                    if var in nc4_entry["group"].variables.keys():
                        for var_attr_key in resource_data[
                                "variable_attributes"][var]:
                            var_attr_val = resource_data[
                                "variable_attributes"][var][var_attr_key]
                            var_attr_key = str(var_attr_key)

                            # We need to convert unicode to ASCII
                            if type(var_attr_val) == unicode:
                                var_attr_val = list(str(var_attr_val))

                            # BUG fix - NetCDF really, really, REALLY does not like
                            # 64-bit integers. We forcefully convert the value to a
                            # 32-bit signed integer, with some help from numpy!
                            if type(var_attr_val) == int:
                                var_attr_val = numpy.int32(var_attr_val)

                            setattr(nc4_entry["group"].variables[var],
                                    var_attr_key, var_attr_val)
                    else:
                        warning_msg("Can't find variable %s in file %s!" %
                                    (var, nc4_entry["file"]))
            line_msg_done()

    # Close everything
    init_counter(len(nc4_files_root), "Saving changes to file")
    for nc4_entry in nc4_files_root:
        progress_counter(nc4_entry["file"])
        nc4_entry["group"].close()

    line_msg_done()

    info_msg("Attribute appending complete!")
import sys
import traceback
import numpy

try:
    import ujson as json
except:
    import json

# Version information
__version__ = "0.9b"

VERSION_STR = 'nc_diag_attr v' + __version__ + "\n\n" + \
    "Using the following library/runtime versions:\n" + \
    ("    netcdf4-python v%s\n" % netCDF4.__version__) + \
    ("    NetCDF v%s\n" % getlibversion()) + \
    ("    HDF5 v%s\n" % netCDF4.__hdf5libversion__) + \
    ("    Python v%s\n" % sys.version.split("\n")[0].strip())

# CLI Arguments
global args


def parse_cli_args():
    global args
    parser = argparse.ArgumentParser(  #prog='ipush',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=
        "Tool to add/modify global and variable attributes for NetCDF files",
        version=VERSION_STR)
Exemple #21
0
def write_bathy(x, h, path, y=None, ncsave=True, dt=None):
    '''
    
    Parameters:    
    ----------
    x           : array of x coordinates
    y           : array of x coordinates (optional)
    h           : Bathymetry
    path        : Full path where the output will be saved
    ncsave      : Save bathy as NetCDF file
    dt          : (Optional) informs about the stability for a chosen dt
    
    Output:
    -------
    depth.txt   : Text file with the depth information for Funwave input.
    depth.nc    : (Optional) NetCDF4 bathymetry file. 
    
    Notes:
    ------
    1. Variables are assumed to be on a regularly spaced grid.
    2. If y is passed then 2D bathymetry is assumed. This means that 
       x,y,h have to be 2D arrays. Otherwise the code will fail.
    
    '''

    # Output the text file -----------------------------------------------------
    fid = open(path + 'depth.txt', 'w')
    if y is None:
        for aa in range(len(h)):
            fid.write('%12.3f\n' % h[aa])
        fid.close()
    else:
        for aa in range(h.shape[1]):
            for bb in range(h.shape[0]):
                fid.write('%12.3f' % h[bb, aa])
            fid.write('\n')
        fid.close()

    if ncsave:

        # Global attributes
        nc = netCDF4.Dataset(path + 'depth.nc', 'w', format='NETCDF4')
        nc.Description = 'Funwave 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
        if y is None:
            xi_rho = len(h)
            nc.createDimension('xi_rho', xi_rho)
            varShape = ('xi_rho')
        else:
            eta_rho, xi_rho = np.shape(h)
            nc.createDimension('xi_rho', xi_rho)
            nc.createDimension('eta_rho', eta_rho)
            varShape = ('eta_rho', 'xi_rho')

            # Write y variable
            create_nc_var(nc, 'y_rho', varShape, 'meter',
                          'y-locations of RHO-points')
            nc.variables['y_rho'][:] = y

        # Write coordinates and depth to netcdf file
        create_nc_var(nc, 'x_rho', varShape, 'meter',
                      'x-locations of RHO-points')
        nc.variables['x_rho'][:] = x

        create_nc_var(nc, 'h', varShape, 'meter', 'bathymetry at RHO-points')
        nc.variables['h'][:] = h

        # Close NetCDF file
        nc.close()

    else:

        print("NetCDF file not requested")

    #===========================================================================
    # Print input file options
    #===========================================================================
    print(' ')
    print(
        '===================================================================')
    print('In your funwaveC init file:')
    if y is None:
        dx = np.abs(x[1] - x[0])
        print('dimension ' + np.str(len(x) + 1) + ' 6 ' + np.str(dx) + ' 1')
    else:
        dx = np.abs(x[0, 1] - x[0, 0])  # For later use
        dy = np.abs(y[1, 0] - y[0, 0])
        print('dimension ' + np.str(x.shape[1] + 1) + ' ' +
              np.str(x.shape[0]) + ' ' + np.str(dx) + ' ' + np.str(dy))
    print(
        '===================================================================')
    print(' ')

    # Stability options
    stabilityCriteria(dx, h.max(), dt=dt, verbose=True)
Exemple #22
0
def write_bathy(x,z,outfld,y=None,ncsave=True):
    """
    
    Parameters:
    -----------
    x      : Vector or gridded x coordinates
    y      : Vector or gridded y coordinates (optional)
    outfld : Full path to where the files will be written
    z      : Vector or gridded depth
    ncsave : Save as netcdf file as well
    
    Output:
    -------
    Writes two or three files depending on the configuration
      x.grd, y.grd, z.dep
    
    Notes:
    ------
    Right now has been tested in 1d mode only
    
    """
    

    # Output the text file -----------------------------------------------------
    
    if y is not None:
        
        print("Writing 2D grids")
        fidx = open(outfld + 'x.grd','w')
        fidy = open(outfld + 'y.grd','w')
        fidz = open(outfld + 'z.dep','w')
                
        for aa in range(z.shape[0]):
            for bb in range(z.shape[1]):
                fidx.write('%16.4f' % x[aa,bb])
                fidy.write('%16.4f' % y[aa,bb])
                fidz.write('%16.4f' % z[aa,bb])
        
            fidx.write('\n')
            fidy.write('\n')
            fidz.write('\n')
        
        fidx.close()
        fidy.close()
        fidz.close()
        
    else:
        
        print("Writing 1D grids")
        
        # Water depth        
        fid = open(outfld + 'z.dep','w')
        for aa in range(len(z)):
            fid.write('%16.4f' % z[aa])
        fid.write('\n')
        fid.close()
        
        # Coordinates
        fid = open(outfld + 'x.grd','w')
        for aa in range(len(x)):
            fid.write('%16.4f' % x[aa])
        fid.write('\n')
        fid.close()        

    # NetCDF File --------------------------------------------------------------
    if ncsave:
    
        # Global attributes  
        nc = netCDF4.Dataset(outfld + 'depth.nc', 'w', format='NETCDF4')
        nc.Description = 'Xbeach 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
        if y is not None:
            tmpDims = ('eta_rho','xi_rho')
            xi_rho  = z.shape[1]
            eta_rho = z.shape[0]
            nc.createDimension('eta_rho',eta_rho)
        else:
            tmpDims = ('xi_rho')
            xi_rho = z.shape[-1]
        
        nc.createDimension('xi_rho', xi_rho)
    
        # Write coordinates and depth to netcdf file
        nc.createVariable('x_rho','f8',tmpDims)
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].long_name = 'x-locations of RHO-points'
        nc.variables['x_rho'][:] = x
        
        nc.createVariable('h','f8',tmpDims)
        nc.variables['h'].units = 'meter'
        nc.variables['h'].long_name = 'bathymetry at RHO-points'
        nc.variables['h'][:] = z
        
        if y is not None:
            nc.createVariable('y_rho','f8',tmpDims)
            nc.variables['y_rho'].units = 'meter'
            nc.variables['y_rho'].long_name = 'y-locations of RHO-points'
            nc.variables['y_rho'][:] = y
                        
        # Close NetCDF file
        nc.close()
        

    #===========================================================================
    # Print input file options
    #===========================================================================
    print(' ')
    print('===================================================================')
    print('In your params.txt:')
    print('  nx = ' + np.str(xi_rho - 1))
    if y is not None:
        print('  ny = ' + np.str(eta_rho - 1))
    else:
        print('  ny = 0')
    print('===================================================================')
Exemple #23
0
else:
    NC_RESOURCE = {
        'transect': 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/jarkus/profiles/transect.nc',
        # Use this if we break the deltares server:
        #'transect': 'http://opendap.tudelft.nl/thredds/dodsC/data2/deltares/rijkswaterstaat/jarkus/profiles/transect.nc',
        'BKL_TKL_TND': 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/BKL_TKL_MKL/BKL_TKL_TND.nc',
        'DF': 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/DuneFoot/DF.nc',
        # 'DF': 'http://dtvirt5.deltares.nl:8080/thredds/dodsC/opendap/rijkswaterstaat/DuneFoot/DF_r2011.nc',
        'MKL': 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/BKL_TKL_MKL/MKL.nc',
        'strandbreedte': 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/strandbreedte/strandbreedte.nc',
        'strandlijnen': 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/MHW_MLW/MHW_MLW.nc',
        'suppleties': 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/suppleties/suppleties.nc',
        'faalkans': 'http://opendap.deltares.nl/thredds/dodsC/opendap/rijkswaterstaat/faalkans_PC-Ring/faalkans.nc',
    }

if '4.1.3' in netCDF4.getlibversion():
    logger.warn('There is a problem with the netCDF 4.1.3 library that causes performance issues for opendap queries, you are using netcdf version {0}'.format(netCDF4.getlibversion()))

proj = pyproj.Proj('+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.237,50.0087,465.658,-0.406857,0.350733,-1.87035,4.0812 +units=m +no_defs')


class NoDataForTransect(Exception):
    def __init__(self, transect_id):
        message = "Could not find transect data for transect {0}".format(transect_id)
        super(NoDataForTransect, self).__init__(message)


class Transect(object):
    """Transect that has coordinates and time"""
    def __init__(self, id):
        self.id = id
Exemple #24
0
def fort14_to_nc(fort14, **kwargs):
    """ 
    Script to read an unstructured grid in fort.14 format and store it in a 
    netcdf4 file

    PARAMETERS:
    -----------
    fort14: Path to fort14 file
    savepath(optional)

    RETURNS:
    --------
    Netcdf containing
    x,y:     node coordinates
    element: triangular elements
    nbdv:    node numbers on each elevation specified boundary segment
    nbvv:    node numbers on normal flow boundary segment
    depth:   depth at each node
    """
    grid = ustr.read_fort14(fort14)

    # Create the file and add global attributes
    if 'savepath' in kwargs:
        ncfile = kwargs['savepath']
    else:
        ncfile = fort14 + '.nc'
    nc = netCDF4.Dataset(ncfile, 'w', format='NETCDF4')

    # Global attributes
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())

    # Get record lengths
    node = grid['x'].size
    nele = grid['triang'].shape[0]
    nvertex = grid['triang'].shape[1]
    #    nope = grid['nope']
    neta = grid['neta']
    #    nbou = grid['nbou']
    nvel = grid['nvel']

    # Create dimensions
    nc.createDimension('node', node)  # Number of nodes
    nc.createDimension('nele', nele)  # Number of elements
    nc.createDimension('nvertex', nvertex)  # Number of vertex
    nc.createDimension('neta', neta)  # Number of elevation boundary nodes
    nc.createDimension('nvel', nvel)  # Number of normal flow boundary nodes

    # Create variables
    nc.createVariable('x', 'f8', 'node')
    nc.variables['x'].long_name = 'longitude'
    nc.variables['x'].units = 'degrees_east'
    nc.variables['x'].positive = 'east'
    nc.variables['x'][:] = np.float64(grid['x'])

    nc.createVariable('y', 'f8', 'node')
    nc.variables['y'].long_name = 'latitude'
    nc.variables['y'].units = 'degrees_north'
    nc.variables['y'].positive = 'north'
    nc.variables['y'][:] = np.float64(grid['y'])

    nc.createVariable('element', 'i4', ('nele', 'nvertex'))
    nc.variables['element'].long_name = 'element'
    nc.variables['element'].units = 'nondimensional'
    # Add 1 back to node indexing to match standard adcirc files convention
    nc.variables['element'][:, :] = np.int32(grid['triang'] + 1)

    nc.createVariable('nbdv', 'i4', 'neta')
    nc.variables[
        'nbdv'].long_name = 'node numbers on each elevation specified boundary segment'
    nc.variables['nbdv'].units = 'nondimensional'
    nc.variables['nbdv'][:] = np.int32(np.hstack(grid['nbdv']))

    nc.createVariable('nbvv', 'i4', 'nvel')
    nc.variables[
        'nbvv'].long_name = 'node numbers on normal flow boundary segment'
    nc.variables['nbvv'].units = 'nondimensional'
    nc.variables['nbvv'][:] = np.int32(np.hstack(grid['nbvv']))

    nc.createVariable('depth', 'f8', 'node')
    nc.variables['depth'].long_name = 'distance below geoid'
    nc.variables['depth'].units = 'm'
    nc.variables['depth'][:] = np.float64(grid['z'])

    # All done here
    nc.close()
Exemple #25
0
def write_bathy(x, z, outfld, y=None, ncsave=True):
    """
    
    Parameters:
    -----------
    x      : Vector or gridded x coordinates
    y      : Vector or gridded y coordinates (optional)
    outfld : Full path to where the files will be written
    z      : Vector or gridded depth
    ncsave : Save as netcdf file as well
    
    Output:
    -------
    Writes two or three files depending on the configuration
      x.grd, y.grd, z.dep
    
    Notes:
    ------
    Right now has been tested in 1d mode only
    
    """

    # Output the text file -----------------------------------------------------

    if y is not None:

        print("Writing 2D grids")
        fidx = open(outfld + 'x.grd', 'w')
        fidy = open(outfld + 'y.grd', 'w')
        fidz = open(outfld + 'z.dep', 'w')

        for aa in range(z.shape[0]):
            for bb in range(z.shape[1]):
                fidx.write('%16.3f' % x[aa, bb])
                fidy.write('%16.3f' % y[aa, bb])
                fidz.write('%16.3f' % z[aa, bb])

            fidx.write('\n')
            fidy.write('\n')
            fidz.write('\n')

        fidx.close()
        fidy.close()
        fidz.close()

    else:

        print("Writing 1D grids")

        # Water depth
        fid = open(outfld + 'z.dep', 'w')
        for aa in range(len(z)):
            fid.write('%16.3f' % z[aa])
        fid.write('\n')
        fid.close()

        # Coordinates
        fid = open(outfld + 'x.grd', 'w')
        for aa in range(len(x)):
            fid.write('%16.3f' % x[aa])
        fid.write('\n')
        fid.close()

    # NetCDF File --------------------------------------------------------------
    if ncsave:

        # Global attributes
        nc = netCDF4.Dataset(outfld + 'depth.nc', 'w', format='NETCDF4')
        nc.Description = 'Xbeach 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
        if y is not None:
            tmpDims = ('eta_rho', 'xi_rho')
            xi_rho = z.shape[1]
            eta_rho = z.shape[0]
            nc.createDimension('eta_rho', eta_rho)
        else:
            tmpDims = ('xi_rho')
            xi_rho = z.shape[-1]

        nc.createDimension('xi_rho', xi_rho)

        # Write coordinates and depth to netcdf file
        nc.createVariable('x_rho', 'f8', tmpDims)
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].long_name = 'x-locations of RHO-points'
        nc.variables['x_rho'][:] = x

        nc.createVariable('h', 'f8', tmpDims)
        nc.variables['h'].units = 'meter'
        nc.variables['h'].long_name = 'bathymetry at RHO-points'
        nc.variables['h'][:] = z

        if y is not None:
            nc.createVariable('y_rho', 'f8', tmpDims)
            nc.variables['y_rho'].units = 'meter'
            nc.variables['y_rho'].long_name = 'y-locations of RHO-points'
            nc.variables['y_rho'][:] = y

        # Close NetCDF file
        nc.close()

    #===========================================================================
    # Print input file options
    #===========================================================================
    print(' ')
    print(
        '===================================================================')
    print('In your params.txt:')
    print('  nx = ' + np.str(xi_rho - 1))
    if y is not None:
        print('  ny = ' + np.str(eta_rho - 1))
    else:
        print('  ny = 0')
    print(
        '===================================================================')
Exemple #26
0
fnc.variables['longitude'][:] = long_host
fnc.variables['longitude'].long_name = 'Longitude E'
fnc.variables['longitude'].units = 'degrees'

fnc.createVariable('time', 'i', dimensions=['time'])
fnc.variables['time'][:] = months_out
fnc.variables['time'].units = 'months'
fnc.variables[
    'time'].long_name = 'number of months that have elapsed since 2001-01-01'

fnc.createVariable('ForestLoss',
                   'd',
                   dimensions=['time', 'latitude', 'longitude'],
                   zlib=True,
                   complevel=1)
fnc.variables['ForestLoss'][:, :, :] = GFW_monthly
fnc.variables['ForestLoss'].long_name = 'GFL/FORMA fusion monthly forest loss'
fnc.variables[
    'ForestLoss'].units = 'fraction of grid cell in which forest loss has occurred within that month'
fnc.variables['ForestLoss'].missing_value = 0.

fnc.production_date = '%s %s' % (time.asctime(), time.tzname[0])
fnc.production_software = 'Python %s - netCDF4 library %s' % (
    sys.version, netCDF4.getlibversion())
fnc.production_source = 'UMD Global Forest Loss Dataset & FORMA'
fnc.production_method = 'This file contains a forest loss product created by fusing Hansen and FORMA.   Data are regridded to a %4.2fx%4.2f grid.  Monthly forest loss are estimated by scaling annual GFL forest loss extents by ratio of FORMA disturbance for each month divided by annual FORMA disturbance in that year' % (
    dX, dY)

fnc.sync()
fnc.close()
Exemple #27
0
def unSWANCompToNetcdf(swanFile, swanGrid):
    """

    Convert UnSWAN results over all the computational grid to NetCDF4

    PARAMETERS:
    -----------
    swanFile - Ascii file with bulk parameter output over all computational
               grid
    swanGrid - The fort.14 file (for now)
    
    RETURNS:
    --------
    NetCDF file with the same name as swanFile with .nc extension    

    NOTES:
    ------
    1. Only works with fort.14 files
    2. It is assumed that the first three variables in swanFile are:
       Time Xp Yp ...

    TODO:
    -----
    1. Implement conversion from stationary conditions
    2. Implement ability to read from Triangle
    
    """

    # Read grid file -----------------------------------------------------------
    fobj = open(swanGrid, 'r')
    fobj.readline()
    tmpline = fobj.readline().split()
    nele = np.int(tmpline[0])
    npt = np.int(tmpline[1])

    xp = np.zeros((npt, ))
    yp = np.zeros_like(xp)

    # Read the grid (just in case)
    for aa in range(npt):
        tmpline = fobj.readline().split()
        xp[aa] = np.float(tmpline[1])
        yp[aa] = np.float(tmpline[2])

    # Read triangles
    triang = np.zeros((nele, 3), dtype=np.int)
    for aa in range(nele):
        tmpline = fobj.readline().split()
        triang[aa, 0] = np.int(tmpline[2])
        triang[aa, 1] = np.int(tmpline[3])
        triang[aa, 2] = np.int(tmpline[4])

    # All done here
    fobj.close()

    # Remember zero counting in python
    triang -= 1

    # Read the computational grid output ---------------------------------------
    fobj = open(swanFile, 'r')

    # Discard the first two lines
    fobj.readline()
    fobj.readline()

    # Get the model information
    modInfo = fobj.readline().split(':')
    modInfo = {
        'Run': modInfo[1].split(' ')[0],
        'Table': modInfo[2].split(' ')[0],
        'SWAN': modInfo[3][:-1]
    }

    # Empty line
    fobj.readline()

    # Variables
    varkeys = fobj.readline()[1:].split()
    # varkeys = fobj.readline()[1:-1]
    # varkeys = [item for item in filter(None,varkeys.split(' '))]

    # Find if the grid information is in the file
    gridFlag = 'Xp' in varkeys and 'Yp' in varkeys

    # Units
    units = fobj.readline()[1:].split()[1:]
    units[0] = '[UTC]'  # Manually overwrite

    # Empty line
    fobj.readline()

    # Find all nodes in file
    tmpLine = fobj.readline().split()
    date0 = tmpLine[0]
    if gridFlag:
        xp = []
        yp = []
        xp.append(np.float64(tmpLine[1]))
        yp.append(np.float64(tmpLine[2]))
    outpnt = 1
    for line in fobj:
        if line.split()[0] == date0:
            if gridFlag:
                xp.append(np.float64(line.split()[1]))
                yp.append(np.float64(line.split()[2]))
            outpnt += 1
        else:
            break

    if gridFlag:
        xp = np.asarray(xp)
        yp = np.asarray(yp)

    # Close the file
    fobj.close()

    # Sanity check here
    #if outpnt != npt:
    #    print("Dimensions of grid and output are different")
    #    return

    # Read File and Prepare NetCDF File ----------------------------------------
    print("Creating netCDF file")

    # Create the file and add global attributes
    outFile = swanFile + '.nc'
    nc = _netCDF4.Dataset(outFile, 'w', format='NETCDF4')
    nc.Description = 'UnSWAN Output'
    nc.Author = _getpass.getuser()
    nc.Created = _time.ctime()
    nc.Software = 'Created with Python ' + _sys.version
    nc.NetCDF_Lib = str(_netCDF4.getlibversion())
    nc.Source = swanFile
    nc.Run = modInfo['Run']
    nc.Version = modInfo['SWAN']
    nc.Table = modInfo['Table']

    # Create dimensions
    nc.createDimension('three', 3)
    nc.createDimension('nele', nele)  # Number of elements
    nc.createDimension('npnt', npt)  # Number of nodes
    nc.createDimension('time', 0)  # The unlimited dimension

    # Create time vector
    nc.createVariable('ocean_time', 'f8', ('time'))
    nc.variables['ocean_time'].units = 'seconds since 1900-01-01 00:00:00'
    nc.variables['ocean_time'].calendar = 'julian'

    nc.createVariable('matlab_time', 'f8', ('time'))
    nc.variables['matlab_time'].units = 'Days since 0000-01-01 00:00:00'

    # Write coordinates
    nc.createVariable(varkeys[1], 'f8', ('npnt'))
    nc.variables[varkeys[1]].units = units[1][1:-1]
    nc.variables[varkeys[1]][:] = xp

    nc.createVariable(varkeys[2], 'f8', ('npnt'))
    nc.variables[varkeys[2]].units = units[2][1:-1]
    nc.variables[varkeys[2]][:] = yp

    # Write the elements
    nc.createVariable('elements', 'f8', ('nele', 'three'))
    nc.variables['elements'].long_name = 'Triangulation'
    nc.variables['elements'][:] = triang

    # Create the rest of the variables
    for aa in range(3, len(varkeys)):
        nc.createVariable(varkeys[aa], 'f8', ('time', 'npnt'))
        nc.variables[varkeys[aa]].units = units[aa][1:-1]

    # ==============================================================================
    # Read and write variables to netCDF file
    # ==============================================================================

    print("  Reading and writing the file contents ...")

    # First three variables are already considered
    varkeys = varkeys[3:]

    # Load the swan file again
    fobj = open(swanFile)

    # Ignore the first seven lines
    for aa in range(7):
        fobj.readline()

    # Preallocate variable container
    #   If the grid is not crazy large this should be ok
    tmpvars = np.zeros((len(varkeys), npt))
    cnt = 0
    tstep = -1  # Time step counter (location in netcdf file)

    # Loop until the end of the file
    for line in fobj:

        # Increase counter variable
        cnt += 1

        # Temporarily allocate variables
        aa = np.asarray([np.float64(aa) for aa in line.split()])
        tmpvars[:, cnt - 1] = aa[3:]

        # Write variables if all nodes have been read for the current time
        if cnt == npt:

            # Quick update
            print('  Storing ' + line.split()[0])

            # Increase time step variable
            tstep += 1

            # Time management
            timePython = datetime.datetime.strptime(line.split()[0],
                                                    "%Y%m%d.%H%M%S")
            nc.variables['matlab_time'][tstep] = _gtime.datetime_to_datenum(
                timePython)
            ocean_time = timePython - datetime.datetime(1900, 1, 1)
            nc.variables['ocean_time'][tstep] = ocean_time.total_seconds()

            # Write variables to netcdf file
            for aa in range(len(varkeys)):
                nc.variables[varkeys[aa]][tstep, ...] = tmpvars[aa, :]

            # Reset counter variable
            cnt = 0

            # Reset variable container
            tmpvars *= np.NAN

    # All done here
    fobj.close()
    nc.close()
Exemple #28
0
def spec2nc(buoyfld,dtheta=5):
    '''
    Code to convert NDBC spectral data files to netCDF format. 
    
    Usage:
    ------
    spec2nc(buoyfld,dtheta)
    
    Input:
    ------
    buoyfld  : Folder where the text files reside. Those should be the only
               files in the folder.
    dtheta   : Directional resolution for the reconstruction of the frequency-
               direction spectrum. Defaults to 5 degrees. 
    
    Notes:
      1. NetCDF4 file will be generated
      2. Code is not optimized since this is not something you will want to be
         running often. Beware of slow performance for large datasets.
    
    References:
    Kuik, A.J., G.Ph. van Vledder, and L.H. Holthuijsen, 1998: "Method for
      the Routine Analysis of Pitch-and-Roll Buoy Wave Data", Journal of
      Physical Oceanography, 18, 1020-1034.
      
    TODO:
    Only works with newer formats (YY MM DD hh mm)
    
    '''
    
    # For testing only ---------------------------------------------------------
    # buoyfld = '/home/shusin2/users/ggarcia/data/wave/b46029/spec/'
    # dtheta = 5
    # --------------------------------------------------------------------------
    
    # Construct directional angle
    angles = np.arange(0.0,360.0,dtheta)
    
    # Time reference
    basetime = datetime.datetime(1900,01,01,0,0,0)

    #===========================================================================
    # Read file information
    #===========================================================================
    
    # Get all files in folder
    archivos = os.listdir(buoyfld)
    
    # Year information
    years = [x.split('.')[0][-4:] for x in archivos]    # Get all year stamps
    years = list(set(years))                            # Find unique years
    years.sort()                                        # Sort years
    
    # Get buoy ID information
    buoyid = [x[0:5] for x in archivos]                 # Find buoy ids
    buoyid = list(set(buoyid))                          # Find unique ids    
    if len(buoyid)>1:
        print('This code does not support conversion for multiple buoys')
        buoyid = buoyid[0]
        print('  ' +  buoyid + ' will be processed')
    else:
        buoyid = buoyid[0]
        
    
    # Create output netcdf file ------------------------------------------------
    # Global attributes  
    nc = netCDF4.Dataset(buoyfld + '/' + buoyid + '_spec.nc',
                         'w',format='NETCDF4')
    nc.Description = buoyid + ' NDBC Spectral Data'
    nc.Rawdata = 'National Data Buoy Center \nwww.ndbc.noaa.gov'
    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__)
    nc.Notes = 'Nautical convention used for directions'
    
    # Create dimensions  (NetCDF4 supports multiple unlimited dimensions)
    nc.createDimension('wave_time',None)
    nc.createDimension('dir_time',None)
    
    # Create bulk parameter variables
    nc.createVariable('Hsig','f8','wave_time')
    nc.variables['Hsig'].units = 'meter'
    nc.variables['Hsig'].long_name = 'Significant wave height'
        
    
    
    # Reconstruct the spectrum -------------------------------------------------        

    # counter variable to create variables in the netcdf file
    cnt_freq = 0 
    cnt_dir = 0
    tstep_freq = 0
    tstep_dir = 0
    
    # Loop over years
    for aa in years:
                
        # Load spectral density files
        # Check if file exists
        tmpfile = buoyfld + buoyid + 'w' + aa + '.txt'
        if os.path.isfile(tmpfile) == False:
            # No spectral density found for the given year, go to next one
            continue
        
        # Read spectral density data (frequency spectra)
        f_w = open(tmpfile,'r')
        freq = f_w.readline().split()
               
        # Read frequencies
        freq = np.array(freq[5:],dtype=float)
        f_w.close()
        
        # Load spectral density
        freq_spec = np.loadtxt(tmpfile,skiprows=1)
        
        # Allocate time and spectral density data    
        freq_time = np.zeros((freq_spec.shape[0]))  
        for bb in range(freq_time.shape[0]):
            freq_time[bb] = (datetime.datetime(np.int(freq_spec[bb,0]),
                                               np.int(freq_spec[bb,1]),
                                               np.int(freq_spec[bb,2]),
                                               np.int(freq_spec[bb,3]),
                                               np.int(freq_spec[bb,4])) - 
                             basetime).total_seconds()
        freq_spec = freq_spec[:,5:]
        
        # Create frequency spectra variables
        cnt_freq += 1
        if cnt_freq == 1:
            nc.createDimension('freq',freq.shape[0])
            
            nc.createVariable('wave_time','f8','wave_time')
            nc.variables['wave_time'].units = \
            "seconds since 1900-01-01 00:00:00"
            nc.variables['wave_time'].calendar = "julian"
            
            nc.createVariable('freq_spec','f8',('wave_time','freq'))
            nc.variables['freq_spec'].units = 'meter2 second'
            nc.variables['freq_spec'].long_name = 'Frequency variance spectrum'            
            
            nc.createVariable('frequency','f8',('freq'))
            nc.variables['frequency'].units = 'Hz'
            nc.variables['frequency'].long_name = 'Spectral frequency'
            nc.variables['frequency'][:] = freq
        
        # Check if directional data exists
        tmp_alpha_1 = buoyfld  + buoyid + 'd' + aa + '.txt'
        tmp_alpha_2 = buoyfld  + buoyid + 'i' + aa + '.txt'
        tmp_r_1 = buoyfld  + buoyid + 'j' + aa + '.txt'
        tmp_r_2 = buoyfld  + buoyid + 'k' + aa + '.txt'
    
    
        if (os.path.isfile(tmp_alpha_1) and os.path.isfile(tmp_alpha_2) and
            os.path.isfile(tmp_r_1) and os.path.isfile(tmp_r_2)):
            
            # Create directional spectra variables
            cnt_dir += 1
            if cnt_dir == 1:
                nc.createDimension('dir',angles.shape[0])
            
                nc.createVariable('dir_time','f8','dir_time')
                nc.variables['dir_time'].units = \
                "seconds since 1900-01-01 00:00:00"
                nc.variables['dir_time'].calendar = "julian"
            
                nc.createVariable('dir_spec','f8',('dir_time','freq','dir'))
                nc.variables['dir_spec'].units = 'meter2 second degree-1'
                nc.variables['dir_spec'].long_name = \
                    'Frequency-Direction variance spectrum'  
                    
                nc.createVariable('direction','f8',('dir'))
                nc.variables['direction'].units = 'degree'
                nc.variables['direction'].long_name = \
                    'Degrees from true north in oceanographic convention'
                nc.variables['direction'][:] = angles
            
            
            # Read spectral data
            alpha_1 = np.loadtxt(tmp_alpha_1,skiprows=1)
            alpha_2 = np.loadtxt(tmp_alpha_1,skiprows=1)
            r_1 = np.loadtxt(tmp_alpha_1,skiprows=1) * 0.01
            r_2 = np.loadtxt(tmp_alpha_1,skiprows=1) * 0.01
    
            # Allocate data
            dir_time = np.zeros((alpha_1.shape[0]))              
            for bb in range(dir_time.shape[0]):
                dir_time[bb] = (datetime.datetime(np.int(alpha_1[bb,0]),
                                                  np.int(alpha_1[bb,1]),
                                                  np.int(alpha_1[bb,2]),
                                                  np.int(alpha_1[bb,3]),
                                                  np.int(alpha_1[bb,4])) - 
                                basetime).total_seconds()
                             
                                         
            alpha_1 = alpha_1[:,5:]
            alpha_2 = alpha_2[:,5:]
            r_1 = r_1[:,5:]
            r_2 = r_2[:,5:]
            
            
            # Construct 2D spectra
            # See http://www.ndbc.noaa.gov/measdes.shtml
            wspec = np.NaN * np.zeros((alpha_1.shape[0],
                                       freq.shape[0],angles.shape[0]))
            
            
            # Time loop
            for bb in range(wspec.shape[0]):
                # Frequency loop  
                for cc in range(wspec.shape[1]):
                    # Direction loop
                    for dd in range(wspec.shape[2]):
                        wspec[bb,cc,dd] = (freq_spec[bb,cc] * np.pi/180.0 *
                                           (1.0/np.pi) * 
                                           (0.5 + r_1[bb,cc] * 
                                            np.cos((angles[dd]-alpha_1[bb,cc])*
                                                   np.pi/180.0) +
                                            r_2[bb,cc] * 
                                            np.cos(2 * np.pi / 180.0 * 
                                                   (angles[dd]-alpha_2[bb,cc])))
                                           )
            
            # Write to file
            if cnt_dir == 1:
                nc.variables['dir_spec'][:] = wspec
                nc.variables['dir_time'][:] = dir_time
            else:
                nc.variables['dir_spec'][tstep_dir:,:,:] = wspec
                nc.variables['dir_time'][tstep_dir:] = dir_time
            
            tstep_dir += dir_time.shape[0]
            
        
        # Compute bulk parameters
        moment0 = np.trapz(freq_spec.T,freq,axis=0)
        Hsig = 4.004*(moment0)**0.5
        
        # Write to NetCDF file
        if cnt_freq == 1:
            nc.variables['Hsig'][:] = Hsig
            nc.variables['freq_spec'][:] = freq_spec
            nc.variables['wave_time'][:] = freq_time
        else:
            nc.variables['Hsig'][tstep_freq:] = Hsig
            nc.variables['freq_spec'][tstep_freq:,:] = freq_spec
            nc.variables['wave_time'][tstep_freq:] = freq_time
        
        tstep_freq += freq_time.shape[0]
        
        
       
    # Wrap up ------------------------------------------------------------------
    # Close NetCDF File 
    nc.close()
Exemple #29
0
def max63_to_nc(max63,
                varname='zeta',
                longname='water surface elevation above geoid',
                varunits='m',
                ncdate='0000-00-00 00:00:00 UTC',
                **kwargs):
    """ 
    Script to read max63-type (max-min) files and store in a netcdf4 file

    PARAMETERS:
    -----------
    max63: Path to max63-type file
    ncdate : cold start date/time in CF standard: yyyy-MM-dd hh:mm:ss tz

    RETURNS:
    --------
    Netcdf containing
    time         : seconds since beginning of run 
    x,y variable : temporal variables (name provided in 'xy_varname') recorded
                   at the nodes of an unstructured grid. Size: [time,nodes]
    """

    fobj = open(max63, 'r')

    # Create the file and add global attributes
    if 'savename' in kwargs:
        ncfile = kwargs['savename']
    else:
        ncfile = max63 + '.nc'
    nc = netCDF4.Dataset(ncfile, 'w', format='NETCDF4')

    # Global attributes
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    tmpline = fobj.readline()
    nc.description = tmpline[2:34]
    nc.rundes = tmpline[2:34]
    nc.runid = tmpline[36:60]
    nc.model = 'ADCIRC'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())

    # Record number of time steps and nodes
    nodes = np.int(fobj.readline().split()[1])

    # Create dimensions
    nc.createDimension('time', 0)  # The unlimited dimension
    nc.createDimension('node', nodes)  # Number of nodes

    # Create time vector
    nc.createVariable('time', 'f8', ('time'))
    nc.variables['time'].long_name = 'model time'
    nc.variables['time'].standard_name = 'time'
    nc.variables['time'].units = 'seconds since ' + ncdate
    nc.variables['time'].base_date = ncdate

    # Create the rest of the variables
    nc.createVariable(varname + '_max', 'f8', 'node')
    nc.variables[varname + '_max'].long_name = 'maximum ' + longname
    nc.variables[varname + '_max'].units = varunits

    nc.createVariable('time_of_' + varname + '_max', 'f8', 'node')
    nc.variables['time_of_' + varname +
                 '_max'].long_name = 'time of maximum ' + longname
    nc.variables['time_of_' + varname + '_max'].units = 'sec'

    # Store last time-step in run for reference
    nc.variables['time'][0] = np.float64(fobj.readline().split()[0])

    # Store max variable observations
    for aa in range(nodes):
        nc.variables[varname + '_max'][aa] = np.float64(
            fobj.readline().split()[1])

    # Skip repeated time
    fobj.readline()

    for aa in range(nodes):
        nc.variables['time_of_' + varname + '_max'][aa] = np.float64(
            fobj.readline().split()[1])

    # All done here
    fobj.close()
    nc.close()
Exemple #30
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()
Exemple #31
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()
Exemple #32
0
    def _process(self, l1a_file, monitor):
        running = True
        surface_processing = False
        status = -1
        self.beam_angles_list_size_prev = -1
        self.beam_angles_trend_prev = -1
        self.surfaces_count = 0

        # find base name of input file
        l1a_base, _ = os.path.splitext(os.path.basename(l1a_file))
        if l1a_base.startswith('L1A'):
            l1a_base = l1a_base[len('L1A'):]

        l1a_base_part = ''
        if l1a_base:
            l1a_base_part = '_%s' % l1a_base

        name_part = ''
        if self.name:
            name_part = '_%s' % self.name

        # create l1b-s output path
        l1bs_name = 'L1BS%s%s.nc' % (l1a_base_part, name_part)
        l1bs_path = os.path.join(self.out_path, l1bs_name)

        # create l1b output path
        l1b_name = 'L1B%s%s.nc' % (l1a_base_part, name_part)
        l1b_path = os.path.join(self.out_path, l1b_name)

        # create output file objects
        writerCls = L1BWriter if self.cnf.output_format == OutputFormat.s3 else L1BWriterExtended
        self.l1b_file = writerCls(filename=l1b_path, chd=self.chd, cnf=self.cnf, cst=self.cst)
        if not self.skip_l1bs:
            self.l1bs_file = L1BSWriter(filename=l1bs_path, chd=self.chd, cnf=self.cnf, cst=self.cst)
        else:
            self.l1bs_file = None

        # open output files
        self.l1b_file.open()
        if self.l1bs_file is not None:
            self.l1bs_file.open()

        prev_time = None
        gap_processing = False
        gap_resume = False
        sub_monitor = None

        index = -1

        while running:
            index += 1

            if monitor.is_cancelled():
                running = False

            # if a gap has been encountered, then the current lists of input packets & surfaces need to be processed
            #  before reading another input.
            if not gap_processing:

                # monitor.progress(1)

                # if this is the first iteration after finishing a gap, then the next packet has already been read
                #  so another one should not be retrieved from the L1A
                if not gap_resume:
                    # input_packet = next(self.l1a_file)
                    try:
                        input_packet = next(self.l1a_file)
                    except StopIteration:
                        input_packet = None
                        if not surface_processing:
                            raise Exception("insufficient input records")
                    else:
                        monitor.progress(1)

                if input_packet is not None:
                    # apply calibrations
                    self.cal1_algorithm(input_packet)
                    self.cal2_algorithm(input_packet)

                    # check if there is a gap (or if this is the first packet & prev_time has not been set)
                    if prev_time is None or input_packet.time_sar_ku - prev_time < self.gap_threshold:

                        prev_time = input_packet.time_sar_ku
                        new_surface = self.surface_locations(input_packet, force_new=gap_resume)

                        gap_resume = False

                        if new_surface is None:
                            continue

                    else:
                        gap_processing = True
                        prev_time = None
                        sub_monitor = monitor.child(1)
                        sub_monitor.start("processing gap", len(self.surf_locs))

            elif sub_monitor is not None:
                sub_monitor.progress(1, len(self.surf_locs))

            if surface_processing or len(self.surf_locs) >= self.min_surfs or gap_processing:
                surface_processing = True

                working_loc = self.surf_locs[0]

                for processed_packet in self.source_isps:
                    if not processed_packet.burst_processed:

                        self.beam_angles(self.surf_locs, processed_packet, working_loc)

                        self.azimuth_processing(processed_packet)

                        processed_packet.burst_processed = True

                        if not self.beam_angles_algorithm.work_location_seen:
                            break

                self.stack_gathering(working_loc)

                # if the current surface doesn't have enough contributing bursts, then
                #  it should not be written to the outputs - and so the rest of the processing
                #  is not needed
                if working_loc.data_stack_size < (self.cnf.n_looks_stack // 2):
                    del self.surf_locs[0]  # remove this surface from the queue
                else:
                    self.geometry_corrections(working_loc)
                    self.range_compression(working_loc)
                    self.stack_masking(working_loc)
                    self.multilooking(working_loc)
                    self.sigma_zero_scaling(working_loc)

                    if self.l1b_file is not None:
                        self.l1b_file.write_record(working_loc)
                    if self.l1bs_file is not None:
                        self.l1bs_file.write_record(working_loc)

                    self.clear_old_records(working_loc)

            if not self.surf_locs:
                if gap_processing:
                    # all the remaining surfaces & bursts before the gap have been processed
                    gap_processing = False  # end gap mode
                    gap_resume = True  # next iteration will be the first after the gap
                    surface_processing = False  # require min. number of surfaces again
                    sub_monitor.done()
                else:
                    # the end of the input has been reached
                    running = False
                    status = None

        l1a_globals = self.l1a_file.read_globals()

        ctime = iso_format()
        ftime = iso_format(self.l1a_file.first_time())
        ltime = iso_format(self.l1a_file.last_time())
        # close output files
        self.l1b_file.write_globals(
            title='DeDop SRAL Level 1 Measurement',
            mission_name=l1a_globals.mission_name,
            altimeter_sensor_name=l1a_globals.altimeter_sensor_name,
            gnss_sensor_name=l1a_globals.gnss_sensor_name,
            doris_sensor_name=l1a_globals.doris_sensor_name,
            references=l1a_globals.references,
            acq_station_name=l1a_globals.acq_station_name,
            xref_altimeter_level0=l1a_globals.xref_altimeter_level0,
            xref_navatt_level0=l1a_globals.xref_navatt_level0,
            xref_altimeter_orbit=l1a_globals.xref_altimeter_orbit,
            xref_doris_uso=l1a_globals.xref_doris_uso,
            xref_altimeter_ltm_lrm_cal1=l1a_globals.xref_altimeter_ltm_lrm_cal1,
            xref_altimeter_ltm_sar_cal1=l1a_globals.xref_altimeter_ltm_sar_cal1,
            xref_altimeter_ltm_ku_cal2=l1a_globals.xref_altimeter_ltm_ku_cal2,
            xref_altimeter_ltm_c_cal2=l1a_globals.xref_altimeter_ltm_c_cal2,
            xref_altimeter_characterisation=l1a_globals.xref_altimeter_characterisation,
            xref_time_correlation=l1a_globals.xref_time_correlation,
            semi_major_ellipsoid_axis=self.cst.semi_major_axis,
            ellipsoid_flattening=self.cst.flat_coeff,
            netcdf_version=getlibversion(),
            product_name=l1a_globals.get_l1b_product_name(),
            institution='isardSAT',
            source='DeDop {}'.format(__version__),
            history=l1a_globals.history,
            contact='http://www.dedop.org/',
            creation_time=ctime,
            first_meas_time=ftime,
            last_meas_time=ltime
        )
        self.l1b_file.close()
        if self.l1bs_file is not None:
            self.l1bs_file.write_globals(
                title='DeDop SRAL Level 1BS Measurement',
                mission_name=l1a_globals.mission_name,
                altimeter_sensor_name=l1a_globals.altimeter_sensor_name,
                gnss_sensor_name=l1a_globals.gnss_sensor_name,
                doris_sensor_name=l1a_globals.doris_sensor_name,
                references=l1a_globals.references,
                acq_station_name=l1a_globals.acq_station_name,
                xref_altimeter_level0=l1a_globals.xref_altimeter_level0,
                xref_navatt_level0=l1a_globals.xref_navatt_level0,
                xref_altimeter_orbit=l1a_globals.xref_altimeter_orbit,
                xref_doris_uso=l1a_globals.xref_doris_uso,
                xref_altimeter_ltm_lrm_cal1=l1a_globals.xref_altimeter_ltm_lrm_cal1,
                xref_altimeter_ltm_sar_cal1=l1a_globals.xref_altimeter_ltm_sar_cal1,
                xref_altimeter_ltm_ku_cal2=l1a_globals.xref_altimeter_ltm_ku_cal2,
                xref_altimeter_ltm_c_cal2=l1a_globals.xref_altimeter_ltm_c_cal2,
                xref_altimeter_characterisation=l1a_globals.xref_altimeter_characterisation,
                xref_platform=l1a_globals.xref_platform,
                xref_time_correlation=l1a_globals.xref_time_correlation,
                semi_major_ellipsoid_axis=self.cst.semi_major_axis,
                ellipsoid_flattening=self.cst.flat_coeff,
                netcdf_version=getlibversion(),
                product_name=l1a_globals.get_l1bs_product_name(),
                institution='isardSAT',
                source='DeDop {}'.format(__version__),
                history=l1a_globals.history,
                contact='http://www.dedop.org/',
                creation_time=ctime,
                first_meas_time=ftime,
                last_meas_time=ltime
            )
            self.l1bs_file.close()

        return status
Exemple #33
0
def writeROMSGrid(outFile, variables, varinfo, timeinfo=None, verbose=False):
    """
    Code to write roms grids based on input variables
    
    INPUT:
    ------
    outFile    : Full path to output netcdf file
    variables  : Dictionary containing variables. (see notes)
    varinfo    : Path to ROMS varinfo.dat. Usually under:
                 /path/to/roms/trunk/ROMS/External/varinfo.dat
    timeinfo   : Time vector in nested dictionary form (see example)
    verbose    : some info displayed on the terminal                 
    
    RETURNS:
    --------
    
    NOTES:
    ------
    -  variables need rho variables (x_rho,y_rho)
    
    TODO:
    -----
    -  Include a varinfo.dat with the pynmd package
    
    EXAMPLE:
    ---------
    >>> import numpy as np
    >>> from collections import defaultdict
    >>> import pynmd.models.roms.pre as groms    
    >>>
    >>> x_rho,y_rho = np.meshgrid(np.arange(0,10,1),np.arange(0,10,1)
    >>> variables = {}
    >>> variables['x_rho'] = x_rho
    >>> variables['y_rho'] = y_rho
    >>>
    >>> variables['type'] = 'ROMS FORCING FILE'
    >>>
    >>> timeinfo = defaultdict(dict)
    >>> timeinfo['sms_time']['units'] = 'seconds since 1970-01-01 00:00:00 UTC'
    >>> timeinfo['sms_time']['data'] = np.arange(0,1000,10)
    >>> timeinfo['sms_time']['long_name'] = 'surface momentum stress time'
    >>>
    >>> groms.writeROMSGrid(outFile,...)
    
    """

    # Testing only
    #outFile = ('/home/shusin3/users/ggarcia/projects/other/' +
    #           'columbiaRiverPlume/11-romsIdealized/03-extendedNR2/' +
    #           'orIdealizedExtStr.nc')
    #varinfo = ('/home/shusin3/users/ggarcia/projects/other/' +
    #           'columbiaRiverPlume/94-roms/trunk/ROMS/External/varinfo.dat')
    #verbose = True

    # Read varinfo -------------------------------------------------------------
    if verbose:
        print('Reading Varinfo')
        print('  ' + varinfo)

    # Create dictionary to get information from
    varinfodict = defaultdict(dict)

    # Structure of the variables
    # hardcoded because I couldn't find a generalized description
    varStruct = ['long_name', 'units', 'field', 'time', 'id', 'dimensions']

    # Read the varinfo
    with open(varinfo) as f:

        # Read into a list of lines
        lines = f.readlines()

        # Loop through lines
        for line in lines:

            #Skip lines starting with !
            if line.startswith("!"):
                continue

            # Skip blank lines
            if line.isspace():
                continue

            # Skip other non variable lines
            if line.startswith("'$"):
                continue

            # Read variables and allocate properties
            if line.startswith("'"):
                tmpVar = line.split(' ')[0][1:-1]
                cnt = -1
                continue

            # Add counter variable and allocate only the necessary fields
            cnt += 1
            if cnt > (len(varStruct) - 1):
                continue

            varinfodict[tmpVar][varStruct[cnt]] =\
              line.split('  ')[1].split('\n')[0][1:-1]

    f.close()

    # Import grid variables and update the dictionary
    gridVariables = gridVars()
    varinfodict.update(gridVariables)

    # Create netCDF file -------------------------------------------------------
    if verbose:
        print('Creating: ' + outFile)

    nc = netCDF4.Dataset(outFile, 'w', format='NETCDF4')
    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())

    if 'type' in variables.keys():
        nc.type = variables['type']

    # Create dimensions --------------------------------------------------------

    if verbose:
        print("  Creating Dimensions ...")
    # Horizontal dimensions
    nc.createDimension('xi_psi', np.size(variables['x_rho'], 1) - 1)
    nc.createDimension('xi_rho', np.size(variables['x_rho'], 1))
    nc.createDimension('xi_u', np.size(variables['x_rho'], 1) - 1)
    nc.createDimension('xi_v', np.size(variables['x_rho'], 1))
    nc.createDimension('eta_psi', np.size(variables['x_rho'], 0) - 1)
    nc.createDimension('eta_rho', np.size(variables['x_rho'], 0))
    nc.createDimension('eta_u', np.size(variables['x_rho'], 0))
    nc.createDimension('eta_v', np.size(variables['x_rho'], 0) - 1)

    # Vertical dimensions
    if 's_rho' in variables.keys():
        nc.createDimension('s_rho', variables['s_rho'].size)
    if 's_w' in variables.keys():
        nc.createDimension('s_w', variables['s_w'].size)

    # river variables
    if 'river' in variables.keys():
        nc.createDimension('river', variables['river'].size)

    # Time dimension and variable (unlimited,netCDF4 supports multiple)
    if timeinfo:

        if verbose:
            print('  Writing Time Variables:')

        for aa in timeinfo.keys():

            if verbose:
                print('    ' + aa)

            # Create dimension
            nc.createDimension(aa, 0)
            nc.createVariable(aa, 'f8', (aa))

            # Write variable information
            for bb in timeinfo[aa].keys():

                if bb == 'data':
                    nc.variables[aa][:] = timeinfo[aa]['data']
                else:
                    nc.variables[aa].__setattr__(bb, timeinfo[aa][bb])

    # Write other variables
    if verbose:
        print('  Writing variables:')

    # Loading dimensions
    dimInfo = gridDims()

    for aa in variables.keys():

        # Determine dimensions
        try:
            tmpdims = dimInfo[varinfodict[aa]['dimensions']]
            if varinfodict[aa]['dimensions'] == 'nulvar':
                tmpdims = tmpdims[aa]
        except:
            if verbose:
                #print('    ' + aa + ': Not in varinfodict[aa][dimensions]')
                print('    ' + aa + ': skipped')
            continue

        if verbose:
            print('    ' + aa)

        if 'time' in varinfodict[aa].keys():
            # Some variables have info on the time slot no time
            # See river_Xpoisition for example
            if 'time' in varinfodict[aa]['time']:
                tmpdims = (varinfodict[aa]['time'], ) + tmpdims
            else:
                # Get rid of the time variable
                varinfodict[aa].pop('time')

        # Create Variable
        nc.createVariable(aa, 'f8', tmpdims)

        # Write attributes
        for bb in varinfodict[aa].keys():
            if bb == 'dimensions' or bb == 'id':
                continue
            nc.variables[aa].__setattr__(bb, varinfodict[aa][bb])

        # Write data
        nc.variables[aa][:] = variables[aa]

    # Close netcdf file
    nc.close()

    if verbose:
        print('Done')
Exemple #34
0
def write_bathy_1d(x,h,path,ncsave=True):
    '''
    
    Parameters:    
    ----------
    x           : 1D array of x coordinates
    h           : Bathymetry
    path        : Full path where the output will be saved
    ncsave      : Save bathy as NetCDF file
    
    Output:
    -------
    depth.txt   : Text file with the depth information for Funwave input.
    depth.nc    : (Optional) NetCDF4 bathymetry file. 
    
    Notes:
    ------
    Variables are assumed to be on a regularly spaced grid.
    
    '''

    # Output the text file -----------------------------------------------------        
    fid = open(path + 'depth.txt','w')
    for aa in range(len(h)):
        fid.write('%12.3f' % h[aa])
    fid.write('\n')
    fid.close()

    if ncsave:
    
        # Global attributes  
        nc = netCDF4.Dataset(path + 'depth.nc', 'w', format='NETCDF4')
        nc.Description = 'Funwave 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
        xi_rho = len(h)
        nc.createDimension('xi_rho', xi_rho)
    
        # Write coordinates and depth to netcdf file
        create_nc_var(nc, 'x_rho',('xi_rho'), 
                     'meter','x-locations of RHO-points')
        nc.variables['x_rho'][:] = x
        create_nc_var(nc,'h',('xi_rho'), 
                     'meter','bathymetry at RHO-points')
        nc.variables['h'][:] = h      
                
        # Close NetCDF file
        nc.close()

    else: 
    
        print("NetCDF file not requested")
        
        

    #===========================================================================
    # Print input file options
    #===========================================================================
    print(' ')
    print('===================================================================')
    print('In your FUNWAVE input file:')
    print('Mglob = ' + np.str(len(x)))
    print('Nglob = 1')
    print('DX = ' + np.str(np.abs(x[1] - x[0])))
    print('DY = anything larger than DX works')
    print('DEP_WK = ' + str(h.max()))
    print('Check sponge layer widths')
    print('===================================================================')
    print(' ')
Exemple #35
0
def bulk2nc(buoyfld, buoyid, ncformat=4, verbose=True, suffix='.txt'):
    '''
    Code to convert bulk parameter text files into netcdf file
    
    Usage:
    ------
    bulk2nc(buoyfld,buoyid,ncformat)
    
    Input:
    ------
    buoyfld  = Folder where the bulk paramerter text files reside.
    buoyid   = Netcdf buoy identifier (to figure out the file names)
    ncformat = set as 3 for netCDF3, set as 4 for netCDF4 (default)
    verbose  = some extra information (True is default)
    
    Notes:
    Only the bulk parameter files must be present in that directory. The code is
    not smart enough (and I do not have the time to make it so) to figure out 
    the bulk parameter files. 
    
    '''

    #===========================================================================
    # Read and Clean Up Data
    #===========================================================================

    # Get all files in folder
    archivos = os.listdir(buoyfld)
    archivos.sort()

    # Initialize variables
    wavetime = np.empty([
        1,
    ])
    WDIR = np.empty([
        1,
    ])  #AKA WD
    WSPD = np.empty([
        1,
    ])
    GST = np.empty([
        1,
    ])
    WVHT = np.empty([
        1,
    ])
    DPD = np.empty([
        1,
    ])
    APD = np.empty([
        1,
    ])
    MWD = np.empty([
        1,
    ])
    PRES = np.empty([
        1,
    ])  #AKA BAR
    ATMP = np.empty([
        1,
    ])
    WTMP = np.empty([
        1,
    ])

    # Loop over files
    for tmpFile in archivos:

        if tmpFile.endswith(suffix):

            if verbose:
                print(tmpFile)

            # Read header lines to determine the location of variables
            with open(buoyfld + '/' + tmpFile, 'r') as f:
                header1 = f.readline()
                header2 = f.readline()

                # Determine the number of header lines (NDBC uses one or two)
                if header1.startswith('Y') or header1.startswith('#'):
                    headcnt = 1
                if header2.startswith('Y') or header2.startswith('#'):
                    headcnt = 2

            # Collapse multiple spaces into one
            header3 = ' '.join(header1.split())
            header4 = header3.split()

            # Load buoy data
            tmpdata = pl.loadtxt(buoyfld + '/' + tmpFile, skiprows=headcnt)

            # ======================  Allocate variables  ==================== #
            # Wind direction
            if any(tt == 'WD' for tt in header4):
                tind = header4.index('WD')
                WDIR = np.concatenate((WDIR, tmpdata[:, tind]))
            elif any(tt == 'WDIR' for tt in header4):
                tind = header4.index('WDIR')
                WDIR = np.concatenate((WDIR, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                WDIR = np.concatenate((WDIR, tmparray))
                del tmparray

            # Wind Speed
            if any(tt == 'WSPD' for tt in header4):
                tind = header4.index('WSPD')
                WSPD = np.concatenate((WSPD, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                WSPD = np.concatenate((WSPD, tmparray))
                del tmparray

            # Wind Gust
            if any(tt == 'GST' for tt in header4):
                tind = header4.index('GST')
                GST = np.concatenate((GST, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                GST = np.concatenate((GST, tmparray))
                del tmparray

            # Wave Height
            if any(tt == 'WVHT' for tt in header4):
                tind = header4.index('WVHT')
                WVHT = np.concatenate((WVHT, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                WVHT = np.concatenate((WVHT, tmparray))
                del tmparray

            # Dominant Wave Period
            if any(tt == 'DPD' for tt in header4):
                tind = header4.index('DPD')
                DPD = np.concatenate((DPD, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                DPD = np.concatenate((DPD, tmparray))
                del tmparray

            # Average Wave Period
            if any(tt == 'APD' for tt in header4):
                tind = header4.index('APD')
                APD = np.concatenate((APD, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                APD = np.concatenate((APD, tmparray))
                del tmparray

            # Mean Wave Direction
            if any(tt == 'MWD' for tt in header4):
                tind = header4.index('MWD')
                MWD = np.concatenate((MWD, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                MWD = np.concatenate((MWD, tmparray))
                del tmparray

            # Sea Level Pressure
            if any(tt == 'PRES' for tt in header4):
                tind = header4.index('PRES')
                PRES = np.concatenate((PRES, tmpdata[:, tind]))
            elif any(tt == 'BAR' for tt in header4):
                tind = header4.index('BAR')
                PRES = np.concatenate((PRES, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                PRES = np.concatenate((PRES, tmparray))
                del tmparray

            # Air temperature
            if any(tt == 'ATMP' for tt in header4):
                tind = header4.index('ATMP')
                ATMP = np.concatenate((ATMP, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                ATMP = np.concatenate((ATMP, tmparray))
                del tmparray

            # Sea surface temperature
            if any(tt == 'WTMP' for tt in header4):
                tind = header4.index('WTMP')
                WTMP = np.concatenate((WTMP, tmpdata[:, tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0], 1])
                tmparray[:] = np.NaN
                WTMP = np.concatenate((WTMP, tmparray))
                del tmparray

            # ================== Time management =================
            # Years
            if any(tt == 'YY' for tt in header4):
                tind = header4.index('YY')
                years = tmpdata[:, tind] + 1900
            elif any(tt == '#YY' for tt in header4):
                tind = header4.index('#YY')
                years = tmpdata[:, tind]
            else:
                tind = header4.index('YYYY')
                years = tmpdata[:, tind]

            # Minutes
            if any(tt == 'mm' for tt in header4):
                tind = header4.index('mm')
                mm = tmpdata[:, tind]
            else:
                mm = np.zeros([tmpdata.shape[0], 1])

            # Create time vector
            # Seconds from 1900-01-01 will be used
            for aa in range(tmpdata.shape[0]):
                tmptime = datetime.datetime(int(years[aa]), int(tmpdata[aa,
                                                                        1]),
                                            int(tmpdata[aa, 2]),
                                            int(tmpdata[aa, 3]), int(mm[aa]),
                                            0)
                sectime = tmptime - datetime.datetime(1900, 1, 1, 0, 0, 0)
                secsecs = sectime.total_seconds()
                wavetime = np.concatenate([wavetime, np.array([secsecs])])
                del tmptime, sectime, secsecs

            # ================ Clean up ================
            del header1, header2, header3, header4, years, mm

    # Remove first term of each array
    wavetime = np.delete(wavetime, 0)
    WDIR = np.delete(WDIR, 0)
    WSPD = np.delete(WSPD, 0)
    GST = np.delete(GST, 0)
    WVHT = np.delete(WVHT, 0)
    DPD = np.delete(DPD, 0)
    APD = np.delete(APD, 0)
    MWD = np.delete(MWD, 0)
    PRES = np.delete(PRES, 0)
    ATMP = np.delete(ATMP, 0)
    WTMP = np.delete(WTMP, 0)

    # Clean up variables
    WDIR[WDIR == 999] = np.NaN
    WSPD[WSPD == 99] = np.NaN
    GST[GST == 99] = np.NaN
    WVHT[WVHT == 99] = np.NaN
    DPD[DPD == 99] = np.NaN
    APD[APD == 99] = np.NaN
    MWD[MWD == 999] = np.NaN
    PRES[PRES == 9999] = np.NaN
    ATMP[ATMP == 99] = np.NaN
    WTMP[WTMP == 99] = np.NaN

    # Order chronologically
    sorted_index = np.argsort(wavetime)
    wavetime = [wavetime[i] for i in sorted_index]
    WDIR = [WDIR[i] for i in sorted_index]
    WSPD = [WSPD[i] for i in sorted_index]
    GST = [GST[i] for i in sorted_index]
    WVHT = [WVHT[i] for i in sorted_index]
    DPD = [DPD[i] for i in sorted_index]
    APD = [APD[i] for i in sorted_index]
    MWD = [MWD[i] for i in sorted_index]
    PRES = [PRES[i] for i in sorted_index]
    ATMP = [ATMP[i] for i in sorted_index]
    WTMP = [WTMP[i] for i in sorted_index]

    #===========================================================================
    # Save as NetCDF
    #===========================================================================

    # Global attributes
    if ncformat == 4:
        print("Saving the buoy data with NetCDF4 format")
        nc = netCDF4.Dataset(buoyfld + '/' + buoyid + '.nc',
                             'w',
                             format='NETCDF4')
    else:
        print("Saving the buoy data with NetCDF3 format")
        nc = netCDF4.Dataset(buoyfld + '/' + buoyid + '.nc',
                             'w',
                             format='NETCDF3_CLASSIC')
    nc.Description = buoyid + ' NDBC Bulk Parameter Data'
    nc.rawdata = 'National Data Buoy Center \nwww.ndbc.noaa.gov'
    nc.Author = '[email protected] \nNearshore Modeling Group'
    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('wave_time', None)

    # pyroms subroutine to write NetCDF fields
    def write_nc_var(var, name, dimensions, units=None, longname=None):
        nc.createVariable(name, 'f8', dimensions)
        if units is not None:
            nc.variables[name].units = units
        if longname is not None:
            nc.variables[name].long_name = longname
        nc.variables[name][:] = var

    # Write Variables To NetCDF file
    write_nc_var(wavetime, 'wave_time', 'wave_time',
                 'seconds since 1900-01-01 00:00:00', 'measurement time UTC')
    write_nc_var(
        WDIR, 'WDIR', 'wave_time', 'degrees',
        'Wind direction (direction the wind is coming from in ' +
        'degrees clockwise from true North')
    write_nc_var(WSPD, 'WSPD', 'wave_time', 'meter second-1',
                 'Wind speed averaged over an eight-minute period')
    write_nc_var(GST, 'GST', 'wave_time', 'meter second-1', 'Peak gust speed')
    write_nc_var(
        WVHT, 'WVHT', 'wave_time', 'meter',
        'Significant wave height during the 20 minute sampling period')
    write_nc_var(DPD, 'DPD', 'wave_time', 'second',
                 'Dominant wave period (period with the maximum wave energy)')
    write_nc_var(
        APD, 'APD', 'wave_time', 'second',
        'Average wave period of all waves during the 20 minute' +
        ' sampling period')
    write_nc_var(
        MWD, 'MWD', 'wave_time', 'degrees',
        'The direction from which the waves at the dominant period ' +
        'are coming in degrees from true North, increasing clockwise')
    write_nc_var(PRES, 'PRES', 'wave_time', 'hPa', 'Sea level pressure')
    write_nc_var(ATMP, 'ATMP', 'wave_time', 'Celsius', 'Air temperature')
    write_nc_var(WTMP, 'WTMP', 'wave_time', 'Celsius',
                 'Sea surface temperature')

    # Close NetCDF File
    nc.close()
Exemple #36
0
def write_bathy(x,y,h,path,ncsave=True):
    '''
    
    Parameters:
    ----------
    x,y         : 2D arrays of coordinates
    h           : Bathymetry
    path        : Full path where the output will be saved
    ncsave      : Save as NetCDF4 file (optional, defaults to True)
    
    Output:
    -------
    depth.nc    : NetCDF4 file with the bathymetry
    depth.txt   : Text file with the depth information for Funwave input.
    
    '''
    
    # Get bathymetry dimensions
    eta_rho, xi_rho = x.shape
    
    if ncsave:
    
        # Global attributes  
        nc = netCDF4.Dataset(path + 'depth.nc', 'w', format='NETCDF4')
        nc.Description = 'Funwave 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', xi_rho)
        nc.createDimension('eta_rho', eta_rho)
    
        # Write coordinates and depth to netcdf file
        create_nc_var(nc, 'x_rho', 
                     ('eta_rho', 'xi_rho'), 
                     'meter','x-locations of RHO-points')
        nc.variables['x_rho'][:] = x
        create_nc_var(nc, 'y_rho', 
                     ('eta_rho', 'xi_rho'), 
                     'meter','y-locations of RHO-points')
        nc.variables['y_rho'][:] = y
        create_nc_var(nc, 'h', 
                     ('eta_rho', 'xi_rho'), 
                     'meter','bathymetry at RHO-points')          
        nc.variables['h'][:] = h
                        
        # Close NetCDF file
        nc.close()

    else: 
    
        print("NetCDF file not requested")
        
        

    # Output the text file -----------------------------------------------------        
    fid = open(path + 'depth.txt','w')
    for aa in range(x.shape[0]):
        for bb in range(x.shape[1]):
            fid.write('%12.3f' % h[aa,bb])
        fid.write('\n')
    fid.close()



    #===========================================================================
    # Print input file options
    #===========================================================================
    print(' ')
    print('===================================================================')
    print('In your FUNWAVE input file:')
    print('Mglob = ' + np.str(xi_rho))
    print('Nglob = ' + np.str(eta_rho))
    print('DX = ' + np.str(np.abs(x[0,1] - x[0,0])))
    print('DY = ' + np.str(np.abs(y[1,0] - y[0,0])))
    print('Ywidth_WK > ' + str(y.max() - y.min()))
    print('DEP_WK = ' + str(h.max()))
    print('Check sponge layer widths')
    print('===================================================================')
    print(' ')
Exemple #37
0
def main():
    # Parse arguments
    parse_cli_args()

    # Sanity checks

    # Check to make sure that the JSON resource file exists!
    try:
        resource_file_fh = open(args.resource_file, "r")
    except IOError:
        error_msg("Resource file '%s' is not accessible or does not exist!" % args.resource_file)
        exit(1)

    # Check to make sure that the JSON resource file is valid!
    try:
        resource_data = json.loads(resource_file_fh.read())
    except KeyboardInterrupt:
        info_msg("CTRL-C detected, exiting.")
        exit(0)
    except:
        error_msg("Resource file '%s' is not a valid JSON file!" % args.resource_file)
        print(traceback.format_exc())
        exit(1)

    # Close file - we got the data already!
    resource_file_fh.close()

    # Print verbose version information
    if args.verbose:
        info_msg("Using following versions:")
        info_msg("    netcdf4-python v%s" % netCDF4.__version__)
        info_msg("    NetCDF v%s" % getlibversion())
        info_msg("    HDF5 v%s" % netCDF4.__hdf5libversion__)
        info_msg("    Python v%s\n" % sys.version.split("\n")[0].strip())
        info_msg("Reading and validating NetCDF4 files...")

    # Check to make sure the NetCDF4 files are legitimate!
    nc4_files_root = []

    init_counter(len(args.nc4_files), "Reading/verifying file")
    for nc4_file in args.nc4_files:
        try:
            open(nc4_file, "r").close()
        except KeyboardInterrupt:
            info_msg("CTRL-C detected, exiting.")
            exit(0)
        except IOError:
            error_msg("The NetCDF4 file '%s' does not exist!" % nc4_file)
            exit(1)

        progress_counter(nc4_file)

        try:
            rootgrp = Dataset(nc4_file, "a", format="NETCDF4")
            nc4_files_root.append({"file": nc4_file, "group": rootgrp})
        except KeyboardInterrupt:
            info_msg("CTRL-C detected, exiting.")
            exit(0)
        except:
            error_msg("'%s' is not a valid NetCDF4 file!" % nc4_file)
            exit(1)

    line_msg_done()

    # Global attributes
    if args.global_attributes:
        # Check if we have a global attributes entry in the resource file
        if not "global_attributes" in resource_data:
            warning_msg("Resource file '%s' does not have any global attributes, skipping." % args.resource_file)
        else:
            # Initialize our counter
            init_counter(len(nc4_files_root), "Applying global attributes to file")

            for nc4_entry in nc4_files_root:
                # Update progress counter
                progress_counter(nc4_entry["file"])

                for global_attr_key in resource_data["global_attributes"]:
                    global_attr_val = resource_data["global_attributes"][global_attr_key]

                    # We need to convert unicode to ASCII
                    if type(global_attr_val) == unicode:
                        global_attr_val = str(global_attr_val)

                    # BUG fix - NetCDF really, really, REALLY does not like
                    # 64-bit integers. We forcefully convert the value to a
                    # 32-bit signed integer, with some help from numpy!
                    if type(global_attr_val) == int:
                        global_attr_val = numpy.int32(global_attr_val)

                    setattr(nc4_entry["group"], global_attr_key, global_attr_val)
            line_msg_done()

    # Variable attributes
    if args.var_attributes:
        # Check if we have a variable attributes entry in the resource file
        if not "variable_attributes" in resource_data:
            warning_msg("Resource file '%s' does not have any variable attributes, skipping." % args.resource_file)
        else:
            # Initialize our counter
            init_counter(len(nc4_files_root), "Applying variable attributes to file")

            for nc4_entry in nc4_files_root:
                # Update progress counter
                progress_counter(nc4_entry["file"])

                # Iterate through all of our var_attr variables
                for var in resource_data["variable_attributes"]:
                    if var in nc4_entry["group"].variables.keys():
                        for var_attr_key in resource_data["variable_attributes"][var]:
                            var_attr_val = resource_data["variable_attributes"][var][var_attr_key]
                            var_attr_key = str(var_attr_key)

                            # We need to convert unicode to ASCII
                            if type(var_attr_val) == unicode:
                                var_attr_val = list(str(var_attr_val))

                            # BUG fix - NetCDF really, really, REALLY does not like
                            # 64-bit integers. We forcefully convert the value to a
                            # 32-bit signed integer, with some help from numpy!
                            if type(var_attr_val) == int:
                                var_attr_val = numpy.int32(var_attr_val)

                            setattr(nc4_entry["group"].variables[var], var_attr_key, var_attr_val)
                    else:
                        warning_msg("Can't find variable %s in file %s!" % (var, nc4_entry["file"]))
            line_msg_done()

    # Close everything
    init_counter(len(nc4_files_root), "Saving changes to file")
    for nc4_entry in nc4_files_root:
        progress_counter(nc4_entry["file"])
        nc4_entry["group"].close()

    line_msg_done()

    info_msg("Attribute appending complete!")
Exemple #38
0
sys.path.append("build/temp.linux-x86_64-2.6")
from netCDF4 import getlibversion,__hdf5libversion__,__netcdf4libversion__,__version__

__all__ = ['test']
# Find all test files.
test_files = glob.glob('tst_*.py')
py_path = os.environ.get('PYTHONPATH')
if py_path is None:
    py_path = '.'
else:
    py_path = os.pathsep.join(['.',py_path])
os.environ['PYTHONPATH'] = py_path

# Build the test suite from the tests found in the test files.
testsuite = unittest.TestSuite()
version = getlibversion().split()[0]
for f in test_files:
    m = __import__(os.path.splitext(f)[0])
    testsuite.addTests(unittest.TestLoader().loadTestsFromModule(m))

# Run the test suite. 


def test(verbosity=1):
    runner = unittest.TextTestRunner(verbosity=verbosity)
    runner.run(testsuite)

if __name__ == '__main__':
    test(verbosity=1)
    import sys
    sys.stdout.write('\n')
Exemple #39
0
def convert_output(workfld,outfile,time_int,bathyfile=None,inpfile=None):
    '''
    
    Parameters:
    -----------
    workfld      : Path to the folder where output files reside
    outfile      : Output NetCDF file
    time_int     : Time interval between output files [s] (will be updated if
                   input file is provided)
    bathyfile    : Full path to input netcdf bathy file (optional)
    inpfile      : Funwave input file used for metadata (optional)
         
    Output:
    -------
    NetCDF File with the variables in the folder. Not all are supported so you 
    may need to edit this file.
    
    '''
    
    # For testing only
    #workfld = '/scratch/temp/ggarcia/agate/out/'
    #outfile = '/scratch/temp/ggarcia/agate/tmpout.nc'
    #time_int = 0.5
    #bathyfile = '/scratch/temp/ggarcia/agate/depth.nc'
    #inpfile = '/scratch/temp/ggarcia/agate/input.txt'

    # Get variable information ------------------------------------------------
    archivos = os.listdir(workfld)                      # Get all files
    tmpvars = [x.split('_')[0] for x in archivos]       # All variables
    tmpvars = list(set(tmpvars))                        # Unique variables
    
    # If no variables found exit    
    if not tmpvars:
        print('No files found in ' + workfld)
        print('Quitting ...')
        return None
    
    # Make sure variables are within the supported ones
    supported_vars_time = ['eta','etamean','havg','hmax','hmin','hrms',
                           'mask','mask9','MFmax','u','umax','umean','v',
                           'vmean','VORmax']
    vars_2d = [x for x in tmpvars if x in supported_vars_time]
    
    
    # Read input file if provided ----------------------------------------------
    if inpfile:
        
        print("Reading data from input file:")
        print("  " + inpfile)
        
        # Open file
        tmpinpfile = open(inpfile,'r')
        
        # Output dictionary
        inpinfo = {}
        
        # Extract information (need to add wavemaker support)
        for tmpline in tmpinpfile:
            
            # Skip blank lines
            if len(tmpline.strip()) == 0:
                continue
            
            if "TITLE" == tmpline.split()[0]:
                inpinfo['title'] = tmpline.split()[2]
            elif "PX" == tmpline.split()[0]:
                inpinfo['px'] = tmpline.split()[2]
            elif "PY" == tmpline.split()[0]:
                inpinfo["py"] = tmpline.split()[2]
            elif "Mglob" == tmpline.split()[0]:
                inpinfo['mglob'] = tmpline.split()[2]
            elif "Nglob" == tmpline.split()[0]:
                inpinfo['nglob'] = tmpline.split()[2]
            elif "TOTAL_TIME" == tmpline.split()[0]:
                inpinfo['total_time'] = tmpline.split()[2]
            elif "PLOT_INTV" == tmpline.split()[0]:
                inpinfo["plot_intv"] = tmpline.split()[2]
                time_int = np.double(tmpline.split()[2])
            elif "DX" == tmpline.split()[0]:
                inpinfo['dx'] = tmpline.split()[2]
                dx = float(tmpline.split()[2])
            elif "DY" == tmpline.split()[0]:
                inpinfo['dy'] = tmpline.split()[2]
                dy = float(tmpline.split()[2])
            elif "WAVEMAKER" == tmpline.split()[0]:
                inpinfo['wavemaker'] = tmpline.split()[2]
            elif "PERIODIC" == tmpline.split()[0]:
                inpinfo['periodic'] = tmpline.split()[2]
            elif "SPONGE_ON" == tmpline.split()[0]:
                sponge = tmpline.split()[2]
                inpinfo['sponge'] = sponge
            elif "Sponge_west_width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_west_width'] = tmpline.split()[2]
            elif "Sponge_east_width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_east_width'] = tmpline.split()[2]
            elif "Sponge_wouth_width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_south_width'] = tmpline.split()[2]
            elif "Sponge_worth_width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_north_width'] = tmpline.split()[2]
            elif "R_sponge" == tmpline.split()[0] and sponge == 'T':
                inpinfo['r_sponge'] = tmpline.split()[2]
            elif "A_sponge" == tmpline.split()[0] and sponge == 'T':
                inpinfo['a_sponge'] = tmpline.split()[2]
            elif "DISPERSION" == tmpline.split()[0]:
                inpinfo['dispersion'] = tmpline.split()[2]
            elif "Gamma1" == tmpline.split()[0]:
                inpinfo['gamma1'] = tmpline.split()[2]
            elif "Gamma2" == tmpline.split()[0]:
                inpinfo['gamma2'] = tmpline.split()[2]
            elif "Gamma3" == tmpline.split()[0]:
                inpinfo['gamma3'] = tmpline.split()[2]
            elif "Beta_ref" == tmpline.split()[0]:
                inpinfo['beta_ref'] = tmpline.split()[2]
            elif "SWE_ETA_DEP" == tmpline.split()[0]:
                inpinfo['swe_eta_dep'] = tmpline.split()[2]
            elif "Friction_Matrix" == tmpline.split()[0]:
                inpinfo['friction_matrix'] = tmpline.split()[2]
            elif "Cd_file" == tmpline.split()[0]:
                inpinfo['cd_file'] = tmpline.split()[2]
            elif "Cd" == tmpline.split()[0]:
                inpinfo['cd'] = tmpline.split()[2]                              
            elif "Time_Scheme" == tmpline.split()[0]:
                inpinfo['time_scheme'] = tmpline.split()[2]
            elif "HIGH_ORDER" == tmpline.split()[0]:
                inpinfo['spatial_scheme'] = tmpline.split()[2]
            elif "CONSTRUCTION" == tmpline.split()[0]:
                inpinfo['construction'] = tmpline.split()[2]
            elif "CFL" == tmpline.split()[0]:
                inpinfo['cfl'] = tmpline.split()[2]                
            elif "MinDepth" == tmpline.split()[0]:
                inpinfo['min_depth'] = tmpline.split()[2]
            elif "MinDepthFrc" == tmpline.split()[0]:
                inpinfo['mindepthfrc'] = tmpline.split()[2]
            
        # Close file
        tmpinpfile.close()
            
    else:
        
        # Assume grid spacing to be 1 meter
        print("Input file not provided")
        dx = 1
        dy = 1
        inpinfo = False
    
    
    # Coordinates and depth ---------------------------------------------------
    # Bathymetry file provided
    if bathyfile: 
        
        print("Reading coordinates and depth from:")
        print("  " + bathyfile)
        
        ncfile = netCDF4.Dataset(bathyfile,'r')
        x_rho = ncfile.variables['x_rho'][:]
        if ncfile.variables.has_key('y_rho'):
            y_rho = ncfile.variables['y_rho'][:]
        else:
            y_rho = None
        h = ncfile.variables['h'][:]
        ncfile.close()
        
    # Bathymetry file not provided but have output file        
    elif os.path.isfile(workfld + '/dep.out'):
               
        # Fix this               
        h = np.loadtxt(workfld + '/dep.out')
        
        hdims = h.ndim
        if hdims == 1:
            x_rho = np.arange(0,h.shape[0],dx)
        elif hdims == 2:
            x_rho, y_rho = np.meshgrid(np.arange(0,h.shape[1],dx),
                                       np.arange(0,h.shape[0],dy))           
        else:
            print('Something is wrong with the depth file')
            return None    
    
    # No bathymetry file provided (I am not capable of reading the input file)
    else:
        print("No bathymetry file provided")
        print("You could copy your input bathymetry text file to ")
        print(workfld + '/dep.out')
        return None
        
    
    # Get dimensions of variables
    hdims = h.ndim
    
    # Create NetCDF file -------------------------------------------------------
    
    print("Creating " + outfile)
    
    # Global attributes  
    nc = netCDF4.Dataset(outfile, 'w', format='NETCDF4')
    nc.Description = 'Funwave Output'
    nc.Author = '*****@*****.**'
    nc.Created = time.ctime()
    nc.Type = 'Funwave v2.1 snapshot output'
    nc.Owner = 'Nearshore Modeling Group'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Source = workfld
    nc.Script = os.path.realpath(__file__)
    
    # Add more global variables to output
    if inpinfo:
        for tmpatt in inpinfo.keys():
            nc.__setattr__(tmpatt,inpinfo[tmpatt][:])
    
    # Create dimensions
    if hdims == 2:
        eta_rho, xi_rho = h.shape
        nc.createDimension('eta_rho', eta_rho)
    else:
        xi_rho = h.shape[0]
        eta_rho = 1
    nc.createDimension('xi_rho', xi_rho)            
    nc.createDimension('ocean_time',0)
    
    # Write coordinate axes ----------------------------------------------
    if hdims == 2:
        
        nc.createVariable('x_rho','f8',('eta_rho','xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho
        
        nc.createVariable('y_rho','f8',('eta_rho','xi_rho'))
        nc.variables['y_rho'].units = 'meter'
        nc.variables['y_rho'].longname = 'y-locations of RHO points'
        nc.variables['y_rho'][:] = y_rho

        nc.createVariable('h','f8',('eta_rho','xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h


    else:
        
        nc.createVariable('x_rho','f8',('xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho
        
        nc.createVariable('h','f8',('xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h
        
           
    # Create time vector -------------------------------------------
    tmpruns = [x for x in archivos if x.split('_')[0] == vars_2d[0]]
    tmpruns.sort()
    time_max = float(tmpruns[-1].split('_')[-1])
    time_min = float(tmpruns[0].split('_')[-1])
    
    
    twave = np.arange(time_min-1,time_int*(time_max-time_min+1)+time_min-1,
                      time_int)
    nc.createVariable('ocean_time','f8','ocean_time')
    nc.variables['ocean_time'].units = 'seconds since 2000-01-01 00:00:00'
    nc.variables['ocean_time'].calendar = 'julian'
    nc.variables['ocean_time'].long_name = 'beach time'
    nc.variables['ocean_time'][:] = twave
        
    # Create variables --------------------------------------------------------

    # Variable information
    varinfo = defaultdict(dict)

    varinfo['eta']['units'] = 'meter'
    varinfo['eta']['longname'] = 'water surface elevation'
    varinfo['etamean']['units'] = 'meter'
    varinfo['etamean']['longname'] = 'Mean wave induced setup'
    
    varinfo['u']['units'] = 'meter second-1'
    varinfo['u']['longname'] = 'Flow velocity in the xi direction'
    varinfo['v']['units'] = 'meter second-1'
    varinfo['v']['longname'] = 'Flow velocity in the eta direction'
    
    varinfo['umean']['units'] = 'meter second-1'
    varinfo['umean']['longname'] = 'Time-averaged flow velocity in xi direction'
    varinfo['vmean']['units'] = 'meter second-1'
    varinfo['vmean']['longname'] = 'Time-averaged flow velocity in eta direction'
    
    varinfo['umax']['units'] = 'meter second-1'
    varinfo['umax']['longname'] = 'Maximum flow velocity in xi direction'
    varinfo['vmax']['units'] = 'meter second-1'
    varinfo['vmax']['longname'] = 'Maximum flow velocity in eta direction'    
    
    varinfo['hmax']['units'] = 'meter'
    varinfo['hmax']['longname'] = 'Maximum wave height'
    varinfo['hmin']['units'] = 'meter'
    varinfo['hmin']['longname'] = 'Minimum wave height'
    varinfo['havg']['units'] = 'meter'
    varinfo['havg']['longname'] = 'Average wave height'
    varinfo['hrms']['units'] = 'meter'
    varinfo['hrms']['longname'] = 'Root mean squared wave height'
    
    varinfo['mask']['units'] = 'Boolean'
    varinfo['mask']['longname'] = 'Logical parameter for output wetting-drying'
    varinfo['mask9']['units'] = 'Boolean'
    varinfo['mask9']['longname'] = 'Logical parameter for output MASK9'
    
    varinfo['VORmax']['units'] = 'second-1'
    varinfo['VORmax']['longname'] = 'Maximum vorticity'
    varinfo['MFmax']['units'] = 'meter second-s'
    varinfo['MFmax']['longname'] = 'Maximum momentum flux'    
    
    
    # Create variables        
    if hdims == 1:
        nc_dims = ('ocean_time','xi_rho')
    else:
        nc_dims = ('ocean_time','eta_rho','xi_rho')
          
          
    print("Creating variables")          
    for aa in vars_2d:
        
        print('  ' + aa)
        
        # Create variable
        create_nc_var(nc,aa,nc_dims,varinfo[aa]['units'],
                      varinfo[aa]['longname'])
        
        try:
            tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % time_min)
        except ValueError:
            tmpvar = np.zeros_like(h) * np.NAN
                    
        nc.variables[aa][:] = np.expand_dims(tmpvar,axis=0)
        
        for bb in range(len(twave)):
            
            try:
                tmpvar = np.loadtxt(workfld + '/' + aa + '_' + 
                                    '%05.0f' % (bb + time_min))
            except ValueError:
                tmpvar = np.zeros_like(h) * np.NAN
                
            append_nc_var(nc,tmpvar,aa,bb-1)   
                    
    # Close NetCDF file
    print('Closing ' + outfile)
    nc.close()
Exemple #40
0
def convert_output(workfld,
                   outfile,
                   bathyfile=None,
                   inpfile=None,
                   verbose=False):
    '''
    
    Tools to convert ASCII output from NHWAVE to NetCDF4
    
    Parameters:
    -----------
    workfld      : Path to the folder where output files reside
    outfile      : Output file
    bathyfile    : Full path to input NetCDF bathy file (optional) 
    inpfile      : NHwave input files used to add metadata (optional)
    verbose      : Display progress messages (optional)
    
    Output:
    -------
    NetCDF File with the variables in the folder. Not all are supported so you 
    may need to edit this file.
    
    Notes:
    ------    
    
    TODO:
    -----
    1. Need to test for 2DH simulations.
    2. Add support for exponential vertical layers
    
    '''

    # Get variable information -------------------------------------------------
    archivos = os.listdir(workfld)  # All files
    tmpvars = [x.split('_')[0] for x in archivos]  # Variables
    tmpvars = list(set(tmpvars))  # Unique variables

    # If no variables found exit
    if not tmpvars:
        print('No files found in ' + workfld)
        print('Quitting ...')
        return None

    # Make sure variables are within the supported ones (exclude time here)
    supported_vars_2d_time = ['eta']
    vars_2d_time = [x for x in tmpvars if x in supported_vars_2d_time]
    supported_vars_2d = ['setup', 'waveheight', 'umean', 'vmean']
    vars_2d = [x for x in tmpvars if x in supported_vars_2d]
    supported_vars_3d_time = ['u', 'v', 'w']
    vars_3d_time = [x for x in tmpvars if x in supported_vars_3d_time]
    supported_vars_3d = ['euler', 'lag']
    vars_3d = [x for x in tmpvars if x in supported_vars_3d]

    # Read input file if provided ----------------------------------------------
    if inpfile:

        if verbose:
            print("Reading data from input file:")
            print("  " + inpfile)

        # Open file
        tmpinpfile = open(inpfile, 'r')

        # Output dictionary
        inpinfo = {}

        # Extract information (need to add wavemaker support)
        for tmpline in tmpinpfile:

            # Skip blank lines
            if len(tmpline.strip()) == 0:
                continue

            # Read selected keywords
            if "TITLE" == tmpline.split()[0]:
                inpinfo['title'] = tmpline.split()[2]
            elif "Mglob" == tmpline.split()[0]:
                inpinfo['mglob'] = tmpline.split()[2]
            elif "Nglob" == tmpline.split()[0]:
                inpinfo['nglob'] = tmpline.split()[2]
            elif "Kglob" == tmpline.split()[0]:
                inpinfo['kglob'] = tmpline.split()[2]
            elif "PX" == tmpline.split()[0]:
                inpinfo['px'] = tmpline.split()[2]
            elif "PY" == tmpline.split()[0]:
                inpinfo["py"] = tmpline.split()[2]
            elif "TOTAL_TIME" == tmpline.split()[0]:
                inpinfo['total_time'] = tmpline.split()[2]
            elif "PLOT_START" == tmpline.split()[0]:
                inpinfo['plot_start'] = tmpline.split()[2]
            elif "PLOT_INTV" == tmpline.split()[0]:
                inpinfo["plot_intv"] = tmpline.split()[2]
            elif "DX" == tmpline.split()[0]:
                inpinfo['dx'] = tmpline.split()[2]
                dx = float(tmpline.split()[2])
            elif "DY" == tmpline.split()[0]:
                inpinfo['dy'] = tmpline.split()[2]
                dy = float(tmpline.split()[2])
            elif "IVGRD" == tmpline.split()[0]:
                inpinfo['ivgrd'] = tmpline.split()[2]
            elif "DT_INI" == tmpline.split()[0]:
                inpinfo['dt_ini'] = tmpline.split()[2]
            elif "DT_MIN" == tmpline.split()[0]:
                inpinfo['dt_min'] = tmpline.split()[2]
            elif "DT_MAX" == tmpline.split()[0]:
                inpinfo['dt_max'] = tmpline.split()[2]
            elif "HIGH_ORDER" == tmpline.split()[0]:
                inpinfo['high_order'] = tmpline.split()[2]
            elif "TIME_ORDER" == tmpline.split()[0]:
                inpinfo['time_order'] = tmpline.split()[2]
            elif "CONVECTION" == tmpline.split()[0]:
                inpinfo['convection'] = tmpline.split()[2]
            elif "HLLC" == tmpline.split()[0]:
                inpinfo['hllc'] = tmpline.split()[2]
            elif "Ibot" == tmpline.split()[0]:
                inpinfo['ibot'] = tmpline.split()[2]
                ibot = int(tmpline.split()[2])
            elif "Cd0" == tmpline.split()[0] and ibot == 1:
                inpinfo['cd0'] = tmpline.split()[2]
            elif "Zob" == tmpline.split()[0] and ibot == 2:
                inpinfo['zob'] = tmpline.split()[2]
            elif "Iws" == tmpline.split()[0]:
                inpinfo['Iws'] = tmpline.split()[2]
                iws = int(tmpline.split()[2])
            elif "WindU" == tmpline.split()[0] and iws == 1:
                inpinfo['windu'] = tmpline.split()[2]
            elif "WindV" == tmpline.split()[0] and iws == 1:
                inpinfo['windv'] = tmpline.split()[2]
            elif "slat" == tmpline.split()[0]:
                inpinfo['slat'] = tmpline.split()[2]
            elif "BAROTROPIC" == tmpline.split()[0]:
                inpinfo['barotropic'] = tmpline.split()[2]
            elif "NON_HYDRO" == tmpline.split()[0]:
                inpinfo['non_hydro'] = tmpline.split()[2]
            elif "CFL" == tmpline.split()[0]:
                inpinfo['cfl'] = tmpline.split()[2]
            elif "TRAMP" == tmpline.split()[0]:
                inpinfo['tramp'] = tmpline.split()[2]
            elif "MinDep" == tmpline.split()[0]:
                inpinfo['min_dep'] = tmpline.split()[2]
            elif "ISOLVER" == tmpline.split()[0]:
                inpinfo['isolver'] = tmpline.split()[2]
            elif "PERIODIC_X" == tmpline.split()[0]:
                inpinfo['periodic_x'] = tmpline.split()[2]
            elif "PERIODIC_Y" == tmpline.split()[0]:
                inpinfo['periodic_y'] = tmpline.split()[2]
            elif "BC_X0" == tmpline.split()[0]:
                inpinfo['bc_x0'] = tmpline.split()[2]
            elif "BC_Xn" == tmpline.split()[0]:
                inpinfo['bc_xn'] = tmpline.split()[2]
            elif "BC_Y0" == tmpline.split()[0]:
                inpinfo['bc_y0'] = tmpline.split()[2]
            elif "BC_Yn" == tmpline.split()[0]:
                inpinfo['bc_yn'] = tmpline.split()[2]
            elif "BC_Z0" == tmpline.split()[0]:
                inpinfo['bc_z0'] = tmpline.split()[2]
            elif "BC_Zn" == tmpline.split()[0]:
                inpinfo['bc_zn'] = tmpline.split()[2]
            elif "WAVEMAKER" == tmpline.split()[0]:
                inpinfo['wavemaker'] = tmpline.split()[2]
            elif "Xsource_West" == tmpline.split()[0] and \
                 inpinfo['wavemaker'][0:3] == 'INT':
                inpinfo['xsource_west'] = tmpline.split()[2]
            elif "Xsource_East" == tmpline.split()[0] and \
                 inpinfo['wavemaker'][0:3] == 'INT':
                inpinfo['xsource_east'] = tmpline.split()[2]
            elif "Ysource_Suth" == tmpline.split()[0] and \
                 inpinfo['wavemaker'][0:3] == 'INT':
                inpinfo['ysource_suth'] = tmpline.split()[2]
            elif "Ysource_Nrth" == tmpline.split()[0] and \
                 inpinfo['wavemaker'][0:3] == 'INT':
                inpinfo['xsource_nrth'] = tmpline.split()[2]
            elif "SPONGE_ON" == tmpline.split()[0]:
                inpinfo['sponge'] = tmpline.split()[2]
                sponge = tmpline.split()[2]
            elif "Sponge_West_Width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_west_width'] = tmpline.split()[2]
            elif "Sponge_East_Width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_east_width'] = tmpline.split()[2]
            elif "Sponge_South_Width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_south_width'] = tmpline.split()[2]
            elif "Sponge_North_Width" == tmpline.split()[0] and sponge == 'T':
                inpinfo['sponge_north_width'] = tmpline.split()[2]
            elif "Seed" == tmpline.split()[0]:
                inpinfo['Seed'] = tmpline.split()[2]

        # Close file
        tmpinpfile.close()

    else:

        inpinfo = None

        if verbose:
            print("Input file not provided")

    # If bathymetry file is given then the coordinates should be taken from
    # this file, otherwise unit coordinates will be assumed with the shape of
    # one of the output files.
    if bathyfile:
        ncfile = netCDF4.Dataset(bathyfile, 'r')
        x_rho = ncfile.variables['x_rho'][:]
        if ncfile.variables.has_key('y_rho'):
            y_rho = ncfile.variables['y_rho'][:]
        h = ncfile.variables['h'][:]
        ncfile.close()
        hdims = h.ndim

    else:

        if not os.path.isfile(workfld + '/depth'):
            print('No depth file found in ' + workfld)
            return None

        h = np.loadtxt(workfld + '/depth')

        # Check if it is a 1D or 2D model
        hdims = h.ndim  # Horizontal dimensions
        if hdims == 1:
            x_rho = np.arange(0, h.shape[0], 1)
        elif hdims == 2:
            x_rho, y_rho = np.meshgrid(np.arange(0, h.shape[1], 1),
                                       np.arange(0, h.shape[0], 1))
        else:
            print('Something is wrong with the depth file')
            print('Quitting...')
            return None

    # Load time vector
    if not os.path.isfile(workfld + '/time'):
        print("No time file found in " + workfld)
        print("Quitting ...")
        return None

    ocean_time = np.loadtxt(workfld + '/time')

    # Create NetCDF file ------------------------------------------------------
    nc = netCDF4.Dataset(outfile, 'w', format='NETCDF4')
    nc.Description = 'NHWAVE Output'
    nc.Author = getpass.getuser()
    nc.Created = time.ctime()
    nc.Owner = 'Nearshore Modeling Group'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Source = workfld
    nc.Script = os.path.realpath(__file__)

    # Add more global variables to output (if input file is provided)
    if inpinfo:
        for tmpatt in inpinfo.keys():
            nc.__setattr__(tmpatt, inpinfo[tmpatt][:])

    # Create dimensions
    if verbose:
        print('Creating dimensions')

    if hdims == 2:
        eta_rho, xi_rho = h.shape
        nc.createDimension('eta_rho', eta_rho)
    else:
        xi_rho = h.shape[0]
        eta_rho = 1
    nc.createDimension('xi_rho', xi_rho)
    nc.createDimension('ocean_time', 0)

    # Get vertical layers
    if not vars_3d and not vars_3d_time:
        print("No 3D variables found")
        s_rho = False
    else:
        # Load any 3D variables
        if os.path.isfile(workfld + '/' + vars_3d_time[0] + '_00001'):
            tmpvar = np.loadtxt(workfld + '/' + vars_3d_time[0] + '_00001')
        elif os.path.isfile(workfld + '/' + vars_3d[0] + '_umean'):
            tmpvar = np.loadtxt(workfld + '/' + vars_3d[0] + '_umean')
        elif os.path.isfile(workfld + '/' + vars_3d[0] + '_vmean'):
            tmpvar = np.loadtxt(workfld + '/' + vars_3d[0] + '_vmean')
        else:
            tmpvar = np.loadtxt(workfld + '/' + vars_3d[0])

        # Outputs are stacked on the first dimension of the file
        # I need to enhance this and will probably have to use the input file
#         if hdims == 2:
#             s_rho = tmpvar.shape[0]/h.shape[0]
#         else:
#             s_rho = tmpvar.shape[0]
        s_rho = tmpvar.size / h.shape[0]

        nc.createDimension('s_rho', s_rho)

    # Write coordinates, bathymetry and time ----------------------------------
    if verbose:
        print("Saving coordinates and time")

    if hdims == 2:

        nc.createVariable('x_rho', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho

        nc.createVariable('y_rho', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['y_rho'].units = 'meter'
        nc.variables['y_rho'].longname = 'y-locations of RHO points'
        nc.variables['y_rho'][:] = y_rho

        nc.createVariable('h', 'f8', ('eta_rho', 'xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h

    else:

        nc.createVariable('x_rho', 'f8', ('xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho

        nc.createVariable('h', 'f8', ('xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h

    # Create s_rho vector
    if s_rho:
        ds = 1.0 / s_rho
        sigma = np.arange(ds / 2.0, 1 - ds / 2.0, ds)
        nc.createVariable('s_rho', 'f8', ('s_rho'))
        nc.variables['s_rho'].longname = 's-coordinate at cell centers'
        nc.variables['s_rho'].positive = 'up'
        nc.variables['s_rho'].notes = 'small s_rho means close to bottom'
        nc.variables['s_rho'][:] = sigma

    # Create time vector
    nc.createVariable('ocean_time', 'f8', 'ocean_time')
    nc.variables['ocean_time'].units = 'seconds since 2000-01-01 00:00:00'
    nc.variables['ocean_time'].calendar = 'julian'
    nc.variables['ocean_time'].long_name = 'beach time since initialization'
    nc.variables['ocean_time'].notes = 'units are arbitrary'
    nc.variables['ocean_time'][:] = ocean_time

    # Create variables ---------------------------------------------------------

    # Variable information
    varinfo = defaultdict(dict)

    varinfo['eta']['units'] = 'meter'
    varinfo['eta']['longname'] = 'water surface elevation'

    varinfo['waveheight']['units'] = 'meter'
    varinfo['waveheight']['longname'] = 'Mean wave height'
    varinfo['setup']['units'] = 'meter'
    varinfo['setup']['longname'] = 'Mean wave induced setup'

    varinfo['u']['units'] = 'meter second-1'
    varinfo['u']['longname'] = 'Flow velocity in the xi direction'
    varinfo['v']['units'] = 'meter second-1'
    varinfo['v']['longname'] = 'Flow velocity in the eta direction'
    varinfo['w']['units'] = 'meter second-1'
    varinfo['w']['longname'] = 'Flow velocity in the vertical direction'

    varinfo['umean']['units'] = 'meter second-1'
    varinfo['umean'][
        'longname'] = 'Depth-averaged flow velocity in xi direction'
    varinfo['vmean']['units'] = 'meter second-1'
    varinfo['vmean'][
        'longname'] = 'Depth-averaged flow velocity in eta direction'

    varinfo['lag_umean']['units'] = 'meter second-1'
    varinfo['lag_umean'][
        'longname'] = 'Lagrangian mean velocity in xi direction'
    varinfo['lag_vmean']['units'] = 'meter second-1'
    varinfo['lag_vmean'][
        'longname'] = 'Lagrangian mean velocity in eta direction'
    varinfo['lag_wmean']['units'] = 'meter second-1'
    varinfo['lag_wmean'][
        'longname'] = 'Lagrangian mean velocity in vertical direction'

    varinfo['euler_umean']['units'] = 'meter second-1'
    varinfo['euler_umean'][
        'longname'] = 'Eulerian mean velocity in xi direction'
    varinfo['euler_vmean']['units'] = 'meter second-1'
    varinfo['euler_vmean'][
        'longname'] = 'Eulerian mean velocity in eta direction'
    varinfo['euler_wmean']['units'] = 'meter second-1'
    varinfo['euler_wmean'][
        'longname'] = 'Eulerian mean velocity in vertical direction'

    # Loop over 2D variables that have no time component ----------------------
    if hdims == 1:
        nc_dims = ('xi_rho')
    else:
        nc_dims = ('eta_rho', 'xi_rho')

    for aa in vars_2d:

        if verbose:
            print('  Writing ' + aa)

        # Create variable
        create_nc_var(nc, aa, nc_dims, varinfo[aa]['units'],
                      varinfo[aa]['longname'])
        nc.variables[aa][:] = np.loadtxt(workfld + '/' + aa)

    # Loop over 3D variables that have no time component ----------------------
    if hdims == 1:
        nc_dims = ('s_rho', 'xi_rho')
    else:
        nc_dims = ('s_rho', 'eta_rho', 'xi_rho')

    for aa in vars_3d:

        if verbose:
            print('  Writing ' + aa)

        if aa == 'euler' or aa == 'lag':
            for bb in ['umean', 'vmean', 'wmean']:
                create_nc_var(nc, aa + '_' + bb, nc_dims,
                              varinfo[aa + '_' + bb]['units'],
                              varinfo[aa + '_' + bb]['longname'])
                if hdims == 1:
                    nc.variables[aa + '_' + bb][:] = \
                    np.loadtxt(workfld + '/' + aa + '_' + bb)
                else:
                    tmpvar = np.loadtxt(workfld + '/' + aa + '_' + bb)
                    tmpvar2 = np.zeros((s_rho, eta_rho, xi_rho))
                    for cc in range(s_rho):
                        tmpvar2[cc, :, :] = tmpvar[cc * eta_rho:(cc + 1) *
                                                   eta_rho, :]

                    nc.variables[aa + '_' + bb][:] = tmpvar2
                    del tmpvar, tmpvar2

        else:
            # Need to test this part with a full 3d code
            print("need to fix this")

    # Loop over 2D variables that have a time component -----------------------
    if hdims == 1:
        nc_dims = ('ocean_time', 'xi_rho')
    else:
        nc_dims = ('ocean_time', 'eta_rho', 'xi_rho')

    for aa in vars_2d_time:

        if verbose:
            print('  Writing ' + aa)

        # Create variable
        create_nc_var(nc, aa, nc_dims, varinfo[aa]['units'],
                      varinfo[aa]['longname'])

        tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % 1)
        nc.variables[aa][:] = np.expand_dims(tmpvar, axis=0)

        for bb in range(2, len(ocean_time) + 1):
            tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % bb)
            append_nc_var(nc, tmpvar, aa, bb - 1)

    # Loop over 3D variables that have a time component -----------------------
    if hdims == 1:
        nc_dims = ('ocean_time', 's_rho', 'xi_rho')
    else:
        nc_dims = ('ocean_time', 's_rho', 'eta_rho', 'xi_rho')

    for aa in vars_3d_time:

        if verbose:
            print('  Writing ' + aa)

        # Create variable
        create_nc_var(nc, aa, nc_dims, varinfo[aa]['units'],
                      varinfo[aa]['longname'])

        if hdims == 1:

            tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % 1)
            if s_rho == 1:
                nc.variables[aa][:] = np.expand_dims(np.expand_dims(tmpvar,
                                                                    axis=0),
                                                     axis=0)
            else:
                nc.variables[aa][:] = np.expand_dims(tmpvar, axis=0)
            for bb in range(2, len(ocean_time) + 1):
                tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % bb)
                append_nc_var(nc, tmpvar, aa, bb - 1)

        else:
            for bb in range(1, len(ocean_time) + 1):
                tmpvar = np.loadtxt(workfld + '/' + aa + '_' + '%05.0f' % bb)
                tmpvar2 = np.zeros((s_rho, eta_rho, xi_rho))
                for cc in range(s_rho):
                    tmpvar2[cc, :, :] = tmpvar[cc * eta_rho:(cc + 1) *
                                               eta_rho, :]

                if bb == 1:
                    nc.variables[aa][:] = np.expand_dims(tmpvar2, axis=0)
                else:
                    append_nc_var(nc, tmpvar2, aa, bb - 1)
                del tmpvar, tmpvar2

    # Close NetCDF file -------------------------------------------------------
    if verbose:
        print('Created: ' + outfile)
    nc.close()
Exemple #41
0
        os.remove(self.file)
        #pass

    def runTest(self):
        """testing compound variables"""
        f = Dataset(self.file, 'r')
        v = f.variables[VAR_NAME]
        g = f.groups[GROUP_NAME]
        vv = g.variables[VAR_NAME]
        dataout = v[:]
        dataoutg = vv[:]
        # make sure data type is aligned
        assert (f.cmptypes['cmp4'] == dtype4a)
        assert(list(f.cmptypes.keys()) ==\
               [TYPE_NAME1,TYPE_NAME2,TYPE_NAME3,TYPE_NAME4,TYPE_NAME5])
        assert_array_equal(dataout['xxx']['xx']['i'],data['xxx']['xx']['i'])
        assert_array_equal(dataout['xxx']['xx']['j'],data['xxx']['xx']['j'])
        assert_array_almost_equal(dataout['xxx']['yy']['x'],data['xxx']['yy']['x'])
        assert_array_almost_equal(dataout['xxx']['yy']['y'],data['xxx']['yy']['y'])
        assert_array_almost_equal(dataout['yyy'],data['yyy'])
        assert_array_equal(dataoutg['x1']['i'],datag['x1']['i'])
        assert_array_equal(dataoutg['x1']['j'],datag['x1']['j'])
        assert_array_almost_equal(dataoutg['y1']['x'],datag['y1']['x'])
        assert_array_almost_equal(dataoutg['y1']['y'],datag['y1']['y'])
        f.close()

if __name__ == '__main__':
    from netCDF4 import getlibversion
    version =  getlibversion().split()[0]
    unittest.main()
Exemple #42
0
try:
    import ujson as json
except:
    import json

# Version information
__version__ = "0.9b"

VERSION_STR = (
    "nc_diag_attr v"
    + __version__
    + "\n\n"
    + "Using the following library/runtime versions:\n"
    + ("    netcdf4-python v%s\n" % netCDF4.__version__)
    + ("    NetCDF v%s\n" % getlibversion())
    + ("    HDF5 v%s\n" % netCDF4.__hdf5libversion__)
    + ("    Python v%s\n" % sys.version.split("\n")[0].strip())
)

# CLI Arguments
global args


def parse_cli_args():
    global args
    parser = argparse.ArgumentParser(  # prog='ipush',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description="Tool to add/modify global and variable attributes for NetCDF files",
        version=VERSION_STR,
    )
Exemple #43
0
def spec2nc(buoyfld,dtheta=5):
    '''
    Code to convert NDBC spectral data files to netCDF format. 
    
    Usage:
    ------
    spec2nc(buoyfld,dtheta)
    
    Input:
    ------
    buoyfld  : Folder where the text files reside. Those should be the only
               files in the folder.
    dtheta   : Directional resolution for the reconstruction of the frequency-
               direction spectrum. Defaults to 5 degrees. 
    
    Notes:
      1. NetCDF4 file will be generated
      2. Code is not optimized since this is not something you will want to be
         running often. Beware of slow performance for large datasets.
    
    References:
    Kuik, A.J., G.Ph. van Vledder, and L.H. Holthuijsen, 1998: "Method for
      the Routine Analysis of Pitch-and-Roll Buoy Wave Data", Journal of
      Physical Oceanography, 18, 1020-1034.
      
    TODO:
    Only works with newer formats (YY MM DD hh mm)
    
    '''
    
    # For testing only ---------------------------------------------------------
    #buoyfld = '/home/shusin2/users/ggarcia/data/wave/b46029/spec/'
    #dtheta = 20
    # --------------------------------------------------------------------------
    
    # Construct directional angle
    angles = np.arange(0.0,360.0,dtheta)
    
    # Time reference
    basetime = datetime.datetime(1900,1,1,0,0,0)

    #===========================================================================
    # Read file information
    #===========================================================================
    
    # Get all files in folder
    archivos = glob.glob(buoyfld + '/*.txt')
    archivos = [x.split('/')[-1] for x in archivos]
    
    # Year information
    years = [x.split('.')[0][-4:] for x in archivos]    # Get all year stamps
    years = list(set(years))                            # Find unique years
    years.sort()                                        # Sort years
    
    # Get buoy ID information
    buoyid = [x[0:5] for x in archivos]                 # Find buoy ids
    buoyid = list(set(buoyid))                          # Find unique ids    
    if len(buoyid)>1:
        print('This code does not support conversion for multiple buoys')
        buoyid = buoyid[0]
        print('  ' +  buoyid + ' will be processed')
    else:
        buoyid = buoyid[0]
        
    # Info
    print('Found ' + np.str(len(years)) + ' files')
    print(buoyfld)    
    
    # Create output netcdf file ------------------------------------------------
    # Global attributes  
    nc = netCDF4.Dataset(buoyfld + '/' + buoyid + '_spec.nc',
                         'w',format='NETCDF4')
    nc.Description = buoyid + ' NDBC Spectral Data'
    nc.Rawdata = 'National Data Buoy Center \nwww.ndbc.noaa.gov'
    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__)
    nc.Notes = 'Nautical convention used for directions'    
    
    # Reconstruct the spectrum -------------------------------------------------        

    # counter variable to create variables in the netcdf file
    masterCnt = 0
    cnt_freq = 0 
    cnt_dir = 0
    tstep_freq = 0
    tstep_dir = 0
    
    # This variable will change if the format changes
    formIdCnt = 0
    formId = '0'
            
    # Frequency array to find if the reported frequencies changed
    freqArray = []
    
    # Loop over years
    for aa in years:
        
        # Info
        print('  Working on year ' + aa)
        
        # Load spectral density files
        # Check if file exists
        tmpfile = buoyfld + buoyid + 'w' + aa + '.txt'
        if os.path.isfile(tmpfile) == False:
            # No spectral density found for the given year, go to next one
            continue
        
        # Info
        print('    Spectral density data')
        
        # Increase master counter variable
        masterCnt += 1
        
        # Read spectral density data (frequency spectra) and identify the time
        # information given
        f_w = open(tmpfile,'r')
        freq = f_w.readline().split()
               
        # Allocate the frequency array and determine if the format changed ----
        freqArray.append(freq)
        if masterCnt > 1:
            if freq != freqArray[masterCnt-2]:
                
                # Reset counter variables                
                cnt_freq = 0 
                cnt_dir = 0
                tstep_freq = 0
                tstep_dir = 0
                
                # Update form Id counter
                formIdCnt += 1
                
                if formIdCnt > 9:
                    print('\n10 Different Formats Found')
                    print('Check your data, quitting ...')
                    nc.close()
                    sys.exit()
                    
                # Update form Id text
                formId = '%01.0f' % formIdCnt
                
                # Message to user
                print('    Different format found')
                print('      New variables introduced')
                
               
        # Find if minutes are given
        if freq[4] == 'mm':
            freqInd0 = 5
        else:
            freqInd0 = 4
               
        # Read frequencies
        freq = np.array(freq[freqInd0:],dtype=float)
        f_w.close()
        
        # Load spectral density
        freq_spec = np.loadtxt(tmpfile,skiprows=1)
        
        # Allocate time and spectral density data    
        freq_time = np.zeros((freq_spec.shape[0]))  
        for bb in range(freq_time.shape[0]):
            tmpYear  = np.int(freq_spec[bb,0])
            tmpMonth = np.int(freq_spec[bb,1])
            tmpDay   = np.int(freq_spec[bb,2])
            tmpHour  = np.int(freq_spec[bb,3])
            if freqInd0 == 4:
                tmpMin = np.int(0)
            else:
                tmpMin = np.int(freq_spec[bb,4])
            
            if tmpYear < 100:
                tmpYear = tmpYear + 1900
            
            freq_time[bb] = (datetime.datetime(tmpYear,tmpMonth,tmpDay,
                                               tmpHour,tmpMin) -
                             basetime).total_seconds()

        freq_spec = freq_spec[:,freqInd0:]
        
        # No Data Filter (NDBC uses 999.00 when there is no data)
        goodDataInd = freq_spec[:,1] < 990.00
        freq_time = freq_time[goodDataInd]
        freq_spec = freq_spec[goodDataInd,:]
        
        # Create frequency spectra variables
        cnt_freq += 1
        if cnt_freq == 1:
            
            # Create dimensions  (NetCDF4 supports multiple unlimited dimensions)
            nc.createDimension('wave_time'+formId,None)
        
            # Create bulk parameter variables
            nc.createVariable('Hsig'+formId,'f8','wave_time'+formId)
            nc.variables['Hsig'+formId].units = 'meter'
            nc.variables['Hsig'+formId].long_name = 'Significant wave height'
            
            # Create frequency dimension
            nc.createDimension('freq'+formId,freq.shape[0])
            
            nc.createVariable('wave_time'+formId,'f8','wave_time'+formId)
            nc.variables['wave_time'+formId].units = \
            "seconds since 1900-01-01 00:00:00"
            nc.variables['wave_time'+formId].calendar = "julian"
            
            nc.createVariable('freq_spec'+formId,'f8',
                              ('wave_time'+formId,'freq'+formId))
            nc.variables['freq_spec'+formId].units = 'meter2 second'
            nc.variables['freq_spec'+formId].long_name = 'Frequency variance spectrum'            
            
            nc.createVariable('frequency'+formId,'f8',('freq'+formId))
            nc.variables['frequency'+formId].units = 'Hz'
            nc.variables['frequency'+formId].long_name = 'Spectral frequency'
            nc.variables['frequency'+formId][:] = freq
        
    
        # Information
        print('    Computing Bulk Parameters')
        
        # Compute bulk parameters
        moment0 = np.trapz(freq_spec.T,freq,axis=0)
        Hsig = 4.004*(moment0)**0.5
        
        # Write to NetCDF file
        if cnt_freq == 1:
            nc.variables['Hsig'+formId][:] = Hsig
            nc.variables['freq_spec'+formId][:] = freq_spec
            nc.variables['wave_time'+formId][:] = freq_time
        else:
            nc.variables['Hsig'+formId][tstep_freq:] = Hsig
            nc.variables['freq_spec'+formId][tstep_freq:,:] = freq_spec
            nc.variables['wave_time'+formId][tstep_freq:] = freq_time

                
        # Check if directional data exists -------------------------------------
        tmp_alpha_1 = buoyfld  + buoyid + 'd' + aa + '.txt'
        tmp_alpha_2 = buoyfld  + buoyid + 'i' + aa + '.txt'
        tmp_r_1 = buoyfld  + buoyid + 'j' + aa + '.txt'
        tmp_r_2 = buoyfld  + buoyid + 'k' + aa + '.txt'
    
    
        if (os.path.isfile(tmp_alpha_1) and os.path.isfile(tmp_alpha_2) and
            os.path.isfile(tmp_r_1) and os.path.isfile(tmp_r_2)):
            
            # Information
            print('    Directional Data')
            
            # Read frequency of the directional spectra (not always agree with
            # the spectral densities)
            f_w2 = open(tmp_alpha_1,'r')
            freqDirSpec = f_w2.readline().split()
            freqDirSpec = np.array(freqDirSpec[freqInd0:],dtype=float)
            f_w2.close()  
            
            # Create directional spectra variables
            cnt_dir += 1
            if cnt_dir == 1:
                nc.createDimension('dir_time'+formId,None)
                nc.createDimension('dir'+formId,angles.shape[0])
                
                # Create frequency dimension
                nc.createDimension('freqDir'+formId,freqDirSpec.shape[0])
            
                nc.createVariable('dir_time'+formId,'f8','dir_time'+formId)
                nc.variables['dir_time'+formId].units = \
                "seconds since 1900-01-01 00:00:00"
                nc.variables['dir_time'+formId].calendar = "julian"
            
                nc.createVariable('dir_spec'+formId,'f8',
                                  ('dir_time'+formId,'freqDir'+formId,
                                   'dir'+formId))
                nc.variables['dir_spec'+formId].units = 'meter2 second degree-1'
                nc.variables['dir_spec'+formId].long_name = \
                    'Frequency-Direction variance spectrum'  
                    
                nc.createVariable('direction'+formId,'f8',('dir'+formId))
                nc.variables['direction'+formId].units = 'degree'
                nc.variables['direction'+formId].long_name = \
                    'Degrees from true north in oceanographic convention'
                nc.variables['direction'+formId][:] = angles
                
                nc.createVariable('frequencyDir'+formId,'f8',('freqDir'+formId))
                nc.variables['frequencyDir'+formId].units = 'Hz'
                nc.variables['frequencyDir'+formId].long_name = 'Spectral frequency for dir_spec'
                nc.variables['frequencyDir'+formId][:] = freqDirSpec
            
            
            # Read spectral data
            alpha_1 = np.loadtxt(tmp_alpha_1,skiprows=1)
            alpha_2 = np.loadtxt(tmp_alpha_1,skiprows=1)
            r_1 = np.loadtxt(tmp_alpha_1,skiprows=1) * 0.01
            r_2 = np.loadtxt(tmp_alpha_1,skiprows=1) * 0.01
    
            # Allocate date
            dir_time = np.zeros((alpha_1.shape[0]))              
            for bb in range(dir_time.shape[0]):
                tmpYear  = np.int(alpha_1[bb,0])
                tmpMonth = np.int(alpha_1[bb,1])
                tmpDay   = np.int(alpha_1[bb,2])
                tmpHour  = np.int(alpha_1[bb,3])
                if freqInd0 == 4:
                    tmpMin = np.int(0)
                else:
                    tmpMin = np.int(alpha_1[bb,4])
                                
                if tmpYear < 100:
                    tmpYear = tmpYear + 1900                                
                
                dir_time[bb] = (datetime.datetime(tmpYear,tmpMonth,tmpDay,
                                                  tmpHour,tmpMin) - 
                                basetime).total_seconds()

                             
            # Read data
            alpha_1 = alpha_1[:,freqInd0:]
            alpha_2 = alpha_2[:,freqInd0:]
            r_1 = r_1[:,freqInd0:]
            r_2 = r_2[:,freqInd0:]
            
            # No Data Filter (NDBC uses 999.00 when there is no data)
            goodDataInd = np.logical_and(alpha_1[:,1] != 999.00,
                                         alpha_1[:,2] != 999.00)
            alpha_1  = alpha_1[goodDataInd,:]
            alpha_2  = alpha_2[goodDataInd,:]
            r_1      = r_1[goodDataInd,:]
            r_2      = r_2[goodDataInd,:]
            dir_time = dir_time[goodDataInd]
            
            
            # Find where dir_time and freq_time match and compute those values
            # only
            repInd    = np.in1d(dir_time,freq_time)
            alpha_1   = alpha_1[repInd]
            alpha_2   = alpha_2[repInd]
            r_1       = r_1[repInd]
            r_2       = r_2[repInd]
            dir_time  = dir_time[repInd]
            
            repInd    = np.in1d(freq_time,dir_time)
            freq_spec = freq_spec[repInd] 

            # Interpolate density spectrum into directional bins            
            if not np.array_equal(freq,freqDirSpec):
                freqSpecAll = np.copy(freq_spec)
                freq_spec   = np.zeros_like((r_1)) * np.NAN
                for bb in range(freq_spec.shape[0]):
                    freq_spec[bb,:] = np.interp(freqDirSpec,freq,
                                                freqSpecAll[bb,:])
            
            # Construct 2D spectra
            # See http://www.ndbc.noaa.gov/measdes.shtml
            wspec = np.NaN * np.zeros((alpha_1.shape[0],
                                       alpha_1.shape[1],angles.shape[0]))
                        
            # Time loop
            for bb in range(wspec.shape[0]):
                # Frequency loop  
                for cc in range(wspec.shape[1]):
                    # Direction loop
                    for dd in range(wspec.shape[2]):
                        wspec[bb,cc,dd] = (freq_spec[bb,cc] * np.pi/180.0 *
                                           (1.0/np.pi) * 
                                           (0.5 + r_1[bb,cc] * 
                                            np.cos((angles[dd]-alpha_1[bb,cc])*
                                                   np.pi/180.0) +
                                            r_2[bb,cc] * 
                                            np.cos(2 * np.pi / 180.0 * 
                                                   (angles[dd]-alpha_2[bb,cc])))
                                           )
            
            # Write to file
            if cnt_dir == 1:
                nc.variables['dir_spec'+formId][:] = wspec
                nc.variables['dir_time'+formId][:] = dir_time
            else:
                nc.variables['dir_spec'+formId][tstep_dir:,:,:] = wspec
                nc.variables['dir_time'+formId][tstep_dir:] = dir_time
            
            tstep_dir += dir_time.shape[0]
                    
        # Update frequency time step and go to next year        
        tstep_freq += freq_time.shape[0]
        
       
    # Wrap up ------------------------------------------------------------------
    # Information
    print('Data stored as:')
    print('  ' + buoyfld + '/' + buoyid + '.nc')
    
    # Close NetCDF File     
    nc.close()
        

    
Exemple #44
0
def spec2nc(buoyfld, dtheta=5):
    '''
    Code to convert NDBC spectral data files to netCDF format. 
    
    Usage:
    ------
    spec2nc(buoyfld,dtheta)
    
    Input:
    ------
    buoyfld  : Folder where the text files reside. Those should be the only
               files in the folder.
    dtheta   : Directional resolution for the reconstruction of the frequency-
               direction spectrum. Defaults to 5 degrees. 
    
    Notes:
      1. NetCDF4 file will be generated
      2. Code is not optimized since this is not something you will want to be
         running often. Beware of slow performance for large datasets.
    
    References:
    Kuik, A.J., G.Ph. van Vledder, and L.H. Holthuijsen, 1998: "Method for
      the Routine Analysis of Pitch-and-Roll Buoy Wave Data", Journal of
      Physical Oceanography, 18, 1020-1034.
      
    TODO:
    Only works with newer formats (YY MM DD hh mm)
    
    '''

    # For testing only ---------------------------------------------------------
    # buoyfld = '/home/shusin2/users/ggarcia/data/wave/b46029/spec/'
    # dtheta = 5
    # --------------------------------------------------------------------------

    # Construct directional angle
    angles = np.arange(0.0, 360.0, dtheta)

    # Time reference
    basetime = datetime.datetime(1900, 01, 01, 0, 0, 0)

    #===========================================================================
    # Read file information
    #===========================================================================

    # Get all files in folder
    archivos = os.listdir(buoyfld)

    # Year information
    years = [x.split('.')[0][-4:] for x in archivos]  # Get all year stamps
    years = list(set(years))  # Find unique years
    years.sort()  # Sort years

    # Get buoy ID information
    buoyid = [x[0:5] for x in archivos]  # Find buoy ids
    buoyid = list(set(buoyid))  # Find unique ids
    if len(buoyid) > 1:
        print('This code does not support conversion for multiple buoys')
        buoyid = buoyid[0]
        print('  ' + buoyid + ' will be processed')
    else:
        buoyid = buoyid[0]

    # Create output netcdf file ------------------------------------------------
    # Global attributes
    nc = netCDF4.Dataset(buoyfld + '/' + buoyid + '_spec.nc',
                         'w',
                         format='NETCDF4')
    nc.Description = buoyid + ' NDBC Spectral Data'
    nc.Rawdata = 'National Data Buoy Center \nwww.ndbc.noaa.gov'
    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__)
    nc.Notes = 'Nautical convention used for directions'

    # Create dimensions  (NetCDF4 supports multiple unlimited dimensions)
    nc.createDimension('wave_time', None)
    nc.createDimension('dir_time', None)

    # Create bulk parameter variables
    nc.createVariable('Hsig', 'f8', 'wave_time')
    nc.variables['Hsig'].units = 'meter'
    nc.variables['Hsig'].long_name = 'Significant wave height'

    # Reconstruct the spectrum -------------------------------------------------

    # counter variable to create variables in the netcdf file
    cnt_freq = 0
    cnt_dir = 0
    tstep_freq = 0
    tstep_dir = 0

    # Loop over years
    for aa in years:

        # Load spectral density files
        # Check if file exists
        tmpfile = buoyfld + buoyid + 'w' + aa + '.txt'
        if os.path.isfile(tmpfile) == False:
            # No spectral density found for the given year, go to next one
            continue

        # Read spectral density data (frequency spectra)
        f_w = open(tmpfile, 'r')
        freq = f_w.readline().split()

        # Read frequencies
        freq = np.array(freq[5:], dtype=float)
        f_w.close()

        # Load spectral density
        freq_spec = np.loadtxt(tmpfile, skiprows=1)

        # Allocate time and spectral density data
        freq_time = np.zeros((freq_spec.shape[0]))
        for bb in range(freq_time.shape[0]):
            freq_time[bb] = (datetime.datetime(
                np.int(freq_spec[bb, 0]), np.int(freq_spec[bb, 1]),
                np.int(freq_spec[bb, 2]), np.int(freq_spec[bb, 3]),
                np.int(freq_spec[bb, 4])) - basetime).total_seconds()
        freq_spec = freq_spec[:, 5:]

        # Create frequency spectra variables
        cnt_freq += 1
        if cnt_freq == 1:
            nc.createDimension('freq', freq.shape[0])

            nc.createVariable('wave_time', 'f8', 'wave_time')
            nc.variables['wave_time'].units = \
            "seconds since 1900-01-01 00:00:00"
            nc.variables['wave_time'].calendar = "julian"

            nc.createVariable('freq_spec', 'f8', ('wave_time', 'freq'))
            nc.variables['freq_spec'].units = 'meter2 second'
            nc.variables['freq_spec'].long_name = 'Frequency variance spectrum'

            nc.createVariable('frequency', 'f8', ('freq'))
            nc.variables['frequency'].units = 'Hz'
            nc.variables['frequency'].long_name = 'Spectral frequency'
            nc.variables['frequency'][:] = freq

        # Check if directional data exists
        tmp_alpha_1 = buoyfld + buoyid + 'd' + aa + '.txt'
        tmp_alpha_2 = buoyfld + buoyid + 'i' + aa + '.txt'
        tmp_r_1 = buoyfld + buoyid + 'j' + aa + '.txt'
        tmp_r_2 = buoyfld + buoyid + 'k' + aa + '.txt'

        if (os.path.isfile(tmp_alpha_1) and os.path.isfile(tmp_alpha_2)
                and os.path.isfile(tmp_r_1) and os.path.isfile(tmp_r_2)):

            # Create directional spectra variables
            cnt_dir += 1
            if cnt_dir == 1:
                nc.createDimension('dir', angles.shape[0])

                nc.createVariable('dir_time', 'f8', 'dir_time')
                nc.variables['dir_time'].units = \
                "seconds since 1900-01-01 00:00:00"
                nc.variables['dir_time'].calendar = "julian"

                nc.createVariable('dir_spec', 'f8',
                                  ('dir_time', 'freq', 'dir'))
                nc.variables['dir_spec'].units = 'meter2 second degree-1'
                nc.variables['dir_spec'].long_name = \
                    'Frequency-Direction variance spectrum'

                nc.createVariable('direction', 'f8', ('dir'))
                nc.variables['direction'].units = 'degree'
                nc.variables['direction'].long_name = \
                    'Degrees from true north in oceanographic convention'
                nc.variables['direction'][:] = angles

            # Read spectral data
            alpha_1 = np.loadtxt(tmp_alpha_1, skiprows=1)
            alpha_2 = np.loadtxt(tmp_alpha_1, skiprows=1)
            r_1 = np.loadtxt(tmp_alpha_1, skiprows=1) * 0.01
            r_2 = np.loadtxt(tmp_alpha_1, skiprows=1) * 0.01

            # Allocate data
            dir_time = np.zeros((alpha_1.shape[0]))
            for bb in range(dir_time.shape[0]):
                dir_time[bb] = (datetime.datetime(
                    np.int(alpha_1[bb, 0]), np.int(alpha_1[bb, 1]),
                    np.int(alpha_1[bb, 2]), np.int(alpha_1[bb, 3]),
                    np.int(alpha_1[bb, 4])) - basetime).total_seconds()

            alpha_1 = alpha_1[:, 5:]
            alpha_2 = alpha_2[:, 5:]
            r_1 = r_1[:, 5:]
            r_2 = r_2[:, 5:]

            # Construct 2D spectra
            # See http://www.ndbc.noaa.gov/measdes.shtml
            wspec = np.NaN * np.zeros(
                (alpha_1.shape[0], freq.shape[0], angles.shape[0]))

            # Time loop
            for bb in range(wspec.shape[0]):
                # Frequency loop
                for cc in range(wspec.shape[1]):
                    # Direction loop
                    for dd in range(wspec.shape[2]):
                        wspec[bb, cc, dd] = (
                            freq_spec[bb, cc] * np.pi / 180.0 * (1.0 / np.pi) *
                            (0.5 + r_1[bb, cc] * np.cos(
                                (angles[dd] - alpha_1[bb, cc]) * np.pi / 180.0)
                             + r_2[bb, cc] *
                             np.cos(2 * np.pi / 180.0 *
                                    (angles[dd] - alpha_2[bb, cc]))))

            # Write to file
            if cnt_dir == 1:
                nc.variables['dir_spec'][:] = wspec
                nc.variables['dir_time'][:] = dir_time
            else:
                nc.variables['dir_spec'][tstep_dir:, :, :] = wspec
                nc.variables['dir_time'][tstep_dir:] = dir_time

            tstep_dir += dir_time.shape[0]

        # Compute bulk parameters
        moment0 = np.trapz(freq_spec.T, freq, axis=0)
        Hsig = 4.004 * (moment0)**0.5

        # Write to NetCDF file
        if cnt_freq == 1:
            nc.variables['Hsig'][:] = Hsig
            nc.variables['freq_spec'][:] = freq_spec
            nc.variables['wave_time'][:] = freq_time
        else:
            nc.variables['Hsig'][tstep_freq:] = Hsig
            nc.variables['freq_spec'][tstep_freq:, :] = freq_spec
            nc.variables['wave_time'][tstep_freq:] = freq_time

        tstep_freq += freq_time.shape[0]

    # Wrap up ------------------------------------------------------------------
    # Close NetCDF File
    nc.close()
Exemple #45
0
def convert_output(workfld,outfile,time_int=1.0,bathyfile=None,
                   inpfile=None,verbose=False):
    '''
    
    Parameters:
    -----------
    workfld      : Path to the folder where output files reside
    outfile      : Output NetCDF file
    time_int     : Time interval between output files [s] (will be updated if
                   input file is provided)
    bathyfile    : Full path to input netcdf bathy file (optional)
    inpfile      : Funwave input file used for metadata (optional)
    verbose      : Defaults to False
         
    Output:
    -------
    NetCDF File with the variables in the folder. Not all are supported so you 
    may need to edit this file.
    
    '''
    
    # For testing only
    #workfld = '/scratch/temp/ggarcia/funwaveC_ensemble/r0/'
    #outfile = '/scratch/temp/ggarcia/funwaveC_ensemble/02-runs/tmp.nc'
    #time_int = 0.5
    #bathyfile = '/scratch/temp/ggarcia/funwaveC_ensemble/r0/depth.nc'
    #inpfile = '/scratch/temp/ggarcia/funwaveC_ensemble/r0/input.init'

    # Get variable information ------------------------------------------------
    # Need to generalize
    archivos = glob.glob(workfld + '*.dat')                       # All files
    tmpvars = [x.split('/')[-1].split('.')[0] for x in archivos]  # All vars
    
    # If no variables found exit    
    if not tmpvars:
        print('No files found in ' + workfld)
        print('Quitting ...')
        return None
    
    # Make sure variables are within the supported ones
    supported_vars_time = ['eta','u']
    vars_2d = [x for x in tmpvars if x in supported_vars_time]
    
    
    # Read input file if provided ----------------------------------------------
    if inpfile:
        
        if verbose:
            print("Reading data from input file:")
            print("  " + inpfile)
        
        # Open file
        tmpinpfile = open(inpfile,'r')
        
        # Output dictionary
        inpinfo = {}
        
        # funwaveC is very structured so this is a simple way of reading
        # Dynamics line
        tmpLine = tmpinpfile.readline().rstrip()
        inpinfo['dynamics'] = tmpLine.split(' ')[-1]
        # Dimensions
        tmpLine = tmpinpfile.readline().rstrip()
        dx = np.float64(tmpLine.split(' ')[3])
        dy = np.float64(tmpLine.split(' ')[4])
        # Bottom stress
        tmpLine = tmpinpfile.readline().rstrip()
        inpinfo['bottomstress'] = tmpLine.split(' ')[2]
        # Mixing
        tmpLine = tmpinpfile.readline().rstrip()
        inpinfo['mixing'] = tmpLine.split(' ')[1] + ' ' + tmpLine.split(' ')[2]
        # Bathymetry
        tmpinpfile.readline()
        # Tide
        tmpinpfile.readline()
        # Wavemaker
        tmpLine = tmpinpfile.readline().rstrip()        
        inpinfo['eta_source'] = tmpLine[14:]
        # Wave breaking
        tmpLine = tmpinpfile.readline().rstrip()        
        inpinfo['breaking'] = tmpLine[9:]
        # Sponge layer
        tmpLine = tmpinpfile.readline().rstrip()        
        inpinfo['sponge'] = tmpLine[7:]
        # Forcing, initial conditions, tracers
        tmpinpfile.readline()
        tmpinpfile.readline()
        tmpinpfile.readline()
        tmpinpfile.readline()
        tmpinpfile.readline()
        tmpinpfile.readline()
        # Timing
        tmpLine = tmpinpfile.readline().rstrip()
        inpinfo['timing'] = tmpLine[7:]
        time_int = np.float64(tmpLine.split(' ')[5])
        
        # Close me
        tmpinpfile.close()
        
            
    else:
        
        # Assume grid spacing to be 1 meter
        if verbose:
            print("Input file not provided")
        dx = 1.0
        dy = 1.0
        inpinfo = False
    
    
    # Coordinates and depth ---------------------------------------------------
    # Bathymetry file provided
    if bathyfile: 
        
        if verbose:
            print("Reading coordinates and depth from:")
            print("  " + bathyfile)
        
        ncfile = netCDF4.Dataset(bathyfile,'r')
        x_rho = ncfile.variables['x_rho'][:]
        if ncfile.variables.has_key('y_rho'):
            y_rho = ncfile.variables['y_rho'][:]
        else:
            y_rho = None
        h = ncfile.variables['h'][:]
        ncfile.close()
       
        # Create u grid
        x_u       = np.zeros((x_rho.shape[0]+1,))
        x_u[0]    = x_rho[0] - dx/2
        x_u[-1]   = x_rho[-1] + dx/2
        x_u[1:-1] = (x_rho[1:] + x_rho[:-1])/2.0
        
    # Bathymetry file not provided but have output file        
    elif os.path.isfile(workfld + '/depth.txt'):
               
        # Fix this               
        h = np.loadtxt(workfld + '/depth.txt')
        
        hdims = h.ndim
        if hdims == 1:
            x_rho = np.arange(0,h.shape[0],dx)
        elif hdims == 2:
            x_rho, y_rho = np.meshgrid(np.arange(0,h.shape[1],dx),
                                       np.arange(0,h.shape[0],dy))           
        else:
            if verbose:
                print('Something is wrong with the depth file')
    
    # No bathymetry file provided
    else:
        
        if verbose:
            print("No bathymetry file provided")

    # Get dimensions of variables
    hdims = h.ndim
    
    # Create NetCDF file -------------------------------------------------------
    if verbose:
        print("Creating " + outfile)
    
    # Global attributes  
    nc = netCDF4.Dataset(outfile, 'w', format='NETCDF4')
    nc.Description = 'FunwaveC Output'
    nc.Author = '*****@*****.**'
    nc.Created = time.ctime()
    nc.Type = 'FunwaveC snapshot output'
    nc.Owner = 'Nearshore Modeling Group'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Source = workfld
    nc.Script = os.path.realpath(__file__)
    
    # Add more global variables to output
    if inpinfo:
        for tmpatt in inpinfo.keys():
            nc.__setattr__(tmpatt,inpinfo[tmpatt][:])
    
    # Create dimensions
    if hdims == 2:
        eta_rho, xi_rho = h.shape
        nc.createDimension('eta_rho', eta_rho)
    else:
        xi_rho = h.shape[0]
        xi_u   = xi_rho + 1
        eta_rho = 1
    nc.createDimension('xi_rho', xi_rho)
    nc.createDimension('xi_u',xi_u)            
    nc.createDimension('ocean_time',0)
    
    # Write coordinate axes ----------------------------------------------
    if hdims == 2:
        
        nc.createVariable('x_rho','f8',('eta_rho','xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho
        
        nc.createVariable('y_rho','f8',('eta_rho','xi_rho'))
        nc.variables['y_rho'].units = 'meter'
        nc.variables['y_rho'].longname = 'y-locations of RHO points'
        nc.variables['y_rho'][:] = y_rho

        nc.createVariable('h','f8',('eta_rho','xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h


    else:
        
        nc.createVariable('x_rho','f8',('xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho
        
        nc.createVariable('h','f8',('xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h

        nc.createVariable('x_u','f8',('xi_u'))
        nc.variables['x_u'].units = 'meter'
        nc.variables['x_u'].longname = 'x-locations of U points'
        nc.variables['x_u'][:] = x_u        
        
    # Create time vector -------------------------------------------------------
    tmpvar = np.loadtxt(workfld + vars_2d[0] + '.dat')
    twave  = np.arange(time_int,time_int*tmpvar.shape[0]+time_int,time_int)
            
    nc.createVariable('ocean_time','f8','ocean_time')
    nc.variables['ocean_time'].units = 'seconds since 2000-01-01 00:00:00'
    nc.variables['ocean_time'].calendar = 'julian'
    nc.variables['ocean_time'].long_name = 'beach time'
    nc.variables['ocean_time'][:] = twave
        
    # Create variables --------------------------------------------------------

    # Variable information
    varinfo = defaultdict(dict)

    varinfo['eta']['units'] = 'meter'
    varinfo['eta']['longname'] = 'water surface elevation'
    varinfo['eta']['dims'] = ('ocean_time','xi_rho')
    
    varinfo['u']['units'] = 'meter second-1'
    varinfo['u']['longname'] = 'Flow velocity in the xi direction'
    varinfo['u']['dims'] = ('ocean_time','xi_u')
    
    varinfo['v']['units'] = 'meter second-1'
    varinfo['v']['longname'] = 'Flow velocity in the eta direction'
    varinfo['v']['dims'] = ('ocean_time','xi_v')
         
    if verbose:          
        print("Creating variables")
                  
    for aa in vars_2d:
        
        if verbose:
            print('  ' + aa)
        
                # Load variable
        try:
            tmpvar = np.loadtxt(workfld + '/' + aa + '.dat')
        except:
            if verbose:
                print("  Could not create " + aa)
                print("  Input file error")
            continue
        
        # Create variable
        create_nc_var(nc,aa,varinfo[aa]['dims'],varinfo[aa]['units'],
                      varinfo[aa]['longname'])        

        # Write variable
        nc.variables[aa][:] = tmpvar
        
                    
    # Close NetCDF file
    if verbose:
        print('Closing ' + outfile)
    nc.close()
Exemple #46
0
def bulk2nc(buoyfld,buoyid,ncformat=4,verbose=True):
    '''
    Code to convert bulk parameter text files into netcdf file
    
    Usage:
    ------
    bulk2nc(buoyfld,buoyid,ncformat)
    
    Input:
    ------
    buoyfld  = Folder where the bulk paramerter text files reside.
    buoyid   = Netcdf buoy identifier (to figure out the file names)
    ncformat = set as 3 for netCDF3, set as 4 for netCDF4 (default)
    verbose  = some extra information (True is default)
    
    Notes:
    Only the bulk parameter files must be present in that directory. The code is
    not smart enough (and I do not have the time to make it so) to figure out 
    the bulk parameter files. 
    
    '''
    
    #===========================================================================
    # Read and Clean Up Data
    #===========================================================================
    
    # Get all files in folder
    archivos = os.listdir(buoyfld)
    archivos.sort()
    
    # Initialize variables
    wavetime = np.empty([1,])
    WDIR = np.empty([1,]) #AKA WD
    WSPD = np.empty([1,])
    GST = np.empty([1,])
    WVHT = np.empty([1,])
    DPD = np.empty([1,])
    APD = np.empty([1,])
    MWD = np.empty([1,])
    PRES = np.empty([1,]) #AKA BAR
    ATMP = np.empty([1,])
    WTMP = np.empty([1,])
    
    
    # Loop over files
    for tmpFile in archivos:
        
        if tmpFile.endswith('.txt'):
            
            if verbose:
                print(tmpFile)

            # Read header lines to determine the location of variables
            with open(buoyfld + '/' + tmpFile,'r') as f:
                header1 = f.readline()
                header2 = f.readline()
                
                # Determine the number of header lines (NDBC uses one or two)
                if header1.startswith('Y') or header1.startswith('#'):
                    headcnt = 1
                if header2.startswith('Y') or header2.startswith('#'):
                    headcnt = 2
                    
                
            # Collapse multiple spaces into one
            header3 = ' '.join(header1.split())
            header4 = header3.split()
            
            # Load buoy data
            tmpdata = pl.loadtxt(buoyfld + '/' + tmpFile,skiprows=headcnt)
            
            
            # ======================  Allocate variables  ==================== #
            # Wind direction
            if any(tt == 'WD' for tt in header4):
                tind = header4.index('WD')
                WDIR = np.concatenate((WDIR,tmpdata[:,tind]))
            elif any(tt == 'WDIR' for tt in header4):
                tind = header4.index('WDIR')
                WDIR = np.concatenate((WDIR,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                WDIR = np.concatenate((WDIR,tmparray))
                del tmparray 
            
            # Wind Speed
            if any(tt == 'WSPD' for tt in header4):
                tind = header4.index('WSPD')
                WSPD = np.concatenate((WSPD,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                WSPD = np.concatenate((WSPD,tmparray))
                del tmparray 
                
            # Wind Gust
            if any(tt == 'GST' for tt in header4):
                tind = header4.index('GST')
                GST = np.concatenate((GST,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                GST = np.concatenate((GST,tmparray))
                del tmparray 
            
            # Wave Height
            if any(tt == 'WVHT' for tt in header4):
                tind = header4.index('WVHT')
                WVHT = np.concatenate((WVHT,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                WVHT = np.concatenate((WVHT,tmparray))
                del tmparray 
                
            # Dominant Wave Period
            if any(tt == 'DPD' for tt in header4):
                tind = header4.index('DPD')
                DPD = np.concatenate((DPD,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                DPD = np.concatenate((DPD,tmparray))
                del tmparray
                
            # Average Wave Period
            if any(tt == 'APD' for tt in header4):
                tind = header4.index('APD')
                APD = np.concatenate((APD,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                APD = np.concatenate((APD,tmparray))
                del tmparray 
                            
            # Mean Wave Direction
            if any(tt == 'MWD' for tt in header4):
                tind = header4.index('MWD')
                MWD = np.concatenate((MWD,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                MWD = np.concatenate((MWD,tmparray))
                del tmparray 
    
            # Sea Level Pressure
            if any(tt == 'PRES' for tt in header4):
                tind = header4.index('PRES')
                PRES = np.concatenate((PRES,tmpdata[:,tind]))
            elif any(tt == 'BAR' for tt in header4):
                tind = header4.index('BAR')
                PRES = np.concatenate((PRES,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                PRES = np.concatenate((PRES,tmparray))
                del tmparray 
    
            # Air temperature
            if any(tt == 'ATMP' for tt in header4):
                tind = header4.index('ATMP')
                ATMP = np.concatenate((ATMP,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                ATMP = np.concatenate((ATMP,tmparray))
                del tmparray  
    
            # Sea surface temperature
            if any(tt == 'WTMP' for tt in header4):
                tind = header4.index('WTMP')
                WTMP = np.concatenate((WTMP,tmpdata[:,tind]))
            else:
                tmparray = np.ones([tmpdata.shape[0],1])
                tmparray[:] = np.NaN
                WTMP = np.concatenate((WTMP,tmparray))
                del tmparray                   
      
      
            # ================== Time management =================
            # Years
            if any(tt == 'YY' for tt in header4):
                tind = header4.index('YY')
                years = tmpdata[:,tind] + 1900   
            elif any(tt == '#YY' for tt in header4):
                tind = header4.index('#YY')
                years = tmpdata[:,tind]             
            else:
                tind = header4.index('YYYY')
                years = tmpdata[:,tind]
    
            # Minutes
            if any(tt == 'mm' for tt in header4):
                tind = header4.index('mm')
                mm = tmpdata[:,tind]
            else:
                mm = np.zeros([tmpdata.shape[0],1])
    
    
            # Create time vector
            # Seconds from 1900-01-01 will be used
            for aa in range(tmpdata.shape[0]):
                tmptime = datetime.datetime(int(years[aa]),
                                            int(tmpdata[aa,1]),
                                            int(tmpdata[aa,2]),
                                            int(tmpdata[aa,3]),
                                            int(mm[aa]),
                                            0)
                sectime = tmptime - datetime.datetime(1900,1,1,0,0,0)
                secsecs = sectime.total_seconds()
                wavetime = np.concatenate([wavetime,np.array([secsecs])])            
                del tmptime,sectime,secsecs
            
            # ================ Clean up ================
            del header1,header2,header3,header4,years,mm
    
    
    # Remove first term of each array
    wavetime = np.delete(wavetime,0)
    WDIR = np.delete(WDIR,0)
    WSPD = np.delete(WSPD,0)
    GST = np.delete(GST,0)
    WVHT = np.delete(WVHT,0)
    DPD = np.delete(DPD,0)
    APD = np.delete(APD,0)
    MWD = np.delete(MWD,0)
    PRES = np.delete(PRES,0)
    ATMP = np.delete(ATMP,0)
    WTMP = np.delete(WTMP,0)
    
    # Clean up variables
    WDIR[WDIR==999] = np.NaN
    WSPD[WSPD==99] = np.NaN
    GST[GST==99] = np.NaN
    WVHT[WVHT==99] = np.NaN
    DPD[DPD==99] = np.NaN
    APD[APD==99] = np.NaN
    MWD[MWD==999] = np.NaN
    PRES[PRES==9999] = np.NaN
    ATMP[ATMP==99] = np.NaN
    WTMP[WTMP==99] = np.NaN
    
    # Order chronologically
    sorted_index = np.argsort(wavetime)
    wavetime = [wavetime[i] for i in sorted_index]
    WDIR = [WDIR[i] for i in sorted_index]
    WSPD = [WSPD[i] for i in sorted_index]
    GST = [GST[i] for i in sorted_index]
    WVHT = [WVHT[i] for i in sorted_index]
    DPD = [DPD[i] for i in sorted_index]
    APD = [APD[i] for i in sorted_index]
    MWD = [MWD[i] for i in sorted_index]
    PRES = [PRES[i] for i in sorted_index]
    ATMP = [ATMP[i] for i in sorted_index]
    WTMP = [WTMP[i] for i in sorted_index]
    
    
    #===========================================================================
    # Save as NetCDF 
    #===========================================================================
      
      
    # Global attributes  
    if ncformat == 4:
        print("Saving the buoy data with NetCDF4 format")
        nc = netCDF4.Dataset(buoyfld + '/' + buoyid + '.nc', 'w',
                             format='NETCDF4')
    else:
        print("Saving the buoy data with NetCDF3 format")
        nc = netCDF4.Dataset(buoyfld + '/' + buoyid + '.nc', 'w', 
                             format='NETCDF3_CLASSIC')
    nc.Description = buoyid + ' NDBC Bulk Parameter Data'
    nc.rawdata = 'National Data Buoy Center \nwww.ndbc.noaa.gov'
    nc.Author = '[email protected] \nNearshore Modeling Group'
    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('wave_time',None)
    
    
    # pyroms subroutine to write NetCDF fields
    def write_nc_var(var, name, dimensions, units=None, longname=None):
        nc.createVariable(name, 'f8', dimensions)
        if units is not None:
            nc.variables[name].units = units  
        if longname is not None:
            nc.variables[name].long_name = longname  
        nc.variables[name][:] = var
          
    
    # Write Variables To NetCDF file
    write_nc_var(wavetime,'wave_time','wave_time',
                 'seconds since 1900-01-01 00:00:00','measurement time UTC')
    write_nc_var(WDIR, 'WDIR', 'wave_time', 'degrees',
                 'Wind direction (direction the wind is coming from in ' + 
                 'degrees clockwise from true North')
    write_nc_var(WSPD, 'WSPD', 'wave_time', 'meter second-1',
                 'Wind speed averaged over an eight-minute period')
    write_nc_var(GST, 'GST','wave_time','meter second-1','Peak gust speed')
    write_nc_var(WVHT,'WVHT','wave_time','meter',
                 'Significant wave height during the 20 minute sampling period')
    write_nc_var(DPD,'DPD','wave_time','second',
                 'Dominant wave period (period with the maximum wave energy)')
    write_nc_var(APD,'APD','wave_time','second',
                 'Average wave period of all waves during the 20 minute' + 
                 ' sampling period')
    write_nc_var(MWD,'MWD','wave_time','degrees',
                 'The direction from which the waves at the dominant period ' + 
                 'are coming in degrees from true North, increasing clockwise')
    write_nc_var(PRES,'PRES','wave_time','hPa','Sea level pressure')
    write_nc_var(ATMP,'ATMP','wave_time','Celsius','Air temperature')
    write_nc_var(WTMP,'WTMP','wave_time','Celsius','Sea surface temperature')
      
    # Close NetCDF File 
    nc.close()
Exemple #47
0
def writeROMSGrid(outFile,variables,varinfo,
                  timeinfo=None,verbose=False):
    """
    Code to write roms grids based on input variables
    
    INPUT:
    ------
    outFile    : Full path to output netcdf file
    variables  : Dictionary containing variables. (see notes)
    varinfo    : Path to ROMS varinfo.dat. Usually under:
                 /path/to/roms/trunk/ROMS/External/varinfo.dat
    timeinfo   : Time vector in nested dictionary form (see example)
    verbose    : some info displayed on the terminal                 
    
    RETURNS:
    --------
    
    NOTES:
    ------
    -  variables need rho variables (x_rho,y_rho)
    
    TODO:
    -----
    -  Include a varinfo.dat with the pynmd package
    
    EXAMPLE:
    ---------
    >>> import numpy as np
    >>> from collections import defaultdict
    >>> import pynmd.models.roms.pre as groms    
    >>>
    >>> x_rho,y_rho = np.meshgrid(np.arange(0,10,1),np.arange(0,10,1)
    >>> variables = {}
    >>> variables['x_rho'] = x_rho
    >>> variables['y_rho'] = y_rho
    >>>
    >>> variables['type'] = 'ROMS FORCING FILE'
    >>>
    >>> timeinfo = defaultdict(time)
    >>> timeinfo['sms_time']['units'] = 'seconds since 1970-01-01 00:00:00 UTC'
    >>> timeinfo['sms_time']['data'] = np.arange(0,1000,10)
    >>> timeinfo['sms_time']['long_name'] = 'surface momentum stress time'
    >>>
    >>> groms.writeROMSGrid(outFile,...)
    
    """

    # Testing only
    #outFile = ('/home/shusin3/users/ggarcia/projects/other/' + 
    #           'columbiaRiverPlume/11-romsIdealized/03-extendedNR2/' + 
    #           'orIdealizedExtStr.nc')
    #varinfo = ('/home/shusin3/users/ggarcia/projects/other/' + 
    #           'columbiaRiverPlume/94-roms/trunk/ROMS/External/varinfo.dat')
    #verbose = True
    
   
    # Read varinfo -------------------------------------------------------------
    if verbose:
        print('Reading Varinfo')
        print('  ' + varinfo)
    
    # Create dictionary to get information from
    varinfodict = defaultdict(dict)
    
    # Structure of the variables 
    # hardcoded because I couldn't find a generalized description
    varStruct = ['long_name','units','field','time','id','dimensions']
       
    # Read the varinfo
    with open(varinfo) as f:
        
        # Read into a list of lines
        lines = f.readlines()
        
        # Loop through lines
        for line in lines:
            
            #Skip lines starting with !
            if line.startswith("!"):
                continue
            
            # Skip blank lines
            if line.isspace():
                continue
            
            # Skip other non variable lines
            if line.startswith("'$"):
                continue
            
            # Read variables and allocate properties
            if line.startswith("'"):
                tmpVar = line.split(' ')[0][1:-1]
                cnt = -1
                continue
            
            # Add counter variable and allocate only the necessary fields
            cnt += 1            
            if cnt > (len(varStruct) - 1):
                continue
            
            varinfodict[tmpVar][varStruct[cnt]] =\
              line.split('  ')[1].split('\n')[0][1:-1]
            
    f.close()    
    
    # Import grid variables and update the dictionary
    gridVariables = gridVars()
    varinfodict.update(gridVariables)
    
    # Create netCDF file -------------------------------------------------------
    if verbose:
        print('Creating: ' + outFile)
        
    nc = netCDF4.Dataset(outFile, 'w', format='NETCDF4')    
    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())    
    
    if 'type' in variables.keys():
        nc.type = variables['type']
    
    # Create dimensions --------------------------------------------------------
    
    if verbose:
        print("  Creating Dimensions ...")
    # Horizontal dimensions
    nc.createDimension('xi_psi',np.size(variables['x_rho'],1)-1)
    nc.createDimension('xi_rho',np.size(variables['x_rho'],1))
    nc.createDimension('xi_u',np.size(variables['x_rho'],1)-1)
    nc.createDimension('xi_v',np.size(variables['x_rho'],1))
    nc.createDimension('eta_psi',np.size(variables['x_rho'],0)-1)
    nc.createDimension('eta_rho',np.size(variables['x_rho'],0))
    nc.createDimension('eta_u',np.size(variables['x_rho'],0))
    nc.createDimension('eta_v',np.size(variables['x_rho'],0)-1)
    
    # Vertical dimensions
    if 's_rho' in variables.keys():
        nc.createDimension('s_rho',variables['s_rho'].size)
        nc.createDimension('s_w',variables['s_w'].size)
    
    # Time dimension and variable (unlimited,netCDF4 supports multiple)
    if timeinfo:
        
        if verbose:
            print('  Writing Time Variables:')
            
        for aa in timeinfo.keys():
            
            if verbose:
                print('    ' + aa)
                
            # Create dimension
            nc.createDimension(aa,0)
            nc.createVariable(aa,'f8',(aa))
            
            # Write variable information
            for bb in timeinfo[aa].keys():
                
                if bb == 'data':
                    nc.variables[aa][:] = timeinfo[aa]['data'] 
                else:
                    nc.variables[aa].__setattr__(bb,timeinfo[aa][bb])
        
    # Write other variables
    if verbose:
        print('  Writing variables:')

    # Loading dimensions
    dimInfo = gridDims()

    for aa in variables.keys():
        
        # Determine dimensions
        try:
            tmpdims = dimInfo[varinfodict[aa]['dimensions']]
            if varinfodict[aa]['dimensions'] == 'nulvar':
                tmpdims = tmpdims[aa]
        except:
            continue
        
        if verbose:
            print('    ' + aa)
            
        if 'time' in varinfodict[aa].keys():
            tmpdims = (varinfodict[aa]['time'],) + tmpdims
        
        # Create Variable
        nc.createVariable(aa,'f8',tmpdims)
        
        # Write attributes
        for bb in varinfodict[aa].keys():
            if bb == 'dimensions' or bb == 'id':
                continue
            nc.variables[aa].__setattr__(bb,varinfodict[aa][bb])
        
        # Write data
        nc.variables[aa][:] = variables[aa]
                
        
    # Close netcdf file
    nc.close()
    
    if verbose:
        print('Done')
Exemple #48
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()
Exemple #49
0
def write_bathy(x,h,path,y=None,ncsave=True,dt=None):
    '''
    
    Parameters:    
    ----------
    x           : array of x coordinates
    y           : array of x coordinates (optional)
    h           : Bathymetry
    path        : Full path where the output will be saved
    ncsave      : Save bathy as NetCDF file
    dt          : (Optional) informs about the stability for a chosen dt
    
    Output:
    -------
    depth.txt   : Text file with the depth information for Funwave input.
    depth.nc    : (Optional) NetCDF4 bathymetry file. 
    
    Notes:
    ------
    1. Variables are assumed to be on a regularly spaced grid.
    2. If y is passed then 2D bathymetry is assumed. This means that 
       x,y,h have to be 2D arrays. Otherwise the code will fail.
    
    '''

    # Output the text file -----------------------------------------------------        
    fid = open(path + 'depth.txt','w')
    if y is None:
        for aa in range(len(h)):
            fid.write('%12.3f\n' % h[aa])
        fid.close()
    else:
        for aa in range(h.shape[1]):
            for bb in range(h.shape[0]):
                fid.write('%12.3f' % h[bb,aa])
            fid.write('\n')
        fid.close()

    if ncsave:
    
        # Global attributes  
        nc = netCDF4.Dataset(path + 'depth.nc', 'w', format='NETCDF4')
        nc.Description = 'Funwave 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
        if y is None:
            xi_rho = len(h)
            nc.createDimension('xi_rho', xi_rho)
            varShape = ('xi_rho')
        else:
            eta_rho,xi_rho = np.shape(h)
            nc.createDimension('xi_rho', xi_rho)
            nc.createDimension('eta_rho',eta_rho)
            varShape = ('eta_rho','xi_rho')
            
            # Write y variable
            create_nc_var(nc, 'y_rho',varShape, 
                          'meter','y-locations of RHO-points')
            nc.variables['y_rho'][:] = y
                    
        # Write coordinates and depth to netcdf file
        create_nc_var(nc, 'x_rho',varShape, 
                     'meter','x-locations of RHO-points')
        nc.variables['x_rho'][:] = x
        
        create_nc_var(nc,'h',varShape, 
                     'meter','bathymetry at RHO-points')
        nc.variables['h'][:] = h      

        # Close NetCDF file
        nc.close()

    else: 
    
        print("NetCDF file not requested")
        
        

    #===========================================================================
    # Print input file options
    #===========================================================================
    print(' ')
    print('===================================================================')
    print('In your funwaveC init file:')
    if y is None:
        dx = np.abs(x[1] - x[0])
        print('dimension ' + np.str(len(x)+1) + ' 6 ' +
              np.str(dx) + ' 1')
    else:
        dx = np.abs(x[0,1] - x[0,0]) # For later use
        dy = np.abs(y[1,0] - y[0,0])
        print('dimension ' + np.str(x.shape[1]+1) + ' ' + 
              np.str(x.shape[0]) + ' ' +
              np.str(dx) + ' ' + 
              np.str(dy))
    print('===================================================================')
    print(' ')
    
    # Stability options    
    stabilityCriteria(dx,h.max(),dt=dt,verbose=True)
Exemple #50
0
def convert_output(workfld,outfile,time_int=1.0,bathyfile=None,
                   inpfile=None,verbose=False):
    '''
    
    Parameters:
    -----------
    workfld      : Path to the folder where output files reside
    outfile      : Output NetCDF file
    time_int     : Time interval between output files [s] (will be updated if
                   input file is provided)
    bathyfile    : Full path to input netcdf bathy file (optional)
    inpfile      : Funwave input file used for metadata (optional)
    verbose      : Defaults to False
         
    Output:
    -------
    NetCDF File with the variables in the folder. Not all are supported so you 
    may need to edit this file.
    
    '''
    
    # For testing only
    #workfld = '/scratch/temp/ggarcia/funwaveC_ensemble/r0/'
    #outfile = '/scratch/temp/ggarcia/funwaveC_ensemble/02-runs/tmp.nc'
    #time_int = 0.5
    #bathyfile = '/scratch/temp/ggarcia/funwaveC_ensemble/r0/depth.nc'
    #inpfile = '/scratch/temp/ggarcia/funwaveC_ensemble/r0/input.init'

    # Get variable information ------------------------------------------------
    # Need to generalize
    archivos = glob.glob(workfld + '*.dat')                       # All files
    tmpvars = [x.split('/')[-1].split('.')[0] for x in archivos]  # All vars
    
    # If no variables found exit    
    if not tmpvars:
        print('No files found in ' + workfld)
        print('Quitting ...')
        return None
    
    # Make sure variables are within the supported ones
    supported_vars_time = ['eta','u']
    vars_2d = [x for x in tmpvars if x in supported_vars_time]
    
    
    # Read input file if provided ----------------------------------------------
    if inpfile:
        
        if verbose:
            print("Reading data from input file:")
            print("  " + inpfile)
        
        # Open file
        tmpinpfile = open(inpfile,'r')
        
        # Output dictionary
        inpinfo = {}
        
        # funwaveC is very structured so this is a simple way of reading
        # Dynamics line
        tmpLine = tmpinpfile.readline().rstrip()
        inpinfo['dynamics'] = tmpLine.split(' ')[-1]
        # Dimensions
        tmpLine = tmpinpfile.readline().rstrip()
        dx = np.float64(tmpLine.split(' ')[3])
        dy = np.float64(tmpLine.split(' ')[4])
        # Bottom stress
        tmpLine = tmpinpfile.readline().rstrip()
        inpinfo['bottomstress'] = tmpLine.split(' ')[2]
        # Mixing
        tmpLine = tmpinpfile.readline().rstrip()
        inpinfo['mixing'] = tmpLine.split(' ')[1] + ' ' + tmpLine.split(' ')[2]
        # Bathymetry
        tmpinpfile.readline()
        # Tide
        tmpinpfile.readline()
        # Wavemaker
        tmpLine = tmpinpfile.readline().rstrip()        
        inpinfo['eta_source'] = tmpLine[14:]
        # Wave breaking
        tmpLine = tmpinpfile.readline().rstrip()        
        inpinfo['breaking'] = tmpLine[9:]
        # Sponge layer
        tmpLine = tmpinpfile.readline().rstrip()        
        inpinfo['sponge'] = tmpLine[7:]
        # Forcing, initial conditions, tracers
        tmpinpfile.readline()
        tmpinpfile.readline()
        tmpinpfile.readline()
        tmpinpfile.readline()
        tmpinpfile.readline()
        tmpinpfile.readline()
        # Timing
        tmpLine = tmpinpfile.readline().rstrip()
        inpinfo['timing'] = tmpLine[7:]
        time_int = np.float64(tmpLine.split(' ')[5])
        
        # Close me
        tmpinpfile.close()
        
            
    else:
        
        # Assume grid spacing to be 1 meter
        if verbose:
            print("Input file not provided")
        dx = 1.0
        dy = 1.0
        inpinfo = False
    
    
    # Coordinates and depth ---------------------------------------------------
    # Bathymetry file provided
    if bathyfile: 
        
        if verbose:
            print("Reading coordinates and depth from:")
            print("  " + bathyfile)
        
        ncfile = netCDF4.Dataset(bathyfile,'r')
        x_rho = ncfile.variables['x_rho'][:]
        if ncfile.variables.has_key('y_rho'):
            y_rho = ncfile.variables['y_rho'][:]
        else:
            y_rho = None
        h = ncfile.variables['h'][:]
        ncfile.close()
       
        # Create u grid
        x_u       = np.zeros((x_rho.shape[0]+1,))
        x_u[0]    = x_rho[0] - dx/2
        x_u[-1]   = x_rho[-1] + dx/2
        x_u[1:-1] = (x_rho[1:] + x_rho[:-1])/2.0
        
    # Bathymetry file not provided but have output file        
    elif os.path.isfile(workfld + '/depth.txt'):
               
        # Fix this               
        h = np.loadtxt(workfld + '/depth.txt')
        
        hdims = h.ndim
        if hdims == 1:
        
            x_rho = np.arange(1,h.shape[0]+dx,dx)

            # Create u grid
            x_u       = np.zeros((x_rho.shape[0]+1,))
            x_u[0]    = x_rho[0] - dx/2
            x_u[-1]   = x_rho[-1] + dx/2
            x_u[1:-1] = (x_rho[1:] + x_rho[:-1])/2.0
            
        elif hdims == 2:
            x_rho, y_rho = np.meshgrid(np.arange(0,h.shape[1],dx),
                                       np.arange(0,h.shape[0],dy))           
        else:
            if verbose:
                print('Something is wrong with the depth file')
    
    # No bathymetry file provided
    else:
        
        if verbose:
            print("No bathymetry file provided")

    # Get dimensions of variables
    hdims = h.ndim
    
    # Create NetCDF file -------------------------------------------------------
    if verbose:
        print("Creating " + outfile)
    
    # Global attributes  
    nc = netCDF4.Dataset(outfile, 'w', format='NETCDF4')
    nc.Description = 'FunwaveC Output'
    nc.Author = '*****@*****.**'
    nc.Created = time.ctime()
    nc.Type = 'FunwaveC snapshot output'
    nc.Owner = 'Nearshore Modeling Group'
    nc.Software = 'Created with Python ' + sys.version
    nc.NetCDF_Lib = str(netCDF4.getlibversion())
    nc.Source = workfld
    nc.Script = os.path.realpath(__file__)
    
    # Add more global variables to output
    if inpinfo:
        for tmpatt in inpinfo.keys():
            nc.__setattr__(tmpatt,inpinfo[tmpatt][:])
    
    # Create dimensions
    if hdims == 2:
        eta_rho, xi_rho = h.shape
        nc.createDimension('eta_rho', eta_rho)
    else:
        xi_rho = h.shape[0]
        xi_u   = xi_rho + 1
        eta_rho = 1
    nc.createDimension('xi_rho', xi_rho)
    nc.createDimension('xi_u',xi_u)            
    nc.createDimension('ocean_time',0)
    
    # Write coordinate axes ----------------------------------------------
    if hdims == 2:
        
        nc.createVariable('x_rho','f8',('eta_rho','xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho
        
        nc.createVariable('y_rho','f8',('eta_rho','xi_rho'))
        nc.variables['y_rho'].units = 'meter'
        nc.variables['y_rho'].longname = 'y-locations of RHO points'
        nc.variables['y_rho'][:] = y_rho

        nc.createVariable('h','f8',('eta_rho','xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h


    else:
        
        nc.createVariable('x_rho','f8',('xi_rho'))
        nc.variables['x_rho'].units = 'meter'
        nc.variables['x_rho'].longname = 'x-locations of RHO points'
        nc.variables['x_rho'][:] = x_rho
        
        nc.createVariable('h','f8',('xi_rho'))
        nc.variables['h'].units = 'meter'
        nc.variables['h'].longname = 'bathymetry at RHO points'
        nc.variables['h'][:] = h

        nc.createVariable('x_u','f8',('xi_u'))
        nc.variables['x_u'].units = 'meter'
        nc.variables['x_u'].longname = 'x-locations of U points'
        nc.variables['x_u'][:] = x_u        
        
    # Create time vector -------------------------------------------------------
    tmpvar = np.loadtxt(workfld + vars_2d[0] + '.dat')
    twave  = np.arange(time_int,time_int*tmpvar.shape[0]+time_int,time_int)
            
    nc.createVariable('ocean_time','f8','ocean_time')
    nc.variables['ocean_time'].units = 'seconds since 2000-01-01 00:00:00'
    nc.variables['ocean_time'].calendar = 'julian'
    nc.variables['ocean_time'].long_name = 'beach time'
    nc.variables['ocean_time'][:] = twave
        
    # Create variables --------------------------------------------------------

    # Variable information
    varinfo = defaultdict(dict)

    varinfo['eta']['units'] = 'meter'
    varinfo['eta']['longname'] = 'water surface elevation'
    varinfo['eta']['dims'] = ('ocean_time','xi_rho')
    
    varinfo['u']['units'] = 'meter second-1'
    varinfo['u']['longname'] = 'Flow velocity in the xi direction'
    varinfo['u']['dims'] = ('ocean_time','xi_u')
    
    varinfo['v']['units'] = 'meter second-1'
    varinfo['v']['longname'] = 'Flow velocity in the eta direction'
    varinfo['v']['dims'] = ('ocean_time','xi_v')
         
    if verbose:          
        print("Creating variables")
                  
    for aa in vars_2d:
        
        if verbose:
            print('  ' + aa)
        
                # Load variable
        try:
            tmpvar = np.loadtxt(workfld + '/' + aa + '.dat')
        except:
            if verbose:
                print("  Could not create " + aa)
                print("  Input file error")
            continue
        
        # Create variable
        create_nc_var(nc,aa,varinfo[aa]['dims'],varinfo[aa]['units'],
                      varinfo[aa]['longname'])        

        # Write variable
        nc.variables[aa][:] = tmpvar
        
                    
    # Close NetCDF file
    if verbose:
        print('Closing ' + outfile)
    nc.close()